2013-03-31 14:09:38 +02:00
using System ;
using System.Collections.Generic ;
namespace ChanSort.Api
{
public class ChannelInfo
{
2021-03-14 22:13:22 +01:00
private const int MaxFavListsWithFlags = 8 ;
2013-03-31 14:09:38 +02:00
private string uid ;
2015-09-24 12:46:52 +02:00
private string serviceTypeName ;
2020-08-09 14:09:08 +02:00
private int newProgramNr ;
2021-03-14 22:13:22 +01:00
2013-04-03 12:47:24 +02:00
public virtual bool IsDeleted { get ; set ; }
2013-04-10 00:35:25 +02:00
public SignalSource SignalSource { get ; set ; }
2016-04-27 19:03:50 +02:00
public string Source { get ; set ; }
2019-11-08 02:31:44 +01:00
/// <summary>
/// Index or ID of the data record
/// </summary>
2015-04-17 21:59:44 +02:00
public long RecordIndex { get ; set ; }
2019-11-08 02:31:44 +01:00
/// <summary>
/// logical record order (might be different from the index, like old LG TLL files with a linked list of record indices)
/// </summary>
2013-03-31 14:09:38 +02:00
public int RecordOrder { get ; set ; }
2019-11-08 02:31:44 +01:00
/// <summary>
/// original program number from the file, except for channels with IsDeleted==true, which will have the value -1
/// </summary>
2013-03-31 14:09:38 +02:00
public int OldProgramNr { get ; set ; }
2020-08-09 14:09:08 +02:00
2019-11-08 02:31:44 +01:00
/// <summary>
/// new program number or -1, if the channel isn't assigned a number or has IsDeleted==true
/// </summary>
2020-08-09 14:09:08 +02:00
public int NewProgramNr
{
get = > newProgramNr ;
set
{
if ( value = = 0 )
{
}
newProgramNr = value ;
}
}
2019-11-08 02:31:44 +01:00
2013-03-31 14:09:38 +02:00
public string Name { get ; set ; }
public string ShortName { 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 ; }
2019-02-10 15:56:03 +01:00
public int PcrPid { get ; set ; }
2013-03-31 14:09:38 +02:00
public int VideoPid { get ; set ; }
public int AudioPid { get ; set ; }
public int OriginalNetworkId { get ; set ; }
public int TransportStreamId { get ; set ; }
2014-01-19 19:08:17 +01:00
public string Provider { get ; set ; }
2013-03-31 14:09:38 +02:00
public int SymbolRate { get ; set ; }
public int ServiceType { get ; set ; }
public string SatPosition { get ; set ; }
public Transponder Transponder { get ; set ; }
2019-11-08 02:31:44 +01:00
2021-03-14 22:13:22 +01:00
/// <summary>
/// Defines whether favorite lists have individual ordering (FavIndex, OldFavIndex) or if they use the main channel number (Favorites bitmask)
/// </summary>
public FavoritesMode FavMode { get ; set ; }
2019-11-08 02:31:44 +01:00
/// <summary>
/// Bitmask in which favorite lists the channel is included
/// </summary>
public Favorites Favorites { get ; set ; }
/// <summary>
/// current number of the channel in the various favorite lists (if individual sorting is supported)
/// </summary>
2021-03-13 18:11:30 +01:00
private List < int > FavIndex { get ; }
2019-11-08 02:31:44 +01:00
/// <summary>
/// original number of the channel in the various favorite lists (if individual sorting is supported)
/// </summary>
2021-03-13 18:11:30 +01:00
private List < int > OldFavIndex { get ; }
2019-11-08 02:31:44 +01:00
/// <summary>
/// predefined LCN (logical channel number) assigned by TV firmware or cable/sat operator
/// </summary>
2013-11-12 18:25:15 +01:00
public int ProgramNrPreset { get ; set ; }
2013-03-31 14:09:38 +02:00
public bool IsNameModified { get ; set ; }
2019-11-08 02:31:44 +01:00
/// <summary>
/// A proxy channel is inserted into the current channel list when there was no match for a reference list channel
/// </summary>
2020-05-02 19:04:43 +02:00
public bool IsProxy = > this . RecordIndex = = - 1 ;
2023-01-18 15:27:59 +01:00
/// <summary>
/// can be used to store the offset of the raw data in the input file, e.g. for re-parsing names with different encoding
/// </summary>
public int RawDataOffset { get ; set ; }
2019-11-08 02:31:44 +01:00
/// <summary>
/// arbitrary information that can be shown in a UI column to assist in analyzing a file format while coding a plugin
/// </summary>
public string Debug { get ; private set ; }
2013-03-31 14:09:38 +02:00
#region ctor ( )
2023-02-20 09:34:45 +01:00
public ChannelInfo ( )
2013-04-10 00:35:25 +02:00
{
2019-11-08 02:31:44 +01:00
this . OldProgramNr = - 1 ;
2013-04-10 00:35:25 +02:00
this . NewProgramNr = - 1 ;
2021-03-07 16:12:21 +01:00
this . FavIndex = new List < int > ( ) ;
this . OldFavIndex = new List < int > ( ) ;
2013-11-20 02:42:47 +01:00
this . Name = "" ;
this . ShortName = "" ;
2023-02-20 09:34:45 +01:00
this . Encrypted = null ;
2013-04-03 12:47:24 +02:00
}
2013-03-31 14:09:38 +02:00
/// <summary>
2019-07-16 01:44:18 +02:00
/// Constructor for existing TV channel
2013-03-31 14:09:38 +02:00
/// </summary>
2015-11-25 23:38:29 +01:00
public ChannelInfo ( SignalSource source , long index , int oldProgNr , string name ) : this ( )
2013-03-31 14:09:38 +02:00
{
this . SignalSource = source ;
this . RecordIndex = index ;
2015-11-25 23:38:29 +01:00
this . RecordOrder = ( int ) index ;
2013-03-31 14:09:38 +02:00
this . OldProgramNr = oldProgNr ;
this . Name = name ;
}
/// <summary>
/// Constructor for reference list channels which no longer exist in TV list
/// </summary>
2013-07-02 23:55:02 +02:00
public ChannelInfo ( SignalSource source , string uid , int newProgNr , string name ) : this ( )
2013-03-31 14:09:38 +02:00
{
this . SignalSource = source ;
this . Uid = uid ;
2013-04-29 01:24:49 +02:00
this . RecordIndex = - 1 ;
this . RecordOrder = - 1 ;
2013-04-10 00:35:25 +02:00
this . OldProgramNr = - 1 ;
2013-03-31 14:09:38 +02:00
this . NewProgramNr = newProgNr ;
this . Name = name ;
}
#endregion
#region Uid
2021-04-11 12:08:47 +02:00
public static string GetUid ( SignalSource signalSource , decimal freqInMhz , int onid , int tsid , int sid , string channelOrTransponder )
{
if ( ( signalSource & SignalSource . Analog ) ! = 0 )
return "A-0-" + ( int ) ( freqInMhz * 20 ) + "-0" ;
2023-06-03 10:38:11 +02:00
if ( ( signalSource & SignalSource . MaskBcastMedium ) = = SignalSource . Sat )
2021-04-11 12:08:47 +02:00
return "S" + /*this.SatPosition + */ "-" + onid + "-" + tsid + "-" + sid ;
2023-06-03 10:38:11 +02:00
if ( ( signalSource & SignalSource . MaskBcastMedium ) = = SignalSource . Antenna | | ( signalSource & SignalSource . MaskBcastMedium ) = = SignalSource . Cable )
2021-04-11 12:08:47 +02:00
{
// ChannelOrTransponder is needed for DVB-T where the same ONID+TSID+SID can be received from 2 different radio transmitters, but on different frequencies/channels
if ( string . IsNullOrEmpty ( channelOrTransponder ) )
channelOrTransponder = ( ( signalSource & SignalSource . Antenna ) ! = 0 ? LookupData . Instance . GetDvbtTransponder ( freqInMhz ) : LookupData . Instance . GetDvbcTransponder ( freqInMhz ) ) . ToString ( ) ;
return "C-" + onid + "-" + tsid + "-" + sid + "-" + channelOrTransponder ;
}
return onid + "-" + tsid + "-" + sid ;
}
2019-11-08 02:31:44 +01:00
/// <summary>
/// The Uid is the preferred way of matching channels between the current channel list and a reference list.
/// The basic format of this string was taken from a command line tool "TllSort" for LG TVs but then expanded beyond that
/// in order to support the various file formats and the data provided in those.
/// </summary>
2013-03-31 14:09:38 +02:00
public string Uid
{
2021-04-11 12:08:47 +02:00
get = > this . uid ? ? = GetUid ( this . SignalSource , this . FreqInMhz , this . OriginalNetworkId , this . TransportStreamId , this . ServiceId , this . ChannelOrTransponder ) ;
set = > this . uid = value ;
2013-03-31 14:09:38 +02:00
}
#endregion
#region ToString ( ) , Equals ( ) , GetHashCode ( )
public override string ToString ( )
{
2013-04-12 00:47:50 +02:00
string nr = this . NewProgramNr ! = - 1 ? this . NewProgramNr . ToString ( ) : "@" + this . RecordIndex ;
return nr + ": " + this . Name ;
2013-03-31 14:09:38 +02:00
}
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
2015-09-24 12:46:52 +02:00
public string ServiceTypeName
{
get { return this . serviceTypeName ? ? ( this . serviceTypeName = LookupData . Instance . GetServiceTypeDescription ( this . ServiceType ) ) ; }
set { this . serviceTypeName = value ; }
}
2013-03-31 14:09:38 +02:00
#endregion
#region ParseFavString ( )
public static Favorites ParseFavString ( string value )
{
Favorites favMask = 0 ;
foreach ( Favorites fav in Enum . GetValues ( typeof ( Favorites ) ) )
{
2023-01-03 19:22:58 +01:00
var favChar = fav . ToString ( ) [ 0 ] ;
if ( value . IndexOf ( favChar ) > = 0 )
favMask | = fav ;
2013-03-31 14:09:38 +02:00
}
return favMask ;
}
#endregion
#region AddDebug ( )
2021-09-26 18:52:24 +02:00
public ChannelInfo AddDebug ( byte val )
2013-03-31 14:09:38 +02:00
{
if ( this . Debug = = null )
this . Debug = val . ToString ( "x2" ) ;
else
this . Debug + = " " + val . ToString ( "x2" ) ;
2021-09-26 18:52:24 +02:00
return this ;
2013-03-31 14:09:38 +02:00
}
2021-09-26 18:52:24 +02:00
public ChannelInfo AddDebug ( ushort val )
2013-03-31 14:09:38 +02:00
{
if ( this . Debug = = null )
2019-11-10 11:25:07 +01:00
this . Debug = val . ToString ( "x4" ) ;
2013-03-31 14:09:38 +02:00
else
this . Debug + = " " + val . ToString ( "x4" ) ;
2021-09-26 18:52:24 +02:00
return this ;
2013-03-31 14:09:38 +02:00
}
2021-09-26 18:52:24 +02:00
public ChannelInfo AddDebug ( uint val )
2019-11-10 11:25:07 +01:00
{
if ( this . Debug = = null )
this . Debug = val . ToString ( "x8" ) ;
else
this . Debug + = " " + val . ToString ( "x8" ) ;
2021-09-26 18:52:24 +02:00
return this ;
2019-11-10 11:25:07 +01:00
}
2021-09-26 18:52:24 +02:00
public ChannelInfo AddDebug ( byte [ ] data , int offset , int len )
2013-03-31 14:09:38 +02:00
{
for ( int i = 0 ; i < len ; i + + )
2013-04-12 00:47:50 +02:00
this . AddDebug ( data [ offset + i ] ) ;
2021-09-26 18:52:24 +02:00
return this ;
2013-03-31 14:09:38 +02:00
}
2015-09-24 12:46:52 +02:00
2021-09-26 18:52:24 +02:00
public ChannelInfo AddDebug ( string val )
2015-09-24 12:46:52 +02:00
{
if ( this . Debug = = null )
this . Debug = val ;
else
this . Debug + = " " + val ;
2021-09-26 18:52:24 +02:00
return this ;
2015-09-24 12:46:52 +02:00
}
2013-03-31 14:09:38 +02:00
#endregion
2013-04-03 12:47:24 +02:00
2013-07-02 23:55:02 +02:00
#region UpdateRawData ( )
2019-11-08 02:31:44 +01:00
/// <summary>
/// called during the saving procedure to update the external channel list data with the changes made by the user
/// </summary>
2013-04-03 12:47:24 +02:00
public virtual void UpdateRawData ( )
{
}
2013-07-02 23:55:02 +02:00
#endregion
2013-04-03 12:47:24 +02:00
2013-07-02 23:55:02 +02:00
#region ChangeEncoding ( )
2019-11-08 02:31:44 +01:00
/// <summary>
/// for file formats that allow characters in local code pages, this method should re-parse the raw data bytes for the given encoding
/// </summary>
/// <param name="encoding"></param>
2013-04-03 12:47:24 +02:00
public virtual void ChangeEncoding ( System . Text . Encoding encoding )
2013-07-02 23:55:02 +02:00
{
}
#endregion
#region GetPosition ( ) , SetPosition ( ) , ChangePosition ( )
2019-11-08 02:31:44 +01:00
/// <summary>
2021-03-14 22:13:22 +01:00
/// Gets the new channel number in the main channel list (index=0) or the various favorite lists (1..x)
2019-11-08 02:31:44 +01:00
/// </summary>
2021-03-14 22:13:22 +01:00
public int GetPosition ( int subListIndex ) = > this . GetNewOrOldPosition ( subListIndex , this . NewProgramNr , this . FavIndex ) ;
2013-07-02 23:55:02 +02:00
2019-11-08 02:31:44 +01:00
/// <summary>
2021-03-14 22:13:22 +01:00
/// Gets the original channel number in the main channel list (index=0) or the various favorite lists (1..x)
2019-11-08 02:31:44 +01:00
/// </summary>
2021-03-14 22:13:22 +01:00
public int GetOldPosition ( int subListIndex ) = > this . GetNewOrOldPosition ( subListIndex , this . OldProgramNr , this . OldFavIndex ) ;
private int GetNewOrOldPosition ( int subListIndex , int progNr , List < int > fav )
2016-04-27 19:03:50 +02:00
{
2021-03-14 22:13:22 +01:00
if ( subListIndex < 0 )
return - 1 ;
if ( subListIndex = = 0 )
return progNr ;
if ( this . FavMode = = FavoritesMode . None )
return - 1 ;
if ( this . FavMode = = FavoritesMode . Flags )
return subListIndex > MaxFavListsWithFlags ? - 1 : ( ( uint ) this . Favorites & ( 1 < < ( subListIndex - 1 ) ) ) = = 0 ? 0 : progNr ;
if ( subListIndex - 1 > = fav . Count )
return - 1 ;
return fav [ subListIndex - 1 ] ;
2016-04-27 19:03:50 +02:00
}
2021-03-14 22:13:22 +01:00
2019-11-08 02:31:44 +01:00
/// <summary>
2021-03-14 22:13:22 +01:00
/// Sets the new channel number in the main channel list (index=0) or the various favorite lists (1..x)
2019-11-08 02:31:44 +01:00
/// </summary>
2021-03-14 22:13:22 +01:00
public void SetPosition ( int subListIndex , int newPos ) = > this . SetNewOrOldPosition ( subListIndex , newPos , n = > this . NewProgramNr = n , this . FavIndex , f = > this . Favorites = f ) ;
2013-07-02 23:55:02 +02:00
2019-11-08 02:31:44 +01:00
/// <summary>
2021-03-14 22:13:22 +01:00
/// Sets the original channel number in the main channel list (index=0) or the various favorite lists (1..x)
2019-11-08 02:31:44 +01:00
/// </summary>
2021-03-14 22:13:22 +01:00
public void SetOldPosition ( int subListIndex , int oldPos ) = > this . SetNewOrOldPosition ( subListIndex , oldPos , n = > this . OldProgramNr = n , this . OldFavIndex , null ) ;
private void SetNewOrOldPosition ( int subListIndex , int newPos , Action < int > setMainPosition , List < int > fav , Action < Favorites > setFavFlags )
2017-03-31 16:55:37 +02:00
{
2021-03-07 16:12:21 +01:00
if ( subListIndex < 0 )
return ;
2017-03-31 16:55:37 +02:00
if ( subListIndex = = 0 )
2021-03-14 22:13:22 +01:00
setMainPosition ( newPos ) ;
else if ( this . FavMode ! = FavoritesMode . None )
2021-03-07 16:12:21 +01:00
{
2021-03-14 22:13:22 +01:00
if ( this . FavMode ! = FavoritesMode . Flags )
{
for ( int i = fav . Count ; i < subListIndex ; i + + )
fav . Add ( - 1 ) ;
fav [ subListIndex - 1 ] = newPos ;
}
if ( setFavFlags ! = null & & subListIndex < = MaxFavListsWithFlags )
{
int mask = 1 < < ( subListIndex - 1 ) ;
if ( newPos = = - 1 )
this . Favorites & = ( Favorites ) ~ mask ;
else
this . Favorites | = ( Favorites ) mask ;
}
2021-03-07 16:12:21 +01:00
}
2017-03-31 16:55:37 +02:00
}
2021-03-14 22:13:22 +01:00
2019-11-08 02:31:44 +01:00
/// <summary>
/// Internal helper method to adjust the main or favorite program number by a delta value
/// </summary>
2013-07-02 23:55:02 +02:00
internal void ChangePosition ( int subListIndex , int delta )
{
if ( subListIndex = = 0 )
this . NewProgramNr + = delta ;
2021-03-14 22:13:22 +01:00
else if ( this . FavMode ! = FavoritesMode . None )
2021-03-07 16:12:21 +01:00
{
2021-03-14 22:13:22 +01:00
for ( int i = this . FavIndex . Count ; i < subListIndex ; i + + )
2021-03-07 16:12:21 +01:00
this . FavIndex . Add ( - 1 ) ;
this . FavIndex [ subListIndex - 1 ] + = delta ;
}
2013-07-02 23:55:02 +02:00
}
#endregion
2021-03-14 22:13:22 +01:00
public void ResetFavorites ( )
{
this . FavIndex . Clear ( ) ;
this . Favorites = 0 ;
}
2013-03-31 14:09:38 +02:00
}
2023-02-20 09:34:45 +01:00
public class ChannelInfo < T > : ChannelInfo
{
public T ExtraData { get ; set ; }
}
2013-03-31 14:09:38 +02:00
}