@ -1,5 +1,3 @@
#pragma warning disable CS1591
using System ;
using System.Collections.Concurrent ;
using System.Collections.Generic ;
@ -29,10 +27,11 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Channels
{
/// <summary>
/// The LiveTV channel manager.
/// </summary>
public class ChannelManager : IChannelManager
{
internal IChannel [ ] Channels { get ; private set ; }
private readonly IUserManager _userManager ;
private readonly IUserDataManager _userDataManager ;
private readonly IDtoService _dtoService ;
@ -43,11 +42,28 @@ namespace Emby.Server.Implementations.Channels
private readonly IJsonSerializer _jsonSerializer ;
private readonly IProviderManager _providerManager ;
private readonly ConcurrentDictionary < string , Tuple < DateTime , List < MediaSourceInfo > > > _channelItemMediaInfo =
new ConcurrentDictionary < string , Tuple < DateTime , List < MediaSourceInfo > > > ( ) ;
private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim ( 1 , 1 ) ;
/// <summary>
/// Initializes a new instance of the <see cref="ChannelManager"/> class.
/// </summary>
/// <param name="userManager">The user manager.</param>
/// <param name="dtoService">The dto service.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="loggerFactory">The logger factory.</param>
/// <param name="config">The server configuration manager.</param>
/// <param name="fileSystem">The filesystem.</param>
/// <param name="userDataManager">The user data manager.</param>
/// <param name="jsonSerializer">The JSON serializer.</param>
/// <param name="providerManager">The provider manager.</param>
public ChannelManager (
IUserManager userManager ,
IDtoService dtoService ,
ILibraryManager libraryManager ,
ILoggerFactory loggerFactory ,
ILogger < ChannelManager > logger ,
IServerConfigurationManager config ,
IFileSystem fileSystem ,
IUserDataManager userDataManager ,
@ -57,7 +73,7 @@ namespace Emby.Server.Implementations.Channels
_userManager = userManager ;
_dtoService = dtoService ;
_libraryManager = libraryManager ;
_logger = logger Factory. CreateLogger ( nameof ( ChannelManager ) ) ;
_logger = logger ;
_config = config ;
_fileSystem = fileSystem ;
_userDataManager = userDataManager ;
@ -65,13 +81,17 @@ namespace Emby.Server.Implementations.Channels
_providerManager = providerManager ;
}
internal IChannel [ ] Channels { get ; private set ; }
private static TimeSpan CacheLength = > TimeSpan . FromHours ( 3 ) ;
/// <inheritdoc />
public void AddParts ( IEnumerable < IChannel > channels )
{
Channels = channels . ToArray ( ) ;
}
/// <inheritdoc />
public bool EnableMediaSourceDisplay ( BaseItem item )
{
var internalChannel = _libraryManager . GetItemById ( item . ChannelId ) ;
@ -80,15 +100,16 @@ namespace Emby.Server.Implementations.Channels
return ! ( channel is IDisableMediaSourceDisplay ) ;
}
/// <inheritdoc />
public bool CanDelete ( BaseItem item )
{
var internalChannel = _libraryManager . GetItemById ( item . ChannelId ) ;
var channel = Channels . FirstOrDefault ( i = > GetInternalChannelId ( i . Name ) . Equals ( internalChannel . Id ) ) ;
var supportsDelete = channel as ISupportsDelete ;
return supportsDelete ! = null & & supportsDelete . CanDelete ( item ) ;
return channel is ISupportsDelete supportsDelete & & supportsDelete . CanDelete ( item ) ;
}
/// <inheritdoc />
public bool EnableMediaProbe ( BaseItem item )
{
var internalChannel = _libraryManager . GetItemById ( item . ChannelId ) ;
@ -97,6 +118,7 @@ namespace Emby.Server.Implementations.Channels
return channel is ISupportsMediaProbe ;
}
/// <inheritdoc />
public Task DeleteItem ( BaseItem item )
{
var internalChannel = _libraryManager . GetItemById ( item . ChannelId ) ;
@ -123,11 +145,16 @@ namespace Emby.Server.Implementations.Channels
. OrderBy ( i = > i . Name ) ;
}
/// <summary>
/// Get the installed channel IDs.
/// </summary>
/// <returns>An <see cref="IEnumerable{T}"/> containing installed channel IDs.</returns>
public IEnumerable < Guid > GetInstalledChannelIds ( )
{
return GetAllChannels ( ) . Select ( i = > GetInternalChannelId ( i . Name ) ) ;
}
/// <inheritdoc />
public QueryResult < Channel > GetChannelsInternal ( ChannelQuery query )
{
var user = query . UserId . Equals ( Guid . Empty )
@ -146,15 +173,13 @@ namespace Emby.Server.Implementations.Channels
{
try
{
var hasAttributes = GetChannelProvider ( i ) as IHasFolderAttributes ;
return ( hasAttributes ! = null & & hasAttributes . Attributes . Contains ( "Recordings" , StringComparer . OrdinalIgnoreCase ) ) = = val ;
return ( GetChannelProvider ( i ) is IHasFolderAttributes hasAttributes
& & hasAttributes . Attributes . Contains ( "Recordings" , StringComparer . OrdinalIgnoreCase ) ) = = val ;
}
catch
{
return false ;
}
} ) . ToList ( ) ;
}
@ -171,7 +196,6 @@ namespace Emby.Server.Implementations.Channels
{
return false ;
}
} ) . ToList ( ) ;
}
@ -188,9 +212,9 @@ namespace Emby.Server.Implementations.Channels
{
return false ;
}
} ) . ToList ( ) ;
}
if ( query . IsFavorite . HasValue )
{
var val = query . IsFavorite . Value ;
@ -215,7 +239,6 @@ namespace Emby.Server.Implementations.Channels
{
return false ;
}
} ) . ToList ( ) ;
}
@ -226,6 +249,7 @@ namespace Emby.Server.Implementations.Channels
{
all = all . Skip ( query . StartIndex . Value ) . ToList ( ) ;
}
if ( query . Limit . HasValue )
{
all = all . Take ( query . Limit . Value ) . ToList ( ) ;
@ -248,6 +272,7 @@ namespace Emby.Server.Implementations.Channels
} ;
}
/// <inheritdoc />
public QueryResult < BaseItemDto > GetChannels ( ChannelQuery query )
{
var user = query . UserId . Equals ( Guid . Empty )
@ -256,9 +281,7 @@ namespace Emby.Server.Implementations.Channels
var internalResult = GetChannelsInternal ( query ) ;
var dtoOptions = new DtoOptions ( )
{
} ;
var dtoOptions = new DtoOptions ( ) ;
// TODO Fix The co-variant conversion (internalResult.Items) between Folder[] and BaseItem[], this can generate runtime issues.
var returnItems = _dtoService . GetBaseItemDtos ( internalResult . Items , dtoOptions , user ) ;
@ -272,6 +295,12 @@ namespace Emby.Server.Implementations.Channels
return result ;
}
/// <summary>
/// Refreshes the associated channels.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
/// <returns>The completed task.</returns>
public async Task RefreshChannels ( IProgress < double > progress , CancellationToken cancellationToken )
{
var allChannelsList = GetAllChannels ( ) . ToList ( ) ;
@ -305,14 +334,7 @@ namespace Emby.Server.Implementations.Channels
private Channel GetChannelEntity ( IChannel channel )
{
var item = GetChannel ( GetInternalChannelId ( channel . Name ) ) ;
if ( item = = null )
{
item = GetChannel ( channel , CancellationToken . None ) . Result ;
}
return item ;
return GetChannel ( GetInternalChannelId ( channel . Name ) ) ? ? GetChannel ( channel , CancellationToken . None ) . Result ;
}
private List < MediaSourceInfo > GetSavedMediaSources ( BaseItem item )
@ -341,8 +363,8 @@ namespace Emby.Server.Implementations.Channels
}
catch
{
}
return ;
}
@ -351,6 +373,7 @@ namespace Emby.Server.Implementations.Channels
_jsonSerializer . SerializeToFile ( mediaSources , path ) ;
}
/// <inheritdoc />
public IEnumerable < MediaSourceInfo > GetStaticMediaSources ( BaseItem item , CancellationToken cancellationToken )
{
IEnumerable < MediaSourceInfo > results = GetSavedMediaSources ( item ) ;
@ -360,16 +383,20 @@ namespace Emby.Server.Implementations.Channels
. ToList ( ) ;
}
/// <summary>
/// Gets the dynamic media sources based on the provided item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
/// <returns>The task representing the operation to get the media sources.</returns>
public async Task < IEnumerable < MediaSourceInfo > > GetDynamicMediaSources ( BaseItem item , CancellationToken cancellationToken )
{
var channel = GetChannel ( item . ChannelId ) ;
var channelPlugin = GetChannelProvider ( channel ) ;
var requiresCallback = channelPlugin as IRequiresMediaInfoCallback ;
IEnumerable < MediaSourceInfo > results ;
if ( requiresCallback ! = null )
if ( channelPlugin is IRequiresMediaInfoCallback requiresCallback )
{
results = await GetChannelItemMediaSourcesInternal ( requiresCallback , item . ExternalId , cancellationToken )
. ConfigureAwait ( false ) ;
@ -384,9 +411,6 @@ namespace Emby.Server.Implementations.Channels
. ToList ( ) ;
}
private readonly ConcurrentDictionary < string , Tuple < DateTime , List < MediaSourceInfo > > > _channelItemMediaInfo =
new ConcurrentDictionary < string , Tuple < DateTime , List < MediaSourceInfo > > > ( ) ;
private async Task < IEnumerable < MediaSourceInfo > > GetChannelItemMediaSourcesInternal ( IRequiresMediaInfoCallback channel , string id , CancellationToken cancellationToken )
{
if ( _channelItemMediaInfo . TryGetValue ( id , out Tuple < DateTime , List < MediaSourceInfo > > cachedInfo ) )
@ -409,7 +433,7 @@ namespace Emby.Server.Implementations.Channels
private static MediaSourceInfo NormalizeMediaSource ( BaseItem item , MediaSourceInfo info )
{
info . RunTimeTicks = info . RunTimeTicks ? ? item . RunTimeTicks ;
info . RunTimeTicks ?? = item . RunTimeTicks ;
return info ;
}
@ -444,18 +468,21 @@ namespace Emby.Server.Implementations.Channels
{
isNew = true ;
}
item . Path = path ;
if ( ! item . ChannelId . Equals ( id ) )
{
forceUpdate = true ;
}
item . ChannelId = id ;
if ( item . ParentId ! = parentFolderId )
{
forceUpdate = true ;
}
item . ParentId = parentFolderId ;
item . OfficialRating = GetOfficialRating ( channelInfo . ParentalRating ) ;
@ -472,51 +499,56 @@ namespace Emby.Server.Implementations.Channels
_libraryManager . CreateItem ( item , null ) ;
}
await item . RefreshMetadata ( new MetadataRefreshOptions ( new DirectoryService ( _fileSystem ) )
await item . RefreshMetadata (
new MetadataRefreshOptions ( new DirectoryService ( _fileSystem ) )
{
ForceSave = ! isNew & & forceUpdate
} , cancellationToken ) . ConfigureAwait ( false ) ;
} ,
cancellationToken ) . ConfigureAwait ( false ) ;
return item ;
}
private static string GetOfficialRating ( ChannelParentalRating rating )
{
switch ( rating )
{
case ChannelParentalRating . Adult :
return "XXX" ;
case ChannelParentalRating . UsR :
return "R" ;
case ChannelParentalRating . UsPG13 :
return "PG-13" ;
case ChannelParentalRating . UsPG :
return "PG" ;
default :
return null ;
}
return rating switch
{
ChannelParentalRating . Adult = > "XXX" ,
ChannelParentalRating . UsR = > "R" ,
ChannelParentalRating . UsPG13 = > "PG-13" ,
ChannelParentalRating . UsPG = > "PG" ,
_ = > null
} ;
}
/// <summary>
/// Gets a channel with the provided Guid.
/// </summary>
/// <param name="id">The Guid.</param>
/// <returns>The corresponding channel.</returns>
public Channel GetChannel ( Guid id )
{
return _libraryManager . GetItemById ( id ) as Channel ;
}
/// <inheritdoc />
public Channel GetChannel ( string id )
{
return _libraryManager . GetItemById ( id ) as Channel ;
}
/// <inheritdoc />
public ChannelFeatures [ ] GetAllChannelFeatures ( )
{
return _libraryManager . GetItemIds ( new InternalItemsQuery
return _libraryManager . GetItemIds (
new InternalItemsQuery
{
IncludeItemTypes = new [ ] { typeof ( Channel ) . Name } ,
OrderBy = new [ ] { ( ItemSortBy . SortName , SortOrder . Ascending ) }
} ) . Select ( i = > GetChannelFeatures ( i . ToString ( "N" , CultureInfo . InvariantCulture ) ) ) . ToArray ( ) ;
}
/// <inheritdoc />
public ChannelFeatures GetChannelFeatures ( string id )
{
if ( string . IsNullOrEmpty ( id ) )
@ -530,15 +562,27 @@ namespace Emby.Server.Implementations.Channels
return GetChannelFeaturesDto ( channel , channelProvider , channelProvider . GetChannelFeatures ( ) ) ;
}
/// <summary>
/// Checks whether the provided Guid supports external transfer.
/// </summary>
/// <param name="channelId">The Guid.</param>
/// <returns>Whether or not the provided Guid supports external transfer.</returns>
public bool SupportsExternalTransfer ( Guid channelId )
{
//var channel = GetChannel(channelId);
var channelProvider = GetChannelProvider ( channelId ) ;
return channelProvider . GetChannelFeatures ( ) . SupportsContentDownloading ;
}
public ChannelFeatures GetChannelFeaturesDto ( Channel channel ,
/// <summary>
/// Gets the provided channel's supported features.
/// </summary>
/// <param name="channel">The channel.</param>
/// <param name="provider">The provider.</param>
/// <param name="features">The features.</param>
/// <returns>The supported features.</returns>
public ChannelFeatures GetChannelFeaturesDto (
Channel channel ,
IChannel provider ,
InternalChannelFeatures features )
{
@ -567,9 +611,11 @@ namespace Emby.Server.Implementations.Channels
{
throw new ArgumentNullException ( nameof ( name ) ) ;
}
return _libraryManager . GetNewItemId ( "Channel " + name , typeof ( Channel ) ) ;
}
/// <inheritdoc />
public async Task < QueryResult < BaseItemDto > > GetLatestChannelItems ( InternalItemsQuery query , CancellationToken cancellationToken )
{
var internalResult = await GetLatestChannelItemsInternal ( query , cancellationToken ) . ConfigureAwait ( false ) ;
@ -588,6 +634,7 @@ namespace Emby.Server.Implementations.Channels
return result ;
}
/// <inheritdoc />
public async Task < QueryResult < BaseItem > > GetLatestChannelItemsInternal ( InternalItemsQuery query , CancellationToken cancellationToken )
{
var channels = GetAllChannels ( ) . Where ( i = > i is ISupportsLatestMedia ) . ToArray ( ) ;
@ -614,7 +661,7 @@ namespace Emby.Server.Implementations.Channels
query . IsFolder = false ;
// hack for trailers, figure out a better way later
var sortByPremiereDate = channels . Length = = 1 & & channels [ 0 ] . GetType ( ) . Name . IndexOf( "Trailer" ) ! = - 1 ;
var sortByPremiereDate = channels . Length = = 1 & & channels [ 0 ] . GetType ( ) . Name . Contains( "Trailer" , StringComparison . Ordinal ) ;
if ( sortByPremiereDate )
{
@ -640,10 +687,12 @@ namespace Emby.Server.Implementations.Channels
{
var internalChannel = await GetChannel ( channel , cancellationToken ) . ConfigureAwait ( false ) ;
var query = new InternalItemsQuery ( ) ;
query . Parent = internalChannel ;
query . EnableTotalRecordCount = false ;
query . ChannelIds = new Guid [ ] { internalChannel . Id } ;
var query = new InternalItemsQuery
{
Parent = internalChannel ,
EnableTotalRecordCount = false ,
ChannelIds = new Guid [ ] { internalChannel . Id }
} ;
var result = await GetChannelItemsInternal ( query , new SimpleProgress < double > ( ) , cancellationToken ) . ConfigureAwait ( false ) ;
@ -651,17 +700,20 @@ namespace Emby.Server.Implementations.Channels
{
if ( item is Folder folder )
{
await GetChannelItemsInternal ( new InternalItemsQuery
await GetChannelItemsInternal (
new InternalItemsQuery
{
Parent = folder ,
EnableTotalRecordCount = false ,
ChannelIds = new Guid [ ] { internalChannel . Id }
} , new SimpleProgress < double > ( ) , cancellationToken ) . ConfigureAwait ( false ) ;
} ,
new SimpleProgress < double > ( ) ,
cancellationToken ) . ConfigureAwait ( false ) ;
}
}
}
/// <inheritdoc />
public async Task < QueryResult < BaseItem > > GetChannelItemsInternal ( InternalItemsQuery query , IProgress < double > progress , CancellationToken cancellationToken )
{
// Get the internal channel entity
@ -672,7 +724,8 @@ namespace Emby.Server.Implementations.Channels
var parentItem = query . ParentId = = Guid . Empty ? channel : _libraryManager . GetItemById ( query . ParentId ) ;
var itemsResult = await GetChannelItems ( channelProvider ,
var itemsResult = await GetChannelItems (
channelProvider ,
query . User ,
parentItem is Channel ? null : parentItem . ExternalId ,
null ,
@ -684,13 +737,12 @@ namespace Emby.Server.Implementations.Channels
{
query . Parent = channel ;
}
query . ChannelIds = Array . Empty < Guid > ( ) ;
// Not yet sure why this is causing a problem
query . GroupByPresentationUniqueKey = false ;
//_logger.LogDebug("GetChannelItemsInternal");
// null if came from cache
if ( itemsResult ! = null )
{
@ -707,12 +759,15 @@ namespace Emby.Server.Implementations.Channels
var deadItem = _libraryManager . GetItemById ( deadId ) ;
if ( deadItem ! = null )
{
_libraryManager . DeleteItem ( deadItem , new DeleteOptions
_libraryManager . DeleteItem (
deadItem ,
new DeleteOptions
{
DeleteFileLocation = false ,
DeleteFromExternalProvider = false
} , parentItem , false ) ;
} ,
parentItem ,
false ) ;
}
}
}
@ -720,6 +775,7 @@ namespace Emby.Server.Implementations.Channels
return _libraryManager . GetItemsResult ( query ) ;
}
/// <inheritdoc />
public async Task < QueryResult < BaseItemDto > > GetChannelItems ( InternalItemsQuery query , CancellationToken cancellationToken )
{
var internalResult = await GetChannelItemsInternal ( query , new SimpleProgress < double > ( ) , cancellationToken ) . ConfigureAwait ( false ) ;
@ -735,7 +791,6 @@ namespace Emby.Server.Implementations.Channels
return result ;
}
private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim ( 1 , 1 ) ;
private async Task < ChannelItemResult > GetChannelItems ( IChannel channel ,
User user ,
string externalFolderId ,
@ -743,7 +798,7 @@ namespace Emby.Server.Implementations.Channels
bool sortDescending ,
CancellationToken cancellationToken )
{
var userId = user = = null ? null : user . Id . ToString ( "N" , CultureInfo . InvariantCulture ) ;
var userId = user ? . Id . ToString ( "N" , CultureInfo . InvariantCulture ) ;
var cacheLength = CacheLength ;
var cachePath = GetChannelDataCachePath ( channel , userId , externalFolderId , sortField , sortDescending ) ;
@ -761,11 +816,9 @@ namespace Emby.Server.Implementations.Channels
}
catch ( FileNotFoundException )
{
}
catch ( IOException )
{
}
await _resourcePool . WaitAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
@ -785,16 +838,14 @@ namespace Emby.Server.Implementations.Channels
}
catch ( FileNotFoundException )
{
}
catch ( IOException )
{
}
var query = new InternalChannelItemQuery
{
UserId = user = = null ? Guid . Empty : user . Id ,
UserId = user ? . Id ? ? Guid . Empty ,
SortBy = sortField ,
SortDescending = sortDescending ,
FolderId = externalFolderId
@ -833,7 +884,8 @@ namespace Emby.Server.Implementations.Channels
}
}
private string GetChannelDataCachePath ( IChannel channel ,
private string GetChannelDataCachePath (
IChannel channel ,
string userId ,
string externalFolderId ,
ChannelItemSortField ? sortField ,
@ -843,8 +895,7 @@ namespace Emby.Server.Implementations.Channels
var userCacheKey = string . Empty ;
var hasCacheKey = channel as IHasCacheKey ;
if ( hasCacheKey ! = null )
if ( channel is IHasCacheKey hasCacheKey )
{
userCacheKey = hasCacheKey . GetCacheKey ( userId ) ? ? string . Empty ;
}
@ -858,6 +909,7 @@ namespace Emby.Server.Implementations.Channels
{
filename + = "-sortField-" + sortField . Value ;
}
if ( sortDescending )
{
filename + = "-sortDescending" ;
@ -865,7 +917,8 @@ namespace Emby.Server.Implementations.Channels
filename = filename . GetMD5 ( ) . ToString ( "N" , CultureInfo . InvariantCulture ) ;
return Path . Combine ( _config . ApplicationPaths . CachePath ,
return Path . Combine (
_config . ApplicationPaths . CachePath ,
"channels" ,
channelId ,
version ,
@ -919,60 +972,32 @@ namespace Emby.Server.Implementations.Channels
if ( info . Type = = ChannelItemType . Folder )
{
if ( info . FolderType = = ChannelFolderType . MusicAlbum )
{
item = GetItemById < MusicAlbum > ( info . Id , channelProvider . Name , out isNew ) ;
}
else if ( info . FolderType = = ChannelFolderType . MusicArtist )
{
item = GetItemById < MusicArtist > ( info . Id , channelProvider . Name , out isNew ) ;
}
else if ( info . FolderType = = ChannelFolderType . PhotoAlbum )
{
item = GetItemById < PhotoAlbum > ( info . Id , channelProvider . Name , out isNew ) ;
}
else if ( info . FolderType = = ChannelFolderType . Series )
{
item = GetItemById < Series > ( info . Id , channelProvider . Name , out isNew ) ;
}
else if ( info . FolderType = = ChannelFolderType . Season )
{
item = GetItemById < Season > ( info . Id , channelProvider . Name , out isNew ) ;
}
else
item = info . FolderType switch
{
item = GetItemById < Folder > ( info . Id , channelProvider . Name , out isNew ) ;
}
ChannelFolderType . MusicAlbum = > GetItemById < MusicAlbum > ( info . Id , channelProvider . Name , out isNew ) ,
ChannelFolderType . MusicArtist = > GetItemById < MusicArtist > ( info . Id , channelProvider . Name , out isNew ) ,
ChannelFolderType . PhotoAlbum = > GetItemById < PhotoAlbum > ( info . Id , channelProvider . Name , out isNew ) ,
ChannelFolderType . Series = > GetItemById < Series > ( info . Id , channelProvider . Name , out isNew ) ,
ChannelFolderType . Season = > GetItemById < Season > ( info . Id , channelProvider . Name , out isNew ) ,
_ = > GetItemById < Folder > ( info . Id , channelProvider . Name , out isNew )
} ;
}
else if ( info . MediaType = = ChannelMediaType . Audio )
{
if ( info . ContentType = = ChannelMediaContentType . Podcast )
{
item = GetItemById < AudioBook > ( info . Id , channelProvider . Name , out isNew ) ;
item = info . ContentType = = ChannelMediaContentType . Podcast
? GetItemById < AudioBook > ( info . Id , channelProvider . Name , out isNew )
: GetItemById < Audio > ( info . Id , channelProvider . Name , out isNew ) ;
}
else
{
item = GetItemById < Audio > ( info . Id , channelProvider . Name , out isNew ) ;
}
}
else
{
if ( info . ContentType = = ChannelMediaContentType . Episode )
{
item = GetItemById < Episode > ( info . Id , channelProvider . Name , out isNew ) ;
}
else if ( info . ContentType = = ChannelMediaContentType . Movie )
{
item = GetItemById < Movie > ( info . Id , channelProvider . Name , out isNew ) ;
}
else if ( info . ContentType = = ChannelMediaContentType . Trailer | | info . ExtraType = = ExtraType . Trailer )
{
item = GetItemById < Trailer > ( info . Id , channelProvider . Name , out isNew ) ;
}
else
item = info . ContentType switch
{
item = GetItemById < Video > ( info . Id , channelProvider . Name , out isNew ) ;
}
ChannelMediaContentType . Episode = > GetItemById < Episode > ( info . Id , channelProvider . Name , out isNew ) ,
ChannelMediaContentType . Movie = > GetItemById < Movie > ( info . Id , channelProvider . Name , out isNew ) ,
var x when x = = ChannelMediaContentType . Trailer | | info . ExtraType = = ExtraType . Trailer
= > GetItemById < Trailer > ( info . Id , channelProvider . Name , out isNew ) ,
_ = > GetItemById < Video > ( info . Id , channelProvider . Name , out isNew )
} ;
}
var enableMediaProbe = channelProvider is ISupportsMediaProbe ;
@ -981,7 +1006,6 @@ namespace Emby.Server.Implementations.Channels
{
item . RunTimeTicks = null ;
}
else if ( isNew | | ! enableMediaProbe )
{
item . RunTimeTicks = info . RunTimeTicks ;
@ -1014,26 +1038,24 @@ namespace Emby.Server.Implementations.Channels
}
}
var hasArtists = item as IHasArtist ;
if ( hasArtists ! = null )
if ( item is IHasArtist hasArtists )
{
hasArtists . Artists = info . Artists . ToArray ( ) ;
}
var hasAlbumArtists = item as IHasAlbumArtist ;
if ( hasAlbumArtists ! = null )
if ( item is IHasAlbumArtist hasAlbumArtists )
{
hasAlbumArtists . AlbumArtists = info . AlbumArtists . ToArray ( ) ;
}
var trailer = item as Trailer ;
if ( trailer ! = null )
if ( item is Trailer trailer )
{
if ( ! info . TrailerTypes . SequenceEqual ( trailer . TrailerTypes ) )
{
_logger . LogDebug ( "Forcing update due to TrailerTypes {0}" , item . Name ) ;
forceUpdate = true ;
}
trailer . TrailerTypes = info . TrailerTypes . ToArray ( ) ;
}
@ -1057,6 +1079,7 @@ namespace Emby.Server.Implementations.Channels
forceUpdate = true ;
_logger . LogDebug ( "Forcing update due to ChannelId {0}" , item . Name ) ;
}
item . ChannelId = internalChannelId ;
if ( ! item . ParentId . Equals ( parentFolderId ) )
@ -1064,16 +1087,17 @@ namespace Emby.Server.Implementations.Channels
forceUpdate = true ;
_logger . LogDebug ( "Forcing update due to parent folder Id {0}" , item . Name ) ;
}
item . ParentId = parentFolderId ;
var hasSeries = item as IHasSeries ;
if ( hasSeries ! = null )
if ( item is IHasSeries hasSeries )
{
if ( ! string . Equals ( hasSeries . SeriesName , info . SeriesName , StringComparison . OrdinalIgnoreCase ) )
{
forceUpdate = true ;
_logger . LogDebug ( "Forcing update due to SeriesName {0}" , item . Name ) ;
}
hasSeries . SeriesName = info . SeriesName ;
}
@ -1082,24 +1106,23 @@ namespace Emby.Server.Implementations.Channels
forceUpdate = true ;
_logger . LogDebug ( "Forcing update due to ExternalId {0}" , item . Name ) ;
}
item . ExternalId = info . Id ;
var channelAudioItem = item as Audio ;
if ( channelAudioItem ! = null )
if ( item is Audio channelAudioItem )
{
channelAudioItem . ExtraType = info . ExtraType ;
var mediaSource = info . MediaSources . FirstOrDefault ( ) ;
item . Path = mediaSource = = null ? null : mediaSource . Path ;
item . Path = mediaSource ? . Path ;
}
var channelVideoItem = item as Video ;
if ( channelVideoItem ! = null )
if ( item is Video channelVideoItem )
{
channelVideoItem . ExtraType = info . ExtraType ;
var mediaSource = info . MediaSources . FirstOrDefault ( ) ;
item . Path = mediaSource = = null ? null : mediaSource . Path ;
item . Path = mediaSource ? . Path ;
}
if ( ! string . IsNullOrEmpty ( info . ImageUrl ) & & ! item . HasImage ( ImageType . Primary ) )
@ -1156,7 +1179,7 @@ namespace Emby.Server.Implementations.Channels
}
}
if ( isNew | | forceUpdate | | item . DateLastRefreshed = = default (DateTime ) )
if ( isNew | | forceUpdate | | item . DateLastRefreshed = = default )
{
_providerManager . QueueRefresh ( item . Id , new MetadataRefreshOptions ( new DirectoryService ( _fileSystem ) ) , RefreshPriority . Normal ) ;
}