2013-07-02 23:55:02 +02:00
using System ;
using System.Collections.Generic ;
2013-03-31 14:09:38 +02:00
using System.Linq ;
2013-05-11 16:45:29 +02:00
using System.Text ;
2013-03-31 14:09:38 +02:00
namespace ChanSort.Api
{
public class Editor
{
public DataRoot DataRoot ;
public ChannelList ChannelList ;
2013-07-02 23:55:02 +02:00
public int SubListIndex ;
2013-03-31 14:09:38 +02:00
#region AddChannels ( )
public ChannelInfo AddChannels ( IList < ChannelInfo > channels )
{
2013-07-02 23:55:02 +02:00
int count = channels . Count ( channel = > channel . GetPosition ( this . SubListIndex ) = = - 1 ) ;
2013-03-31 14:09:38 +02:00
if ( count = = 0 ) return null ;
ChannelInfo lastInsertedChannel = null ;
int progNr = this . ChannelList . InsertProgramNumber ;
int relativeChannelNumber = 0 ;
2013-05-05 22:40:57 +02:00
int progNrCopy = progNr ; // prevent "access to modified closure" warning
2016-04-27 19:03:50 +02:00
foreach ( var channel in this . ChannelList . Channels . Where ( c = > c . GetPosition ( this . SubListIndex ) > = progNrCopy ) . OrderBy ( c = > c . GetPosition ( this . SubListIndex ) ) )
2013-03-31 14:09:38 +02:00
{
2013-07-02 23:55:02 +02:00
var curPos = channel . GetPosition ( this . SubListIndex ) ;
int gap = count - ( curPos - progNr - relativeChannelNumber ) ;
2013-04-10 00:35:25 +02:00
if ( gap > 0 )
2013-03-31 14:09:38 +02:00
{
2013-07-02 23:55:02 +02:00
channel . SetPosition ( this . SubListIndex , curPos + gap ) ;
2013-04-10 00:35:25 +02:00
+ + relativeChannelNumber ;
2013-03-31 14:09:38 +02:00
}
}
foreach ( var channel in channels )
{
2013-07-02 23:55:02 +02:00
if ( channel . GetPosition ( this . SubListIndex ) ! = - 1 )
2013-03-31 14:09:38 +02:00
{
// TODO notify user
continue ;
}
2013-07-02 23:55:02 +02:00
channel . SetPosition ( this . SubListIndex , progNr + + ) ;
2013-03-31 14:09:38 +02:00
lastInsertedChannel = channel ;
}
this . ChannelList . InsertProgramNumber + = count ;
this . DataRoot . NeedsSaving | = lastInsertedChannel ! = null ;
return lastInsertedChannel ;
}
2013-07-02 23:55:02 +02:00
2013-03-31 14:09:38 +02:00
#endregion
#region RemoveChannels ( )
2013-04-06 01:46:28 +02:00
public void RemoveChannels ( IList < ChannelInfo > channels , bool closeGap )
2013-03-31 14:09:38 +02:00
{
if ( channels . Count = = 0 ) return ;
2013-07-02 23:55:02 +02:00
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 ) ) ;
2013-03-31 14:09:38 +02:00
foreach ( var channel in channels )
{
2013-07-02 23:55:02 +02:00
if ( channel . GetPosition ( this . SubListIndex ) = = - 1 )
2013-03-31 14:09:38 +02:00
continue ;
2013-04-06 01:46:28 +02:00
if ( closeGap )
2013-03-31 14:09:38 +02:00
{
2013-07-02 23:55:02 +02:00
int prevNr = channel . GetPosition ( this . SubListIndex ) ;
2013-04-06 01:46:28 +02:00
foreach ( var channel2 in orderedChannelList )
2013-03-31 14:09:38 +02:00
{
2013-07-02 23:55:02 +02:00
if ( channel2 . GetPosition ( this . SubListIndex ) > channel . GetPosition ( this . SubListIndex ) )
2013-04-06 01:46:28 +02:00
{
2013-12-15 18:42:08 +01:00
// ignore deleted and proxy channels (prevNr<0), broken channels (==0) and channels after a gap
if ( prevNr < = 0 | | channel2 . GetPosition ( this . SubListIndex ) ! = prevNr + 1 )
2013-04-06 01:46:28 +02:00
break ;
2013-07-02 23:55:02 +02:00
prevNr = channel2 . GetPosition ( this . SubListIndex ) ;
channel2 . ChangePosition ( this . SubListIndex , - 1 ) ;
2013-04-06 01:46:28 +02:00
}
2013-03-31 14:09:38 +02:00
}
}
2013-07-02 23:55:02 +02:00
channel . SetPosition ( this . SubListIndex , - 1 ) ;
2013-03-31 14:09:38 +02:00
}
this . DataRoot . NeedsSaving = true ;
}
#endregion
#region MoveChannels ( )
2013-05-05 22:40:57 +02:00
public void MoveChannels ( IList < ChannelInfo > channels , bool up )
2013-03-31 14:09:38 +02:00
{
if ( channels . Count = = 0 )
return ;
2021-07-26 00:14:21 +02:00
2013-07-02 23:55:02 +02:00
if ( up & & channels [ 0 ] . GetPosition ( this . SubListIndex ) < = this . ChannelList . FirstProgramNumber )
2013-03-31 14:09:38 +02:00
return ;
2021-07-26 00:14:21 +02:00
if ( channels . Any ( ch = > ch . NewProgramNr < 0 ) )
return ;
2013-03-31 14:09:38 +02:00
2021-07-26 00:14:21 +02:00
int maxNr = this . ChannelList . Channels . Count = = 0 ? 0 : this . ChannelList . Channels . Max ( c = > c . GetPosition ( this . SubListIndex ) ) ;
2013-07-02 23:55:02 +02:00
int delta = ( up ? - 1 : + 1 ) ;
2013-06-23 14:58:44 +02:00
foreach ( var channel in ( up ? channels : channels . Reverse ( ) ) )
2013-03-31 14:09:38 +02:00
{
2013-07-02 23:55:02 +02:00
int newProgramNr = channel . GetPosition ( this . SubListIndex ) + delta ;
2021-07-26 00:14:21 +02:00
if ( newProgramNr < 0 ) // can't move a channel up when it's not in the list
continue ;
if ( newProgramNr = = 0 ) // "+" should work like "add at the end" when the channel is not in the list yet
{
newProgramNr = + + maxNr ;
channel . SetPosition ( this . SubListIndex , newProgramNr ) ;
continue ;
}
maxNr = Math . Max ( maxNr , newProgramNr ) ;
ChannelInfo channelAtNewPos = this . ChannelList . Channels . FirstOrDefault ( ch = > ch . GetPosition ( this . SubListIndex ) = = newProgramNr ) ;
2013-07-02 23:55:02 +02:00
if ( channelAtNewPos ! = null )
channelAtNewPos . ChangePosition ( this . SubListIndex , - delta ) ;
channel . ChangePosition ( this . SubListIndex , delta ) ;
2013-03-31 14:09:38 +02:00
}
this . DataRoot . NeedsSaving = true ;
}
#endregion
#region SortSelectedChannels ( ) , ChannelComparerForSortingByName ( )
2013-07-02 23:55:02 +02:00
2013-03-31 14:09:38 +02:00
public void SortSelectedChannels ( List < ChannelInfo > selectedChannels )
{
if ( selectedChannels . Count = = 0 ) return ;
var sortedChannels = new List < ChannelInfo > ( selectedChannels ) ;
sortedChannels . Sort ( this . ChannelComparerForSortingByName ) ;
2013-07-02 23:55:02 +02:00
var programNumbers = selectedChannels . Select ( ch = > ch . GetPosition ( this . SubListIndex ) ) . ToList ( ) ;
2013-03-31 14:09:38 +02:00
for ( int i = 0 ; i < sortedChannels . Count ; i + + )
2013-07-02 23:55:02 +02:00
sortedChannels [ i ] . SetPosition ( this . SubListIndex , programNumbers [ i ] ) ;
2013-03-31 14:09:38 +02:00
this . DataRoot . NeedsSaving = true ;
}
private int ChannelComparerForSortingByName ( ChannelInfo channel1 , ChannelInfo channel2 )
{
return channel1 . Name . CompareTo ( channel2 . Name ) ;
}
2013-07-02 23:55:02 +02:00
2013-03-31 14:09:38 +02:00
#endregion
#region SetSlotNumber ( )
2013-07-02 23:55:02 +02:00
2013-04-06 01:46:28 +02:00
public void SetSlotNumber ( IList < ChannelInfo > channels , int slot , bool swap , bool closeGap )
2013-03-31 14:09:38 +02:00
{
if ( channels . Count = = 0 ) return ;
if ( swap )
{
foreach ( var channel in channels )
{
2013-04-10 00:35:25 +02:00
if ( slot ! = - 1 )
2013-03-31 14:09:38 +02:00
{
var others = this . ChannelList . GetChannelByNewProgNr ( slot ) ;
foreach ( var other in others )
2013-07-02 23:55:02 +02:00
other . SetPosition ( this . SubListIndex , channel . GetPosition ( this . SubListIndex ) ) ;
2013-03-31 14:09:38 +02:00
}
2013-07-02 23:55:02 +02:00
channel . SetPosition ( this . SubListIndex , slot + + ) ;
2013-03-31 14:09:38 +02:00
}
}
else
{
2013-04-06 01:46:28 +02:00
this . RemoveChannels ( channels , closeGap ) ;
2013-03-31 14:09:38 +02:00
this . ChannelList . InsertProgramNumber = slot ;
this . AddChannels ( channels ) ;
}
this . DataRoot . NeedsSaving = true ;
}
2013-07-02 23:55:02 +02:00
2013-03-31 14:09:38 +02:00
#endregion
#region RenumberChannels ( )
2013-07-02 23:55:02 +02:00
2013-03-31 14:09:38 +02:00
public void RenumberChannels ( List < ChannelInfo > channels )
{
if ( channels . Count = = 0 ) return ;
2013-07-02 23:55:02 +02:00
int progNr = channels . Min ( ch = > ch . GetPosition ( this . SubListIndex ) ) ;
foreach ( var channel in channels )
2013-03-31 14:09:38 +02:00
{
2013-07-02 23:55:02 +02:00
if ( channel . GetPosition ( this . SubListIndex ) = = progNr )
2013-03-31 14:09:38 +02:00
{
+ + progNr ;
continue ;
}
var list = new List < ChannelInfo > ( ) ;
list . Add ( channel ) ;
2013-04-06 01:46:28 +02:00
this . RemoveChannels ( list , false ) ;
2013-03-31 14:09:38 +02:00
this . ChannelList . InsertProgramNumber = progNr + + ;
this . AddChannels ( list ) ;
this . DataRoot . NeedsSaving = true ;
}
}
2013-07-02 23:55:02 +02:00
2013-03-31 14:09:38 +02:00
#endregion
2013-04-03 12:47:24 +02:00
2013-05-11 16:45:29 +02:00
#region ApplyReferenceList ( )
2013-07-02 23:55:02 +02:00
2013-05-11 16:45:29 +02:00
public void ApplyReferenceList ( DataRoot refDataRoot )
{
foreach ( var channelList in this . DataRoot . ChannelLists )
{
foreach ( var channel in channelList . Channels )
2016-04-27 01:58:38 +02:00
channel . SetPosition ( 0 , - 1 ) ;
2013-05-11 16:45:29 +02:00
}
StringBuilder log = new StringBuilder ( ) ;
foreach ( var refList in refDataRoot . ChannelLists )
{
var tvList = this . DataRoot . GetChannelList ( refList . SignalSource ) ;
2019-08-11 17:27:07 +02:00
if ( tvList = = null | | tvList . SignalSource ! = refList . SignalSource )
2013-05-11 16:45:29 +02:00
{
log . AppendFormat ( "Skipped reference list {0}\r\n" , refList . ShortCaption ) ;
continue ;
}
2021-03-13 18:11:30 +01:00
ApplyReferenceList ( refDataRoot , refList , - 1 , tvList , - 1 , true ) ;
2016-04-27 01:58:38 +02:00
}
}
2016-05-06 02:30:46 +02:00
/// <summary>
/// Applies the ordering of a reference list to the TV list
/// </summary>
/// <param name="refDataRoot">object representing the whole reference list file</param>
/// <param name="refList">the particular ChannelList to take the order from</param>
2021-03-14 22:13:22 +01:00
/// <param name="refListPosIndex">the sublist index in the reference list that should be applied (0=main channel number, 1=fav1, ...)</param>
2016-05-06 02:30:46 +02:00
/// <param name="tvList">the particular ChannelList to apply the order to</param>
2021-03-14 22:13:22 +01:00
/// <param name="tvListPosIndex">the sublist index in the target list that should be changed (-1=main and all favs, 0=main channel number, 1=fav1, ...)</param>
2016-05-06 02:30:46 +02:00
/// <param name="addProxyChannels">if true, a placeholder channel will be created in the tvList if there is no matching TV channel for a reference channel</param>
/// <param name="positionOffset">can be used to shift the Pr# of the reference list so avoid conflicts with already assigned Pr# in the TV list</param>
/// <param name="chanFilter">a function which is called for each channel in the reference list (with 2nd parameter=true) and TV list (2nd parameter=false) to determine if the channel is part of the reordering
/// This is used to filter for analog/digital, radio/TV, antenna/cable/sat/ip
/// </param>
/// <param name="overwrite">controls whether Pr# will be reassigned to the reference channel when they are already in-use in the TV list</param>
/// <param name="consecutive">when true, consecutive numbers will be used instead of the Pr# in the reference list when applying the order</param>
2021-03-13 18:11:30 +01:00
public void ApplyReferenceList ( DataRoot refDataRoot , ChannelList refList , int refListPosIndex , ChannelList tvList , int tvListPosIndex , bool addProxyChannels = true , int positionOffset = 0 , Func < ChannelInfo , bool , bool > chanFilter = null , bool overwrite = true , bool consecutive = false )
2016-04-27 01:58:38 +02:00
{
2016-05-05 00:12:06 +02:00
// create Hashtable for exact channel lookup
// the UID of a TV channel list contains a source-indicator (Analog, Cable, Sat), which may be undefined in the reference list)
var onidTsidSid = new Dictionary < long , List < ChannelInfo > > ( ) ;
2021-03-14 22:13:22 +01:00
var chansByNewNr = new Dictionary < int , List < ChannelInfo > > ( ) ;
2016-05-05 00:12:06 +02:00
foreach ( var channel in tvList . Channels )
{
var key = DvbKey ( channel . OriginalNetworkId , channel . TransportStreamId , channel . ServiceId ) ;
2021-01-24 11:57:06 +01:00
if ( key = = 0 )
continue ;
2016-05-05 00:12:06 +02:00
var list = onidTsidSid . TryGet ( key ) ;
if ( list = = null )
{
list = new List < ChannelInfo > ( ) ;
onidTsidSid . Add ( key , list ) ;
}
list . Add ( channel ) ;
}
2016-05-06 02:30:46 +02:00
var incNr = 1 + positionOffset ;
2021-03-14 22:13:22 +01:00
var refPos = refListPosIndex < 0 | | ! refDataRoot . SortedFavorites ? 0 : refListPosIndex ;
var refChannels = refList . Channels . OrderBy ( ch = > ch . GetOldPosition ( refPos ) ) . ToList ( ) ;
var newPos = Math . Max ( 0 , tvListPosIndex ) ;
foreach ( var refChannel in refChannels )
2016-04-27 01:58:38 +02:00
{
2016-05-06 02:30:46 +02:00
if ( ! ( chanFilter ? . Invoke ( refChannel , true ) ? ? true ) )
2016-04-27 01:58:38 +02:00
continue ;
2021-07-08 22:13:08 +02:00
var tvChannel = FindChannel ( tvList , newPos , refChannel , onidTsidSid , overwrite ) ;
2016-04-27 01:58:38 +02:00
if ( tvChannel ! = null )
2013-05-11 16:45:29 +02:00
{
2016-05-06 02:30:46 +02:00
if ( ! ( chanFilter ? . Invoke ( tvChannel , false ) ? ? true ) )
2016-04-27 01:58:38 +02:00
continue ;
2021-03-14 22:13:22 +01:00
var newNr = consecutive ? incNr + + : refChannel . GetOldPosition ( refPos ) + positionOffset ;
2016-05-06 02:30:46 +02:00
// handle conflicts when the number is already in-use
2021-03-14 22:13:22 +01:00
if ( chansByNewNr . TryGetValue ( newNr , out var curChans ) )
{
if ( ! overwrite )
continue ;
foreach ( var chan in curChans )
chan . SetPosition ( newPos , - 1 ) ;
}
else
{
curChans = new List < ChannelInfo > ( ) ;
chansByNewNr [ newNr ] = curChans ;
}
curChans . Add ( tvChannel ) ;
2016-04-27 01:58:38 +02:00
2021-03-14 22:13:22 +01:00
tvChannel . SetPosition ( newPos , newNr ) ;
2019-11-24 20:00:48 +01:00
if ( refDataRoot . CanSkip & & this . DataRoot . CanSkip )
tvChannel . Skip = refChannel . Skip ;
if ( refDataRoot . CanLock & & this . DataRoot . CanLock )
tvChannel . Lock = refChannel . Lock ;
if ( refDataRoot . CanHide & & this . DataRoot . CanHide )
tvChannel . Hidden = refChannel . Hidden ;
//tvChannel.IsDeleted = refChannel.IsDeleted;
2016-04-27 01:58:38 +02:00
if ( ( tvChannel . SignalSource & SignalSource . Analog ) ! = 0 & & ! string . IsNullOrEmpty ( refChannel . Name ) )
2013-05-11 16:45:29 +02:00
{
2016-04-27 01:58:38 +02:00
tvChannel . Name = refChannel . Name ;
tvChannel . IsNameModified = true ;
2013-05-11 16:45:29 +02:00
}
2016-04-27 01:58:38 +02:00
2021-03-13 18:11:30 +01:00
if ( tvListPosIndex = = - 1 )
ApplyFavorites ( refDataRoot , refChannel , tvChannel ) ;
2016-04-27 01:58:38 +02:00
}
else if ( addProxyChannels )
{
tvChannel = new ChannelInfo ( refChannel . SignalSource , refChannel . Uid , refChannel . OldProgramNr , refChannel . Name ) ;
tvList . AddChannel ( tvChannel ) ;
}
}
}
2021-07-08 22:13:08 +02:00
private ChannelInfo FindChannel ( ChannelList tvList , int subListIndex , ChannelInfo refChannel , Dictionary < long , List < ChannelInfo > > onidTsidSid , bool overwrite )
2021-03-13 18:11:30 +01:00
{
2021-03-17 07:01:05 +01:00
List < ChannelInfo > candidates ;
2021-03-13 18:11:30 +01:00
2021-03-17 07:01:05 +01:00
// try to find matching channels based on UID or ONID+TSID+SID+Transponder
2021-06-13 04:03:12 +02:00
var channels = refChannel . Uid . EndsWith ( "0-0-0" ) ? new List < ChannelInfo > ( ) : tvList . GetChannelByUid ( refChannel . Uid ) . ToList ( ) ;
2021-03-17 07:01:05 +01:00
if ( channels . Count = = 0 )
2021-03-13 18:11:30 +01:00
{
var key = DvbKey ( refChannel . OriginalNetworkId , refChannel . TransportStreamId , refChannel . ServiceId ) ;
2021-03-17 07:01:05 +01:00
if ( key ! = 0 & & onidTsidSid . TryGetValue ( key , out candidates ) )
channels = candidates ;
2021-03-13 18:11:30 +01:00
2021-03-17 07:01:05 +01:00
// narrow the list down further when a transponder is also provided (i.e. the same channel can be received on multiple DVB-T frequencies)
if ( channels . Count > 1 & & ! string . IsNullOrEmpty ( refChannel . ChannelOrTransponder ) )
{
candidates = channels . Where ( ch = > ch . ChannelOrTransponder = = refChannel . ChannelOrTransponder ) . ToList ( ) ;
if ( candidates . Count > 0 )
channels = candidates ;
2021-03-13 18:11:30 +01:00
}
}
2021-06-13 04:03:12 +02:00
2021-03-17 07:01:05 +01:00
2021-06-13 04:03:12 +02:00
candidates = channels . Where ( c = > c . GetPosition ( subListIndex ) = = - 1 ) . ToList ( ) ;
if ( candidates . Count > 0 )
{
channels = candidates ;
if ( channels . Count > 1 )
{
candidates = channels . Where ( ch = > ch . IsDeleted = = false ) . ToList ( ) ;
if ( candidates . Count > 0 )
channels = candidates ;
}
if ( channels . Count > 0 )
return channels [ 0 ] ;
}
2021-03-13 18:11:30 +01:00
// try to find matching channels by name
2021-03-17 07:01:05 +01:00
channels = tvList . GetChannelByName ( refChannel . Name ) . Where ( c = > c . GetPosition ( subListIndex ) = = - 1 ) . ToList ( ) ;
// if the reference list has information about a service type (tv/radio/data), then only consider channels matching it (or lacking service type information)
var serviceType = refChannel . SignalSource & SignalSource . MaskTvRadioData ;
2021-07-08 22:13:08 +02:00
if ( serviceType ! = 0 & & serviceType ! = SignalSource . MaskTvRadioData )
2021-03-17 07:01:05 +01:00
{
channels = channels . Where ( ch = >
{
var m = ch . SignalSource & SignalSource . MaskTvRadioData ;
2021-07-08 22:13:08 +02:00
return m = = 0 | | ( m & serviceType ) ! = 0 ;
2021-03-17 07:01:05 +01:00
} ) . ToList ( ) ;
}
if ( channels . Count = = 0 )
return null ;
if ( channels . Count > 1 )
{
// exact upper/lowercase matching (often there are channels like "DISCOVERY" and "Discovery")
candidates = channels . Where ( c = > c . Name = = refChannel . Name ) . ToList ( ) ;
if ( candidates . Count > 0 )
channels = candidates ;
}
if ( channels . Count > 1 )
{
// prefer unencrypted channels
candidates = channels . Where ( c = > c . Encrypted . HasValue & & c . Encrypted . Value = = false ) . ToList ( ) ;
if ( candidates . Count > 0 )
channels = candidates ;
}
return channels [ 0 ] ;
2021-03-13 18:11:30 +01:00
}
2016-05-05 00:12:06 +02:00
long DvbKey ( int onid , int tsid , int sid )
{
2016-05-06 02:30:46 +02:00
return ( ( long ) onid < < 32 ) | ( ( long ) tsid < < 16 ) | ( long ) sid ;
2016-05-05 00:12:06 +02:00
}
2016-04-27 01:58:38 +02:00
private void ApplyFavorites ( DataRoot refDataRoot , ChannelInfo refChannel , ChannelInfo tvChannel )
{
if ( this . DataRoot . SortedFavorites )
{
if ( ! this . DataRoot . MixedSourceFavorites | | refDataRoot . MixedSourceFavorites )
{
tvChannel . Favorites = refChannel . Favorites & DataRoot . SupportedFavorites ;
if ( refDataRoot . SortedFavorites )
2013-05-11 16:45:29 +02:00
{
2021-03-13 18:11:30 +01:00
var c = Math . Min ( refDataRoot . FavListCount , this . DataRoot . FavListCount ) ;
2016-04-27 01:58:38 +02:00
for ( int i = 0 ; i < c ; i + + )
2021-03-13 18:11:30 +01:00
tvChannel . SetPosition ( i + 1 , refChannel . GetOldPosition ( i + 1 ) ) ;
2013-05-11 16:45:29 +02:00
}
2016-04-27 01:58:38 +02:00
else
this . ApplyPrNrToFavLists ( tvChannel ) ;
2013-05-11 16:45:29 +02:00
}
}
2016-04-27 01:58:38 +02:00
else
{
tvChannel . Favorites = refChannel . Favorites & DataRoot . SupportedFavorites ;
2020-03-14 16:54:42 +01:00
this . ApplyPrNrToFavLists ( tvChannel ) ;
2016-04-27 01:58:38 +02:00
}
2013-05-11 16:45:29 +02:00
}
#endregion
2013-04-03 12:47:24 +02:00
2013-07-02 23:55:02 +02:00
#region SetFavorites ( )
2021-03-14 22:13:22 +01:00
public void SetFavorites ( IList < ChannelInfo > list , int favIndex , bool set )
2013-07-02 23:55:02 +02:00
{
bool sortedFav = this . DataRoot . SortedFavorites ;
2020-02-11 21:06:37 +01:00
var favMask = ( Favorites ) ( 1 < < favIndex ) ;
var favList = this . DataRoot . ChannelLists . FirstOrDefault ( l = > l . IsMixedSourceFavoritesList ) ? ? this . ChannelList ;
2013-07-02 23:55:02 +02:00
if ( set )
{
int maxPosition = 0 ;
if ( sortedFav )
{
2020-02-11 21:06:37 +01:00
foreach ( var channel in favList . Channels )
2021-03-13 18:11:30 +01:00
maxPosition = Math . Max ( maxPosition , channel . GetPosition ( favIndex + 1 ) ) ;
2013-07-02 23:55:02 +02:00
}
foreach ( var channel in list )
{
2021-03-13 18:11:30 +01:00
if ( sortedFav & & channel . GetPosition ( favIndex + 1 ) = = - 1 )
channel . SetPosition ( favIndex + 1 , + + maxPosition ) ;
2020-02-11 21:06:37 +01:00
channel . Favorites | = favMask ;
2013-07-02 23:55:02 +02:00
}
}
else
{
foreach ( var channel in list )
{
2021-03-13 18:11:30 +01:00
if ( sortedFav & & channel . GetPosition ( favIndex + 1 ) ! = - 1 )
channel . SetPosition ( favIndex + 1 , - 1 ) ;
2020-02-11 21:06:37 +01:00
channel . Favorites & = ~ favMask ;
}
// close gaps when needed
if ( sortedFav & & ! this . DataRoot . AllowGapsInFavNumbers )
{
int i = 0 ;
2021-03-13 18:11:30 +01:00
foreach ( var channel in favList . Channels . OrderBy ( c = > c . GetPosition ( favIndex + 1 ) ) )
2020-02-11 21:06:37 +01:00
{
2021-03-13 18:11:30 +01:00
if ( channel . GetPosition ( favIndex + 1 ) ! = - 1 )
channel . SetPosition ( favIndex + 1 , + + i ) ;
2013-07-02 23:55:02 +02:00
}
}
}
}
2013-04-03 12:47:24 +02:00
#endregion
2014-06-10 19:53:38 +02:00
#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 )
{
2021-03-07 20:48:31 +01:00
var refMask = ( ulong ) tvChannel . Favorites ;
2021-03-14 22:13:22 +01:00
for ( int i = 0 ; i < this . DataRoot . FavListCount ; i + + )
2014-06-10 19:53:38 +02:00
{
2021-03-13 18:11:30 +01:00
tvChannel . SetPosition ( i + 1 , ( refMask & 0x01 ) = = 0 ? - 1 : tvChannel . NewProgramNr ) ;
2014-06-10 19:53:38 +02:00
refMask > > = 1 ;
}
}
#endregion
2015-11-29 20:36:56 +01:00
#region SequentializeFavPos ( )
/// <summary>
/// Put the numbers in channel.FavIndex[i] in a sequential order, starting with 1
/// </summary>
/// <param name="channelList"></param>
/// <param name="favCount">Number of favorite lists (i=0..favCount-1)</param>
2016-04-16 20:01:51 +02:00
/// <returns>true if there were any changes</returns>
public static bool SequentializeFavPos ( ChannelList channelList , int favCount )
{
bool changed = false ;
2015-11-29 20:36:56 +01:00
for ( int fav = 0 ; fav < favCount ; fav + + )
{
2021-03-13 18:11:30 +01:00
var list = channelList . Channels . Where ( c = > c . GetPosition ( fav + 1 ) > = 0 ) . OrderBy ( c = > c . GetPosition ( fav + 1 ) ) . ToList ( ) ;
2016-04-16 20:01:51 +02:00
int i = 1 ;
2015-11-29 20:36:56 +01:00
foreach ( var channel in list )
2016-04-16 20:01:51 +02:00
{
2021-03-13 18:11:30 +01:00
if ( channel . GetPosition ( fav + 1 ) ! = i )
2016-04-16 20:01:51 +02:00
{
2021-03-13 18:11:30 +01:00
channel . SetPosition ( fav + 1 , + + i ) ;
2016-04-16 20:01:51 +02:00
changed = true ;
}
}
2015-11-29 20:36:56 +01:00
}
2016-04-16 20:01:51 +02:00
return changed ;
2015-11-29 20:36:56 +01:00
}
#endregion
2023-10-28 21:28:02 +02:00
#region EnforceTvBeforeRadioBeforeData ( )
public bool EnforceTvBeforeRadioBeforeData ( )
{
bool hadOverlaps = false ;
foreach ( var list in this . DataRoot . ChannelLists )
{
// separate channels into lists for TV, radio and data
var listByServiceType = new List < ChannelInfo > [ 3 ] ; // TV/Radio/Data, min/max
for ( int i = 0 ; i < 3 ; i + + )
listByServiceType [ i ] = new ( ) ;
foreach ( var ch in list . Channels )
{
if ( ch . IsDeleted | | ch . NewProgramNr < 0 | | ch . IsProxy )
continue ;
var serviceType = ch . SignalSource & SignalSource . MaskTvRadioData ;
var i = serviceType = = SignalSource . Tv ? 0 : serviceType = = SignalSource . Radio ? 1 : 2 ;
listByServiceType [ i ] . Add ( ch ) ;
}
// sort the lists by the new program number
for ( int i = 0 ; i < 3 ; i + + )
listByServiceType [ i ] . Sort ( ( a , b ) = > a . NewProgramNr . CompareTo ( b . NewProgramNr ) ) ;
// make sure that program numbers are strictly increasing (so that there are no overlaps between the tv/radio/data groups)
var lastNr = listByServiceType [ 0 ] . Count = = 0 ? 0 : listByServiceType [ 0 ] . Last ( ) . NewProgramNr ;
for ( var i = 1 ; i < = 2 ; i + + )
{
foreach ( var ch in listByServiceType [ i ] )
{
if ( ch . NewProgramNr < = lastNr )
{
ch . NewProgramNr = + + lastNr ;
hadOverlaps = true ;
}
else
lastNr = ch . NewProgramNr ;
}
}
}
return hadOverlaps ;
}
#endregion
2013-03-31 14:09:38 +02:00
}
}