mirror of
https://github.com/PredatH0r/ChanSort.git
synced 2026-05-07 10:55:29 +02:00
- moved all files to a "source" subdirectory to tidy up the GitHub project page
- started to write a readme.md
This commit is contained in:
127
source/ChanSort.Api/ChanSort.Api.csproj
Normal file
127
source/ChanSort.Api/ChanSort.Api.csproj
Normal file
@@ -0,0 +1,127 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.30703</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{DCCFFA08-472B-4D17-BB90-8F513FC01392}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ChanSort.Api</RootNamespace>
|
||||
<AssemblyName>ChanSort.Api</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile>
|
||||
</TargetFrameworkProfile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>..\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
|
||||
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
|
||||
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
|
||||
<CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Controller\ChlFileSerializer.cs" />
|
||||
<Compile Include="Controller\CsvFileSerializer.cs" />
|
||||
<Compile Include="Controller\Editor.cs" />
|
||||
<Compile Include="Controller\ISerializerPlugin.cs" />
|
||||
<Compile Include="Model\ChannelList.cs" />
|
||||
<Compile Include="Model\Enums.cs" />
|
||||
<Compile Include="Model\LnbConfig.cs" />
|
||||
<Compile Include="Model\LookupData.cs" />
|
||||
<Compile Include="Model\NetworkInfo.cs" />
|
||||
<Compile Include="Model\Satellite.cs" />
|
||||
<Compile Include="Model\Transponder.cs" />
|
||||
<Compile Include="Resources.de.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.de.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Utils\DependencyChecker.cs" />
|
||||
<None Include="Utils\ChannelMappingBase.cs" />
|
||||
<Compile Include="Utils\BrowserHelper.cs" />
|
||||
<Compile Include="Utils\DataMapping.cs" />
|
||||
<Compile Include="Utils\Crc32.cs" />
|
||||
<Compile Include="Utils\CsvFile.cs" />
|
||||
<Compile Include="Utils\DvbStringDecoder.cs" />
|
||||
<Compile Include="Utils\IniFile.cs" />
|
||||
<Compile Include="Model\ChannelInfo.cs" />
|
||||
<Compile Include="Controller\SerializerBase.cs" />
|
||||
<Compile Include="Model\DataRoot.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Utils\MappingPool.cs" />
|
||||
<Compile Include="Utils\Tools.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Lookup.csv">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources.de.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.de.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
2
source/ChanSort.Api/ChanSort.Api.csproj.DotSettings
Normal file
2
source/ChanSort.Api/ChanSort.Api.csproj.DotSettings
Normal file
@@ -0,0 +1,2 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=Model/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
120
source/ChanSort.Api/Controller/ChlFileSerializer.cs
Normal file
120
source/ChanSort.Api/Controller/ChlFileSerializer.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Reader for SamToolBox reference lists (*.chl)
|
||||
/// The file has no header, each line represents a channel and fields are separated by semi-colon:
|
||||
/// Number;Channel Name[;Transponder Index]
|
||||
/// </summary>
|
||||
public class ChlFileSerializer
|
||||
{
|
||||
private static readonly char[] Separators = new[] { ';' };
|
||||
private readonly StringBuilder warnings = new StringBuilder();
|
||||
private int lineNumber;
|
||||
private DataRoot dataRoot;
|
||||
private ChannelList channelList;
|
||||
|
||||
#region Load()
|
||||
public string Load(string fileName, DataRoot root, ChannelList list)
|
||||
{
|
||||
if (list.ReadOnly)
|
||||
return "The current channel list is read-only";
|
||||
|
||||
this.lineNumber = 0;
|
||||
this.dataRoot = root;
|
||||
this.channelList = list;
|
||||
this.warnings.Remove(0, this.warnings.Length);
|
||||
|
||||
foreach (var channel in this.channelList.Channels)
|
||||
channel.NewProgramNr = -1;
|
||||
|
||||
using (var stream = new StreamReader(fileName, Encoding.Default))
|
||||
{
|
||||
ReadChannelsFromStream(stream);
|
||||
}
|
||||
return this.warnings.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadChannelsFromStream()
|
||||
|
||||
private void ReadChannelsFromStream(TextReader stream)
|
||||
{
|
||||
string line;
|
||||
while ((line = stream.ReadLine()) != null)
|
||||
{
|
||||
++lineNumber;
|
||||
ParseChannel(line);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ParseChannel()
|
||||
|
||||
private void ParseChannel(string line)
|
||||
{
|
||||
var parts = line.Split(Separators);
|
||||
if (parts.Length < 2) return;
|
||||
int progNr;
|
||||
Transponder transponder = null;
|
||||
if (!int.TryParse(parts[0], out progNr)) return;
|
||||
if (parts.Length >= 3)
|
||||
{
|
||||
int transponderIndex;
|
||||
if (int.TryParse(parts[2], out transponderIndex))
|
||||
{
|
||||
transponder = this.dataRoot.Transponder.TryGet(transponderIndex);
|
||||
if (transponder == null)
|
||||
warnings.AppendFormat("Line #{0,4}: invalid transponder index {1}\r\n", this.lineNumber, transponderIndex);
|
||||
}
|
||||
}
|
||||
|
||||
string name = parts[1].Replace("\"", "");
|
||||
if (name.Trim().Length == 0)
|
||||
return;
|
||||
|
||||
int found = 0;
|
||||
var channels = channelList.GetChannelByName(name);
|
||||
if (transponder != null)
|
||||
channels = channels.Where(chan => chan.Transponder == transponder);
|
||||
|
||||
foreach(var channel in channels)
|
||||
{
|
||||
if (channel.NewProgramNr != -1)
|
||||
continue;
|
||||
++found;
|
||||
if (found > 1)
|
||||
break;
|
||||
channel.NewProgramNr = progNr;
|
||||
}
|
||||
|
||||
if (found == 0)
|
||||
this.warnings.AppendFormat("Line {0,4}: Pr# {1,4}, channel '{2}' could not be found\r\n", this.lineNumber, progNr, name);
|
||||
if (found > 1)
|
||||
this.warnings.AppendFormat("Line {0,4}: Pr# {1,4}, channel '{2}' found multiple times\r\n", this.lineNumber, progNr, name);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Save()
|
||||
public void Save(string fileName, ChannelList list)
|
||||
{
|
||||
using (var writer = new StreamWriter(fileName, false, Encoding.UTF8))
|
||||
{
|
||||
foreach (var channel in list.Channels.OrderBy(c => c.NewProgramNr))
|
||||
{
|
||||
if (channel.NewProgramNr == -1) continue;
|
||||
|
||||
writer.Write(channel.NewProgramNr);
|
||||
writer.Write(';');
|
||||
writer.Write(channel.Name);
|
||||
writer.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
284
source/ChanSort.Api/Controller/CsvFileSerializer.cs
Normal file
284
source/ChanSort.Api/Controller/CsvFileSerializer.cs
Normal file
@@ -0,0 +1,284 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads a reference list from a .csv file with the format
|
||||
/// [dummy1],ProgramNr,[dummy2],UID,ChannelName[,SignalSource,FavAndFlags]
|
||||
/// </summary>
|
||||
public class CsvFileSerializer
|
||||
{
|
||||
private readonly HashSet<ChannelList> clearedLists = new HashSet<ChannelList>();
|
||||
private readonly DataRoot dataRoot;
|
||||
private readonly string fileName;
|
||||
private readonly bool addChannels;
|
||||
|
||||
#region ctor()
|
||||
public CsvFileSerializer(string fileName, DataRoot dataRoot, bool addChannels)
|
||||
{
|
||||
this.fileName = fileName;
|
||||
this.dataRoot = dataRoot;
|
||||
this.addChannels = addChannels;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Load()
|
||||
public void Load()
|
||||
{
|
||||
this.clearedLists.Clear();
|
||||
using (var stream = new StreamReader(fileName))
|
||||
this.ReadChannelsFromStream(stream);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReadChannelsFromStream()
|
||||
|
||||
public void ReadChannelsFromStream(TextReader stream)
|
||||
{
|
||||
int lineNr = 0;
|
||||
string line = "";
|
||||
try
|
||||
{
|
||||
while ((line = stream.ReadLine()) != null)
|
||||
{
|
||||
++lineNr;
|
||||
this.ReadChannel(line);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new FileLoadException(string.Format("Error in reference file line #{0}: {1}", lineNr, line), ex);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ReadChannel()
|
||||
|
||||
private void ReadChannel(string line)
|
||||
{
|
||||
var parts = CsvFile.Parse(line, ',');
|
||||
if (parts.Count < 5) return;
|
||||
int programNr;
|
||||
if (!int.TryParse(parts[1], out programNr)) return;
|
||||
string uid = parts[3];
|
||||
SignalSource signalSource = GetSignalSource(ref programNr, uid, parts);
|
||||
if (signalSource == 0)
|
||||
return;
|
||||
|
||||
string name = parts[4];
|
||||
ChannelList channelList = this.GetInitiallyClearedChannelList(signalSource);
|
||||
if (channelList == null)
|
||||
return;
|
||||
|
||||
IEnumerable<ChannelInfo> channels = FindChannels(channelList, name, uid);
|
||||
var channel = channels == null ? null : channels.FirstOrDefault(c => c.NewProgramNr == -1);
|
||||
if (channel != null)
|
||||
{
|
||||
if (!this.addChannels)
|
||||
{
|
||||
channel.NewProgramNr = programNr;
|
||||
if ((channel.SignalSource & SignalSource.Analog) != 0)
|
||||
{
|
||||
channel.Name = name;
|
||||
channel.IsNameModified = true;
|
||||
}
|
||||
if (parts.Count >= 7)
|
||||
ApplyFlags(channel, parts[6]);
|
||||
}
|
||||
}
|
||||
else if (parts.Count >= 6) // create proxy channel when using the new ref-list format
|
||||
{
|
||||
channel = new ChannelInfo(signalSource, uid, programNr, name);
|
||||
if (addChannels)
|
||||
{
|
||||
channel.NewProgramNr = -1;
|
||||
channel.OldProgramNr = programNr;
|
||||
}
|
||||
channelList.AddChannel(channel);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetSignalSource()
|
||||
private static SignalSource GetSignalSource(ref int slot, string uid, IList<string> parts)
|
||||
{
|
||||
// new lists store a bitmask which defines the type of channel and list it came from
|
||||
if (parts.Count >= 6 && parts[5].Length >= 4)
|
||||
{
|
||||
SignalSource s = 0;
|
||||
string code = parts[5];
|
||||
if (code[0] == 'A') s |= SignalSource.Analog;
|
||||
else if (code[0] == 'D') s |= SignalSource.Digital;
|
||||
|
||||
if (code[1] == 'A') s |= SignalSource.Antenna;
|
||||
else if (code[1] == 'C') s |= SignalSource.Cable;
|
||||
else if (code[1] == 'S') s |= SignalSource.Sat;
|
||||
|
||||
if (code[2] == 'T') s |= SignalSource.Tv;
|
||||
else if (code[2] == 'R') s |= SignalSource.Radio;
|
||||
|
||||
s |= (SignalSource) (int.Parse(code.Substring(3)) << 12);
|
||||
return s;
|
||||
}
|
||||
|
||||
// compatibility for older lists
|
||||
bool isTv = slot < 0x4000;
|
||||
slot &= 0x3FFFF;
|
||||
SignalSource signalSource;
|
||||
switch (uid[0])
|
||||
{
|
||||
case 'S': signalSource = SignalSource.DvbS; break;
|
||||
case 'C': signalSource = SignalSource.DvbCT; break;
|
||||
case 'A': signalSource = SignalSource.AnalogCT; break;
|
||||
case 'H': signalSource = SignalSource.HdPlusD; break;
|
||||
default: return 0;
|
||||
}
|
||||
signalSource |= isTv ? SignalSource.Tv : SignalSource.Radio;
|
||||
return signalSource;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetInitiallyClearedChannelList()
|
||||
private ChannelList GetInitiallyClearedChannelList(SignalSource signalSource)
|
||||
{
|
||||
var channelList = dataRoot.GetChannelList(signalSource);
|
||||
if (channelList == null || channelList.ReadOnly)
|
||||
return null;
|
||||
if (!this.addChannels && !this.clearedLists.Contains(channelList))
|
||||
{
|
||||
foreach (var channel in channelList.Channels)
|
||||
channel.NewProgramNr = -1;
|
||||
this.clearedLists.Add(channelList);
|
||||
}
|
||||
return channelList;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region FindChannels()
|
||||
private IEnumerable<ChannelInfo> FindChannels(ChannelList channelList, string name, string uid)
|
||||
{
|
||||
// if there's only a single channel with the given name, use it regardless of UID (allows for a changed freq/tranpsonder)
|
||||
IList<ChannelInfo> list = channelList.GetChannelByName(name).ToList();
|
||||
if (list.Count == 1)
|
||||
return list;
|
||||
|
||||
string[] uidParts;
|
||||
if (uid.StartsWith("C") && (uidParts = uid.Split('-')).Length <= 4)
|
||||
{
|
||||
// older CSV files didn't use the Transponder as part of the UID, which is necessary
|
||||
// to distinguish between DVB-T channels with identical (onid,tsid,sid), which may be received
|
||||
// from multiple regional transmitters on different transponders
|
||||
int onid = int.Parse(uidParts[1]);
|
||||
int tsid = int.Parse(uidParts[2]);
|
||||
int sid = int.Parse(uidParts[3]);
|
||||
return channelList.Channels.Where(c =>
|
||||
c.OriginalNetworkId == onid &&
|
||||
c.TransportStreamId == tsid &&
|
||||
c.ServiceId == sid
|
||||
).ToList();
|
||||
}
|
||||
|
||||
var byUidList = channelList.GetChannelByUid(uid);
|
||||
return byUidList;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ApplyFlags()
|
||||
private void ApplyFlags(ChannelInfo channel, string flags)
|
||||
{
|
||||
channel.Lock = false;
|
||||
channel.Skip = false;
|
||||
channel.Hidden = false;
|
||||
|
||||
foreach (char c in flags)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '1': channel.Favorites |= Favorites.A; break;
|
||||
case '2': channel.Favorites |= Favorites.B; break;
|
||||
case '3': channel.Favorites |= Favorites.C; break;
|
||||
case '4': channel.Favorites |= Favorites.D; break;
|
||||
case '5': channel.Favorites |= Favorites.E; break;
|
||||
case 'L': channel.Lock = true; break;
|
||||
case 'S': channel.Skip = true; break;
|
||||
case 'H': channel.Hidden = true; break;
|
||||
case 'D': channel.IsDeleted = true; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Save()
|
||||
public void Save()
|
||||
{
|
||||
using (StreamWriter stream = new StreamWriter(fileName))
|
||||
{
|
||||
Save(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public void Save(StreamWriter stream)
|
||||
{
|
||||
foreach (var channelList in dataRoot.ChannelLists)
|
||||
{
|
||||
foreach (var channel in channelList.Channels.Where(ch => ch.NewProgramNr != -1).OrderBy(ch => ch.NewProgramNr))
|
||||
{
|
||||
string line = string.Format("{0},{1},{2},{3},\"{4}\",{5},{6}",
|
||||
"", // past: channel.RecordIndex,
|
||||
channel.NewProgramNr,
|
||||
"", // past: channel.TransportStreamId,
|
||||
channel.Uid,
|
||||
channel.Name,
|
||||
this.EncodeSignalSource(channel.SignalSource),
|
||||
this.EncodeFavoritesAndFlags(channel));
|
||||
stream.WriteLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region EncodeSignalSource()
|
||||
private object EncodeSignalSource(SignalSource signalSource)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if ((signalSource & SignalSource.Analog) != 0) sb.Append('A');
|
||||
else sb.Append('D');
|
||||
|
||||
if ((signalSource & SignalSource.Antenna) != 0) sb.Append('A');
|
||||
else if ((signalSource & SignalSource.Cable) != 0) sb.Append('C');
|
||||
else sb.Append('S');
|
||||
|
||||
if ((signalSource & SignalSource.Radio) != 0) sb.Append('R');
|
||||
else sb.Append('T');
|
||||
|
||||
sb.Append((int)signalSource >> 12);
|
||||
return sb.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region EncodeFavoritesAndFlags()
|
||||
private string EncodeFavoritesAndFlags(ChannelInfo channel)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if ((channel.Favorites & Favorites.A) != 0) sb.Append('1');
|
||||
if ((channel.Favorites & Favorites.B) != 0) sb.Append('2');
|
||||
if ((channel.Favorites & Favorites.C) != 0) sb.Append('3');
|
||||
if ((channel.Favorites & Favorites.D) != 0) sb.Append('4');
|
||||
if ((channel.Favorites & Favorites.E) != 0) sb.Append('5');
|
||||
if (channel.Lock) sb.Append('L');
|
||||
if (channel.Skip) sb.Append('S');
|
||||
if (channel.Hidden) sb.Append('H');
|
||||
if (channel.IsDeleted) sb.Append('D');
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
401
source/ChanSort.Api/Controller/Editor.cs
Normal file
401
source/ChanSort.Api/Controller/Editor.cs
Normal file
@@ -0,0 +1,401 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class Editor
|
||||
{
|
||||
public DataRoot DataRoot;
|
||||
public ChannelList ChannelList;
|
||||
public int SubListIndex;
|
||||
private UnsortedChannelMode unsortedChannelMode;
|
||||
|
||||
#region AddChannels()
|
||||
|
||||
public ChannelInfo AddChannels(IList<ChannelInfo> channels)
|
||||
{
|
||||
int count = channels.Count(channel => channel.GetPosition(this.SubListIndex) == -1);
|
||||
if (count == 0) return null;
|
||||
|
||||
ChannelInfo lastInsertedChannel = null;
|
||||
int progNr = this.ChannelList.InsertProgramNumber;
|
||||
int relativeChannelNumber = 0;
|
||||
int progNrCopy = progNr; // prevent "access to modified closure" warning
|
||||
foreach (
|
||||
var channel in
|
||||
this.ChannelList.Channels.Where(c => c.GetPosition(this.SubListIndex) >= progNrCopy)
|
||||
.OrderBy(c => c.GetPosition(this.SubListIndex)))
|
||||
{
|
||||
var curPos = channel.GetPosition(this.SubListIndex);
|
||||
int gap = count - (curPos - progNr - relativeChannelNumber);
|
||||
if (gap > 0)
|
||||
{
|
||||
channel.SetPosition(this.SubListIndex, curPos + gap);
|
||||
++relativeChannelNumber;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var channel in channels)
|
||||
{
|
||||
if (channel.GetPosition(this.SubListIndex) != -1)
|
||||
{
|
||||
// TODO notify user
|
||||
continue;
|
||||
}
|
||||
|
||||
channel.SetPosition(this.SubListIndex, progNr++);
|
||||
lastInsertedChannel = channel;
|
||||
}
|
||||
this.ChannelList.InsertProgramNumber += count;
|
||||
|
||||
this.DataRoot.NeedsSaving |= lastInsertedChannel != null;
|
||||
return lastInsertedChannel;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RemoveChannels()
|
||||
|
||||
public void RemoveChannels(IList<ChannelInfo> channels, bool closeGap)
|
||||
{
|
||||
if (channels.Count == 0) return;
|
||||
|
||||
this.ChannelList.InsertProgramNumber = channels[0].GetPosition(this.SubListIndex);
|
||||
var orderedChannelList =
|
||||
this.ChannelList.Channels.Where(c => c.GetPosition(this.SubListIndex) != -1)
|
||||
.OrderBy(c => c.GetPosition(this.SubListIndex));
|
||||
foreach (var channel in channels)
|
||||
{
|
||||
if (channel.GetPosition(this.SubListIndex) == -1)
|
||||
continue;
|
||||
if (closeGap)
|
||||
{
|
||||
int prevNr = channel.GetPosition(this.SubListIndex);
|
||||
foreach (var channel2 in orderedChannelList)
|
||||
{
|
||||
if (channel2.GetPosition(this.SubListIndex) > channel.GetPosition(this.SubListIndex))
|
||||
{
|
||||
// ignore deleted and proxy channels (prevNr<0), broken channels (==0) and channels after a gap
|
||||
if (prevNr <= 0 || channel2.GetPosition(this.SubListIndex) != prevNr + 1)
|
||||
break;
|
||||
prevNr = channel2.GetPosition(this.SubListIndex);
|
||||
channel2.ChangePosition(this.SubListIndex, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
channel.SetPosition(this.SubListIndex, -1);
|
||||
}
|
||||
|
||||
this.DataRoot.NeedsSaving = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MoveChannels()
|
||||
|
||||
public void MoveChannels(IList<ChannelInfo> channels, bool up)
|
||||
{
|
||||
if (channels.Count == 0)
|
||||
return;
|
||||
if (up && channels[0].GetPosition(this.SubListIndex) <= this.ChannelList.FirstProgramNumber)
|
||||
return;
|
||||
|
||||
int delta = (up ? -1 : +1);
|
||||
foreach (var channel in (up ? channels : channels.Reverse()))
|
||||
{
|
||||
int newProgramNr = channel.GetPosition(this.SubListIndex) + delta;
|
||||
ChannelInfo channelAtNewPos =
|
||||
this.ChannelList.Channels.FirstOrDefault(ch => ch.GetPosition(this.SubListIndex) == newProgramNr);
|
||||
if (channelAtNewPos != null)
|
||||
channelAtNewPos.ChangePosition(this.SubListIndex, -delta);
|
||||
channel.ChangePosition(this.SubListIndex, delta);
|
||||
}
|
||||
this.DataRoot.NeedsSaving = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SortSelectedChannels(), ChannelComparerForSortingByName()
|
||||
|
||||
public void SortSelectedChannels(List<ChannelInfo> selectedChannels)
|
||||
{
|
||||
if (selectedChannels.Count == 0) return;
|
||||
var sortedChannels = new List<ChannelInfo>(selectedChannels);
|
||||
sortedChannels.Sort(this.ChannelComparerForSortingByName);
|
||||
var programNumbers = selectedChannels.Select(ch => ch.GetPosition(this.SubListIndex)).ToList();
|
||||
for (int i = 0; i < sortedChannels.Count; i++)
|
||||
sortedChannels[i].SetPosition(this.SubListIndex, programNumbers[i]);
|
||||
|
||||
this.DataRoot.NeedsSaving = true;
|
||||
}
|
||||
|
||||
private int ChannelComparerForSortingByName(ChannelInfo channel1, ChannelInfo channel2)
|
||||
{
|
||||
return channel1.Name.CompareTo(channel2.Name);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region SetSlotNumber()
|
||||
|
||||
public void SetSlotNumber(IList<ChannelInfo> channels, int slot, bool swap, bool closeGap)
|
||||
{
|
||||
if (channels.Count == 0) return;
|
||||
if (swap)
|
||||
{
|
||||
foreach (var channel in channels)
|
||||
{
|
||||
if (slot != -1)
|
||||
{
|
||||
var others = this.ChannelList.GetChannelByNewProgNr(slot);
|
||||
foreach (var other in others)
|
||||
other.SetPosition(this.SubListIndex, channel.GetPosition(this.SubListIndex));
|
||||
}
|
||||
channel.SetPosition(this.SubListIndex, slot++);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.RemoveChannels(channels, closeGap);
|
||||
this.ChannelList.InsertProgramNumber = slot;
|
||||
this.AddChannels(channels);
|
||||
}
|
||||
this.DataRoot.NeedsSaving = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RenumberChannels()
|
||||
|
||||
public void RenumberChannels(List<ChannelInfo> channels)
|
||||
{
|
||||
if (channels.Count == 0) return;
|
||||
int progNr = channels.Min(ch => ch.GetPosition(this.SubListIndex));
|
||||
foreach (var channel in channels)
|
||||
{
|
||||
if (channel.GetPosition(this.SubListIndex) == progNr)
|
||||
{
|
||||
++progNr;
|
||||
continue;
|
||||
}
|
||||
|
||||
var list = new List<ChannelInfo>();
|
||||
list.Add(channel);
|
||||
this.RemoveChannels(list, false);
|
||||
this.ChannelList.InsertProgramNumber = progNr++;
|
||||
this.AddChannels(list);
|
||||
this.DataRoot.NeedsSaving = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region ApplyReferenceList()
|
||||
|
||||
public void ApplyReferenceList(DataRoot refDataRoot)
|
||||
{
|
||||
foreach (var channelList in this.DataRoot.ChannelLists)
|
||||
{
|
||||
foreach (var channel in channelList.Channels)
|
||||
channel.SetPosition(this.SubListIndex, -1);
|
||||
}
|
||||
|
||||
StringBuilder log = new StringBuilder();
|
||||
foreach (var refList in refDataRoot.ChannelLists)
|
||||
{
|
||||
var tvList = this.DataRoot.GetChannelList(refList.SignalSource);
|
||||
if (tvList == null)
|
||||
{
|
||||
log.AppendFormat("Skipped reference list {0}\r\n", refList.ShortCaption);
|
||||
continue;
|
||||
}
|
||||
foreach (var refChannel in refList.Channels)
|
||||
{
|
||||
var tvChannels = tvList.GetChannelByUid(refChannel.Uid);
|
||||
ChannelInfo tvChannel = tvChannels.FirstOrDefault(c => c.GetPosition(this.SubListIndex) == -1);
|
||||
if (tvChannel != null)
|
||||
{
|
||||
tvChannel.SetPosition(this.SubListIndex, refChannel.OldProgramNr);
|
||||
tvChannel.Favorites = refChannel.Favorites & DataRoot.SupportedFavorites;
|
||||
tvChannel.Skip = refChannel.Skip;
|
||||
tvChannel.Lock = refChannel.Lock;
|
||||
tvChannel.Hidden = refChannel.Hidden;
|
||||
tvChannel.IsDeleted = refChannel.IsDeleted;
|
||||
if ((tvChannel.SignalSource & SignalSource.Analog) != 0)
|
||||
{
|
||||
tvChannel.Name = refChannel.Name;
|
||||
tvChannel.IsNameModified = true;
|
||||
}
|
||||
if (this.DataRoot.SortedFavorites)
|
||||
{
|
||||
if (refDataRoot.SortedFavorites)
|
||||
{
|
||||
var c = Math.Min(refChannel.FavIndex.Count, tvChannel.FavIndex.Count);
|
||||
for (int i = 0; i < c; i++)
|
||||
tvChannel.FavIndex[i] = refChannel.FavIndex[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
this.ApplyPrNrToFavLists(tvChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tvChannel = new ChannelInfo(refChannel.SignalSource, refChannel.Uid, refChannel.OldProgramNr,
|
||||
refChannel.Name);
|
||||
tvList.AddChannel(tvChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region AutoNumberingForUnassignedChannels()
|
||||
|
||||
public void AutoNumberingForUnassignedChannels(UnsortedChannelMode mode)
|
||||
{
|
||||
this.unsortedChannelMode = mode;
|
||||
foreach (var list in DataRoot.ChannelLists)
|
||||
{
|
||||
var sortedChannels = list.Channels.OrderBy(ChanSortCriteria).ToList();
|
||||
int maxProgNr = 0;
|
||||
|
||||
foreach (var appChannel in sortedChannels)
|
||||
{
|
||||
if (appChannel.RecordIndex < 0)
|
||||
continue;
|
||||
|
||||
if (appChannel.NewProgramNr == -1 && mode == UnsortedChannelMode.MarkDeleted)
|
||||
continue;
|
||||
|
||||
int progNr = GetNewPogramNr(appChannel, ref maxProgNr);
|
||||
appChannel.NewProgramNr = progNr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region ChanSortCriteria()
|
||||
|
||||
private string ChanSortCriteria(ChannelInfo channel)
|
||||
{
|
||||
// explicitly sorted
|
||||
if (channel.GetPosition(this.SubListIndex) != -1)
|
||||
return channel.GetPosition(this.SubListIndex).ToString("d4");
|
||||
|
||||
// eventually hide unsorted channels
|
||||
if (this.unsortedChannelMode == UnsortedChannelMode.MarkDeleted)
|
||||
return "Z";
|
||||
|
||||
// eventually append in old order
|
||||
if (this.unsortedChannelMode == UnsortedChannelMode.AppendInOrder)
|
||||
return "B" + channel.OldProgramNr.ToString("d4");
|
||||
|
||||
// sort alphabetically, with "." and "" on the bottom
|
||||
if (channel.Name == ".")
|
||||
return "B";
|
||||
if (channel.Name == "")
|
||||
return "C";
|
||||
return "A" + channel.Name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetNewPogramNr()
|
||||
|
||||
private int GetNewPogramNr(ChannelInfo appChannel, ref int maxPrNr)
|
||||
{
|
||||
int prNr = appChannel.NewProgramNr;
|
||||
if (prNr > maxPrNr)
|
||||
maxPrNr = prNr;
|
||||
if (prNr == -1)
|
||||
{
|
||||
if (appChannel.OldProgramNr != -1 && this.unsortedChannelMode != UnsortedChannelMode.MarkDeleted)
|
||||
prNr = ++maxPrNr;
|
||||
}
|
||||
return prNr;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region SetFavorites()
|
||||
public void SetFavorites(List<ChannelInfo> list, Favorites favorites, bool set)
|
||||
{
|
||||
bool sortedFav = this.DataRoot.SortedFavorites;
|
||||
int favIndex = 0;
|
||||
if (sortedFav)
|
||||
{
|
||||
for (int mask = (int) favorites; (mask & 1) == 0; mask >>= 1)
|
||||
++favIndex;
|
||||
}
|
||||
|
||||
if (set)
|
||||
{
|
||||
int maxPosition = 0;
|
||||
if (sortedFav)
|
||||
{
|
||||
foreach (var channel in this.ChannelList.Channels)
|
||||
maxPosition = Math.Max(maxPosition, channel.FavIndex[favIndex]);
|
||||
}
|
||||
|
||||
foreach (var channel in list)
|
||||
{
|
||||
if (sortedFav && channel.FavIndex[favIndex] == -1)
|
||||
channel.FavIndex[favIndex] = ++maxPosition;
|
||||
channel.Favorites |= favorites;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var channel in list)
|
||||
{
|
||||
if (sortedFav && channel.FavIndex[favIndex] != -1)
|
||||
{
|
||||
channel.FavIndex[favIndex] = -1;
|
||||
// TODO close gap by pulling down higher numbers
|
||||
}
|
||||
channel.Favorites &= ~favorites;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ApplyPrNrToFavLists()
|
||||
public void ApplyPrNrToFavLists()
|
||||
{
|
||||
if (!this.DataRoot.SortedFavorites)
|
||||
return;
|
||||
|
||||
foreach (var list in this.DataRoot.ChannelLists)
|
||||
{
|
||||
foreach(var channel in list.Channels)
|
||||
this.ApplyPrNrToFavLists(channel);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the number inside the favorites list to the same number as Pr#
|
||||
/// </summary>
|
||||
/// <param name="tvChannel"></param>
|
||||
private void ApplyPrNrToFavLists(ChannelInfo tvChannel)
|
||||
{
|
||||
var supMask = (int)this.DataRoot.SupportedFavorites;
|
||||
var refMask = (int)tvChannel.Favorites;
|
||||
for (int i = 0; supMask != 0; i++)
|
||||
{
|
||||
tvChannel.FavIndex[i] = (refMask & 0x01) == 0 ? -1 : tvChannel.OldProgramNr;
|
||||
supMask >>= 1;
|
||||
refMask >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
21
source/ChanSort.Api/Controller/ISerializerPlugin.cs
Normal file
21
source/ChanSort.Api/Controller/ISerializerPlugin.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public interface ISerializerPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the plugin, as displayed in the OpenFileDialog file-type selection combo box
|
||||
/// </summary>
|
||||
string PluginName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Semicolon separated list of supported file types (e.g. "xxLM*.TTL;xxLV*.TTL")
|
||||
/// </summary>
|
||||
string FileFilter { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Create an object that can read/write the file
|
||||
/// </summary>
|
||||
/// <exception cref="System.IO.IOException">file is not of any supported type</exception>
|
||||
SerializerBase CreateSerializer(string inputFile);
|
||||
}
|
||||
}
|
||||
84
source/ChanSort.Api/Controller/SerializerBase.cs
Normal file
84
source/ChanSort.Api/Controller/SerializerBase.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System.Text;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public abstract class SerializerBase
|
||||
{
|
||||
public class SupportedFeatures
|
||||
{
|
||||
public bool ChannelNameEdit { get; set; }
|
||||
public bool CleanUpChannelData { get; set; }
|
||||
public bool DeviceSettings { get; set; }
|
||||
public bool CanDeleteChannels { get; set; }
|
||||
public bool CanHaveGaps { get; set; }
|
||||
|
||||
public SupportedFeatures()
|
||||
{
|
||||
this.CanDeleteChannels = true;
|
||||
this.CanHaveGaps = true;
|
||||
}
|
||||
}
|
||||
|
||||
private Encoding defaultEncoding;
|
||||
|
||||
public string FileName { get; set; }
|
||||
public DataRoot DataRoot { get; protected set; }
|
||||
public SupportedFeatures Features { get; private set; }
|
||||
|
||||
protected SerializerBase(string inputFile)
|
||||
{
|
||||
this.Features = new SupportedFeatures();
|
||||
this.FileName = inputFile;
|
||||
this.DataRoot = new DataRoot();
|
||||
this.defaultEncoding = Encoding.GetEncoding("iso-8859-9");
|
||||
}
|
||||
|
||||
public abstract string DisplayName { get; }
|
||||
public abstract void Load();
|
||||
public abstract void Save(string tvOutputFile);
|
||||
|
||||
public virtual Encoding DefaultEncoding
|
||||
{
|
||||
get { return this.defaultEncoding; }
|
||||
set { this.defaultEncoding = value; }
|
||||
}
|
||||
|
||||
public virtual void EraseChannelData() { }
|
||||
|
||||
public virtual string GetFileInformation()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("File name: ").AppendLine(this.FileName);
|
||||
sb.AppendLine();
|
||||
foreach (var list in this.DataRoot.ChannelLists)
|
||||
{
|
||||
sb.Append(list.ShortCaption).AppendLine("-----");
|
||||
sb.Append("number of channels: ").AppendLine(list.Count.ToString());
|
||||
sb.Append("number of predefined channel numbers: ").AppendLine(list.PresetProgramNrCount.ToString());
|
||||
sb.Append("number of duplicate program numbers: ").AppendLine(list.DuplicateProgNrCount.ToString());
|
||||
sb.Append("number of duplicate channel identifiers: ").AppendLine(list.DuplicateUidCount.ToString());
|
||||
int deleted = 0;
|
||||
int hidden = 0;
|
||||
int skipped = 0;
|
||||
foreach (var channel in list.Channels)
|
||||
{
|
||||
if (channel.IsDeleted)
|
||||
++deleted;
|
||||
if (channel.Hidden)
|
||||
++hidden;
|
||||
if (channel.Skip)
|
||||
++skipped;
|
||||
}
|
||||
sb.Append("number of deleted channels: ").AppendLine(deleted.ToString());
|
||||
sb.Append("number of hidden channels: ").AppendLine(hidden.ToString());
|
||||
sb.Append("number of skipped channels: ").AppendLine(skipped.ToString());
|
||||
sb.AppendLine();
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public virtual void ShowDeviceSettingsForm(object parentWindow) { }
|
||||
|
||||
public virtual string CleanUpChannelData() { return ""; }
|
||||
}
|
||||
}
|
||||
427
source/ChanSort.Api/Lookup.csv
Normal file
427
source/ChanSort.Api/Lookup.csv
Normal file
@@ -0,0 +1,427 @@
|
||||
ONID;Start;End;Name;Operator
|
||||
ONID;0x0000;0x0000;(Reserved);(Reserved)
|
||||
ONID;0x0001;0x0001;Société Européenne des Satellites;Société Européenne des Satellites
|
||||
ONID;0x0002;0x0002;Société Européenne des Satellites;Société Européenne des Satellites
|
||||
ONID;0x0003;0x0019;Société Européenne des Satellites;Société Européenne des Satellites
|
||||
ONID;0x001A;0x001A;Quiero Televisión ;Quiero Televisión
|
||||
ONID;0x001B;0x001B;RAI;RAI
|
||||
ONID;0x001C;0x001C;Hellas-Sat S.A.;Hellas-Sat S.A.
|
||||
ONID;0x001D;0x001D;TELECOM ITALIA MEDIA BROADCASTING SRL;TELECOM ITALIA MEDIA BROADCASTING SRL
|
||||
ONID;0x001F;0x001F;Europe Online Networks S.A ;Europe Online Networks S.A
|
||||
ONID;0x0020;0x0020;Société Européenne des Satellites;Société Européenne des Satellites
|
||||
ONID;0x0021;0x0021;Hispasat S.A .;Hispasat S.A .
|
||||
ONID;0x0022;0x0022;Hispasat S.A .;Hispasat S.A .
|
||||
ONID;0x0023;0x0023;Hispasat S.A .;Hispasat S.A .
|
||||
ONID;0x0024;0x0024;Hispasat S.A .;Hispasat S.A .
|
||||
ONID;0x0025;0x0025;Hispasat S.A .;Hispasat S.A .
|
||||
ONID;0x0026;0x0026;Hispasat S.A .;Hispasat S.A .
|
||||
ONID;0x0027;0x0027;Hispasat FSS;Hispasat FSS
|
||||
ONID;0x0028;0x0028;Hispasat DBS;Hispasat DBS
|
||||
ONID;0x0029;0x0029;Hispasat America;Hispasat America
|
||||
ONID;0x002A;0x002A;Päijät-Hämeen Puhelin Oyj;Päijät-Hämeen Puhelin Oyj
|
||||
ONID;0x002B;0x002B;Digita Oy;Digita Oy
|
||||
ONID;0x002E;0x002E;Xantic BU Broadband;Xantic BU Broadband
|
||||
ONID;0x002F;0x002F;TVNZ ;TVNZ
|
||||
ONID;0x0030;0x0030;Canal+ SA (for Intelsat 601-325°E);Canal+ SA (for Intelsat 601-325°E)
|
||||
ONID;0x0031;0x0031;Hispasat S.A.;Hispasat S.A.
|
||||
ONID;0x0032;0x0032;Hispasat S.A.;Hispasat S.A.
|
||||
ONID;0x0033;0x0033;Hispasat S.A.;Hispasat S.A.
|
||||
ONID;0x0034;0x0034;Hispasat S.A.;Hispasat S.A.
|
||||
ONID;0x0035;0x0035;NetHold IMS;NetHold IMS
|
||||
ONID;0x0036;0x0036;TV Cabo Portugal ;TV Cabo Portugal
|
||||
ONID;0x0037;0x0037;France Telecom, CNES and DGA;France Telecom, CNES and DGA
|
||||
ONID;0x0038;0x0038;Hellenic Telecommunications Organization S.A .;Hellenic Telecommunications Organization S.A .
|
||||
ONID;0x0039;0x0039;Broadcast Australia Pty.;Broadcast Australia Pty.
|
||||
ONID;0x003A;0x003A;GeoTelecom Satellite Services;GeoTelecom Satellite Services
|
||||
ONID;0x003B;0x003B;BBC;BBC
|
||||
ONID;0x003C;0x003C;KPN Broadcast Services;KPN Broadcast Services
|
||||
ONID;0x003D;0x003D;Skylogic Italia S.A.;Skylogic Italia S.A.
|
||||
ONID;0x003E;0x003E;Eutelsat S.A.;Eutelsat S.A.
|
||||
ONID;0x003F;0x003F;Eutelsat S.A.;Eutelsat S.A.
|
||||
ONID;0x0040;0x0040;Hrvatski Telekom d.d;Hrvatski Telekom d.d
|
||||
ONID;0x0041;0x0041;Mindport ;Mindport
|
||||
ONID;0x0042;0x0042;DTV haber ve Gorsel yayýncilik;DTV haber ve Gorsel yayýncilik
|
||||
ONID;0x0043;0x0043;arena Sport Rechte und Marketing GmbH;arena Sport Rechte und Marketing GmbH
|
||||
ONID;0x0044;0x0044;VisionTV LLC;VisionTV LLC
|
||||
ONID;0x0045;0x0045;SES-Sirius;SES-Sirius
|
||||
ONID;0x0046;0x0046;Telenor ;Telenor
|
||||
ONID;0x0047;0x0047;Telenor;Telenor
|
||||
ONID;0x0048;0x0048;STAR DIGITAL A.S .;STAR DIGITAL A.S .
|
||||
ONID;0x0049;0x0049;Sentech ;Sentech
|
||||
ONID;0x004A;0x004B;Rambouillet ES;Rambouillet ES
|
||||
ONID;0x004C;0x004C;Skylogic S.A.;Skylogic S.A.
|
||||
ONID;0x004D;0x004D;Skylogic S.A.;Skylogic S.A.
|
||||
ONID;0x004E;0x004F;Eutelsat S.A.;Eutelsat S.A.
|
||||
ONID;0x0050;0x0050;HRT – Croatian Radio and Television;HRT – Croatian Radio and Television
|
||||
ONID;0x0051;0x0051;Havas ;Havas
|
||||
ONID;0x0052;0x0052;StarGuide Digital Networks ;StarGuide Digital Networks
|
||||
ONID;0x0053;0x0053;PT Comunicações;PT Comunicações
|
||||
ONID;0x0054;0x0054;Teracom AB Satellite Services;Teracom AB Satellite Services
|
||||
ONID;0x0055;0x0055;NSAB (Teracom);NSAB (Teracom)
|
||||
ONID;0x0056;0x0056;Viasat Satellite Services AB;Viasat Satellite Services AB
|
||||
ONID;0x0058;0x0058;UBC Thailand ;UBC Thailand
|
||||
ONID;0x0059;0x0059;Bharat Business Channel Limited;Bharat Business Channel Limited
|
||||
ONID;0x005A;0x005A;ICO Satellite Services G.P.;ICO Satellite Services G.P.
|
||||
ONID;0x005B;0x005B;ZON;ZON
|
||||
ONID;0x005E;0x005E;NSAB ;NSAB
|
||||
ONID;0x005F;0x005F;NSAB ;NSAB
|
||||
ONID;0x0060;0x0060;Kabel Deutschland ;Kabel Deutschland
|
||||
ONID;0x0064;0x0064;T-Kábel;T-Kábel Magyarország Kft.
|
||||
ONID;0x0065;0x0065;France Telecom Orange;France Telecom Orange
|
||||
ONID;0x0066;0x0066;Zweites Deutsches Fernsehen - ZDF (cable contribution);Zweites Deutsches Fernsehen - ZDF
|
||||
ONID;0x0069;0x0069;Optus B3 156°E;Optus Communications
|
||||
ONID;0x0070;0x0070;BONUM1 36 Degrees East;NTV+
|
||||
ONID;0x0073;0x0073;PanAmSat 4 68.5°E;Pan American Satellite System
|
||||
ONID;0x007D;0x007D;Skylogic;Skylogic Italia
|
||||
ONID;0x007E;0x007F;Eutelsat Satellite System at 7°E;EUTELSAT – European Telecommunications Satellite Organization
|
||||
ONID;0x0085;0x0085;BetaTechnik;BetaTechnik
|
||||
ONID;0x0090;0x0090;National network;TDF
|
||||
ONID;0x009A;0x009B;Eutelsat satellite system at 9°East;Rambouillet ES
|
||||
ONID;0x009C;0x009D;Eutelsat satellite system at 9°East;Skylogic S.A.
|
||||
ONID;0x009E;0x009F;Eutelsat satellite system at 9°East;Eutelsat S.A.
|
||||
ONID;0x00A0;0x00A0;National Cable Network;News Datacom
|
||||
ONID;0x00A1;0x00A1;DigiSTAR;STAR Television Productions Ltd (HK) (NDS)
|
||||
ONID;0x00A2;0x00A2;Sky Entertainment Services;NetSat Serviços Ltda (Brazil), Innova S. de R. L. (Mexico) and Multicountry Partnership L. P. (NDS)
|
||||
ONID;0x00A3;0x00A3;NDS Director systems;Various (product only sold by Tandberg TV) (NDS)
|
||||
ONID;0x00A4;0x00A4;ISkyB;STAR Television Productions Ltd (HK) (NDS)
|
||||
ONID;0x00A5;0x00A5;Indovision;PT. Matahari Lintas Cakrawala (MLC) (NDS)
|
||||
ONID;0x00A6;0x00A6;ART;ART (NDS)
|
||||
ONID;0x00A7;0x00A7;Globecast;France Telecom (NDS)
|
||||
ONID;0x00A8;0x00A8;Foxtel;Foxtel (Australia) (NDS)
|
||||
ONID;0x00A9;0x00A9;Sky New Zealand;Sky Network Television Ltd (NDS)
|
||||
ONID;0x00AA;0x00AA;OTE;OTE (Greece) (NDS)
|
||||
ONID;0x00AB;0x00AB;Yes Satellite Services;DBS (Israel) (NDS)
|
||||
ONID;0x00AC;0x00AC;(NDS satellite services);(NDS to be allocated)
|
||||
ONID;0x00AD;0x00AD;SkyLife;Korea Digital Broadcasting
|
||||
ONID;0x00AE;0x00AF;(NDS satellite services);(NDS to be allocated)
|
||||
ONID;0x00B0;0x00B3;TPS;La Télévision Par Satellite
|
||||
ONID;0x00B4;0x00B4;Telesat 107.3°W;Telesat Canada
|
||||
ONID;0x00B5;0x00B5;Telesat 111.1°W;Telesat Canada
|
||||
ONID;0x00B6;0x00B6;Telstra Saturn;TelstraSaturn Limited
|
||||
ONID;0x00BA;0x00BA;Satellite Express – 6 (80°E);Satellite Express
|
||||
ONID;0x00C0;0x00CD;Canal +;Canal+
|
||||
ONID;0x00D0;0x00D0;CCTV;China Central Television (NDS)
|
||||
ONID;0x00D1;0x00D1;Galaxy;Galaxy Satellite Broadcasting, Hong Kong (NDS)
|
||||
ONID;0x00D2;0x00DF;(NDS satellite services);(NDS to be allocated)
|
||||
ONID;0x00EB;0x00EB;Eurovision Network;European Broadcasting Union
|
||||
ONID;0x0100;0x0100;ExpressVu;ExpressVu Inc.
|
||||
ONID;0x0101;0x0101;Bulsatcom AD;Bulsatcom AD
|
||||
ONID;0x0104;0x0104;MagtiSat;Magticom Ltd.
|
||||
ONID;0x010D;0x010D;Skylogic;Skylogic Italia
|
||||
ONID;0x010E;0x010F;Eutelsat Satellite System at 10°E;European Telecommunications Satellite Organization
|
||||
ONID;0x0110;0x0110;Mediaset;Mediaset
|
||||
ONID;0x011F;0x011F;visAvision Network;European Telecommunications Satellite Organization
|
||||
ONID;0x013D;0x013D;Skylogic;Skylogic Italia
|
||||
ONID;0x013E;0x013F;Eutelsat Satellite System 13°E;European Telecommunications Satellite Organization
|
||||
ONID;0x016D;0x016D;Skylogic;Skylogic Italia
|
||||
ONID;0x016E;0x016F;Eutelsat Satellite System at 16°E;European Telecommunications Satellite Organization
|
||||
ONID;0x0170;0x0170;Audio Visual Global Joint Stock Company;Audio Visual Global Joint Stock Company
|
||||
ONID;0x01F4;0x01F4;MediaKabel B.V;
|
||||
ONID;0x022D;0x022D;Skylogic;Skylogic Italia
|
||||
ONID;0x022E;0x022F;Eutelsat Satellite System at 21.5°E;EUTELSAT – European Telecommunications Satellite Organization
|
||||
ONID;0x026D;0x026D;Skylogic;Skylogic Italia
|
||||
ONID;0x026E;0x026F;Eutelsat Satellite System at 25.5°E;EUTELSAT – European Telecommunications Satellite Organization
|
||||
ONID;0x029D;0x029D;Skylogic;Skylogic Italia
|
||||
ONID;0x029E;0x029F;Eutelsat Satellite System at 29°E;European Telecommunications Satellite Organization
|
||||
ONID;0x02BE;0x02BE;ARABSAT;ARABSAT - Arab Satellite Communications Organization
|
||||
ONID;0x02C0;0x02C0;MTV Networks Europe;MTV Networks Europe
|
||||
ONID;0x033D;0x033D;Skylogic at 33°E;Skylogic Italia
|
||||
ONID;0x033E;0x033F;Eutelsat Satellite System at 33°E;Eutelsat
|
||||
ONID;0x034E;0x034E;IRIB;IRIB
|
||||
ONID;0x036D;0x036D;Skylogic;Skylogic Italia
|
||||
ONID;0x036E;0x036F;Eutelsat Satellite System at 36°E;European Telecommunications Satellite Organization
|
||||
ONID;0x03E8;0x03E8;Telia;Telia, Sweden
|
||||
ONID;0x045D;0x045F;Eutelsat satellite system at 15°West;Eutelsat S.A.
|
||||
ONID;0x047D;0x047D;Skylogic;Skylogic Italia
|
||||
ONID;0x047E;0x047F;Eutelsat Satellite System at 12.5°W;EUTELSAT – European Telecommunications Satellite Organization
|
||||
ONID;0x048D;0x048D;Skylogic;Skylogic Italia
|
||||
ONID;0x048E;0x048F;Eutelsat Satellite System at 48°E;European Telecommunications Satellite Organization
|
||||
ONID;0x049D;0x049F;Eutelsat satellite system at 11°West;Eutelsat S.A.
|
||||
ONID;0x0500;0x0500;Vinasat Center;Vinasat Center
|
||||
ONID;0x0510;0x0510;Almajd;Almajd Satellite Broadcasting FZ LLC
|
||||
ONID;0x052D;0x052D;Skylogic;Skylogic Italia
|
||||
ONID;0x052E;0x052F;Eutelsat Satellite System at 8°W;EUTELSAT – European Telecommunications Satellite Organization
|
||||
ONID;0x053D;0x053F;Eutelsat satellite system at 53°East;Eutelsat S.A.
|
||||
ONID;0x055D;0x055D;Skylogic at 5°W;Skylogic Italia
|
||||
ONID;0x055E;0x055F;Eutelsat Satellite System at 5°W;Eutelsat
|
||||
ONID;0x0600;0x0600;UPC Satellite;UPC
|
||||
ONID;0x0601;0x0601;UPC Cable;UPC
|
||||
ONID;0x0602;0x0602;Tevel;Tevel Cable (Israel )
|
||||
ONID;0x071D;0x071D;Skylogic at 70.5°E;Skylogic Italia
|
||||
ONID;0x071E;0x071F;Eutelsat Satellite System at 70.5°E;Eutelsat S.A.
|
||||
ONID;0x077D;0x077D;Skylogic Satellite System at 7°W;Skylogic Italia
|
||||
ONID;0x077E;0x077F;Eutelsat Satellite System at 7°W;Eutelsat S.A.
|
||||
ONID;0x0800;0x0801;Nilesat 101;Nilesat
|
||||
ONID;0x0880;0x0880;MEASAT 1, 91.5°E;MEASAT Broadcast Network Systems SDN. BHD. (Kuala Lumpur, Malaysia)
|
||||
ONID;0x0882;0x0882;MEASAT 2, 91.5°E;MEASAT Broadcast Network Systems SDN. BHD. (Kuala Lumpur, Malaysia)
|
||||
ONID;0x0883;0x0883;MEASAT 2, 148.0°E;Hsin Chi Broadcast Company Ltd .
|
||||
ONID;0x088F;0x088F;MEASAT 3;MEASAT Broadcast Network Systems SDN. BHD. (Kuala Lumpur, Malaysia)
|
||||
ONID;0x08A0;0x08A0;Mainland Television Limited;Mainland Television Limited
|
||||
ONID;0x0E26;0x0E26;IRIB;IRIB
|
||||
ONID;0x0FFF;0x0FFF;Optus Networks;Optus Networks
|
||||
ONID;0x1000;0x1000;Optus B3 156°E;Optus Communications
|
||||
ONID;0x1001;0x1001;DISH Network;Echostar Communications
|
||||
ONID;0x1002;0x1002;Dish Network 61.5 W;Echostar Communications
|
||||
ONID;0x1003;0x1003;Dish Network 83 W;Echostar Communications
|
||||
ONID;0x1004;0x1004;Dish Network 119 W;Echostar Communications
|
||||
ONID;0x1005;0x1005;Dish Network 121 W;Echostar Communications
|
||||
ONID;0x1006;0x1006;Dish Network 148 W;Echostar Communications
|
||||
ONID;0x1007;0x1007;Dish Network 175 W;Echostar Communications
|
||||
ONID;0x1008;0x100B;Dish Network W - Z;Echostar Communications
|
||||
ONID;0x1010;0x1010;ABC TV;Australian Broadcasting Corporation
|
||||
ONID;0x1011;0x1011;SBS;SBS Australia
|
||||
ONID;0x1012;0x1012;Nine Network Australia;Nine Network Australia
|
||||
ONID;0x1013;0x1013;Seven Network Australia;Seven Network Limited
|
||||
ONID;0x1014;0x1014;Network TEN Australia;Network TEN Limited
|
||||
ONID;0x1015;0x1015;WIN Television Australia;WIN Television Pty Ltd
|
||||
ONID;0x1016;0x1016;Prime Television Australia;Prime Television Limited
|
||||
ONID;0x1017;0x1017;Southern Cross Broadcasting Australia;Southern Cross Broadcasting (Australia) Limited
|
||||
ONID;0x1018;0x1018;Telecasters Australia;Telecasters Australia Limited
|
||||
ONID;0x1019;0x1019;NBN Australia;NBN Limited
|
||||
ONID;0x101A;0x101A;Imparja Television Australia;Imparja Television Australia
|
||||
ONID;0x101B;0x101F;(Reserved for Australian broadcaster);(Reserved for Australian broadcasters)
|
||||
ONID;0x1100;0x1100;GE Americom;GE American Communications
|
||||
ONID;0x1101;0x1101;MiTV Networks Broadcast Terrestrial Network - DVB-H;MiTV Networks Sdn Bhd Malaysia
|
||||
ONID;0x1102;0x1102;Dream Mobile TV;Philippines Multimedia System, Inc.
|
||||
ONID;0x1103;0x1103;PT MAC;PT. Mediatama Anugrah Citra
|
||||
ONID;0x1104;0x1104;Levira Mobile TV;Levira AS
|
||||
ONID;0x1105;0x1105;Mobision;Alsumaria TV
|
||||
ONID;0x1106;0x1106;Trenmobile;PT. Citra Karya Investasi
|
||||
ONID;0x1107;0x1107;VTC Mobile TV;VTC Mobile TV
|
||||
ONID;0x1700;0x1700;Echostar 2A;EchoStar Communications
|
||||
ONID;0x1701;0x1701;Echostar 2B;EchoStar Communications
|
||||
ONID;0x1702;0x1702;Echostar 2C;EchoStar Communications
|
||||
ONID;0x1703;0x1703;Echostar 2D;EchoStar Communications
|
||||
ONID;0x1704;0x1704;Echostar 2E;EchoStar Communications
|
||||
ONID;0x1705;0x1705;Echostar 2F;EchoStar Communications
|
||||
ONID;0x1706;0x1706;Echostar 2G;EchoStar Communications
|
||||
ONID;0x1707;0x1707;Echostar 2H;EchoStar Communications
|
||||
ONID;0x1708;0x1708;Echostar 2I;EchoStar Communications
|
||||
ONID;0x1709;0x1709;Echostar 2J;EchoStar Communications
|
||||
ONID;0x170A;0x170A;Echostar 2K;EchoStar Communications
|
||||
ONID;0x170B;0x170B;Echostar 2L;EchoStar Communications
|
||||
ONID;0x170C;0x170C;Echostar 2M;EchoStar Communications
|
||||
ONID;0x170D;0x170D;Echostar 2N;EchoStar Communications
|
||||
ONID;0x170E;0x170E;Echostar 2O;EchoStar Communications
|
||||
ONID;0x170F;0x170F;Echostar 2P;EchoStar Communications
|
||||
ONID;0x1710;0x1710;Echostar 2Q;EchoStar Communications
|
||||
ONID;0x1711;0x1711;Echostar 2R;EchoStar Communications
|
||||
ONID;0x1712;0x1712;Echostar 2S;EchoStar Communications
|
||||
ONID;0x1713;0x1713;Echostar 2T;EchoStar Communications
|
||||
ONID;0x1714;0x1714;Platforma HD;Platforma HD Ltd.
|
||||
ONID;0x1715;0x1715;Profit Group Terrestrial;Profit Group SpA
|
||||
ONID;0x1716;0x1716;JSC Mostelekom;JSC Mostelekom
|
||||
ONID;0x2000;0x2000;Thiacom 1 & 2 co-located 78.5°E;Shinawatra Satellite
|
||||
ONID;0x2014;0x2014;DTT - Andorran Digital Terrestrial Television;STA
|
||||
ONID;0x2024;0x2024;Australian Digital Terrestrial Television;Australian Broadcasting Authority
|
||||
ONID;0x2028;0x2028;Austrian Digital Terrestrial Television;ORS - Austrian Broadcasting Services
|
||||
ONID;0x2038;0x2038;Belgian Digital Terrestrial Television;BIPT
|
||||
ONID;0x209E;0x209E;Taiwanese Digital Terrestrial Television;Directorate General of Telecommunications
|
||||
ONID;0x20AA;0x20AA;Comision Nacional de Television de Colombia;Comision Nacional de Television de Colombia
|
||||
ONID;0x20BF;0x20BF;Croatian Post and Electronic Communications Agency (HAKOM);Croatian Post and Electronic Communications Agency (HAKOM)
|
||||
ONID;0x20C4;0x20C4;Office Of the Commissioner of Electronic Communications and Postal Regulation;Office Of the Commissioner of Electronic Communications and Postal Regulation
|
||||
ONID;0x20CB;0x20CB;Czech Republic Digital Terrestrial Television;Czech Digital Group
|
||||
ONID;0x20D0;0x20D0;Danish Digital Terrestrial Television;National Telecom Agency Denmark
|
||||
ONID;0x20E9;0x20E9;Estonian Digital Terrestrial Television;Estonian National Communications Board
|
||||
ONID;0x20F6;0x20F6;Finnish Digital Terrestrial Television;Telecommunicatoins Administratoin Centre, Finland
|
||||
ONID;0x20FA;0x20FA;French Digital Terrestrial Television;Conseil Superieur de l'AudioVisuel
|
||||
ONID;0x2114;0x2114;German Digital Terrestrial Television;IRT on behalf of the German DVB-T broadcasts
|
||||
ONID;0x2124;0x2124;Gibraltar Regulatory Authority;Gibraltar Regulatory Authority
|
||||
ONID;0x2168;0x2168;Digital Terrestrial Network of Indonesia;Ministry of Communication and Information Technology of the Republic of Indonesia
|
||||
ONID;0x2174;0x2174;Irish Digital Terrestrial Television;Irish Telecommunications Regulator
|
||||
ONID;0x2178;0x2178;Israeli Digital Terrestrial Television;BEZEQ (The Israel Telecommunication Corp Ltd .)
|
||||
ONID;0x217C;0x217C;Italian Digital Terrestrial Television;
|
||||
ONID;0x21AC;0x21AC;DTT - Latvian Digital Terrestrial Television;Electronic Communications Office
|
||||
ONID;0x21B8;0x21B8;DTT Lithuania;Communications Regulatory Authority
|
||||
ONID;0x21CA;0x21CA;Malaysian Technical Standards Forum Bhd (MTFSB);Malaysian Technical Standards Forum Bhd (MTFSB)
|
||||
ONID;0x2210;0x2210;Netherlands Digital Terrestrial Television;Nozema
|
||||
ONID;0x2213;0x2213;DTT for Country of Curacao;Bureau Telecommunicatie en Post
|
||||
ONID;0x222A;0x222A;DTT - New Zealand Digial Terrestrial Television;TVNZ on behalf of Freeview New Zealand
|
||||
ONID;0x2242;0x2242;Norwegian Digital Terrestrial Television;Norwegian Regulator
|
||||
ONID;0x224F;0x224F;Autoridad Nacional de los Servicios Públicos;Autoridad Nacional de los Servicios Públicos
|
||||
ONID;0x2260;0x2260;DTT - Philippines Digital Terrestrial Television;NTA (porivionally ABS-CBN)
|
||||
ONID;0x2268;0x2268;DTT Poland;Office of Electronic Communications
|
||||
ONID;0x2283;0x2283;DTT - Russian Federation;RTRN
|
||||
ONID;0x22B0;0x22B0;DTT - Serbia JP Emisiona Tehnika i Veze;JP Emisiona Tehnika i Veze
|
||||
ONID;0x22BE;0x22BE;Singapore Digital Terrestrial Television;Singapore Broadcasting Authority
|
||||
ONID;0x22BF;0x22BF;Telecommunications office of the Slovak republic;Telecommunications office of the Slovak republic
|
||||
ONID;0x22C1;0x22C1;DTT - Slovenian Digital Terrestrial Television;APEK
|
||||
ONID;0x22C6;0x22C6;DTT - South African Digital Terrestrial Television;South African Broadcasting Corporation Ltd. (SABC), pending formation of DZONGA
|
||||
ONID;0x22C7;0x22C7;DTT- Hungarian Digital Terrestrial Television;National Communications Authority, Hungary
|
||||
ONID;0x22C8;0x22C8;DTT- Portugal Digital Terrestrial Television;ANACOM- National Communications Authority
|
||||
ONID;0x22D4;0x22D4;Spanish Digital Terrestrial Television;“Spanish Broadcasting Regulator
|
||||
ONID;0x22F1;0x22F1;Swedish Digital Terrestrial Television;“Swedish Broadcasting Regulator ”
|
||||
ONID;0x22F4;0x22F4;Swiss Digital Terrestrial Television;OFCOM
|
||||
ONID;0x233A;0x233A;UK Digital Terrestrial Television;Independent Television Commission
|
||||
ONID;0x2B00;0x2B00;DTT – Sky New Zealand;Sky Network Television Limited
|
||||
ONID;0x3000;0x3000;PanAmSat 4 68.5°E;Pan American Satellite System
|
||||
ONID;0x5000;0x5000;Irdeto Mux System;Irdeto Test Laboratories
|
||||
ONID;0x616D;0x616D;BellSouth Entertainment;BellSouth Entertainment, Atlanta, GA, USA
|
||||
ONID;0x6600;0x6600;UPC Satellite;UPC
|
||||
ONID;0x6601;0x6601;UPC Cable;UPC
|
||||
ONID;0x6602;0x6602;Comcast Media Center;Comcast Media Center
|
||||
ONID;0xA011;0xA011;Sichuan Cable TV Network;Sichuan Cable TV Network (PRC)
|
||||
ONID;0xA012;0xA012;China Network Systems;STAR Koos Finance Company (Taiwan)
|
||||
ONID;0xA013;0xA013;Versatel;Versatel (Russia)
|
||||
ONID;0xA014;0xA014;Chongqing Cable;Chongqing Municipality, PRC
|
||||
ONID;0XA015;0XA015;Guizhou Cable;Guizhou Province, PRC
|
||||
ONID;0xA016;0xA016;Hathway Cable;Hathway Cable and Datacom, India
|
||||
ONID;0xA017;0xA017;RCN;Rogers Cable Network, USA
|
||||
ONID;0xA018;0xA040;(NDS satellite services);(NDS to be allocated)
|
||||
ONID;0xA401;0xA401;ARD;ARD-Sternpunkte
|
||||
ONID;0xA509;0xA509;Welho Cable Network Helsinki;Welho
|
||||
ONID;0xA600;0xA600;Madritel;Madritel (Spain)
|
||||
ONID;0xA602;0xA602;Tevel;Tevel (Israel) (NDS)
|
||||
ONID;0xA603;0xA603;Globo Cabo (to be recycled);Globo Cabo (Brazil) (NDS)
|
||||
ONID;0xA604;0xA604;Cablemas (to be recycled);Cablemas (Mexico) (NDS)
|
||||
ONID;0xA605;0xA605;INC National Cable Network;Information Network Centre of SARFT (PRC) (NDS)
|
||||
ONID;0xA606;0xA607;Pepcom GmbH;Pepcom GmbH
|
||||
ONID;0xA900;0xA900;M-net Telekommunikations GmbH;M-net Telekommunikations GmbH
|
||||
ONID;0xF000;0xF000;SMALL CABLE NETWORKS;(Small cable network network operators)
|
||||
ONID;0xF001;0xF001;Deutsche Telekom;Deutsche Telekom AG
|
||||
ONID;0xF010;0xF010;Telefónica Cable;Telefónica Cable SA
|
||||
ONID;0xF020;0xF020;Cable and Wireless Communication;Cable and Wireless Communications
|
||||
ONID;0xF100;0xF100;Casema;Casema N.V .
|
||||
ONID;0xF750;0xF750;Telewest Communications Cable Network;Telewest Communications Plc
|
||||
ONID;0xF751;0xF751;OMNE Communications;OMNE Communications Ltd.
|
||||
ONID;0xFBFC;0xFBFC;MATAV;MATAV (Israel ) (NDS)
|
||||
ONID;0xFBFD;0xFBFD;Com Hem ab;Com Hem ab
|
||||
ONID;0xFBFE;0xFBFE;TPS;La Télévision Par Satellite
|
||||
ONID;0xFBFF;0xFBFF;Sky Italia;Sky Italia Spa.
|
||||
ONID;0xFC10;0xFC10;Rhône Vision Cable;Rhône Vision Cable
|
||||
ONID;0xFC41;0xFC41;France Telecom Cable;France Telecom
|
||||
ONID;0xFD00;0xFD00;National Cable Network;Lyonnaise Communications
|
||||
ONID;0xFE00;0xFE00;TeleDenmark Cable TV;TeleDenmark
|
||||
ONID;0xFEC0;0xFEFF;Network Interface Modules;Common Interface
|
||||
ONID;0xFF00;0xFFFA;Private_temporary_use;ETSI
|
||||
|
||||
TRANSP;Number;MHz
|
||||
TRANSP;49;10714
|
||||
TRANSP;50;10729
|
||||
TRANSP;51;10744
|
||||
TRANSP;52;10758
|
||||
TRANSP;53;10773
|
||||
TRANSP;54;10788
|
||||
TRANSP;55;10803
|
||||
TRANSP;56;10818
|
||||
TRANSP;57;10832
|
||||
TRANSP;58;10847
|
||||
TRANSP;59;10862
|
||||
TRANSP;60;10876
|
||||
TRANSP;61;10891
|
||||
TRANSP;62;10906
|
||||
TRANSP;63;10921
|
||||
TRANSP;64;10936
|
||||
TRANSP;33;10964
|
||||
TRANSP;34;10979
|
||||
TRANSP;35;10994
|
||||
TRANSP;36;11009
|
||||
TRANSP;37;11023
|
||||
TRANSP;38;11038
|
||||
TRANSP;39;11053
|
||||
TRANSP;40;11067
|
||||
TRANSP;41;11082
|
||||
TRANSP;42;11097
|
||||
TRANSP;43;11112
|
||||
TRANSP;44;11127
|
||||
TRANSP;45;11141
|
||||
TRANSP;46;11156
|
||||
TRANSP;47;11171
|
||||
TRANSP;48;11186
|
||||
TRANSP;1;11214
|
||||
TRANSP;2;11229
|
||||
TRANSP;3;11244
|
||||
TRANSP;4;11258
|
||||
TRANSP;5;11273
|
||||
TRANSP;6;11288
|
||||
TRANSP;7;11303
|
||||
TRANSP;8;11318
|
||||
TRANSP;9;11332
|
||||
TRANSP;10;11347
|
||||
TRANSP;11;11362
|
||||
TRANSP;12;11376
|
||||
TRANSP;13;11391
|
||||
TRANSP;14;11406
|
||||
TRANSP;15;11421
|
||||
TRANSP;16;11436
|
||||
TRANSP;17;11464
|
||||
TRANSP;18;11479
|
||||
TRANSP;19;11494
|
||||
TRANSP;20;11509
|
||||
TRANSP;21;11523
|
||||
TRANSP;22;11538
|
||||
TRANSP;23;11553
|
||||
TRANSP;24;11568
|
||||
TRANSP;25;11582
|
||||
TRANSP;26;11597
|
||||
TRANSP;27;11612
|
||||
TRANSP;28;11627
|
||||
TRANSP;29;11641
|
||||
TRANSP;30;11656
|
||||
TRANSP;31;11671
|
||||
TRANSP;32;11686
|
||||
TRANSP;65;11720
|
||||
TRANSP;66;11739
|
||||
TRANSP;67;11758
|
||||
TRANSP;68;11778
|
||||
TRANSP;69;11798
|
||||
TRANSP;70;11817
|
||||
TRANSP;71;11836
|
||||
TRANSP;72;11856
|
||||
TRANSP;73;11876
|
||||
TRANSP;74;11895
|
||||
TRANSP;75;11914
|
||||
TRANSP;76;11934
|
||||
TRANSP;77;11954
|
||||
TRANSP;78;11973
|
||||
TRANSP;79;11992
|
||||
TRANSP;80;12012
|
||||
TRANSP;81;12032
|
||||
TRANSP;82;12051
|
||||
TRANSP;83;12070
|
||||
TRANSP;84;12090
|
||||
TRANSP;85;12110
|
||||
TRANSP;86;12129
|
||||
TRANSP;87;12148
|
||||
TRANSP;88;12168
|
||||
TRANSP;89;12188
|
||||
TRANSP;90;12207
|
||||
TRANSP;91;12226
|
||||
TRANSP;92;12246
|
||||
TRANSP;93;12266
|
||||
TRANSP;94;12285
|
||||
TRANSP;95;12304
|
||||
TRANSP;96;12324
|
||||
TRANSP;97;12344
|
||||
TRANSP;98;12363
|
||||
TRANSP;99;12382
|
||||
TRANSP;100;12402
|
||||
TRANSP;101;12422
|
||||
TRANSP;102;12441
|
||||
TRANSP;103;12460
|
||||
TRANSP;104;12480
|
||||
TRANSP;105;12515
|
||||
TRANSP;106;12522
|
||||
TRANSP;107;12545
|
||||
TRANSP;108;12552
|
||||
TRANSP;109;12574
|
||||
TRANSP;110;12581
|
||||
TRANSP;111;12604
|
||||
TRANSP;112;12610
|
||||
TRANSP;113;12633
|
||||
TRANSP;114;12640
|
||||
TRANSP;115;12663
|
||||
TRANSP;116;12670
|
||||
TRANSP;117;12692
|
||||
TRANSP;118;12699
|
||||
TRANSP;119;12722
|
||||
TRANSP;120;12728
|
||||
|
||||
SERVICETYPE;Number;Description
|
||||
SERVICETYPE;01;SD-TV
|
||||
SERVICETYPE;02;Radio
|
||||
SERVICETYPE;12;Data/Test
|
||||
SERVICETYPE;22;SD-TV
|
||||
SERVICETYPE;25;HD-TV
|
||||
SERVICETYPE;31;4K-TV
|
||||
SERVICETYPE;211;Option
|
||||
|
260
source/ChanSort.Api/Model/ChannelInfo.cs
Normal file
260
source/ChanSort.Api/Model/ChannelInfo.cs
Normal file
@@ -0,0 +1,260 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class ChannelInfo
|
||||
{
|
||||
private const int MAX_FAV_LISTS = 5;
|
||||
|
||||
private string uid;
|
||||
/// <summary>
|
||||
/// List of channels that have the same UID as this channel and were not added to the channel list directly
|
||||
/// </summary>
|
||||
public readonly List<ChannelInfo> Duplicates = new List<ChannelInfo>();
|
||||
|
||||
public virtual bool IsDeleted { get; set; }
|
||||
public SignalSource SignalSource { get; set; }
|
||||
public long RecordIndex { get; set; }
|
||||
public int RecordOrder { get; set; }
|
||||
public int OldProgramNr { get; set; }
|
||||
public int NewProgramNr { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string ShortName { get; set; }
|
||||
public Favorites Favorites { get; set; }
|
||||
public bool Skip { get; set; }
|
||||
public bool Lock { get; set; }
|
||||
public bool Hidden { get; set; }
|
||||
public bool? Encrypted { get; set; }
|
||||
public string ChannelOrTransponder { get; set; }
|
||||
public string Satellite { get; set; }
|
||||
public decimal FreqInMhz { get; set; }
|
||||
public char Polarity { get; set; }
|
||||
public int ServiceId { get; set; }
|
||||
public int VideoPid { get; set; }
|
||||
public int AudioPid { get; set; }
|
||||
public int OriginalNetworkId { get; set; }
|
||||
public int TransportStreamId { get; set; }
|
||||
public int Bouquet { get; set; }
|
||||
public string Provider { get; set; }
|
||||
public int SymbolRate { get; set; }
|
||||
public int ServiceType { get; set; }
|
||||
public string Debug { get; private set; }
|
||||
public string SatPosition { get; set; }
|
||||
public Transponder Transponder { get; set; }
|
||||
public IList<int> FavIndex { get; private set; }
|
||||
public int ProgramNrPreset { get; set; }
|
||||
|
||||
public bool IsNameModified { get; set; }
|
||||
|
||||
#region ctor()
|
||||
protected ChannelInfo()
|
||||
{
|
||||
this.NewProgramNr = -1;
|
||||
this.FavIndex = new List<int>(MAX_FAV_LISTS);
|
||||
for (int i = 0; i < MAX_FAV_LISTS; i++)
|
||||
this.FavIndex.Add(-1);
|
||||
this.Name = "";
|
||||
this.ShortName = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for exiting TV channel
|
||||
/// </summary>
|
||||
public ChannelInfo(SignalSource source, int index, int oldProgNr, string name) : this()
|
||||
{
|
||||
this.SignalSource = source;
|
||||
this.RecordIndex = index;
|
||||
this.RecordOrder = index;
|
||||
this.NewProgramNr = -1;
|
||||
this.OldProgramNr = oldProgNr;
|
||||
this.Name = name;
|
||||
this.Encrypted = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for reference list channels which no longer exist in TV list
|
||||
/// </summary>
|
||||
public ChannelInfo(SignalSource source, string uid, int newProgNr, string name) : this()
|
||||
{
|
||||
this.SignalSource = source;
|
||||
this.Uid = uid;
|
||||
this.RecordIndex = -1;
|
||||
this.RecordOrder = -1;
|
||||
this.OldProgramNr = -1;
|
||||
this.NewProgramNr = newProgNr;
|
||||
this.Name = name;
|
||||
this.Encrypted = null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Uid
|
||||
public string Uid
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.uid == null)
|
||||
{
|
||||
if ((this.SignalSource & SignalSource.Digital) == 0)
|
||||
this.uid = "A-0-" + (int)(this.FreqInMhz*20) + "-0";
|
||||
else if ((this.SignalSource & SignalSource.Sat) != 0)
|
||||
this.uid = "S" + this.SatPosition + "-" + this.OriginalNetworkId + "-" + this.TransportStreamId + "-" + this.ServiceId;
|
||||
else
|
||||
this.uid = "C-" + this.OriginalNetworkId + "-" + this.TransportStreamId + "-" + this.ServiceId + "-" + this.ChannelOrTransponder;
|
||||
}
|
||||
return this.uid;
|
||||
}
|
||||
set { this.uid = value; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToString(), Equals(), GetHashCode()
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string nr = this.NewProgramNr != -1 ? this.NewProgramNr.ToString() : "@" + this.RecordIndex;
|
||||
return nr + ": " + this.Name;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
//ChannelInfo that = obj as ChannelInfo;
|
||||
//return that != null && this.Uid == that.Uid && this.OldProgramNr == that.OldProgramNr;
|
||||
return ReferenceEquals(this, obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Uid.GetHashCode() + this.OldProgramNr;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region NetworkName, NetworkOperator
|
||||
public string NetworkName
|
||||
{
|
||||
get
|
||||
{
|
||||
var network = LookupData.Instance.GetNetwork(this.OriginalNetworkId);
|
||||
return network == null ? null : network.Name;
|
||||
}
|
||||
}
|
||||
|
||||
public string NetworkOperator
|
||||
{
|
||||
get
|
||||
{
|
||||
var network = LookupData.Instance.GetNetwork(this.OriginalNetworkId);
|
||||
return network == null ? null : network.Operator;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ServiceTypeName
|
||||
public string ServiceTypeName { get { return LookupData.Instance.GetServiceTypeDescription(this.ServiceType); } }
|
||||
#endregion
|
||||
|
||||
#region GetFavString()
|
||||
public static string GetFavString(Favorites favorites)
|
||||
{
|
||||
string sep = "";
|
||||
string text = "";
|
||||
foreach (Favorites favMask in Enum.GetValues(typeof(Favorites)))
|
||||
{
|
||||
if ((favorites & favMask) != 0)
|
||||
{
|
||||
text += sep + favMask.ToString();
|
||||
sep = ",";
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseFavString()
|
||||
public static Favorites ParseFavString(string value)
|
||||
{
|
||||
Favorites favMask = 0;
|
||||
foreach (Favorites fav in Enum.GetValues(typeof (Favorites)))
|
||||
{
|
||||
foreach (char c in value)
|
||||
{
|
||||
if (c == fav.ToString()[0])
|
||||
{
|
||||
favMask |= fav;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return favMask;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddDebug()
|
||||
public void AddDebug(byte val)
|
||||
{
|
||||
if (this.Debug == null)
|
||||
this.Debug = val.ToString("x2");
|
||||
else
|
||||
this.Debug += " " + val.ToString("x2");
|
||||
}
|
||||
|
||||
public void AddDebug(ushort val)
|
||||
{
|
||||
if (this.Debug == null)
|
||||
this.Debug = val.ToString("x2");
|
||||
else
|
||||
this.Debug += " " + val.ToString("x4");
|
||||
}
|
||||
|
||||
public void AddDebug(byte[] data, int offset, int len)
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
this.AddDebug(data[offset + i]);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region UpdateRawData()
|
||||
public virtual void UpdateRawData()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ChangeEncoding()
|
||||
public virtual void ChangeEncoding(System.Text.Encoding encoding)
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetPosition(), SetPosition(), ChangePosition()
|
||||
|
||||
public int GetPosition(int subListIndex)
|
||||
{
|
||||
return subListIndex == 0 ? this.NewProgramNr : this.FavIndex[subListIndex - 1];
|
||||
}
|
||||
|
||||
public void SetPosition(int subListIndex, int newPos)
|
||||
{
|
||||
if (subListIndex == 0)
|
||||
this.NewProgramNr = newPos;
|
||||
else
|
||||
{
|
||||
this.FavIndex[subListIndex - 1] = newPos;
|
||||
int mask = 1 << (subListIndex - 1);
|
||||
if (newPos == -1)
|
||||
this.Favorites &= (Favorites)~mask;
|
||||
else
|
||||
this.Favorites |= (Favorites)mask;
|
||||
}
|
||||
}
|
||||
|
||||
internal void ChangePosition(int subListIndex, int delta)
|
||||
{
|
||||
if (subListIndex == 0)
|
||||
this.NewProgramNr += delta;
|
||||
else
|
||||
this.FavIndex[subListIndex - 1] += delta;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
160
source/ChanSort.Api/Model/ChannelList.cs
Normal file
160
source/ChanSort.Api/Model/ChannelList.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class ChannelList
|
||||
{
|
||||
private readonly SignalSource source;
|
||||
private readonly IList<ChannelInfo> channels = new List<ChannelInfo>();
|
||||
private readonly Dictionary<string, IList<ChannelInfo>> channelByUid = new Dictionary<string, IList<ChannelInfo>>();
|
||||
private readonly Dictionary<int, ChannelInfo> channelByProgNr = new Dictionary<int, ChannelInfo>();
|
||||
private readonly Dictionary<string, IList<ChannelInfo>> channelByName = new Dictionary<string, IList<ChannelInfo>>();
|
||||
private int insertProgramNr = 1;
|
||||
private int duplicateUidCount;
|
||||
private int duplicateProgNrCount;
|
||||
|
||||
public ChannelList(SignalSource source, string caption)
|
||||
{
|
||||
this.source = source;
|
||||
this.ShortCaption = caption;
|
||||
this.FirstProgramNumber = (source & SignalSource.Digital) != 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
public string ShortCaption { get; private set; }
|
||||
public SignalSource SignalSource { get { return this.source; } }
|
||||
public IList<ChannelInfo> Channels { get { return this.channels; } }
|
||||
public int Count { get { return channels.Count; } }
|
||||
public int DuplicateUidCount { get { return duplicateUidCount; } }
|
||||
public int DuplicateProgNrCount { get { return duplicateProgNrCount; } }
|
||||
public bool ReadOnly { get; set; }
|
||||
public int MaxChannelNameLength { get; set; }
|
||||
public int PresetProgramNrCount { get; private set; }
|
||||
|
||||
#region Caption
|
||||
public string Caption
|
||||
{
|
||||
get
|
||||
{
|
||||
string cap = this.ShortCaption;
|
||||
int validChannelCount = this.Channels.Count(ch => ch.OldProgramNr != -1);
|
||||
return cap + " (" + validChannelCount + ")";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region InsertProgramNumber
|
||||
public int InsertProgramNumber
|
||||
{
|
||||
get { return this.Count == 0 ? 1 : this.insertProgramNr; }
|
||||
set { this.insertProgramNr = Math.Max(this.FirstProgramNumber, value); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
public int FirstProgramNumber { get; set; }
|
||||
|
||||
#region AddChannel()
|
||||
public string AddChannel(ChannelInfo ci)
|
||||
{
|
||||
IList<ChannelInfo> others;
|
||||
if (this.channelByUid.TryGetValue(ci.Uid, out others))
|
||||
++duplicateUidCount;
|
||||
else
|
||||
{
|
||||
others = new List<ChannelInfo>();
|
||||
this.channelByUid.Add(ci.Uid, others);
|
||||
}
|
||||
others.Add(ci);
|
||||
|
||||
string warning2 = null;
|
||||
bool isDupeProgNr = false;
|
||||
if (ci.OldProgramNr != -1)
|
||||
{
|
||||
ChannelInfo other;
|
||||
this.channelByProgNr.TryGetValue(ci.OldProgramNr, out other);
|
||||
if (other != null)
|
||||
{
|
||||
warning2 = string.Format(Resources.ChannelList_ProgramNrAssignedToMultipleChannels,
|
||||
this.ShortCaption, ci.OldProgramNr, other.RecordIndex, other.Name, ci.RecordIndex, ci.Name);
|
||||
++duplicateProgNrCount;
|
||||
isDupeProgNr = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isDupeProgNr)
|
||||
this.channelByProgNr[ci.OldProgramNr] = ci;
|
||||
|
||||
var lowerName = (ci.Name ?? "").ToLower().Trim();
|
||||
var byNameList = this.channelByName.TryGet(lowerName);
|
||||
if (byNameList == null)
|
||||
{
|
||||
byNameList = new List<ChannelInfo>();
|
||||
this.channelByName[lowerName] = byNameList;
|
||||
}
|
||||
byNameList.Add(ci);
|
||||
|
||||
if (ci.ProgramNrPreset != 0)
|
||||
++this.PresetProgramNrCount;
|
||||
|
||||
this.channels.Add(ci);
|
||||
|
||||
return warning2;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetChannelByUid()
|
||||
public IList<ChannelInfo> GetChannelByUid(string uid)
|
||||
{
|
||||
IList<ChannelInfo> channel;
|
||||
this.channelByUid.TryGetValue(uid, out channel);
|
||||
return channel ?? new List<ChannelInfo>(0);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ToString()
|
||||
public override string ToString()
|
||||
{
|
||||
return this.Caption;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetChannelByName()
|
||||
public IEnumerable<ChannelInfo> GetChannelByName(string name)
|
||||
{
|
||||
var hits = this.channelByName.TryGet(name.ToLower().Trim());
|
||||
return hits ?? new List<ChannelInfo>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetChannelByNewProgNr()
|
||||
public IList<ChannelInfo> GetChannelByNewProgNr(int newProgNr)
|
||||
{
|
||||
return this.channels.Where(c => c.NewProgramNr == newProgNr).ToList();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetChannelsByNewOrder()
|
||||
public IList<ChannelInfo> GetChannelsByNewOrder()
|
||||
{
|
||||
return this.channels.OrderBy(c => c.NewProgramNr).ToList();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region RemoveChannel()
|
||||
public void RemoveChannel(ChannelInfo channel)
|
||||
{
|
||||
this.channels.Remove(channel);
|
||||
var list = this.channelByUid.TryGet(channel.Uid);
|
||||
if (list != null && list.Contains(channel))
|
||||
list.Remove(channel);
|
||||
list = this.channelByName.TryGet(channel.Name);
|
||||
if (list != null && list.Contains(channel))
|
||||
list.Remove(channel);
|
||||
var chan = this.channelByProgNr.TryGet(channel.OldProgramNr);
|
||||
if (ReferenceEquals(chan, channel))
|
||||
this.channelByProgNr.Remove(channel.OldProgramNr);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
112
source/ChanSort.Api/Model/DataRoot.cs
Normal file
112
source/ChanSort.Api/Model/DataRoot.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class DataRoot
|
||||
{
|
||||
private readonly IDictionary<int, Satellite> satellites = new Dictionary<int, Satellite>();
|
||||
private readonly IDictionary<int, Transponder> transponder = new Dictionary<int, Transponder>();
|
||||
private readonly IDictionary<int, LnbConfig> lnbConfig = new Dictionary<int, LnbConfig>();
|
||||
private readonly IList<ChannelList> channelLists = new List<ChannelList>();
|
||||
private readonly StringBuilder warnings = new StringBuilder();
|
||||
|
||||
public StringBuilder Warnings { get { return this.warnings; } }
|
||||
public IDictionary<int, Satellite> Satellites { get { return this.satellites; } }
|
||||
public IDictionary<int, Transponder> Transponder { get { return this.transponder; } }
|
||||
public IDictionary<int, LnbConfig> LnbConfig { get { return this.lnbConfig; } }
|
||||
public ICollection<ChannelList> ChannelLists { get { return this.channelLists; } }
|
||||
public bool IsEmpty { get { return this.channelLists.Count == 0; } }
|
||||
public bool NeedsSaving { get; set; }
|
||||
public Favorites SupportedFavorites { get; set; }
|
||||
public bool SortedFavorites { get; set; }
|
||||
|
||||
public DataRoot()
|
||||
{
|
||||
this.SupportedFavorites = Favorites.A | Favorites.B | Favorites.C | Favorites.D;
|
||||
}
|
||||
|
||||
#region AddSatellite()
|
||||
public virtual void AddSatellite(Satellite satellite)
|
||||
{
|
||||
this.satellites.Add(satellite.Id, satellite);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddTransponder()
|
||||
public virtual void AddTransponder(Satellite sat, Transponder trans)
|
||||
{
|
||||
trans.Satellite = sat;
|
||||
if (this.transponder.ContainsKey(trans.Id))
|
||||
{
|
||||
this.warnings.AppendFormat("Duplicate transponder data record for satellite #{0} with id {1}\r\n", sat.Id, trans.Id);
|
||||
return;
|
||||
}
|
||||
sat.Transponder.Add(trans.Id, trans);
|
||||
this.transponder.Add(trans.Id, trans);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddLnbConfig()
|
||||
public void AddLnbConfig(LnbConfig lnb)
|
||||
{
|
||||
this.lnbConfig.Add(lnb.Id, lnb);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddChannelList()
|
||||
public virtual void AddChannelList(ChannelList list)
|
||||
{
|
||||
this.channelLists.Add(list);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddChannel()
|
||||
public virtual void AddChannel(ChannelList list, ChannelInfo channel)
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
warnings.AppendFormat("No list found to add channel '{0}'\r\n", channel);
|
||||
return;
|
||||
}
|
||||
string warning = list.AddChannel(channel);
|
||||
if (warning != null)
|
||||
this.Warnings.AppendLine(warning);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region GetChannelList()
|
||||
public ChannelList GetChannelList(SignalSource criteriaMask)
|
||||
{
|
||||
foreach (var list in this.channelLists)
|
||||
{
|
||||
uint searchMask = (uint)criteriaMask;
|
||||
uint listMask = (uint) list.SignalSource;
|
||||
|
||||
if ((listMask & 0x000F & searchMask) != (searchMask & 0x000F)) // digital/analog
|
||||
continue;
|
||||
if ((listMask & 0x00F0 & searchMask) != (searchMask & 0x00F0)) // air/cable/sat/ip
|
||||
continue;
|
||||
if ((listMask & 0x0F00 & searchMask) != (searchMask & 0x0F00)) // tv/radio
|
||||
continue;
|
||||
if ((listMask & 0xF000) != (searchMask & 0xF000)) // preset list
|
||||
continue;
|
||||
return list;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ApplyCurrentProgramNumbers()
|
||||
public void ApplyCurrentProgramNumbers()
|
||||
{
|
||||
foreach (var list in this.ChannelLists)
|
||||
{
|
||||
foreach (var channel in list.Channels)
|
||||
channel.NewProgramNr = channel.OldProgramNr;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
73
source/ChanSort.Api/Model/Enums.cs
Normal file
73
source/ChanSort.Api/Model/Enums.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
#region enum SignalSource
|
||||
/// <summary>
|
||||
/// Bitmask for channel and list classification.
|
||||
/// An individual channel can only have one bit of each group set.
|
||||
/// A ChannelList can have multiple bits set to indicate which type of channels it can hold.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum SignalSource
|
||||
{
|
||||
// bit 1+2: analog/digital
|
||||
MaskAnalogDigital = 0x0003,
|
||||
Analog = 0x0001,
|
||||
Digital = 0x0002,
|
||||
|
||||
// bit 5+6+7+8: Antenna/Cable/Sat/IP
|
||||
MaskAntennaCableSat = 0x00F0,
|
||||
Antenna = 0x0010,
|
||||
Cable = 0x0020,
|
||||
Sat = 0x0040,
|
||||
IP = 0x0080,
|
||||
|
||||
// bit 9+10: TV/Radio
|
||||
MaskTvRadio = 0x0300,
|
||||
Tv = 0x0100,
|
||||
Radio = 0x0200,
|
||||
TvAndRadio = Tv | Radio,
|
||||
|
||||
// bit 13-16: Preset list selector (AstraHD+, Freesat, TivuSat, CanalDigitalSat, ... for Samsung)
|
||||
MaskProvider = 0xFC00,
|
||||
StandardSat = 0 << 12,
|
||||
AstraHdPlus = 1 << 12,
|
||||
Freesat = 2 << 12,
|
||||
TivuSat = 3 << 12,
|
||||
CanalDigital = 4 << 12,
|
||||
DigitalPlus = 5 << 12,
|
||||
CyfraPlus = 6 << 12,
|
||||
|
||||
StandardCable = 0 << 12,
|
||||
CablePrime = 1 << 12,
|
||||
|
||||
AnalogC = Analog + Cable,
|
||||
AnalogT = Analog + Antenna,
|
||||
AnalogCT = Analog + Cable + Antenna,
|
||||
DvbC = Digital + Cable,
|
||||
DvbT = Digital + Antenna,
|
||||
DvbCT = Digital + Cable + Antenna,
|
||||
DvbS = Digital + Sat,
|
||||
SatIP = Digital + Sat + IP,
|
||||
|
||||
CablePrimeD = Digital + Cable + CablePrime,
|
||||
HdPlusD = Digital + Sat + AstraHdPlus,
|
||||
FreesatD = Digital + Sat + Freesat,
|
||||
TivuSatD = Digital + Sat + TivuSat,
|
||||
CanalDigitalSatD = Digital + Sat + CanalDigital,
|
||||
DigitalPlusD = Digital + Sat + DigitalPlus,
|
||||
CyfraPlusD = Digital + Sat + CyfraPlus
|
||||
}
|
||||
#endregion
|
||||
|
||||
[Flags]
|
||||
public enum Favorites : byte { A = 0x01, B = 0x02, C = 0x04, D = 0x08, E = 0x10 }
|
||||
|
||||
public enum UnsortedChannelMode
|
||||
{
|
||||
AppendInOrder=0,
|
||||
AppendAlphabetically=1,
|
||||
MarkDeleted=2
|
||||
}
|
||||
}
|
||||
7
source/ChanSort.Api/Model/LnbConfig.cs
Normal file
7
source/ChanSort.Api/Model/LnbConfig.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class LnbConfig
|
||||
{
|
||||
public int Id { get; protected set; }
|
||||
}
|
||||
}
|
||||
231
source/ChanSort.Api/Model/LookupData.cs
Normal file
231
source/ChanSort.Api/Model/LookupData.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class LookupData
|
||||
{
|
||||
private readonly IDictionary<int, NetworkInfo> networks = new Dictionary<int, NetworkInfo>();
|
||||
private readonly IDictionary<int, int> transponderNrByFreqInMhz = new Dictionary<int, int>();
|
||||
private readonly IDictionary<int, int> transponderFreqInMhzByNr = new Dictionary<int, int>();
|
||||
private readonly IDictionary<int, string> serviceTypeDescriptions = new Dictionary<int, string>();
|
||||
private readonly IDictionary<int, int> dvbtFreqInMhzByTransponder = new Dictionary<int, int>();
|
||||
|
||||
public static readonly LookupData Instance = new LookupData();
|
||||
|
||||
private LookupData()
|
||||
{
|
||||
this.LoadDataFromCsvFile();
|
||||
}
|
||||
|
||||
#region GetNetwork()
|
||||
public NetworkInfo GetNetwork(int networkId)
|
||||
{
|
||||
NetworkInfo network;
|
||||
this.networks.TryGetValue((ushort)networkId, out network);
|
||||
return network;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetTransponderNumber(), GetTransponderFrequency()
|
||||
public int GetTransponderNumber(int frequencyInMhz)
|
||||
{
|
||||
int number;
|
||||
bool found = this.transponderNrByFreqInMhz.TryGetValue(frequencyInMhz, out number) ||
|
||||
this.transponderNrByFreqInMhz.TryGetValue(frequencyInMhz - 1, out number) ||
|
||||
this.transponderNrByFreqInMhz.TryGetValue(frequencyInMhz + 1, out number) ||
|
||||
this.transponderNrByFreqInMhz.TryGetValue(frequencyInMhz - 2, out number) ||
|
||||
this.transponderNrByFreqInMhz.TryGetValue(frequencyInMhz + 2, out number);
|
||||
return found ? number : 0;
|
||||
}
|
||||
|
||||
public int GetTransponderFrequency(int transponderNr)
|
||||
{
|
||||
return this.transponderNrByFreqInMhz.TryGet(transponderNr);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetServiceTypeDescription()
|
||||
public string GetServiceTypeDescription(int serviceType)
|
||||
{
|
||||
string descr;
|
||||
this.serviceTypeDescriptions.TryGetValue(serviceType, out descr);
|
||||
return descr;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region LoadDataFromCsvFile()
|
||||
public void LoadDataFromCsvFile()
|
||||
{
|
||||
this.networks.Clear();
|
||||
this.transponderFreqInMhzByNr.Clear();
|
||||
this.transponderNrByFreqInMhz.Clear();
|
||||
this.serviceTypeDescriptions.Clear();
|
||||
this.dvbtFreqInMhzByTransponder.Clear();
|
||||
|
||||
string file = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "lookup.csv");
|
||||
if (!File.Exists(file))
|
||||
return;
|
||||
using (var reader = new StreamReader(file, System.Text.Encoding.UTF8))
|
||||
{
|
||||
string line;
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
var fields = CsvFile.Parse(line, ';');
|
||||
if (fields.Count == 0)
|
||||
continue;
|
||||
switch (fields[0].ToLower())
|
||||
{
|
||||
case "onid": this.ParseNetwork(fields); break;
|
||||
case "dvbt": this.ParseDvbtTransponder(fields); break;
|
||||
case "transp": this.ParseTransponder(fields); break;
|
||||
case "servicetype": this.ParseServiceType(fields); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddNetwork()
|
||||
private void AddNetwork(NetworkInfo network)
|
||||
{
|
||||
this.networks[network.OriginalNetworkId] = network;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddTransponderMapping()
|
||||
private void AddTransponderMapping(int transponderNr, int frequencyInMhz)
|
||||
{
|
||||
this.transponderNrByFreqInMhz[frequencyInMhz] = transponderNr;
|
||||
this.transponderFreqInMhzByNr[transponderNr] = frequencyInMhz;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddDvbtTransponderMapping()
|
||||
private void AddDvbtTransponderMapping(int transponderNr, int frequencyInMhz)
|
||||
{
|
||||
this.dvbtFreqInMhzByTransponder[transponderNr] = frequencyInMhz;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AddServiceType()
|
||||
public void AddServiceType(int serviceType, string description)
|
||||
{
|
||||
this.serviceTypeDescriptions[serviceType] = description;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseNetwork()
|
||||
private void ParseNetwork(IList<string> fields)
|
||||
{
|
||||
if (fields.Count < 3)
|
||||
return;
|
||||
int start = ParseNumber(fields[1]);
|
||||
int end = ParseNumber(fields[2]);
|
||||
if (start == 0 || end == 0 || start > end)
|
||||
return;
|
||||
for (int onid = start; onid <= end; onid++)
|
||||
{
|
||||
var network = new NetworkInfo();
|
||||
network.OriginalNetworkId = onid;
|
||||
if (fields.Count >= 4)
|
||||
network.Name = fields[3];
|
||||
if (fields.Count >= 5)
|
||||
network.Operator = fields[4];
|
||||
this.AddNetwork(network);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseNumber()
|
||||
private int ParseNumber(string nr)
|
||||
{
|
||||
int number;
|
||||
if (nr.StartsWith("0x"))
|
||||
int.TryParse(nr.Substring(2), System.Globalization.NumberStyles.HexNumber, System.Globalization.NumberFormatInfo.InvariantInfo, out number);
|
||||
else
|
||||
int.TryParse(nr, System.Globalization.NumberStyles.Integer, System.Globalization.NumberFormatInfo.InvariantInfo, out number);
|
||||
return number;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseTransponder()
|
||||
private void ParseTransponder(IList<string> fields)
|
||||
{
|
||||
if (fields.Count < 3)
|
||||
return;
|
||||
int nr, freq;
|
||||
int.TryParse(fields[1], out nr);
|
||||
int.TryParse(fields[2], out freq);
|
||||
if (nr == 0 || freq == 0)
|
||||
return;
|
||||
this.AddTransponderMapping(nr, freq);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseTransponder()
|
||||
private void ParseDvbtTransponder(IList<string> fields)
|
||||
{
|
||||
if (fields.Count < 3)
|
||||
return;
|
||||
int nr, freq;
|
||||
int.TryParse(fields[1], out nr);
|
||||
int.TryParse(fields[2], out freq);
|
||||
if (nr == 0 || freq == 0)
|
||||
return;
|
||||
this.AddDvbtTransponderMapping(nr, freq);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseServiceType()
|
||||
private void ParseServiceType(IList<string> fields)
|
||||
{
|
||||
if (fields.Count < 3) return;
|
||||
int serviceType = this.ParseNumber(fields[1]);
|
||||
if (serviceType <= 0) return;
|
||||
this.AddServiceType(serviceType, fields[2]);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IsRadioOrTv()
|
||||
public SignalSource IsRadioOrTv(int dvbServiceType)
|
||||
{
|
||||
switch (dvbServiceType)
|
||||
{
|
||||
case 0x01: // SD MPEG1
|
||||
case 0x11: // MPEG2-HD
|
||||
case 0x16: // H264/AVC-SD
|
||||
case 0x19: // H264/AVC-HD
|
||||
case 0x1F: // UHD
|
||||
return SignalSource.Tv;
|
||||
case 0x02:
|
||||
case 0x0A:
|
||||
return SignalSource.Radio;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetDvbtTransponder()
|
||||
public int GetDvbtTransponder(decimal freq)
|
||||
{
|
||||
return (int)(freq - 106)/8;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetDvbtFrequencyForTransponder()
|
||||
public decimal GetDvbtFrequenyForTransponder(int transponder)
|
||||
{
|
||||
return transponder * 8 + 106;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetDvbtFrequencyForChannel()
|
||||
public decimal GetDvbtFrequenyForChannel(int channel)
|
||||
{
|
||||
return channel * 8 + 306;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
9
source/ChanSort.Api/Model/NetworkInfo.cs
Normal file
9
source/ChanSort.Api/Model/NetworkInfo.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class NetworkInfo
|
||||
{
|
||||
public int OriginalNetworkId { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Operator { get; set; }
|
||||
}
|
||||
}
|
||||
28
source/ChanSort.Api/Model/Satellite.cs
Normal file
28
source/ChanSort.Api/Model/Satellite.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class Satellite
|
||||
{
|
||||
private readonly int id;
|
||||
private readonly IDictionary<int, Transponder> transponder = new Dictionary<int, Transponder>();
|
||||
|
||||
public int Id { get { return this.id; } }
|
||||
public string Name { get; set; }
|
||||
public string OrbitalPosition { get; set; }
|
||||
public IDictionary<int, Transponder> Transponder { get { return this.transponder; } }
|
||||
|
||||
public Satellite(int id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public LnbConfig LnbConfig { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Name;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
22
source/ChanSort.Api/Model/Transponder.cs
Normal file
22
source/ChanSort.Api/Model/Transponder.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class Transponder
|
||||
{
|
||||
private readonly int id;
|
||||
|
||||
public int Id { get { return id; } }
|
||||
public Satellite Satellite { get; set; }
|
||||
public decimal FrequencyInMhz { get; set; }
|
||||
public int Number { get; set; }
|
||||
public virtual int SymbolRate { get; set; }
|
||||
public char Polarity { get; set; }
|
||||
public int OriginalNetworkId { get; set; }
|
||||
public int TransportStreamId { get; set; }
|
||||
|
||||
public Transponder(int id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
36
source/ChanSort.Api/Properties/AssemblyInfo.cs
Normal file
36
source/ChanSort.Api/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("API")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("API")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2012")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("5cd52683-ba04-4610-8435-ba409a37e08f")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
81
source/ChanSort.Api/Resources.Designer.cs
generated
Normal file
81
source/ChanSort.Api/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,81 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18052
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ChanSort.Api {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ChanSort.Api.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0}: Channel '{1}' has multiple data records: index {2}=Pr#{3} and index {4}=Pr#{5}.
|
||||
/// </summary>
|
||||
internal static string ChannelList_AddChannel__DuplicateUid {
|
||||
get {
|
||||
return ResourceManager.GetString("ChannelList_AddChannel__DuplicateUid", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} Program #{1} is assigned to multiple channels: index {2}='{3}' and index {4}='{5}'.
|
||||
/// </summary>
|
||||
internal static string ChannelList_ProgramNrAssignedToMultipleChannels {
|
||||
get {
|
||||
return ResourceManager.GetString("ChannelList_ProgramNrAssignedToMultipleChannels", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
0
source/ChanSort.Api/Resources.de.Designer.cs
generated
Normal file
0
source/ChanSort.Api/Resources.de.Designer.cs
generated
Normal file
126
source/ChanSort.Api/Resources.de.resx
Normal file
126
source/ChanSort.Api/Resources.de.resx
Normal file
@@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ChannelList_ProgramNrAssignedToMultipleChannels" xml:space="preserve">
|
||||
<value>{0} Program #{1} ist mehreren Sendern zugeordnet: Index {2}='{3}' und Index {4}='{5}'</value>
|
||||
</data>
|
||||
<data name="ChannelList_AddChannel__DuplicateUid" xml:space="preserve">
|
||||
<value>{0}: Sender '{1}' ist in mehreren Datensätzen enthalten: Index {2}=Pr#{3} und Index {4}=Pr#{5}</value>
|
||||
</data>
|
||||
</root>
|
||||
126
source/ChanSort.Api/Resources.resx
Normal file
126
source/ChanSort.Api/Resources.resx
Normal file
@@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="ChannelList_ProgramNrAssignedToMultipleChannels" xml:space="preserve">
|
||||
<value>{0} Program #{1} is assigned to multiple channels: index {2}='{3}' and index {4}='{5}'</value>
|
||||
</data>
|
||||
<data name="ChannelList_AddChannel__DuplicateUid" xml:space="preserve">
|
||||
<value>{0}: Channel '{1}' has multiple data records: index {2}=Pr#{3} and index {4}=Pr#{5}</value>
|
||||
</data>
|
||||
</root>
|
||||
43
source/ChanSort.Api/Utils/BrowserHelper.cs
Normal file
43
source/ChanSort.Api/Utils/BrowserHelper.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System.IO;
|
||||
|
||||
namespace ChanSort
|
||||
{
|
||||
public static class BrowserHelper
|
||||
{
|
||||
public static void OpenUrl(string url)
|
||||
{
|
||||
OpenHtml(@"
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv='Refresh' content='0;" + url + @"'/>
|
||||
</head>
|
||||
</html>");
|
||||
}
|
||||
|
||||
public static void OpenMail(string url)
|
||||
{
|
||||
OpenHtml(@"
|
||||
<html>
|
||||
<head>
|
||||
<script language=""javascript"">
|
||||
window.open(""" + url + @""");
|
||||
window.close();
|
||||
</script>
|
||||
</head>
|
||||
</html>");
|
||||
}
|
||||
|
||||
public static void OpenHtml(string html)
|
||||
{
|
||||
try
|
||||
{
|
||||
string fileName = Path.GetTempFileName() + ".html";
|
||||
File.WriteAllText(fileName, html);
|
||||
System.Diagnostics.Process.Start(fileName);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
151
source/ChanSort.Api/Utils/ChannelMappingBase.cs
Normal file
151
source/ChanSort.Api/Utils/ChannelMappingBase.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using System.Text;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public unsafe class ChannelMappingBase : DataMapping
|
||||
{
|
||||
protected const string offInUse = "offInUse";
|
||||
protected const string maskInUse = "maskInUse";
|
||||
protected const string offProgramNr = "offProgramNr";
|
||||
protected const string offName = "offName";
|
||||
protected const string offNameLength = "offNameLength";
|
||||
protected const string lenName = "lenName";
|
||||
protected const string offSkip = "offSkip";
|
||||
protected const string maskSkip = "maskSkip";
|
||||
protected const string offLock = "offLock";
|
||||
protected const string maskLock = "maskLock";
|
||||
protected const string offLockSkipHide = "offHide";
|
||||
protected const string maskHide = "maskHide";
|
||||
protected const string offFavorites = "offFavorites";
|
||||
private const string offDeleted = "offDeleted";
|
||||
private const string maskDeleted = "maskDeleted";
|
||||
|
||||
#region ctor()
|
||||
public ChannelMappingBase(IniFile.Section settings, int length, Encoding stringEncoding) :
|
||||
base(settings, length, stringEncoding)
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region InUse
|
||||
public virtual bool InUse
|
||||
{
|
||||
get
|
||||
{
|
||||
var val = this.GetOffsets(offInUse);
|
||||
return val.Length == 0 || this.GetFlag(offInUse, maskInUse);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ProgramNr
|
||||
public virtual ushort ProgramNr
|
||||
{
|
||||
get { return this.GetWord(offProgramNr); }
|
||||
set { this.SetWord(offProgramNr, value); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region NameLength
|
||||
public virtual int NameLength
|
||||
{
|
||||
get
|
||||
{
|
||||
var off = this.GetOffsets(offNameLength);
|
||||
if (off.Length > 0)
|
||||
return this.GetWord(off[0]);
|
||||
return MaxNameLength;
|
||||
}
|
||||
set { this.SetByte(offNameLength, (byte) value); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MaxNameLength
|
||||
public virtual int MaxNameLength
|
||||
{
|
||||
get
|
||||
{
|
||||
var off = this.GetOffsets(lenName); // not an offset!
|
||||
return off.Length > 0 ? off[0] : 0;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Name
|
||||
public virtual string Name
|
||||
{
|
||||
get { return this.GetString(offName, this.NameLength); }
|
||||
// ReSharper disable ValueParameterNotUsed
|
||||
set { }
|
||||
// ReSharper restore ValueParameterNotUsed
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region NamePtr
|
||||
|
||||
public virtual byte* NamePtr
|
||||
{
|
||||
get { return this.DataPtr + this.GetOffsets(offName)[0]; }
|
||||
set
|
||||
{
|
||||
int maxLen = this.MaxNameLength - 1;
|
||||
if (maxLen == 0)
|
||||
maxLen = this.NameLength;
|
||||
foreach (int off in this.GetOffsets(offName))
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < maxLen && value[i] != 0; i++)
|
||||
this.DataPtr[off + i] = value[i];
|
||||
for (; i <= maxLen; i++)
|
||||
this.DataPtr[off + i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ShortName
|
||||
public virtual string ShortName { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Skip
|
||||
public virtual bool Skip
|
||||
{
|
||||
get { return this.GetFlag(offSkip, maskSkip); }
|
||||
set { this.SetFlag(offSkip, maskSkip, value); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Lock
|
||||
public virtual bool Lock
|
||||
{
|
||||
get { return this.GetFlag(offLock, maskLock); }
|
||||
set { this.SetFlag(offLock, maskLock, value); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Hide
|
||||
public virtual bool Hide
|
||||
{
|
||||
get { return this.GetFlag(offLockSkipHide, maskHide); }
|
||||
set { this.SetFlag(offLockSkipHide, maskHide, value); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Favorites
|
||||
public virtual Favorites Favorites
|
||||
{
|
||||
get { return (Favorites) this.GetByte(offFavorites); }
|
||||
set { this.SetByte(offFavorites, (byte) value); }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IsDeleted
|
||||
public virtual bool IsDeleted
|
||||
{
|
||||
get { return this.GetFlag(offDeleted, maskDeleted); }
|
||||
set { this.SetFlag(offDeleted, maskDeleted, value); }
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
62
source/ChanSort.Api/Utils/Crc32.cs
Normal file
62
source/ChanSort.Api/Utils/Crc32.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public static class Crc32
|
||||
{
|
||||
private const uint CrcMask = 0xFFFFFFFF;
|
||||
private const uint CrcPoly = 0xEDB88320;
|
||||
|
||||
private static readonly uint[] crc32Table;
|
||||
|
||||
static Crc32()
|
||||
{
|
||||
crc32Table = InitCrc32Table();
|
||||
}
|
||||
|
||||
#region InitCrc32Table()
|
||||
|
||||
private static uint[] InitCrc32Table()
|
||||
{
|
||||
var crcTable = new uint[256];
|
||||
for (uint i = 0; i < 256; i++)
|
||||
{
|
||||
uint r = i;
|
||||
for (uint j = 8; j > 0; j--)
|
||||
{
|
||||
if ((r & 1) == 1)
|
||||
r = ((r >> 1) ^ CrcPoly);
|
||||
else
|
||||
r >>= 1;
|
||||
}
|
||||
crcTable[i] = r;
|
||||
}
|
||||
return crcTable;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region CalcCrc32()
|
||||
public static uint CalcCrc32(byte[] block, int start, int length)
|
||||
{
|
||||
uint crc32 = CrcMask;
|
||||
for (int i = 0; i < length; i++)
|
||||
crc32 = crc32Table[(crc32 & 0xff) ^ block[start + i]] ^ (crc32 >> 8);
|
||||
return crc32;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Crack()
|
||||
#if false
|
||||
public static unsafe int Crack(byte* block, int maxLen, uint checksum)
|
||||
{
|
||||
uint crc32 = CrcMask;
|
||||
for (int i = 0; i < maxLen; i++)
|
||||
{
|
||||
if (crc32 == checksum)
|
||||
return i;
|
||||
crc32 = crc32Table[(crc32 & 0xff) ^ block[i]] ^ (crc32 >> 8);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
45
source/ChanSort.Api/Utils/CsvFile.cs
Normal file
45
source/ChanSort.Api/Utils/CsvFile.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public static class CsvFile
|
||||
{
|
||||
public static IList<string> Parse(string line, char separator)
|
||||
{
|
||||
if (line.EndsWith("\n")) line = line.Substring(0, line.Length - 1);
|
||||
if (line.EndsWith("\r")) line = line.Substring(0, line.Length - 1);
|
||||
|
||||
List<string> tokens = new List<string>();
|
||||
if (line.Length == 0)
|
||||
return tokens;
|
||||
|
||||
bool inQuote = false;
|
||||
StringBuilder token = new StringBuilder();
|
||||
for(int i = 0, len=line.Length; i<len; i++)
|
||||
{
|
||||
char ch = line[i];
|
||||
if (ch == separator && !inQuote)
|
||||
{
|
||||
tokens.Add(token.ToString());
|
||||
token.Remove(0, token.Length);
|
||||
continue;
|
||||
}
|
||||
if (ch == '"')
|
||||
{
|
||||
if (inQuote && i+1 < len && line[i+1] == '"')
|
||||
{
|
||||
token.Append('"');
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
inQuote = !inQuote;
|
||||
continue;
|
||||
}
|
||||
token.Append(ch);
|
||||
}
|
||||
tokens.Add(token.ToString());
|
||||
return tokens;
|
||||
}
|
||||
}
|
||||
}
|
||||
197
source/ChanSort.Api/Utils/DataMapping.cs
Normal file
197
source/ChanSort.Api/Utils/DataMapping.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class DataMapping
|
||||
{
|
||||
protected readonly IniFile.Section settings;
|
||||
private int baseOffset;
|
||||
private byte[] data { get; set; }
|
||||
public Encoding DefaultEncoding { get; set; }
|
||||
|
||||
#region ctor()
|
||||
public DataMapping(IniFile.Section settings)
|
||||
{
|
||||
this.settings = settings;
|
||||
this.DefaultEncoding = Encoding.Default;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetDataPtr(), Data, BaseOffset
|
||||
public void SetDataPtr(byte[] data, int baseOffset)
|
||||
{
|
||||
this.data = data;
|
||||
this.baseOffset = baseOffset;
|
||||
}
|
||||
|
||||
public byte[] Data { get { return this.data; } }
|
||||
public int BaseOffset { get { return this.baseOffset; } set { this.baseOffset = value; } }
|
||||
#endregion
|
||||
|
||||
|
||||
#region GetOffsets()
|
||||
public int[] GetOffsets(string key)
|
||||
{
|
||||
return settings.GetIntList(key);
|
||||
}
|
||||
#endregion
|
||||
|
||||
public IniFile.Section Settings { get { return this.settings; } }
|
||||
|
||||
|
||||
#region Byte
|
||||
public byte GetByte(string key)
|
||||
{
|
||||
var offsets = settings.GetIntList(key);
|
||||
if (offsets.Length==0) return 0;
|
||||
return this.data[baseOffset + offsets[0]];
|
||||
}
|
||||
|
||||
public void SetByte(string key, int value)
|
||||
{
|
||||
var offsets = settings.GetIntList(key);
|
||||
foreach (int offset in offsets)
|
||||
this.data[baseOffset + offset] = (byte)value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Word
|
||||
public ushort GetWord(string key)
|
||||
{
|
||||
var offsets = settings.GetIntList(key);
|
||||
if (offsets.Length == 0) return 0;
|
||||
return BitConverter.ToUInt16(this.data, baseOffset + offsets[0]);
|
||||
}
|
||||
|
||||
public void SetWord(string key, int value)
|
||||
{
|
||||
var offsets = settings.GetIntList(key);
|
||||
foreach (int offset in offsets)
|
||||
{
|
||||
this.data[baseOffset + offset + 0] = (byte)value;
|
||||
this.data[baseOffset + offset + 1] = (byte)(value>>8);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DWord
|
||||
public long GetDword(string key)
|
||||
{
|
||||
var offsets = settings.GetIntList(key);
|
||||
if (offsets.Length == 0) return 0;
|
||||
return BitConverter.ToUInt32(this.data, baseOffset + offsets[0]);
|
||||
}
|
||||
|
||||
public void SetDword(string key, long value)
|
||||
{
|
||||
var offsets = settings.GetIntList(key);
|
||||
foreach (int offset in offsets)
|
||||
{
|
||||
this.data[baseOffset + offset + 0] = (byte)value;
|
||||
this.data[baseOffset + offset + 1] = (byte)(value >> 8);
|
||||
this.data[baseOffset + offset + 2] = (byte)(value >> 16);
|
||||
this.data[baseOffset + offset + 3] = (byte)(value >> 24);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Float
|
||||
public float GetFloat(string key)
|
||||
{
|
||||
var offsets = settings.GetIntList(key);
|
||||
if (offsets.Length == 0) return 0;
|
||||
return BitConverter.ToSingle(this.data, baseOffset + offsets[0]);
|
||||
}
|
||||
|
||||
public void SetFloat(string key, float value)
|
||||
{
|
||||
var offsets = settings.GetIntList(key);
|
||||
var bytes = BitConverter.GetBytes(value);
|
||||
foreach (int offset in offsets)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
this.data[baseOffset + offset + i] = bytes[i];
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetFlag
|
||||
|
||||
public bool GetFlag(string key, bool defaultValue = false)
|
||||
{
|
||||
return GetFlag("off" + key, "mask" + key, defaultValue);
|
||||
}
|
||||
|
||||
public bool GetFlag(string valueKey, string maskKey, bool defaultValue = false)
|
||||
{
|
||||
int mask = settings.GetInt(maskKey);
|
||||
return GetFlag(valueKey, mask, defaultValue);
|
||||
}
|
||||
|
||||
public bool GetFlag(string valueKey, int mask, bool defaultValue = false)
|
||||
{
|
||||
if (mask == 0) return defaultValue;
|
||||
var offsets = settings.GetIntList(valueKey);
|
||||
if (offsets.Length == 0) return defaultValue;
|
||||
return (this.data[baseOffset + offsets[0]] & mask) == mask;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetFlag()
|
||||
public void SetFlag(string key, bool value)
|
||||
{
|
||||
this.SetFlag("off" + key, "mask" + key, value);
|
||||
}
|
||||
|
||||
public void SetFlag(string valueKey, string maskKey, bool value)
|
||||
{
|
||||
int mask = settings.GetInt(maskKey);
|
||||
SetFlag(valueKey, mask, value);
|
||||
}
|
||||
|
||||
public void SetFlag(string valueKey, int mask, bool value)
|
||||
{
|
||||
if (mask == 0) return;
|
||||
var offsets = settings.GetIntList(valueKey);
|
||||
foreach (var offset in offsets)
|
||||
{
|
||||
if (value)
|
||||
this.data[baseOffset + offset] |= (byte)mask;
|
||||
else
|
||||
this.data[baseOffset + offset] &= (byte)~mask;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region GetString()
|
||||
public string GetString(string key, int maxLen)
|
||||
{
|
||||
var offsets = settings.GetIntList(key);
|
||||
if (offsets.Length == 0) return null;
|
||||
int length = this.GetByte(key + "Length");
|
||||
if (length == 0)
|
||||
length = maxLen;
|
||||
var encoding = this.DefaultEncoding;
|
||||
return encoding.GetString(this.data, baseOffset + offsets[0], length).TrimEnd('\0');
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetString()
|
||||
public int SetString(string key, string text, int maxLen)
|
||||
{
|
||||
var bytes = this.DefaultEncoding.GetBytes(text);
|
||||
int len = Math.Min(bytes.Length, maxLen);
|
||||
foreach (var offset in settings.GetIntList(key))
|
||||
{
|
||||
Array.Copy(bytes, 0, this.data, baseOffset + offset, len);
|
||||
for (int i = len; i < maxLen; i++)
|
||||
this.data[baseOffset + offset + i] = 0;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
21
source/ChanSort.Api/Utils/DependencyChecker.cs
Normal file
21
source/ChanSort.Api/Utils/DependencyChecker.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public static class DepencencyChecker
|
||||
{
|
||||
public static bool IsVc2010RedistPackageX86Installed()
|
||||
{
|
||||
object value = Microsoft.Win32.Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\x86",
|
||||
"Installed", null);
|
||||
return value != null && Convert.ToInt32(value) == 1;
|
||||
}
|
||||
|
||||
public static void AssertVc2010RedistPackageX86Installed()
|
||||
{
|
||||
if (!IsVc2010RedistPackageX86Installed())
|
||||
throw new FileLoadException("Please download and install the Microsoft Visual C++ 2010 Redistributable Package (x86)");
|
||||
}
|
||||
}
|
||||
}
|
||||
237
source/ChanSort.Api/Utils/DvbStringDecoder.cs
Normal file
237
source/ChanSort.Api/Utils/DvbStringDecoder.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
#region Documentation
|
||||
/*
|
||||
ETSI EN 300 468
|
||||
|
||||
For one-byte character tables, the codes in the range 0x80 to 0x9F are assigned to control functions
|
||||
as shown in Table A.1: Single byte control codes
|
||||
|
||||
Control code - Control code Description
|
||||
0x80 to 0x85 reserved for future use
|
||||
0x86 character emphasis on
|
||||
0x87 character emphasis off
|
||||
0x88 to 0x89 reserved for future use
|
||||
0x8A CR/LF
|
||||
0x8B to 0x9F user defined
|
||||
|
||||
A.2 Selection of character table
|
||||
First byte value - Character code table - Table description - Reproduced in figure
|
||||
0x01 ISO/IEC 8859-5 [27] Latin/Cyrillic alphabet A.2
|
||||
0x02 ISO/IEC 8859-6 [28] Latin/Arabic alphabet A.3
|
||||
0x03 ISO/IEC 8859-7 [29] Latin/Greek alphabet A.4
|
||||
0x04 ISO/IEC 8859-8 [30] Latin/Hebrew alphabet A.5
|
||||
0x05 ISO/IEC 8859-9 [31] Latin alphabet No. 5 A.6
|
||||
0x06 ISO/IEC 8859-10 [32] Latin alphabet No. 6 A.7
|
||||
0x07 ISO/IEC 8859-11 [33] Latin/Thai (draft only) A.8
|
||||
0x08 reserved for future use (see note)
|
||||
0x09 ISO/IEC 8859-13 [34] Latin alphabet No. 7 A.9
|
||||
0x0A ISO/IEC 8859-14 [35] Latin alphabet No. 8 (Celtic) A.10
|
||||
0x0B ISO/IEC 8859-15 [36] Latin alphabet No. 9 A.11
|
||||
0x0C to 0x0F reserved for future use
|
||||
0x10 ISO/IEC 8859 See table A.4
|
||||
0x11 ISO/IEC 10646 [16] Basic Multilingual Plane (BMP)
|
||||
0x12 KSX1001-2004 [44] Korean Character Set
|
||||
0x13 GB-2312-1980 Simplified Chinese Character
|
||||
0x14 Big5 subset of ISO/IEC 10646 [16] Traditional Chinese
|
||||
0x15 UTF-8 encoding of ISO/IEC 10646 [16] Basic Multilingual Plane (BMP)
|
||||
0x16 to 0x1E reserved for future use
|
||||
0x1F Described by encoding_type_id Described by 8 bit
|
||||
|
||||
Table A.4: Character Coding Tables for first byte 0x10
|
||||
First byte value - Second byte value - Third Byte Value - Selected character code - table - Table Description
|
||||
0x10 0x00 0x00 reserved for future use
|
||||
0x10 0x00 0x01 ISO/IEC 8859-1 [23] West European
|
||||
0x10 0x00 0x02 ISO/IEC 8859-2 [24] East European
|
||||
0x10 0x00 0x03 ISO/IEC 8859-3 [25] South European
|
||||
0x10 0x00 0x04 ISO/IEC 8859-4 [26] North and North-East European
|
||||
0x10 0x00 0x05 ISO/IEC 8859-5 [27] Latin/Cyrillic A.2
|
||||
0x10 0x00 0x06 ISO/IEC 8859-6 [28] Latin/Arabic A.3
|
||||
0x10 0x00 0x07 ISO/IEC 8859-7 [29] Latin/Greek A.4
|
||||
0x10 0x00 0x08 ISO/IEC 8859-8 [30] Latin/Hebrew A.5
|
||||
0x10 0x00 0x09 ISO/IEC 8859-9 [31] West European & Turkish A.6
|
||||
0x10 0x00 0x0A ISO/IEC 8859-10 [32] North European A.7
|
||||
0x10 0x00 0x0B ISO/IEC 8859-11 [33] Thai A.8
|
||||
0x10 0x00 0x0C Reserved for future use
|
||||
0x10 0x00 0x0D ISO/IEC 8859-13 [34] Baltic A.9
|
||||
0x10 0x00 0x0E ISO/IEC 8859-14 [35] Celtic A.10
|
||||
0x10 0x00 0x0F ISO/IEC 8859-15 [36] West European A.11
|
||||
*/
|
||||
#endregion
|
||||
|
||||
public class DvbStringDecoder
|
||||
{
|
||||
static readonly string[] codePages1 =
|
||||
{
|
||||
null, "iso-8859-5", "iso-8859-6", "iso-8859-7", "iso-8859-8", "iso-8859-9", "iso-8859-10", "iso-8859-11",
|
||||
null, "iso-8859-13", "iso-8859-14", "iso-8859-15", null, null, null, null,
|
||||
null, // codePages2 prefix
|
||||
"utf-16", "x-cp20949", "x-cp20936", "utf-16", "utf-8", null, null, null,
|
||||
"utf-8", null, null, null, "utf-8"
|
||||
};
|
||||
|
||||
static readonly string[] codePages2 =
|
||||
{
|
||||
null, "iso-8859-1", "iso-8859-2", "iso-8859-3", "iso-8859-4", "iso-8859-5", "iso-8859-6", "iso-8859-7",
|
||||
"iso-8859-8", "iso-8859-9", "iso-8859-10", "iso-8859-11", null, "iso-8859-13", "iso-8859-14", "iso-8859-15"
|
||||
};
|
||||
|
||||
private readonly Dictionary<string, Decoder> decoderCache = new Dictionary<string, Decoder>();
|
||||
|
||||
public DvbStringDecoder(Encoding defaultEncoding)
|
||||
{
|
||||
this.DefaultEncoding = defaultEncoding;
|
||||
}
|
||||
|
||||
public Encoding DefaultEncoding { get; set; }
|
||||
|
||||
#region GetChannelNames()
|
||||
public void GetChannelNames(byte[] name, int off, int len, out string longName, out string shortName)
|
||||
{
|
||||
longName = "";
|
||||
shortName = "";
|
||||
if (len == 0)
|
||||
return;
|
||||
byte b = name[off];
|
||||
if (b == 0)
|
||||
return;
|
||||
|
||||
Decoder decoder = this.DefaultEncoding.GetDecoder();
|
||||
bool singleByteChar = true;
|
||||
if (b < 0x20)
|
||||
{
|
||||
if (b == 0x10) // prefix for 2-byte code page
|
||||
{
|
||||
int cpIndex = name[off + 1] * 256 + name[off + 2];
|
||||
off += 2;
|
||||
len -= 2;
|
||||
SetDecoder(codePages2, cpIndex, ref decoder);
|
||||
}
|
||||
if (b <= 0x1F)
|
||||
SetDecoder(codePages1, b, ref decoder);
|
||||
singleByteChar = b < 0x10;
|
||||
++off;
|
||||
--len;
|
||||
}
|
||||
if (!singleByteChar)
|
||||
{
|
||||
char[] buffer = new char[100];
|
||||
int l= decoder.GetChars(name, off, len, buffer, 0, false);
|
||||
longName = new string(buffer, 0, l);
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder sbLong = new StringBuilder();
|
||||
StringBuilder sbShort = new StringBuilder();
|
||||
bool inShortMode = false;
|
||||
for (int c = 0; c < len; c++)
|
||||
{
|
||||
int i = off + c;
|
||||
b = name[i];
|
||||
if (b == 0x00)
|
||||
break;
|
||||
|
||||
char ch = '\0';
|
||||
switch (b)
|
||||
{
|
||||
case 0x86: inShortMode = true; continue;
|
||||
case 0x87: inShortMode = false; continue;
|
||||
case 0x8a: ch = '\n'; break;
|
||||
default:
|
||||
if (b >= 0x80 && b <= 0x9f) // DVB-S control characters
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if (ch == '\0')
|
||||
{
|
||||
// read as many bytes as necessary to get a character
|
||||
char[] charArray = new char[1];
|
||||
for (int byteCnt = 1; decoder.GetChars(name, i, byteCnt, charArray, 0) == 0; byteCnt++)
|
||||
++i;
|
||||
ch = charArray[0];
|
||||
}
|
||||
if (ch == '\0')
|
||||
continue;
|
||||
|
||||
sbLong.Append(ch);
|
||||
if (inShortMode)
|
||||
sbShort.Append(ch);
|
||||
}
|
||||
longName = sbLong.ToString();
|
||||
shortName = sbShort.ToString();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetDecoder()
|
||||
private void SetDecoder(string[] codePages, int cpIndex, ref Decoder defaultDecoder)
|
||||
{
|
||||
if (cpIndex >= codePages.Length)
|
||||
return;
|
||||
Decoder decoder;
|
||||
|
||||
string cp = codePages[cpIndex];
|
||||
if (cp == null)
|
||||
return;
|
||||
|
||||
if (this.decoderCache.TryGetValue(cp, out decoder))
|
||||
{
|
||||
defaultDecoder = decoder;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var encoding = Encoding.GetEncoding(cp);
|
||||
defaultDecoder = encoding.GetDecoder();
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
}
|
||||
decoderCache[cp] = defaultDecoder;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetCodepageBytes()
|
||||
public static byte[] GetCodepageBytes(Encoding encoding)
|
||||
{
|
||||
var encName = encoding.WebName;
|
||||
for (int i = 0; i < codePages1.Length; i++)
|
||||
{
|
||||
if (codePages1[i] == encName)
|
||||
return new [] {(byte)i};
|
||||
}
|
||||
|
||||
for (int i = 0; i < codePages2.Length; i++)
|
||||
{
|
||||
if (codePages2[i] == encName)
|
||||
return new[] { (byte)0x10, (byte)i };
|
||||
}
|
||||
|
||||
return new byte[0];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetEncoding()
|
||||
/// <summary>
|
||||
/// Pass in either a value <=0x1F excluding 0x10 or 0x10xxyy
|
||||
/// </summary>
|
||||
public static Encoding GetEncoding(int encodingMarker)
|
||||
{
|
||||
string enc = null;
|
||||
if (encodingMarker < 0x20)
|
||||
enc = codePages1[encodingMarker];
|
||||
else
|
||||
{
|
||||
encodingMarker &= 0xFFFF;
|
||||
if (encodingMarker < codePages2.Length)
|
||||
enc = codePages2[encodingMarker];
|
||||
}
|
||||
return enc == null ? null : Encoding.GetEncoding(enc);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
177
source/ChanSort.Api/Utils/IniFile.cs
Normal file
177
source/ChanSort.Api/Utils/IniFile.cs
Normal file
@@ -0,0 +1,177 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class IniFile
|
||||
{
|
||||
#region class Section
|
||||
|
||||
public class Section
|
||||
{
|
||||
private readonly Dictionary<string, string> data = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
|
||||
|
||||
public Section(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
}
|
||||
|
||||
#region Name
|
||||
public string Name { get; private set; }
|
||||
#endregion
|
||||
|
||||
#region Set()
|
||||
internal void Set(string key, string value)
|
||||
{
|
||||
data[key] = value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Keys
|
||||
public IEnumerable<string> Keys { get { return data.Keys; } }
|
||||
#endregion
|
||||
|
||||
#region GetString()
|
||||
|
||||
public string GetString(string key)
|
||||
{
|
||||
string value;
|
||||
if (!data.TryGetValue(key, out value))
|
||||
return null;
|
||||
return value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetInt()
|
||||
|
||||
public int GetInt(string key, int defaultValue = 0)
|
||||
{
|
||||
string value;
|
||||
if (!data.TryGetValue(key, out value))
|
||||
return defaultValue;
|
||||
return this.ParseNumber(value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetBytes()
|
||||
|
||||
public byte[] GetBytes(string key)
|
||||
{
|
||||
string value;
|
||||
if (!data.TryGetValue(key, out value))
|
||||
return null;
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return new byte[0];
|
||||
|
||||
string[] parts = value.Split(',');
|
||||
byte[] bytes = new byte[parts.Length];
|
||||
int i = 0;
|
||||
foreach (var part in parts)
|
||||
bytes[i++] = (byte)this.ParseNumber(part);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetIntList()
|
||||
public int[] GetIntList(string key)
|
||||
{
|
||||
string value = this.GetString(key);
|
||||
if (string.IsNullOrEmpty(value))
|
||||
return new int[0];
|
||||
string[] numbers = value.Split(',');
|
||||
int[] ret = new int[numbers.Length];
|
||||
for (int i = 0; i < numbers.Length; i++)
|
||||
ret[i] = this.ParseNumber(numbers[i]);
|
||||
return ret;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ParseNumber()
|
||||
private int ParseNumber(string value)
|
||||
{
|
||||
if (value.ToLower().StartsWith("0x"))
|
||||
{
|
||||
try { return Convert.ToInt32(value, 16); }
|
||||
catch { return 0; }
|
||||
}
|
||||
int intValue;
|
||||
int.TryParse(value, out intValue);
|
||||
return intValue;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
|
||||
private readonly Dictionary<string, Section> sectionDict;
|
||||
private readonly List<Section> sectionList;
|
||||
|
||||
public IniFile(string fileName)
|
||||
{
|
||||
this.sectionDict = new Dictionary<string, Section>();
|
||||
this.sectionList = new List<Section>();
|
||||
this.ReadIniFile(fileName);
|
||||
}
|
||||
|
||||
public IEnumerable<Section> Sections
|
||||
{
|
||||
get { return this.sectionList; }
|
||||
}
|
||||
|
||||
public Section GetSection(string sectionName)
|
||||
{
|
||||
return sectionDict.TryGet(sectionName);
|
||||
}
|
||||
|
||||
#region ReadIniFile()
|
||||
private void ReadIniFile(string fileName)
|
||||
{
|
||||
using (StreamReader rdr = new StreamReader(fileName))
|
||||
{
|
||||
Section currentSection = null;
|
||||
string line;
|
||||
string key = null;
|
||||
string val = null;
|
||||
while ((line = rdr.ReadLine()) != null)
|
||||
{
|
||||
string trimmedLine = line.Trim();
|
||||
if (trimmedLine.StartsWith(";"))
|
||||
continue;
|
||||
if (trimmedLine.StartsWith("["))
|
||||
{
|
||||
string sectionName = trimmedLine.EndsWith("]")
|
||||
? trimmedLine.Substring(1, trimmedLine.Length - 2)
|
||||
: trimmedLine.Substring(1);
|
||||
currentSection = new Section(sectionName);
|
||||
this.sectionList.Add(currentSection);
|
||||
this.sectionDict[sectionName] = currentSection;
|
||||
continue;
|
||||
}
|
||||
if (currentSection == null)
|
||||
continue;
|
||||
if (val == null)
|
||||
{
|
||||
int idx = trimmedLine.IndexOf("=");
|
||||
if (idx < 0)
|
||||
continue;
|
||||
key = trimmedLine.Substring(0, idx).Trim();
|
||||
val = trimmedLine.Substring(idx + 1).Trim();
|
||||
}
|
||||
else
|
||||
val += line;
|
||||
if (val.EndsWith("\\"))
|
||||
val = val.Substring(val.Length - 1).Trim();
|
||||
else
|
||||
{
|
||||
currentSection.Set(key, val);
|
||||
val = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
47
source/ChanSort.Api/Utils/MappingPool.cs
Normal file
47
source/ChanSort.Api/Utils/MappingPool.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public class MappingPool<T> where T : DataMapping
|
||||
{
|
||||
private const string ERR_unknownACTChannelDataLength = "Configuration doesn't contain a {0} data mapping for length {1}";
|
||||
private readonly Dictionary<string, T> mappings = new Dictionary<string, T>();
|
||||
private readonly string caption;
|
||||
public System.Text.Encoding DefaultEncoding { get; set; }
|
||||
|
||||
public MappingPool(string caption)
|
||||
{
|
||||
this.caption = caption;
|
||||
}
|
||||
|
||||
public void AddMapping(int dataLength, T mapping)
|
||||
{
|
||||
this.AddMapping(dataLength.ToString(), mapping);
|
||||
}
|
||||
|
||||
public void AddMapping(string id, T mapping)
|
||||
{
|
||||
this.mappings.Add(id, mapping);
|
||||
}
|
||||
|
||||
public T GetMapping(int dataLength, bool throwException = true)
|
||||
{
|
||||
return this.GetMapping(dataLength.ToString(), throwException);
|
||||
}
|
||||
|
||||
public T GetMapping(string id, bool throwException = true)
|
||||
{
|
||||
if (id == "0" || string.IsNullOrEmpty(id))
|
||||
return null;
|
||||
|
||||
T mapping;
|
||||
if (!mappings.TryGetValue(id, out mapping) && throwException)
|
||||
throw new FileLoadException(string.Format(ERR_unknownACTChannelDataLength, this.caption, id));
|
||||
|
||||
if (mapping != null && this.DefaultEncoding != null)
|
||||
mapping.DefaultEncoding = this.DefaultEncoding;
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
}
|
||||
122
source/ChanSort.Api/Utils/Tools.cs
Normal file
122
source/ChanSort.Api/Utils/Tools.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ChanSort.Api
|
||||
{
|
||||
public static class Tools
|
||||
{
|
||||
public static V TryGet<K, V>(this IDictionary<K, V> dict, K key)
|
||||
{
|
||||
V val;
|
||||
dict.TryGetValue(key, out val);
|
||||
return val;
|
||||
}
|
||||
|
||||
#region GetAnalogChannelNumber()
|
||||
public static string GetAnalogChannelNumber(int freq)
|
||||
{
|
||||
if (freq < 41) return "";
|
||||
if (freq <= 68) return ((freq - 41)/7 + 1).ToString("d2"); // Band I (01-04)
|
||||
if (freq < 105) return "";
|
||||
if (freq <= 174) return "S" + ((freq - 105)/7 + 1).ToString("d2"); // Midband (S01-S10)
|
||||
if (freq <= 230) return ((freq - 175)/7 + 5).ToString("d2"); // Band III (05-12)
|
||||
if (freq <= 300) return "S" + ((freq - 231)/7 + 11); // Superband (S11-S20)
|
||||
if (freq <= 469) return "S" + ((freq - 303)/8 + 21); // Hyperband (S21-S41)
|
||||
if (freq <= 1000) return ((freq - 471)/8 + 21).ToString("d2"); // Band IV, V
|
||||
return "";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region GetInt16/32()
|
||||
|
||||
public static int GetInt16(byte[] data, int offset, bool littleEndian)
|
||||
{
|
||||
return littleEndian ? BitConverter.ToInt16(data, offset) : (data[offset] << 8) + data[offset + 1];
|
||||
}
|
||||
|
||||
public static int GetInt32(byte[] data, int offset, bool littleEndian)
|
||||
{
|
||||
return littleEndian ? BitConverter.ToInt32(data, offset) :
|
||||
(data[offset] << 24) + (data[offset + 1] << 16) + (data[offset + 2] << 8) + data[offset + 3];
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SetInt16/32()
|
||||
|
||||
public static void SetInt16(byte[] data, int offset, int value, bool littleEndian = true)
|
||||
{
|
||||
if (littleEndian)
|
||||
{
|
||||
data[offset + 0] = (byte) value;
|
||||
data[offset + 1] = (byte) (value >> 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
data[offset + 0] = (byte)(value >> 8);
|
||||
data[offset + 1] = (byte) value;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetInt32(byte[] data, int offset, int value, bool littleEndian = true)
|
||||
{
|
||||
if (littleEndian)
|
||||
{
|
||||
data[offset + 0] = (byte) value;
|
||||
data[offset + 1] = (byte) (value >> 8);
|
||||
data[offset + 2] = (byte) (value >> 16);
|
||||
data[offset + 3] = (byte) (value >> 24);
|
||||
}
|
||||
else
|
||||
{
|
||||
data[offset + 0] = (byte)(value >> 24);
|
||||
data[offset + 1] = (byte)(value >> 16);
|
||||
data[offset + 2] = (byte)(value >> 8);
|
||||
data[offset + 3] = (byte)value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region MemCopy(), MemSet()
|
||||
|
||||
public static void MemCopy(byte[] source, int sourceIndex, byte[] dest, int destIndex, int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
dest[destIndex + i] = source[sourceIndex + i];
|
||||
}
|
||||
|
||||
public static void MemSet(byte[] data, int offset, byte value, int count)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
data[offset++] = value;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReverseByteOrder()
|
||||
public static ushort ReverseByteOrder(ushort input)
|
||||
{
|
||||
return (ushort)(((input & 0x00FF) << 8) | (input >> 8));
|
||||
}
|
||||
|
||||
public static uint ReverseByteOrder(uint input)
|
||||
{
|
||||
return ((input & 0x000000FF) << 24) | ((input & 0x0000FF00) << 8) | ((input & 0x00FF0000) >> 8) | ((input & 0xFF000000) >> 24);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region HexDecode()
|
||||
public static byte[] HexDecode(string input)
|
||||
{
|
||||
var bytes = new byte[input.Length/2];
|
||||
for (int i = 0, c = input.Length/2; i < c; i++)
|
||||
{
|
||||
char ch = Char.ToUpper(input[i*2]);
|
||||
var high = Char.IsDigit(ch) ? ch - '0' : ch - 'A' + 10;
|
||||
ch = Char.ToUpper(input[i*2 + 1]);
|
||||
var low = Char.IsDigit(ch) ? ch - '0' : ch - 'A' + 10;
|
||||
bytes[i] = (byte)((high << 4) | low);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user