aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2016-03-25 13:52:36 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2016-03-25 13:52:36 -0400
commitd9108f69f35080acb5ebefaefcd469595529afa2 (patch)
tree3f04e719877b9cdec9529ca34406b753f6492abc /MediaBrowser.Controller
parentd6832e7a41c2a24f7dd998284e8e4f6eacf1d188 (diff)
parent72fe76ab1008f0bd38157cc37cde45797b5f6417 (diff)
Merge branch 'master' of https://github.com/MediaBrowser/Emby
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Channels/Channel.cs15
-rw-r--r--MediaBrowser.Controller/Channels/ChannelAudioItem.cs2
-rw-r--r--MediaBrowser.Controller/Channels/ChannelFolderItem.cs2
-rw-r--r--MediaBrowser.Controller/Channels/ChannelVideoItem.cs18
-rw-r--r--MediaBrowser.Controller/Channels/IChannelManager.cs4
-rw-r--r--MediaBrowser.Controller/Dto/DtoOptions.cs1
-rw-r--r--MediaBrowser.Controller/Entities/Audio/Audio.cs61
-rw-r--r--MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs12
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs23
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs157
-rw-r--r--MediaBrowser.Controller/Entities/Book.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs576
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs27
-rw-r--r--MediaBrowser.Controller/Entities/Movies/Movie.cs20
-rw-r--r--MediaBrowser.Controller/Entities/SourceType.cs10
-rw-r--r--MediaBrowser.Controller/Entities/Trailer.cs79
-rw-r--r--MediaBrowser.Controller/Entities/UserRootFolder.cs9
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs146
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs60
-rw-r--r--MediaBrowser.Controller/IServerApplicationHost.cs7
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs21
-rw-r--r--MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs3
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvItem.cs10
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs40
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs4
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs14
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvChannel.cs15
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvProgram.cs12
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs14
-rw-r--r--MediaBrowser.Controller/LiveTv/RecordingGroup.cs10
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj13
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs3
-rw-r--r--MediaBrowser.Controller/Persistence/IItemRepository.cs23
-rw-r--r--MediaBrowser.Controller/Providers/ChannelItemLookupInfo.cs11
-rw-r--r--MediaBrowser.Controller/Providers/TrailerInfo.cs2
-rw-r--r--MediaBrowser.Controller/Sorting/SortHelper.cs31
-rw-r--r--MediaBrowser.Controller/packages.config2
37 files changed, 1160 insertions, 299 deletions
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index 839b7d68f..43f7b6637 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Querying;
using System;
using System.Linq;
+using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
@@ -30,6 +31,13 @@ namespace MediaBrowser.Controller.Channels
return base.IsVisible(user);
}
+ [IgnoreDataMember]
+ public override SourceType SourceType
+ {
+ get { return SourceType.Channel; }
+ set { }
+ }
+
public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
{
try
@@ -75,5 +83,12 @@ namespace MediaBrowser.Controller.Channels
{
return false;
}
+
+ internal static bool IsChannelVisible(BaseItem channelItem, User user)
+ {
+ var channel = ChannelManager.GetChannel(channelItem.ChannelId);
+
+ return channel.IsVisible(user);
+ }
}
}
diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
index 17dcf138b..bcb2dc234 100644
--- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
@@ -12,7 +12,7 @@ using System.Threading;
namespace MediaBrowser.Controller.Channels
{
- public class ChannelAudioItem : Audio, IChannelMediaItem
+ public class ChannelAudioItem : Audio
{
public ChannelMediaContentType ContentType { get; set; }
diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
index f662020bb..174cd282a 100644
--- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
@@ -11,7 +11,7 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Channels
{
- public class ChannelFolderItem : Folder, IChannelItem
+ public class ChannelFolderItem : Folder
{
public ChannelFolderType ChannelFolderType { get; set; }
diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
index 79ad4b36b..e12a84ba2 100644
--- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
@@ -13,7 +13,7 @@ using System.Threading;
namespace MediaBrowser.Controller.Channels
{
- public class ChannelVideoItem : Video, IChannelMediaItem, IHasLookupInfo<ChannelItemLookupInfo>
+ public class ChannelVideoItem : Video
{
public ChannelMediaContentType ContentType { get; set; }
@@ -103,20 +103,6 @@ namespace MediaBrowser.Controller.Channels
return list;
}
- public ChannelItemLookupInfo GetLookupInfo()
- {
- var info = GetItemLookupInfo<ChannelItemLookupInfo>();
-
- info.ContentType = ContentType;
-
- if (ExtraType.HasValue)
- {
- info.ExtraType = ExtraType.Value;
- }
-
- return info;
- }
-
protected override string GetInternalMetadataPath(string basePath)
{
return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
@@ -132,7 +118,7 @@ namespace MediaBrowser.Controller.Channels
return IsVisibleStandaloneInternal(user, false) && IsChannelVisible(this, user);
}
- internal static bool IsChannelVisible(IChannelItem item, User user)
+ internal static bool IsChannelVisible(BaseItem item, User user)
{
var channel = ChannelManager.GetChannel(item.ChannelId);
diff --git a/MediaBrowser.Controller/Channels/IChannelManager.cs b/MediaBrowser.Controller/Channels/IChannelManager.cs
index fec550df8..e3d2d0440 100644
--- a/MediaBrowser.Controller/Channels/IChannelManager.cs
+++ b/MediaBrowser.Controller/Channels/IChannelManager.cs
@@ -116,7 +116,7 @@ namespace MediaBrowser.Controller.Channels
/// <param name="includeCachedVersions">if set to <c>true</c> [include cached versions].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
- Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(IChannelMediaItem item, bool includeCachedVersions, CancellationToken cancellationToken);
+ Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(BaseItem item, bool includeCachedVersions, CancellationToken cancellationToken);
/// <summary>
/// Gets the channel folder.
@@ -141,6 +141,6 @@ namespace MediaBrowser.Controller.Channels
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task DownloadChannelItem(IChannelMediaItem item, string destinationPath, IProgress<double> progress, CancellationToken cancellationToken);
+ Task DownloadChannelItem(BaseItem item, string destinationPath, IProgress<double> progress, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Dto/DtoOptions.cs b/MediaBrowser.Controller/Dto/DtoOptions.cs
index a8d1b1862..d627cc67a 100644
--- a/MediaBrowser.Controller/Dto/DtoOptions.cs
+++ b/MediaBrowser.Controller/Dto/DtoOptions.cs
@@ -17,6 +17,7 @@ namespace MediaBrowser.Controller.Dto
public List<ImageType> ImageTypes { get; set; }
public int ImageTypeLimit { get; set; }
public bool EnableImages { get; set; }
+ public bool AddProgramRecordingInfo { get; set; }
public string DeviceId { get; set; }
public DtoOptions()
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 766f1e5ed..4c66a6562 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -8,6 +8,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using System.Threading;
+using MediaBrowser.Controller.Channels;
namespace MediaBrowser.Controller.Entities.Audio
{
@@ -24,6 +26,8 @@ namespace MediaBrowser.Controller.Entities.Audio
IThemeMedia,
IArchivable
{
+ public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
+
public long? Size { get; set; }
public string Container { get; set; }
public int? TotalBitrate { get; set; }
@@ -153,6 +157,31 @@ namespace MediaBrowser.Controller.Entities.Audio
/// <returns>System.String.</returns>
protected override string CreateUserDataKey()
{
+ if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
+ {
+ var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty;
+
+
+ if (ParentIndexNumber.HasValue)
+ {
+ songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey;
+ }
+ songKey+= Name;
+
+ if (!string.IsNullOrWhiteSpace(Album))
+ {
+ songKey = Album + "-" + songKey;
+ }
+
+ var albumArtist = AlbumArtists.FirstOrDefault();
+ if (!string.IsNullOrWhiteSpace(albumArtist))
+ {
+ songKey = albumArtist + "-" + songKey;
+ }
+
+ return songKey;
+ }
+
var parent = AlbumEntity;
if (parent != null)
@@ -173,7 +202,11 @@ namespace MediaBrowser.Controller.Entities.Audio
public override UnratedItem GetBlockUnratedType()
{
- return UnratedItem.Music;
+ if (SourceType == SourceType.Library)
+ {
+ return UnratedItem.Music;
+ }
+ return base.GetBlockUnratedType();
}
public SongInfo GetLookupInfo()
@@ -189,6 +222,32 @@ namespace MediaBrowser.Controller.Entities.Audio
public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
{
+ if (SourceType == SourceType.Channel)
+ {
+ var sources = ChannelManager.GetStaticMediaSources(this, false, CancellationToken.None)
+ .Result.ToList();
+
+ if (sources.Count > 0)
+ {
+ return sources;
+ }
+
+ var list = new List<MediaSourceInfo>
+ {
+ GetVersionInfo(this, enablePathSubstitution)
+ };
+
+ foreach (var mediaSource in list)
+ {
+ if (string.IsNullOrWhiteSpace(mediaSource.Path))
+ {
+ mediaSource.Type = MediaSourceType.Placeholder;
+ }
+ }
+
+ return list;
+ }
+
var result = new List<MediaSourceInfo>
{
GetVersionInfo(this, enablePathSubstitution)
diff --git a/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs b/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs
new file mode 100644
index 000000000..983cc0100
--- /dev/null
+++ b/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Entities.Audio
+{
+ public class AudioPodcast : Audio
+ {
+ }
+}
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index c5ce6a2f7..e6178c183 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -34,7 +34,17 @@ namespace MediaBrowser.Controller.Entities.Audio
{
get
{
- return GetParents().OfType<MusicArtist>().FirstOrDefault();
+ var artist = GetParents().OfType<MusicArtist>().FirstOrDefault();
+
+ if (artist == null)
+ {
+ var name = AlbumArtist;
+ if (!string.IsNullOrWhiteSpace(name))
+ {
+ artist = LibraryManager.GetArtist(name);
+ }
+ }
+ return artist;
}
}
@@ -106,6 +116,15 @@ namespace MediaBrowser.Controller.Entities.Audio
return "MusicAlbum-Musicbrainz-" + id;
}
+ if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
+ {
+ var albumArtist = AlbumArtist;
+ if (!string.IsNullOrWhiteSpace(albumArtist))
+ {
+ return albumArtist + "-" + Name;
+ }
+ }
+
return base.CreateUserDataKey();
}
@@ -125,7 +144,7 @@ namespace MediaBrowser.Controller.Entities.Audio
id.AlbumArtists = AlbumArtists;
- var artist = GetParents().OfType<MusicArtist>().FirstOrDefault();
+ var artist = MusicArtist;
if (artist != null)
{
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 3dfbdec56..4117b7521 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -20,9 +20,11 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Controller.Entities
@@ -57,7 +59,9 @@ namespace MediaBrowser.Controller.Entities
public static string ThemeSongFilename = "theme";
public static string ThemeVideosFolderName = "backdrops";
+ [IgnoreDataMember]
public string PreferredMetadataCountryCode { get; set; }
+ [IgnoreDataMember]
public string PreferredMetadataLanguage { get; set; }
public List<ItemImageInfo> ImageInfos { get; set; }
@@ -88,6 +92,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets a value indicating whether this instance is in mixed folder.
/// </summary>
/// <value><c>true</c> if this instance is in mixed folder; otherwise, <c>false</c>.</value>
+ [IgnoreDataMember]
public bool IsInMixedFolder { get; set; }
[IgnoreDataMember]
@@ -166,6 +171,9 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public bool IsOffline { get; set; }
+ [IgnoreDataMember]
+ public virtual SourceType SourceType { get; set; }
+
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
@@ -185,6 +193,13 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
+ /// Gets or sets the name of the service.
+ /// </summary>
+ /// <value>The name of the service.</value>
+ [IgnoreDataMember]
+ public string ServiceName { get; set; }
+
+ /// <summary>
/// If this content came from an external service, the id of the content on that service
/// </summary>
[IgnoreDataMember]
@@ -252,6 +267,11 @@ namespace MediaBrowser.Controller.Entities
{
get
{
+ if (SourceType == SourceType.Channel)
+ {
+ return false;
+ }
+
var locationType = LocationType;
return locationType != LocationType.Remote && locationType != LocationType.Virtual;
@@ -281,6 +301,40 @@ namespace MediaBrowser.Controller.Entities
}
}
+ private List<Tuple<StringBuilder,bool>> GetSortChunks(string s1)
+ {
+ var list = new List<Tuple<StringBuilder, bool>>();
+
+ int thisMarker = 0, thisNumericChunk = 0;
+
+ while ((thisMarker < s1.Length))
+ {
+ if (thisMarker >= s1.Length)
+ {
+ break;
+ }
+ char thisCh = s1[thisMarker];
+
+ StringBuilder thisChunk = new StringBuilder();
+
+ while ((thisMarker < s1.Length) && (thisChunk.Length == 0 || SortHelper.InChunk(thisCh, thisChunk[0])))
+ {
+ thisChunk.Append(thisCh);
+ thisMarker++;
+
+ if (thisMarker < s1.Length)
+ {
+ thisCh = s1[thisMarker];
+ }
+ }
+
+ var isNumeric = thisChunk.Length > 0 && char.IsDigit(thisChunk[0]);
+ list.Add(new Tuple<StringBuilder, bool>(thisChunk, isNumeric));
+ }
+
+ return list;
+ }
+
/// <summary>
/// This is just a helper for convenience
/// </summary>
@@ -298,6 +352,11 @@ namespace MediaBrowser.Controller.Entities
public virtual bool CanDelete()
{
+ if (SourceType == SourceType.Channel)
+ {
+ return false;
+ }
+
var locationType = LocationType;
return locationType != LocationType.Remote &&
locationType != LocationType.Virtual;
@@ -342,6 +401,7 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public DateTime DateModified { get; set; }
+ [IgnoreDataMember]
public DateTime DateLastSaved { get; set; }
[IgnoreDataMember]
@@ -380,6 +440,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the locked fields.
/// </summary>
/// <value>The locked fields.</value>
+ [IgnoreDataMember]
public List<MetadataFields> LockedFields { get; set; }
/// <summary>
@@ -433,11 +494,6 @@ namespace MediaBrowser.Controller.Entities
{
get
{
- if (!string.IsNullOrWhiteSpace(ForcedSortName))
- {
- return ForcedSortName;
- }
-
return _sortName ?? (_sortName = CreateSortName());
}
set
@@ -455,6 +511,11 @@ namespace MediaBrowser.Controller.Entities
protected virtual string GetInternalMetadataPath(string basePath)
{
+ if (SourceType == SourceType.Channel)
+ {
+ return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
+ }
+
var idString = Id.ToString("N");
basePath = System.IO.Path.Combine(basePath, "library");
@@ -468,6 +529,11 @@ namespace MediaBrowser.Controller.Entities
/// <returns>System.String.</returns>
protected virtual string CreateSortName()
{
+ if (!string.IsNullOrWhiteSpace(ForcedSortName))
+ {
+ return ModifySortChunks(ForcedSortName).ToLower();
+ }
+
if (Name == null) return null; //some items may not have name filled in properly
if (!EnableAlphaNumericSorting)
@@ -497,7 +563,32 @@ namespace MediaBrowser.Controller.Entities
sortable = sortable.Remove(sortable.Length - (searchLower.Length + 1));
}
}
- return sortable;
+ return ModifySortChunks(sortable);
+ }
+
+ private string ModifySortChunks(string name)
+ {
+ var chunks = GetSortChunks(name);
+
+ var builder = new StringBuilder();
+
+ foreach (var chunk in chunks)
+ {
+ var chunkBuilder = chunk.Item1;
+
+ // This chunk is numeric
+ if (chunk.Item2)
+ {
+ while (chunkBuilder.Length < 10)
+ {
+ chunkBuilder.Insert(0, '0');
+ }
+ }
+
+ builder.Append(chunkBuilder);
+ }
+ //Logger.Debug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString());
+ return builder.ToString();
}
[IgnoreDataMember]
@@ -596,6 +687,18 @@ namespace MediaBrowser.Controller.Entities
public string OfficialRating { get; set; }
/// <summary>
+ /// Gets or sets the critic rating.
+ /// </summary>
+ /// <value>The critic rating.</value>
+ public float? CriticRating { get; set; }
+
+ /// <summary>
+ /// Gets or sets the critic rating summary.
+ /// </summary>
+ /// <value>The critic rating summary.</value>
+ public string CriticRatingSummary { get; set; }
+
+ /// <summary>
/// Gets or sets the official rating description.
/// </summary>
/// <value>The official rating description.</value>
@@ -620,6 +723,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the studios.
/// </summary>
/// <value>The studios.</value>
+ [IgnoreDataMember]
public List<string> Studios { get; set; }
/// <summary>
@@ -633,6 +737,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
+ [IgnoreDataMember]
public List<string> Tags { get; set; }
/// <summary>
@@ -1025,6 +1130,13 @@ namespace MediaBrowser.Controller.Entities
protected virtual string CreateUserDataKey()
{
+ if (SourceType == SourceType.Channel)
+ {
+ if (!string.IsNullOrWhiteSpace(ExternalId))
+ {
+ return ExternalId;
+ }
+ }
return Id.ToString();
}
@@ -1103,6 +1215,11 @@ namespace MediaBrowser.Controller.Entities
public virtual bool IsSaveLocalMetadataEnabled()
{
+ if (SourceType == SourceType.Channel)
+ {
+ return false;
+ }
+
return ConfigurationManager.Configuration.SaveLocalMeta;
}
@@ -1218,6 +1335,11 @@ namespace MediaBrowser.Controller.Entities
public virtual UnratedItem GetBlockUnratedType()
{
+ if (SourceType == SourceType.Channel)
+ {
+ return UnratedItem.ChannelContent;
+ }
+
return UnratedItem.Other;
}
@@ -1261,6 +1383,11 @@ namespace MediaBrowser.Controller.Entities
public virtual bool IsVisibleStandalone(User user)
{
+ if (SourceType == SourceType.Channel)
+ {
+ return IsVisibleStandaloneInternal(user, false) && Channel.IsChannelVisible(this, user);
+ }
+
return IsVisibleStandaloneInternal(user, true);
}
@@ -1312,6 +1439,11 @@ namespace MediaBrowser.Controller.Entities
public virtual string GetClientTypeName()
{
+ if (IsFolder && SourceType == SourceType.Channel)
+ {
+ return "ChannelFolderItem";
+ }
+
return GetType().Name;
}
@@ -1835,8 +1967,8 @@ namespace MediaBrowser.Controller.Entities
ProviderIds = ProviderIds,
IndexNumber = IndexNumber,
ParentIndexNumber = ParentIndexNumber,
- Year = ProductionYear,
- PremiereDate = PremiereDate
+ Year = ProductionYear,
+ PremiereDate = PremiereDate
};
}
@@ -1985,5 +2117,14 @@ namespace MediaBrowser.Controller.Entities
{
return LibraryManager.DeleteItem(this, options);
}
+
+ public virtual Task OnFileDeleted()
+ {
+ // Remove from database
+ return Delete(new DeleteOptions
+ {
+ DeleteFileLocation = false
+ });
+ }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs
index f006fedd2..5ef098ff8 100644
--- a/MediaBrowser.Controller/Entities/Book.cs
+++ b/MediaBrowser.Controller/Entities/Book.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Model.Configuration;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.Serialization;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
@@ -9,6 +10,7 @@ namespace MediaBrowser.Controller.Entities
{
public class Book : BaseItem, IHasTags, IHasLookupInfo<BookInfo>, IHasSeries
{
+ [IgnoreDataMember]
public override string MediaType
{
get
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 824a067ad..bec8cd28b 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -15,6 +15,9 @@ using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Playlists;
+using MediaBrowser.Model.Channels;
namespace MediaBrowser.Controller.Entities
{
@@ -145,60 +148,38 @@ namespace MediaBrowser.Controller.Entities
item.DateModified = DateTime.UtcNow;
}
- AddChildInternal(item);
+ AddChildInternal(item.Id);
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
-
- if (!EnableNewFolderQuerying())
- {
- await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
- }
- }
-
- private static bool EnableNewFolderQuerying()
- {
- return ConfigurationManager.Configuration.MigrationVersion >= 1;
}
- protected void AddChildrenInternal(IEnumerable<BaseItem> children)
+ protected void AddChildrenInternal(List<Guid> children)
{
- var actualChildren = ActualChildren;
-
lock (_childrenSyncLock)
{
- var newChildren = actualChildren.ToList();
+ var newChildren = ChildIds.ToList();
newChildren.AddRange(children);
- _children = newChildren;
+ _children = newChildren.ToList();
}
}
- protected void AddChildInternal(BaseItem child)
+ protected void AddChildInternal(Guid child)
{
- var actualChildren = ActualChildren;
-
lock (_childrenSyncLock)
{
- var newChildren = actualChildren.ToList();
- newChildren.Add(child);
- _children = newChildren;
- }
- }
-
- protected void RemoveChildrenInternal(IEnumerable<BaseItem> children)
- {
- var ids = children.Select(i => i.Id).ToList();
- var actualChildren = ActualChildren;
-
- lock (_childrenSyncLock)
- {
- _children = actualChildren.Where(i => !ids.Contains(i.Id)).ToList();
+ var childIds = ChildIds.ToList();
+ if (!childIds.Contains(child))
+ {
+ childIds.Add(child);
+ _children = childIds.ToList();
+ }
}
}
- protected void ClearChildrenInternal()
+ protected void RemoveChildrenInternal(List<Guid> children)
{
lock (_childrenSyncLock)
{
- _children = new List<BaseItem>();
+ _children = ChildIds.Except(children).ToList();
}
}
@@ -206,40 +187,11 @@ namespace MediaBrowser.Controller.Entities
/// Removes the child.
/// </summary>
/// <param name="item">The item.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.InvalidOperationException">Unable to remove + item.Name</exception>
- public Task RemoveChild(BaseItem item, CancellationToken cancellationToken)
+ public void RemoveChild(BaseItem item)
{
- RemoveChildrenInternal(new[] { item });
+ RemoveChildrenInternal(new[] { item.Id }.ToList());
item.SetParent(null);
-
- if (!EnableNewFolderQuerying())
- {
- return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
- }
-
- return Task.FromResult(true);
- }
-
- /// <summary>
- /// Clears the children.
- /// </summary>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- public Task ClearChildren(CancellationToken cancellationToken)
- {
- var items = ActualChildren.ToList();
-
- ClearChildrenInternal();
-
- foreach (var item in items)
- {
- LibraryManager.ReportItemRemoved(item);
- }
-
- return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
}
#region Indexing
@@ -276,7 +228,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// The children
/// </summary>
- private IReadOnlyList<BaseItem> _children;
+ private IReadOnlyList<Guid> _children;
/// <summary>
/// The _children sync lock
/// </summary>
@@ -285,21 +237,30 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the actual children.
/// </summary>
/// <value>The actual children.</value>
- protected virtual IEnumerable<BaseItem> ActualChildren
+ protected virtual IEnumerable<Guid> ChildIds
{
get
{
- if (_children == null)
+ lock (_childrenSyncLock)
{
- lock (_childrenSyncLock)
+ if (_children == null)
{
- if (_children == null)
- {
- _children = LoadChildren().ToList();
- }
+ _children = LoadChildren().ToList();
}
+ return _children.ToList();
}
- return _children;
+ }
+ }
+
+ /// <summary>
+ /// Gets the actual children.
+ /// </summary>
+ /// <value>The actual children.</value>
+ protected virtual IEnumerable<BaseItem> ActualChildren
+ {
+ get
+ {
+ return ChildIds.Select(LibraryManager.GetItemById).Where(i => i != null);
}
}
@@ -353,7 +314,7 @@ namespace MediaBrowser.Controller.Entities
/// Loads our children. Validation will occur externally.
/// We want this sychronous.
/// </summary>
- protected virtual IEnumerable<BaseItem> LoadChildren()
+ protected virtual IEnumerable<Guid> LoadChildren()
{
//just load our children from the repo - the library will be validated and maintained in other processes
return GetCachedChildren();
@@ -503,7 +464,7 @@ namespace MediaBrowser.Controller.Entities
if (actualRemovals.Count > 0)
{
- RemoveChildrenInternal(actualRemovals);
+ RemoveChildrenInternal(actualRemovals.Select(i => i.Id).ToList());
foreach (var item in actualRemovals)
{
@@ -518,12 +479,7 @@ namespace MediaBrowser.Controller.Entities
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
- AddChildrenInternal(newItems);
-
- if (!EnableNewFolderQuerying())
- {
- await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
- }
+ AddChildrenInternal(newItems.Select(i => i.Id).ToList());
}
}
@@ -751,51 +707,459 @@ namespace MediaBrowser.Controller.Entities
/// Get our children from the repo - stubbed for now
/// </summary>
/// <returns>IEnumerable{BaseItem}.</returns>
- protected IEnumerable<BaseItem> GetCachedChildren()
+ protected IEnumerable<Guid> GetCachedChildren()
{
- if (EnableNewFolderQuerying())
+ return ItemRepository.GetItemIdsList(new InternalItemsQuery
{
- return ItemRepository.GetItemList(new InternalItemsQuery
+ ParentId = Id
+
+ });
+ }
+
+ public QueryResult<BaseItem> QueryRecursive(InternalItemsQuery query)
+ {
+ var user = query.User;
+
+ if (RequiresPostFiltering(query))
+ {
+ IEnumerable<BaseItem> items;
+ Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
+
+ if (query.User == null)
{
- ParentId = Id
+ items = GetRecursiveChildren(filter);
+ }
+ else
+ {
+ items = GetRecursiveChildren(user, filter);
+ }
+
+ return PostFilterAndSort(items, query);
+ }
- }).Select(RetrieveChild).Where(i => i != null);
+ if (!(this is UserRootFolder) && !(this is AggregateFolder))
+ {
+ query.ParentId = query.ParentId ?? Id;
}
- return ItemRepository.GetChildrenItems(Id).Select(RetrieveChild).Where(i => i != null);
+ return LibraryManager.GetItemsResult(query);
}
- private BaseItem RetrieveChild(BaseItem child)
+ private bool RequiresPostFiltering(InternalItemsQuery query)
{
- if (child == null || child.Id == Guid.Empty)
+ if (LinkedChildren.Count > 0)
{
- Logger.Error("Item found with empty Id: " + (child.Path ?? child.Name));
- return null;
+ if (!(this is ICollectionFolder))
+ {
+ Logger.Debug("Query requires post-filtering due to LinkedChildren");
+ return true;
+ }
}
- var item = LibraryManager.GetMemoryItemById(child.Id);
-
- if (item != null)
+ if (query.SortBy != null && query.SortBy.Length > 0)
{
- if (item is IByReferenceItem)
+ if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.DatePlayed");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase))
{
- return LibraryManager.GetOrAddByReferenceItem(item);
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
+ return true;
}
+ if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.IsPlayed");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.IsUnplayed");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.Album, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.Album");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.Artist, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.Budget, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.Budget");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.DateLastContentAdded, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.DateLastContentAdded");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.GameSystem, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.GameSystem");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.Metascore, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.Metascore");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.OfficialRating, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.OfficialRating");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.PlayCount");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.Players");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.Revenue, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.Revenue");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.SeriesSortName, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.StartDate, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.StartDate");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.Studio, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.Studio");
+ return true;
+ }
+ if (query.SortBy.Contains(ItemSortBy.VideoBitRate, StringComparer.OrdinalIgnoreCase))
+ {
+ Logger.Debug("Query requires post-filtering due to ItemSortBy.VideoBitRate");
+ return true;
+ }
+ }
- item.SetParent(this);
+ if (query.ItemIds.Length > 0)
+ {
+ Logger.Debug("Query requires post-filtering due to ItemIds");
+ return true;
}
- else
+
+ if (query.PersonIds.Length > 0)
+ {
+ Logger.Debug("Query requires post-filtering due to PersonIds");
+ return true;
+ }
+
+ if (query.IsLiked.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to IsLiked");
+ return true;
+ }
+
+ if (query.IsFavoriteOrLiked.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to IsFavoriteOrLiked");
+ return true;
+ }
+
+ if (query.IsFavorite.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to IsFavorite");
+ return true;
+ }
+
+ if (query.IsResumable.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to IsResumable");
+ return true;
+ }
+
+ if (query.IsPlayed.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to IsPlayed");
+ return true;
+ }
+
+ if (query.IsInBoxSet.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to IsInBoxSet");
+ return true;
+ }
+
+ // Filter by Video3DFormat
+ if (query.Is3D.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to Is3D");
+ return true;
+ }
+
+ if (query.HasImdbId.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to HasImdbId");
+ return true;
+ }
+
+ if (query.HasTmdbId.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to HasTmdbId");
+ return true;
+ }
+
+ if (query.HasTvdbId.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to HasTvdbId");
+ return true;
+ }
+
+ if (query.IsYearMismatched.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to IsYearMismatched");
+ return true;
+ }
+
+ if (query.HasOfficialRating.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to HasOfficialRating");
+ return true;
+ }
+
+ if (query.IsPlaceHolder.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to IsPlaceHolder");
+ return true;
+ }
+
+ if (query.HasSpecialFeature.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to HasSpecialFeature");
+ return true;
+ }
+
+ if (query.HasSubtitles.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to HasSubtitles");
+ return true;
+ }
+
+ if (query.HasTrailer.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to HasTrailer");
+ return true;
+ }
+
+ if (query.HasThemeSong.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to HasThemeSong");
+ return true;
+ }
+
+ if (query.HasThemeVideo.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to HasThemeVideo");
+ return true;
+ }
+
+ // Filter by VideoType
+ if (query.VideoTypes.Length > 0)
+ {
+ Logger.Debug("Query requires post-filtering due to VideoTypes");
+ return true;
+ }
+
+ if (query.ImageTypes.Length > 0)
{
- child.SetParent(this);
- LibraryManager.RegisterItem(child);
- item = child;
+ Logger.Debug("Query requires post-filtering due to ImageTypes");
+ return true;
+ }
+
+ // Apply studio filter
+ if (query.StudioIds.Length > 0)
+ {
+ Logger.Debug("Query requires post-filtering due to StudioIds");
+ return true;
+ }
+
+ // Apply genre filter
+ if (query.GenreIds.Length > 0)
+ {
+ Logger.Debug("Query requires post-filtering due to GenreIds");
+ return true;
}
- return item;
+ // Apply person filter
+ if (query.ItemIdsFromPersonFilters != null)
+ {
+ Logger.Debug("Query requires post-filtering due to ItemIdsFromPersonFilters");
+ return true;
+ }
+
+ if (query.MinPlayers.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to MinPlayers");
+ return true;
+ }
+
+ if (query.MaxPlayers.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to MaxPlayers");
+ return true;
+ }
+
+ if (query.OfficialRatings.Length > 0)
+ {
+ Logger.Debug("Query requires post-filtering due to OfficialRatings");
+ return true;
+ }
+
+ if (query.IsMissing.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to IsMissing");
+ return true;
+ }
+
+ if (query.IsUnaired.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to IsUnaired");
+ return true;
+ }
+
+ if (query.IsVirtualUnaired.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to IsVirtualUnaired");
+ return true;
+ }
+
+ if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User))
+ {
+ Logger.Debug("Query requires post-filtering due to CollapseBoxSetItems");
+ return true;
+ }
+
+ if (!string.IsNullOrWhiteSpace(query.AdjacentTo))
+ {
+ Logger.Debug("Query requires post-filtering due to AdjacentTo");
+ return true;
+ }
+
+ if (!string.IsNullOrWhiteSpace(query.NameContains))
+ {
+ Logger.Debug("Query requires post-filtering due to NameContains");
+ return true;
+ }
+
+ if (!string.IsNullOrWhiteSpace(query.NameLessThan))
+ {
+ Logger.Debug("Query requires post-filtering due to NameLessThan");
+ return true;
+ }
+
+ if (!string.IsNullOrWhiteSpace(query.NameStartsWith))
+ {
+ Logger.Debug("Query requires post-filtering due to NameStartsWith");
+ return true;
+ }
+
+ if (!string.IsNullOrWhiteSpace(query.NameStartsWithOrGreater))
+ {
+ Logger.Debug("Query requires post-filtering due to NameStartsWithOrGreater");
+ return true;
+ }
+
+ if (query.AirDays.Length > 0)
+ {
+ Logger.Debug("Query requires post-filtering due to AirDays");
+ return true;
+ }
+
+ if (query.SeriesStatuses.Length > 0)
+ {
+ Logger.Debug("Query requires post-filtering due to SeriesStatuses");
+ return true;
+ }
+
+ if (query.AiredDuringSeason.HasValue)
+ {
+ Logger.Debug("Query requires post-filtering due to AiredDuringSeason");
+ return true;
+ }
+
+ if (!string.IsNullOrWhiteSpace(query.AlbumArtistStartsWithOrGreater))
+ {
+ Logger.Debug("Query requires post-filtering due to AlbumArtistStartsWithOrGreater");
+ return true;
+ }
+
+ if (query.AlbumNames.Length > 0)
+ {
+ Logger.Debug("Query requires post-filtering due to AlbumNames");
+ return true;
+ }
+
+ if (query.ArtistNames.Length > 0)
+ {
+ Logger.Debug("Query requires post-filtering due to ArtistNames");
+ return true;
+ }
+
+ return false;
}
- public virtual Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
+ public virtual async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
{
+ if (SourceType == SourceType.Channel)
+ {
+ try
+ {
+ // Don't blow up here because it could cause parent screens with other content to fail
+ return await ChannelManager.GetChannelItemsInternal(new ChannelItemQuery
+ {
+ ChannelId = ChannelId,
+ FolderId = Id.ToString("N"),
+ Limit = query.Limit,
+ StartIndex = query.StartIndex,
+ UserId = query.User.Id.ToString("N"),
+ SortBy = query.SortBy,
+ SortOrder = query.SortOrder
+
+ }, new Progress<double>(), CancellationToken.None);
+ }
+ catch
+ {
+ // Already logged at lower levels
+ return new QueryResult<BaseItem>
+ {
+
+ };
+ }
+ }
+
+ if (query.Recursive)
+ {
+ return QueryRecursive(query);
+ }
+
var user = query.User;
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
@@ -817,7 +1181,7 @@ namespace MediaBrowser.Controller.Entities
var result = PostFilterAndSort(items, query);
- return Task.FromResult(result);
+ return result;
}
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index 8b623d64e..b568aec18 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -83,6 +83,7 @@ namespace MediaBrowser.Controller.Entities
public string[] OfficialRatings { get; set; }
public DateTime? MinPremiereDate { get; set; }
+ public DateTime? MaxPremiereDate { get; set; }
public DateTime? MinStartDate { get; set; }
public DateTime? MaxStartDate { get; set; }
public DateTime? MinEndDate { get; set; }
@@ -96,28 +97,45 @@ namespace MediaBrowser.Controller.Entities
public int? MinPlayers { get; set; }
public int? MaxPlayers { get; set; }
public int? MinIndexNumber { get; set; }
+ public int? AiredDuringSeason { get; set; }
public double? MinCriticRating { get; set; }
public double? MinCommunityRating { get; set; }
public string[] ChannelIds { get; set; }
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
+ public int? ParentIndexNumber { get; set; }
+ public int? MinParentalRating { get; set; }
public int? MaxParentalRating { get; set; }
public bool? IsCurrentSchema { get; set; }
public bool? HasDeadParentId { get; set; }
public bool? IsOffline { get; set; }
- public LocationType? LocationType { get; set; }
public Guid? ParentId { get; set; }
public string[] AncestorIds { get; set; }
public string[] TopParentIds { get; set; }
+ public LocationType[] LocationTypes { get; set; }
public LocationType[] ExcludeLocationTypes { get; set; }
public string[] PresetViews { get; set; }
+ public SourceType[] SourceTypes { get; set; }
+ public SourceType[] ExcludeSourceTypes { get; set; }
+ public TrailerType[] TrailerTypes { get; set; }
+ public TrailerType[] ExcludeTrailerTypes { get; set; }
+ public DayOfWeek[] AirDays { get; set; }
+ public SeriesStatus[] SeriesStatuses { get; set; }
+ public string AlbumArtistStartsWithOrGreater { get; set; }
+
+ public string[] AlbumNames { get; set; }
+ public string[] ArtistNames { get; set; }
+
public InternalItemsQuery()
{
+ AlbumNames = new string[] { };
+ ArtistNames = new string[] { };
+
BlockUnratedItems = new UnratedItem[] { };
Tags = new string[] { };
OfficialRatings = new string[] { };
@@ -139,8 +157,15 @@ namespace MediaBrowser.Controller.Entities
AncestorIds = new string[] { };
TopParentIds = new string[] { };
ExcludeTags = new string[] { };
+ LocationTypes = new LocationType[] { };
ExcludeLocationTypes = new LocationType[] { };
PresetViews = new string[] { };
+ SourceTypes = new SourceType[] { };
+ ExcludeSourceTypes = new SourceType[] { };
+ TrailerTypes = new TrailerType[] { };
+ ExcludeTrailerTypes = new TrailerType[] { };
+ AirDays = new DayOfWeek[] { };
+ SeriesStatuses = new SeriesStatus[] { };
}
public InternalItemsQuery(User user)
diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs
index 749d562ac..4c31356d0 100644
--- a/MediaBrowser.Controller/Entities/Movies/Movie.cs
+++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs
@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
@@ -68,23 +69,18 @@ namespace MediaBrowser.Controller.Entities.Movies
public double? Revenue { get; set; }
/// <summary>
- /// Gets or sets the critic rating.
- /// </summary>
- /// <value>The critic rating.</value>
- public float? CriticRating { get; set; }
-
- /// <summary>
- /// Gets or sets the critic rating summary.
- /// </summary>
- /// <value>The critic rating summary.</value>
- public string CriticRatingSummary { get; set; }
-
- /// <summary>
/// Gets or sets the name of the TMDB collection.
/// </summary>
/// <value>The name of the TMDB collection.</value>
public string TmdbCollectionName { get; set; }
+ [IgnoreDataMember]
+ public string CollectionName
+ {
+ get { return TmdbCollectionName; }
+ set { TmdbCollectionName = value; }
+ }
+
/// <summary>
/// Gets the trailer ids.
/// </summary>
diff --git a/MediaBrowser.Controller/Entities/SourceType.cs b/MediaBrowser.Controller/Entities/SourceType.cs
new file mode 100644
index 000000000..9c307b4e6
--- /dev/null
+++ b/MediaBrowser.Controller/Entities/SourceType.cs
@@ -0,0 +1,10 @@
+
+namespace MediaBrowser.Controller.Entities
+{
+ public enum SourceType
+ {
+ Library = 0,
+ Channel = 1,
+ LiveTV = 2
+ }
+}
diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs
index 3c7d39e0d..9d5ef2035 100644
--- a/MediaBrowser.Controller/Entities/Trailer.cs
+++ b/MediaBrowser.Controller/Entities/Trailer.cs
@@ -14,7 +14,6 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Class Trailer
/// </summary>
- [Obsolete]
public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo<TrailerInfo>
{
public List<string> ProductionLocations { get; set; }
@@ -25,14 +24,23 @@ namespace MediaBrowser.Controller.Entities
Taglines = new List<string>();
Keywords = new List<string>();
ProductionLocations = new List<string>();
+ TrailerTypes = new List<TrailerType>();
}
+ public List<TrailerType> TrailerTypes { get; set; }
+
public float? Metascore { get; set; }
public List<MediaUrl> RemoteTrailers { get; set; }
public List<string> Keywords { get; set; }
+ [IgnoreDataMember]
+ public bool IsLocalTrailer
+ {
+ get { return TrailerTypes.Contains(TrailerType.LocalTrailer); }
+ }
+
/// <summary>
/// Gets or sets the taglines.
/// </summary>
@@ -51,32 +59,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The revenue.</value>
public double? Revenue { get; set; }
- /// <summary>
- /// Gets or sets the critic rating.
- /// </summary>
- /// <value>The critic rating.</value>
- public float? CriticRating { get; set; }
-
- /// <summary>
- /// Gets or sets the critic rating summary.
- /// </summary>
- /// <value>The critic rating summary.</value>
- public string CriticRatingSummary { get; set; }
-
- /// <summary>
- /// Gets a value indicating whether this instance is local trailer.
- /// </summary>
- /// <value><c>true</c> if this instance is local trailer; otherwise, <c>false</c>.</value>
- [IgnoreDataMember]
- public bool IsLocalTrailer
- {
- get
- {
- // Local trailers are not part of children
- return GetParent() == null;
- }
- }
-
protected override string CreateUserDataKey()
{
var key = Movie.GetMovieUserDataKey(this);
@@ -106,9 +88,50 @@ namespace MediaBrowser.Controller.Entities
{
var info = GetItemLookupInfo<TrailerInfo>();
- info.IsLocalTrailer = IsLocalTrailer;
+ info.IsLocalTrailer = TrailerTypes.Contains(TrailerType.LocalTrailer);
+
+ if (!IsInMixedFolder)
+ {
+ info.Name = System.IO.Path.GetFileName(ContainingFolderPath);
+ }
return info;
}
+
+ public override bool BeforeMetadataRefresh()
+ {
+ var hasChanges = base.BeforeMetadataRefresh();
+
+ if (!ProductionYear.HasValue)
+ {
+ var info = LibraryManager.ParseName(Name);
+
+ var yearInName = info.Year;
+
+ if (yearInName.HasValue)
+ {
+ ProductionYear = yearInName;
+ hasChanges = true;
+ }
+ else
+ {
+ // Try to get the year from the folder name
+ if (!IsInMixedFolder)
+ {
+ info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath));
+
+ yearInName = info.Year;
+
+ if (yearInName.HasValue)
+ {
+ ProductionYear = yearInName;
+ hasChanges = true;
+ }
+ }
+ }
+ }
+
+ return hasChanges;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs
index daf590871..104408860 100644
--- a/MediaBrowser.Controller/Entities/UserRootFolder.cs
+++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs
@@ -19,13 +19,9 @@ namespace MediaBrowser.Controller.Entities
{
public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
{
- var user = query.User;
- Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
-
if (query.Recursive)
{
- var items = query.User.RootFolder.GetRecursiveChildren(query.User, filter);
- return PostFilterAndSort(items, query);
+ return QueryRecursive(query);
}
var result = await UserViewManager.GetUserViews(new UserViewQuery
@@ -35,6 +31,9 @@ namespace MediaBrowser.Controller.Entities
}, CancellationToken.None).ConfigureAwait(false);
+ var user = query.User;
+ Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
+
return PostFilterAndSort(result.Where(filter), query);
}
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index 721ec3f1b..a74859a46 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -50,15 +50,15 @@ namespace MediaBrowser.Controller.Entities
{
var user = query.User;
- if (query.IncludeItemTypes != null &&
- query.IncludeItemTypes.Length == 1 &&
- string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase))
- {
- if (!string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
- {
- return await FindPlaylists(queryParent, user, query).ConfigureAwait(false);
- }
- }
+ //if (query.IncludeItemTypes != null &&
+ // query.IncludeItemTypes.Length == 1 &&
+ // string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase))
+ //{
+ // if (!string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
+ // {
+ // return await FindPlaylists(queryParent, user, query).ConfigureAwait(false);
+ // }
+ //}
switch (viewType)
{
@@ -766,7 +766,7 @@ namespace MediaBrowser.Controller.Entities
return items;
}
- private static bool CollapseBoxSetItems(InternalItemsQuery query,
+ public static bool CollapseBoxSetItems(InternalItemsQuery query,
BaseItem queryParent,
User user)
{
@@ -1199,6 +1199,11 @@ namespace MediaBrowser.Controller.Entities
return false;
}
+ if (query.ExcludeLocationTypes.Length > 0 && query.ExcludeLocationTypes.Contains(item.LocationType))
+ {
+ return false;
+ }
+
if (query.IsFolder.HasValue && query.IsFolder.Value != item.IsFolder)
{
return false;
@@ -1689,6 +1694,127 @@ namespace MediaBrowser.Controller.Entities
}
}
+ if (query.MinPremiereDate.HasValue)
+ {
+ var val = query.MinPremiereDate.Value;
+
+ if (!(item.PremiereDate.HasValue && item.PremiereDate.Value >= val))
+ {
+ return false;
+ }
+ }
+
+ if (query.MaxPremiereDate.HasValue)
+ {
+ var val = query.MaxPremiereDate.Value;
+
+ if (!(item.PremiereDate.HasValue && item.PremiereDate.Value <= val))
+ {
+ return false;
+ }
+ }
+
+ if (query.ParentIndexNumber.HasValue)
+ {
+ var filterValue = query.ParentIndexNumber.Value;
+
+ if (item.ParentIndexNumber.HasValue && item.ParentIndexNumber.Value != filterValue)
+ {
+ return false;
+ }
+ }
+
+ if (query.AirDays.Length > 0)
+ {
+ var ok = new[] { item }.OfType<Series>().Any(p => p.AirDays != null && query.AirDays.Any(d => p.AirDays.Contains(d)));
+ if (!ok)
+ {
+ return false;
+ }
+ }
+
+ if (query.SeriesStatuses.Length > 0)
+ {
+ var ok = new[] { item }.OfType<Series>().Any(p => p.Status.HasValue && query.SeriesStatuses.Contains(p.Status.Value));
+ if (!ok)
+ {
+ return false;
+ }
+ }
+
+ if (query.AiredDuringSeason.HasValue)
+ {
+ var episode = item as Episode;
+
+ if (episode == null)
+ {
+ return false;
+ }
+
+ if (!Series.FilterEpisodesBySeason(new[] { episode }, query.AiredDuringSeason.Value, true).Any())
+ {
+ return false;
+ }
+ }
+
+ if (!string.IsNullOrEmpty(query.AlbumArtistStartsWithOrGreater))
+ {
+ var ok = new[] { item }.OfType<IHasAlbumArtist>()
+ .Any(p => string.Compare(query.AlbumArtistStartsWithOrGreater, p.AlbumArtists.FirstOrDefault(), StringComparison.CurrentCultureIgnoreCase) < 1);
+
+ if (!ok)
+ {
+ return false;
+ }
+ }
+
+ // Artists
+ if (query.ArtistNames.Length > 0)
+ {
+ var audio = item as IHasArtist;
+
+ if (!(audio != null && query.ArtistNames.Any(audio.HasAnyArtist)))
+ {
+ return false;
+ }
+ }
+
+ // Albums
+ if (query.AlbumNames.Length > 0)
+ {
+ var audio = item as Audio.Audio;
+
+ if (audio != null)
+ {
+ if (!query.AlbumNames.Any(a => string.Equals(a, audio.Album, StringComparison.OrdinalIgnoreCase)))
+ {
+ return false;
+ }
+ }
+
+ var album = item as MusicAlbum;
+
+ if (album != null)
+ {
+ if (!query.AlbumNames.Any(a => string.Equals(a, album.Name, StringComparison.OrdinalIgnoreCase)))
+ {
+ return false;
+ }
+ }
+
+ var musicVideo = item as MusicVideo;
+
+ if (musicVideo != null)
+ {
+ if (!query.AlbumNames.Any(a => string.Equals(a, musicVideo.Album, StringComparison.OrdinalIgnoreCase)))
+ {
+ return false;
+ }
+ }
+
+ return false;
+ }
+
return true;
}
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index 197222669..3b1da85b5 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -6,13 +6,16 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.MediaInfo;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Linq;
+using System.Net.Mime;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Channels;
namespace MediaBrowser.Controller.Entities
{
@@ -33,6 +36,7 @@ namespace MediaBrowser.Controller.Entities
public List<string> AdditionalParts { get; set; }
public List<string> LocalAlternateVersions { get; set; }
public List<LinkedChild> LinkedAlternateVersions { get; set; }
+ public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
[IgnoreDataMember]
public bool IsThemeMedia
@@ -79,6 +83,23 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
+ public override LocationType LocationType
+ {
+ get
+ {
+ if (SourceType == SourceType.Channel)
+ {
+ if (string.IsNullOrEmpty(Path))
+ {
+ return LocationType.Remote;
+ }
+ }
+
+ return base.LocationType;
+ }
+ }
+
+ [IgnoreDataMember]
public override bool SupportsAddingToPlaylist
{
get { return LocationType == LocationType.FileSystem && RunTimeTicks.HasValue; }
@@ -130,6 +151,29 @@ namespace MediaBrowser.Controller.Entities
return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
}
+ protected override string CreateUserDataKey()
+ {
+ if (ExtraType.HasValue)
+ {
+ var key = this.GetProviderId(MetadataProviders.Imdb) ?? this.GetProviderId(MetadataProviders.Tmdb);
+
+ if (!string.IsNullOrWhiteSpace(key))
+ {
+ key = key + "-" + ExtraType.ToString().ToLower();
+
+ // Make sure different trailers have their own data.
+ if (RunTimeTicks.HasValue)
+ {
+ key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
+ }
+
+ return key;
+ }
+ }
+
+ return base.CreateUserDataKey();
+ }
+
/// <summary>
/// Gets the linked children.
/// </summary>
@@ -441,6 +485,22 @@ namespace MediaBrowser.Controller.Entities
public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
{
+ if (SourceType == SourceType.Channel)
+ {
+ var sources = ChannelManager.GetStaticMediaSources(this, false, CancellationToken.None)
+ .Result.ToList();
+
+ if (sources.Count > 0)
+ {
+ return sources;
+ }
+
+ return new List<MediaSourceInfo>
+ {
+ GetVersionInfo(enablePathSubstitution, this, MediaSourceType.Placeholder)
+ };
+ }
+
var item = this;
var result = item.GetAlternateVersions()
diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs
index fb843d191..e4eecec18 100644
--- a/MediaBrowser.Controller/IServerApplicationHost.cs
+++ b/MediaBrowser.Controller/IServerApplicationHost.cs
@@ -79,5 +79,12 @@ namespace MediaBrowser.Controller
/// <param name="host">The host.</param>
/// <returns>System.String.</returns>
string GetLocalApiUrl(string host);
+
+ /// <summary>
+ /// Gets the local API URL.
+ /// </summary>
+ /// <param name="ipAddress">The ip address.</param>
+ /// <returns>System.String.</returns>
+ string GetLocalApiUrl(IPAddress ipAddress);
}
}
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index ff44953ef..752ac2dad 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -153,13 +153,6 @@ namespace MediaBrowser.Controller.Library
BaseItem GetItemById(Guid id);
/// <summary>
- /// Gets the items.
- /// </summary>
- /// <param name="query">The query.</param>
- /// <returns>QueryResult&lt;BaseItem&gt;.</returns>
- QueryResult<BaseItem> GetItems(InternalItemsQuery query);
-
- /// <summary>
/// Gets the memory item by identifier.
/// </summary>
/// <param name="id">The identifier.</param>
@@ -551,18 +544,24 @@ namespace MediaBrowser.Controller.Library
/// Gets the items.
/// </summary>
/// <param name="query">The query.</param>
+ /// <returns>QueryResult&lt;BaseItem&gt;.</returns>
+ IEnumerable<BaseItem> GetItemList(InternalItemsQuery query);
+
+ /// <summary>
+ /// Gets the items.
+ /// </summary>
+ /// <param name="query">The query.</param>
/// <param name="parentIds">The parent ids.</param>
/// <returns>List&lt;BaseItem&gt;.</returns>
- IEnumerable<BaseItem> GetItems(InternalItemsQuery query, IEnumerable<string> parentIds);
+ IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, IEnumerable<string> parentIds);
/// <summary>
/// Gets the items result.
/// </summary>
/// <param name="query">The query.</param>
- /// <param name="parentIds">The parent ids.</param>
/// <returns>QueryResult&lt;BaseItem&gt;.</returns>
- QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query, IEnumerable<string> parentIds);
-
+ QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query);
+
/// <summary>
/// Ignores the file.
/// </summary>
diff --git a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
index 50528c6ae..bcf39558e 100644
--- a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
+++ b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
@@ -15,11 +15,14 @@ namespace MediaBrowser.Controller.Library
public BaseItem Item { get; set; }
public BaseItemInfo MediaInfo { get; set; }
public string MediaSourceId { get; set; }
+ public bool IsPaused { get; set; }
public string DeviceId { get; set; }
public string DeviceName { get; set; }
public string ClientName { get; set; }
+ public string PlaySessionId { get; set; }
+
public PlaybackProgressEventArgs()
{
Users = new List<User>();
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvItem.cs b/MediaBrowser.Controller/LiveTv/ILiveTvItem.cs
deleted file mode 100644
index 36727f4ae..000000000
--- a/MediaBrowser.Controller/LiveTv/ILiveTvItem.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using MediaBrowser.Controller.Entities;
-
-namespace MediaBrowser.Controller.LiveTv
-{
- public interface ILiveTvItem : IHasId
- {
- string ServiceName { get; set; }
- string ExternalId { get; set; }
- }
-}
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index 501e48a74..4cc7b27ea 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -50,7 +50,7 @@ namespace MediaBrowser.Controller.LiveTv
/// </summary>
/// <param name="recording">The recording.</param>
/// <returns>Task.</returns>
- Task DeleteRecording(ILiveTvRecording recording);
+ Task DeleteRecording(BaseItem recording);
/// <summary>
/// Cancels the timer.
@@ -75,15 +75,6 @@ namespace MediaBrowser.Controller.LiveTv
void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders);
/// <summary>
- /// Gets the channels.
- /// </summary>
- /// <param name="query">The query.</param>
- /// <param name="options">The options.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>IEnumerable{Channel}.</returns>
- Task<QueryResult<ChannelInfoDto>> GetChannels(LiveTvChannelQuery query, DtoOptions options, CancellationToken cancellationToken);
-
- /// <summary>
/// Gets the recording.
/// </summary>
/// <param name="id">The identifier.</param>
@@ -92,15 +83,6 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="user">The user.</param>
/// <returns>Task{RecordingInfoDto}.</returns>
Task<BaseItemDto> GetRecording(string id, DtoOptions options, CancellationToken cancellationToken, User user = null);
-
- /// <summary>
- /// Gets the channel.
- /// </summary>
- /// <param name="id">The identifier.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <param name="user">The user.</param>
- /// <returns>Task{RecordingInfoDto}.</returns>
- Task<ChannelInfoDto> GetChannel(string id, CancellationToken cancellationToken, User user = null);
/// <summary>
/// Gets the timer.
@@ -156,7 +138,7 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>LiveTvRecording.</returns>
- Task<ILiveTvRecording> GetInternalRecording(string id, CancellationToken cancellationToken);
+ Task<BaseItem> GetInternalRecording(string id, CancellationToken cancellationToken);
/// <summary>
/// Gets the recording stream.
@@ -385,10 +367,22 @@ namespace MediaBrowser.Controller.LiveTv
/// <summary>
/// Adds the channel information.
/// </summary>
- /// <param name="dto">The dto.</param>
- /// <param name="channel">The channel.</param>
+ /// <param name="items">The items.</param>
/// <param name="options">The options.</param>
/// <param name="user">The user.</param>
- void AddChannelInfo(BaseItemDto dto, LiveTvChannel channel, DtoOptions options, User user);
+ void AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> items, DtoOptions options, User user);
+
+ /// <summary>
+ /// Called when [recording file deleted].
+ /// </summary>
+ /// <param name="recording">The recording.</param>
+ /// <returns>Task.</returns>
+ Task OnRecordingFileDeleted(BaseItem recording);
+
+ /// <summary>
+ /// Gets the sat ini mappings.
+ /// </summary>
+ /// <returns>List&lt;NameValuePair&gt;.</returns>
+ List<NameValuePair> GetSatIniMappings();
}
}
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
index 5dc5f68cd..257024d01 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
@@ -9,8 +9,10 @@ using System.Threading.Tasks;
namespace MediaBrowser.Controller.LiveTv
{
- public interface ILiveTvRecording : IHasImages, IHasMediaSources, IHasUserData, ILiveTvItem, IHasStartDate, IHasProgramAttributes
+ public interface ILiveTvRecording : IHasImages, IHasMediaSources, IHasUserData, IHasStartDate, IHasProgramAttributes
{
+ string ServiceName { get; set; }
+ string ExternalId { get; set; }
string ChannelId { get; }
string MediaType { get; }
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
index c3d843f85..2657ade42 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
@@ -39,6 +39,13 @@ namespace MediaBrowser.Controller.LiveTv
[IgnoreDataMember]
public bool IsPremiere { get; set; }
+ [IgnoreDataMember]
+ public override SourceType SourceType
+ {
+ get { return SourceType.LiveTV; }
+ set { }
+ }
+
/// <summary>
/// Gets the user data key.
/// </summary>
@@ -50,8 +57,6 @@ namespace MediaBrowser.Controller.LiveTv
return name + "-" + Name + (EpisodeTitle ?? string.Empty);
}
- public string ServiceName { get; set; }
-
/// <summary>
/// Gets a value indicating whether this instance is owned item.
/// </summary>
@@ -151,5 +156,10 @@ namespace MediaBrowser.Controller.LiveTv
{
return LiveTvManager.DeleteRecording(this);
}
+
+ public override Task OnFileDeleted()
+ {
+ return LiveTvManager.OnRecordingFileDeleted(this);
+ }
}
}
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
index 8c4ee92cd..24ec3f5e1 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
@@ -11,7 +11,7 @@ using System.Runtime.Serialization;
namespace MediaBrowser.Controller.LiveTv
{
- public class LiveTvChannel : BaseItem, IHasMediaSources, ILiveTvItem
+ public class LiveTvChannel : BaseItem, IHasMediaSources
{
/// <summary>
/// Gets the user data key.
@@ -40,6 +40,13 @@ namespace MediaBrowser.Controller.LiveTv
}
}
+ [IgnoreDataMember]
+ public override SourceType SourceType
+ {
+ get { return SourceType.LiveTV; }
+ set { }
+ }
+
/// <summary>
/// Gets or sets the number.
/// </summary>
@@ -52,12 +59,6 @@ namespace MediaBrowser.Controller.LiveTv
/// <value>The type of the channel.</value>
public ChannelType ChannelType { get; set; }
- /// <summary>
- /// Gets or sets the name of the service.
- /// </summary>
- /// <value>The name of the service.</value>
- public string ServiceName { get; set; }
-
[IgnoreDataMember]
public override LocationType LocationType
{
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
index fcd065e79..684af9974 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
@@ -11,7 +11,7 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.LiveTv
{
- public class LiveTvProgram : BaseItem, ILiveTvItem, IHasLookupInfo<LiveTvProgramLookupInfo>, IHasStartDate, IHasProgramAttributes
+ public class LiveTvProgram : BaseItem, IHasLookupInfo<LiveTvProgramLookupInfo>, IHasStartDate, IHasProgramAttributes
{
/// <summary>
/// Gets the user data key.
@@ -39,12 +39,12 @@ namespace MediaBrowser.Controller.LiveTv
return base.CreateUserDataKey();
}
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
[IgnoreDataMember]
- public string ServiceName { get; set; }
+ public override SourceType SourceType
+ {
+ get { return SourceType.LiveTV; }
+ set { }
+ }
/// <summary>
/// The start date of the program, in UTC.
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
index 5492a29f3..6dff66438 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
@@ -39,6 +39,13 @@ namespace MediaBrowser.Controller.LiveTv
[IgnoreDataMember]
public bool IsPremiere { get; set; }
+ [IgnoreDataMember]
+ public override SourceType SourceType
+ {
+ get { return SourceType.LiveTV; }
+ set { }
+ }
+
/// <summary>
/// Gets the user data key.
/// </summary>
@@ -65,8 +72,6 @@ namespace MediaBrowser.Controller.LiveTv
return base.CreateUserDataKey();
}
- public string ServiceName { get; set; }
-
[IgnoreDataMember]
public override string MediaType
{
@@ -166,5 +171,10 @@ namespace MediaBrowser.Controller.LiveTv
{
return LiveTvManager.DeleteRecording(this);
}
+
+ public override Task OnFileDeleted()
+ {
+ return LiveTvManager.OnRecordingFileDeleted(this);
+ }
}
}
diff --git a/MediaBrowser.Controller/LiveTv/RecordingGroup.cs b/MediaBrowser.Controller/LiveTv/RecordingGroup.cs
index 2d58ef67f..5c86de08b 100644
--- a/MediaBrowser.Controller/LiveTv/RecordingGroup.cs
+++ b/MediaBrowser.Controller/LiveTv/RecordingGroup.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using System.Runtime.Serialization;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Users;
@@ -24,5 +25,12 @@ namespace MediaBrowser.Controller.LiveTv
return false;
}
}
+
+ [IgnoreDataMember]
+ public override SourceType SourceType
+ {
+ get { return SourceType.LiveTV; }
+ set { }
+ }
}
}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index f74d82caa..6f429ed2f 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -46,7 +46,7 @@
<ItemGroup>
<Reference Include="CommonIO, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\CommonIO.1.0.0.8\lib\net45\CommonIO.dll</HintPath>
+ <HintPath>..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll</HintPath>
</Reference>
<Reference Include="Interfaces.IO">
<HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath>
@@ -75,6 +75,7 @@
</Compile>
<Compile Include="Activity\IActivityManager.cs" />
<Compile Include="Activity\IActivityRepository.cs" />
+ <Compile Include="Channels\ChannelAudioItem.cs" />
<Compile Include="Channels\ChannelFolderItem.cs" />
<Compile Include="Channels\ChannelItemInfo.cs" />
<Compile Include="Channels\ChannelItemResult.cs" />
@@ -82,11 +83,10 @@
<Compile Include="Channels\ChannelMediaInfo.cs" />
<Compile Include="Channels\ChannelParentalRating.cs" />
<Compile Include="Channels\ChannelSearchInfo.cs" />
+ <Compile Include="Channels\ChannelVideoItem.cs" />
<Compile Include="Channels\IChannel.cs" />
- <Compile Include="Channels\IChannelManager.cs" />
<Compile Include="Channels\IChannelItem.cs" />
- <Compile Include="Channels\ChannelAudioItem.cs" />
- <Compile Include="Channels\ChannelVideoItem.cs" />
+ <Compile Include="Channels\IChannelManager.cs" />
<Compile Include="Channels\Channel.cs" />
<Compile Include="Channels\IChannelMediaItem.cs" />
<Compile Include="Channels\IHasCacheKey.cs" />
@@ -128,6 +128,7 @@
<Compile Include="Drawing\ImageStream.cs" />
<Compile Include="Dto\DtoOptions.cs" />
<Compile Include="Dto\IDtoService.cs" />
+ <Compile Include="Entities\Audio\AudioPodcast.cs" />
<Compile Include="Entities\Audio\IHasAlbumArtist.cs" />
<Compile Include="Entities\Audio\IHasMusicGenres.cs" />
<Compile Include="Entities\Book.cs" />
@@ -180,6 +181,7 @@
<Compile Include="Entities\Photo.cs" />
<Compile Include="Entities\PhotoAlbum.cs" />
<Compile Include="Entities\Share.cs" />
+ <Compile Include="Entities\SourceType.cs" />
<Compile Include="Entities\UserView.cs" />
<Compile Include="Entities\UserViewBuilder.cs" />
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
@@ -202,7 +204,6 @@
<Compile Include="Library\UserDataSaveEventArgs.cs" />
<Compile Include="LiveTv\IHasRegistrationInfo.cs" />
<Compile Include="LiveTv\IListingsProvider.cs" />
- <Compile Include="LiveTv\ILiveTvItem.cs" />
<Compile Include="LiveTv\ITunerHost.cs" />
<Compile Include="LiveTv\RecordingGroup.cs" />
<Compile Include="LiveTv\RecordingStatusChangedEventArgs.cs" />
@@ -271,7 +272,6 @@
<Compile Include="Providers\ArtistInfo.cs" />
<Compile Include="Providers\BookInfo.cs" />
<Compile Include="Providers\BoxSetInfo.cs" />
- <Compile Include="Providers\ChannelItemLookupInfo.cs" />
<Compile Include="Providers\DirectoryService.cs" />
<Compile Include="Providers\DynamicImageInfo.cs" />
<Compile Include="Providers\DynamicImageResponse.cs" />
@@ -331,6 +331,7 @@
<Compile Include="Security\IEncryptionManager.cs" />
<Compile Include="Session\AuthenticationRequest.cs" />
<Compile Include="Social\ISharingManager.cs" />
+ <Compile Include="Sorting\SortHelper.cs" />
<Compile Include="Subtitles\ISubtitleManager.cs" />
<Compile Include="Subtitles\ISubtitleProvider.cs" />
<Compile Include="Providers\ItemIdentifier.cs" />
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
index f8f4e9ec9..ddaf7ff6d 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
@@ -90,8 +90,7 @@ namespace MediaBrowser.Controller.MediaEncoding
Cabac = info.Cabac;
Context = info.Context;
- if (info.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode ||
- info.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Embed)
+ if (info.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External)
{
SubtitleStreamIndex = info.SubtitleStreamIndex;
}
diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs
index 533d66b95..15df1f649 100644
--- a/MediaBrowser.Controller/Persistence/IItemRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs
@@ -43,13 +43,6 @@ namespace MediaBrowser.Controller.Persistence
IEnumerable<ItemReview> GetCriticReviews(Guid itemId);
/// <summary>
- /// Gets the children items.
- /// </summary>
- /// <param name="parentId">The parent identifier.</param>
- /// <returns>IEnumerable&lt;BaseItem&gt;.</returns>
- IEnumerable<BaseItem> GetChildrenItems(Guid parentId);
-
- /// <summary>
/// Saves the critic reviews.
/// </summary>
/// <param name="itemId">The item id.</param>
@@ -97,22 +90,6 @@ namespace MediaBrowser.Controller.Persistence
Task SaveChapters(Guid id, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);
/// <summary>
- /// Gets the children.
- /// </summary>
- /// <param name="parentId">The parent id.</param>
- /// <returns>IEnumerable{ChildDefinition}.</returns>
- IEnumerable<Guid> GetChildren(Guid parentId);
-
- /// <summary>
- /// Saves the children.
- /// </summary>
- /// <param name="parentId">The parent id.</param>
- /// <param name="children">The children.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- Task SaveChildren(Guid parentId, IEnumerable<Guid> children, CancellationToken cancellationToken);
-
- /// <summary>
/// Gets the media streams.
/// </summary>
/// <param name="query">The query.</param>
diff --git a/MediaBrowser.Controller/Providers/ChannelItemLookupInfo.cs b/MediaBrowser.Controller/Providers/ChannelItemLookupInfo.cs
deleted file mode 100644
index 6c972f3bf..000000000
--- a/MediaBrowser.Controller/Providers/ChannelItemLookupInfo.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using MediaBrowser.Model.Channels;
-using MediaBrowser.Model.Entities;
-
-namespace MediaBrowser.Controller.Providers
-{
- public class ChannelItemLookupInfo : ItemLookupInfo
- {
- public ChannelMediaContentType ContentType { get; set; }
- public ExtraType ExtraType { get; set; }
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/TrailerInfo.cs b/MediaBrowser.Controller/Providers/TrailerInfo.cs
index fe26ec43e..65ddc2d1e 100644
--- a/MediaBrowser.Controller/Providers/TrailerInfo.cs
+++ b/MediaBrowser.Controller/Providers/TrailerInfo.cs
@@ -1,3 +1,5 @@
+using MediaBrowser.Model.Entities;
+
namespace MediaBrowser.Controller.Providers
{
public class TrailerInfo : ItemLookupInfo
diff --git a/MediaBrowser.Controller/Sorting/SortHelper.cs b/MediaBrowser.Controller/Sorting/SortHelper.cs
new file mode 100644
index 000000000..95a3c26c4
--- /dev/null
+++ b/MediaBrowser.Controller/Sorting/SortHelper.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Sorting
+{
+ public static class SortHelper
+ {
+ private enum ChunkType { Alphanumeric, Numeric };
+
+ public static bool InChunk(char ch, char otherCh)
+ {
+ var type = ChunkType.Alphanumeric;
+
+ if (char.IsDigit(otherCh))
+ {
+ type = ChunkType.Numeric;
+ }
+
+ if ((type == ChunkType.Alphanumeric && char.IsDigit(ch))
+ || (type == ChunkType.Numeric && !char.IsDigit(ch)))
+ {
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/packages.config b/MediaBrowser.Controller/packages.config
index 34e16d2ad..84422d9da 100644
--- a/MediaBrowser.Controller/packages.config
+++ b/MediaBrowser.Controller/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="CommonIO" version="1.0.0.8" targetFramework="net45" />
+ <package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
<package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
<package id="morelinq" version="1.4.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />