aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
authorEric Reed <ebr@mediabrowser3.com>2013-12-04 15:07:56 -0500
committerEric Reed <ebr@mediabrowser3.com>2013-12-04 15:07:56 -0500
commit6819be81601f6a95a60ce2735474ae0015d19bff (patch)
tree7e2743455e53d4a028fae789f2fc74a7c5ae87b9 /MediaBrowser.Controller
parent190be6311fbdf3a73f9c8e330f44edafe7764284 (diff)
parentcb882a4b48e9cf03cd363c54d93338ad62153e7e (diff)
Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Entities/Audio/Artist.cs86
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs82
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicGenre.cs4
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs89
-rw-r--r--MediaBrowser.Controller/Entities/Extensions.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs53
-rw-r--r--MediaBrowser.Controller/Entities/Game.cs24
-rw-r--r--MediaBrowser.Controller/Entities/GameGenre.cs4
-rw-r--r--MediaBrowser.Controller/Entities/Genre.cs8
-rw-r--r--MediaBrowser.Controller/Entities/IHasAspectRatio.cs14
-rw-r--r--MediaBrowser.Controller/Entities/IHasBudget.cs18
-rw-r--r--MediaBrowser.Controller/Entities/IHasTrailers.cs21
-rw-r--r--MediaBrowser.Controller/Entities/IItemByName.cs30
-rw-r--r--MediaBrowser.Controller/Entities/IndexFolder.cs1
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs20
-rw-r--r--MediaBrowser.Controller/Entities/Movies/Movie.cs20
-rw-r--r--MediaBrowser.Controller/Entities/MusicVideo.cs14
-rw-r--r--MediaBrowser.Controller/Entities/Person.cs14
-rw-r--r--MediaBrowser.Controller/Entities/Studio.cs4
-rw-r--r--MediaBrowser.Controller/Entities/TV/Episode.cs84
-rw-r--r--MediaBrowser.Controller/Entities/TV/Season.cs50
-rw-r--r--MediaBrowser.Controller/Entities/TV/Series.cs18
-rw-r--r--MediaBrowser.Controller/Entities/Trailer.cs19
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs20
-rw-r--r--MediaBrowser.Controller/Entities/Year.cs4
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs15
-rw-r--r--MediaBrowser.Controller/Library/TVUtils.cs2
-rw-r--r--MediaBrowser.Controller/LiveTv/Channel.cs73
-rw-r--r--MediaBrowser.Controller/LiveTv/ChannelInfo.cs6
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs90
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvService.cs83
-rw-r--r--MediaBrowser.Controller/LiveTv/ImageResponseInfo.cs19
-rw-r--r--MediaBrowser.Controller/LiveTv/ProgramInfo.cs98
-rw-r--r--MediaBrowser.Controller/LiveTv/RecordingInfo.cs102
-rw-r--r--MediaBrowser.Controller/LiveTv/SeriesTimerInfo.cs85
-rw-r--r--MediaBrowser.Controller/LiveTv/TimerInfo.cs73
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj11
-rw-r--r--MediaBrowser.Controller/Providers/BaseItemXmlParser.cs110
-rw-r--r--MediaBrowser.Controller/Providers/NameParser.cs39
39 files changed, 1260 insertions, 249 deletions
diff --git a/MediaBrowser.Controller/Entities/Audio/Artist.cs b/MediaBrowser.Controller/Entities/Audio/Artist.cs
deleted file mode 100644
index 947ee11227..0000000000
--- a/MediaBrowser.Controller/Entities/Audio/Artist.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Runtime.Serialization;
-
-namespace MediaBrowser.Controller.Entities.Audio
-{
- /// <summary>
- /// Class Artist
- /// </summary>
- public class Artist : BaseItem, IItemByName, IHasMusicGenres
- {
- public Artist()
- {
- UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
- }
-
- public string LastFmImageUrl { get; set; }
- public string LastFmImageSize { get; set; }
-
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- public override string GetUserDataKey()
- {
- return GetUserDataKey(this);
- }
-
- [IgnoreDataMember]
- public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
-
- /// <summary>
- /// Finds the music artist.
- /// </summary>
- /// <param name="artist">The artist.</param>
- /// <param name="libraryManager">The library manager.</param>
- /// <returns>MusicArtist.</returns>
- public static MusicArtist FindMusicArtist(Artist artist, ILibraryManager libraryManager)
- {
- return FindMusicArtist(artist, libraryManager.RootFolder.RecursiveChildren.OfType<MusicArtist>());
- }
-
- /// <summary>
- /// Finds the music artist.
- /// </summary>
- /// <param name="artist">The artist.</param>
- /// <param name="allMusicArtists">All music artists.</param>
- /// <returns>MusicArtist.</returns>
- public static MusicArtist FindMusicArtist(Artist artist, IEnumerable<MusicArtist> allMusicArtists)
- {
- var musicBrainzId = artist.GetProviderId(MetadataProviders.Musicbrainz);
-
- return allMusicArtists.FirstOrDefault(i =>
- {
- if (!string.IsNullOrWhiteSpace(musicBrainzId) && string.Equals(musicBrainzId, i.GetProviderId(MetadataProviders.Musicbrainz), StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
-
- return string.Compare(i.Name, artist.Name, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols) == 0;
- });
- }
-
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns>System.String.</returns>
- public static string GetUserDataKey(BaseItem item)
- {
- var id = item.GetProviderId(MetadataProviders.Musicbrainz);
-
- if (!string.IsNullOrEmpty(id))
- {
- return "Artist-Musicbrainz-" + id;
- }
-
- return "Artist-" + item.Name;
- }
- }
-}
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index d791c92ae9..d5572b9a5e 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -1,11 +1,65 @@
-
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Threading;
+using System.Threading.Tasks;
+
namespace MediaBrowser.Controller.Entities.Audio
{
/// <summary>
/// Class MusicArtist
/// </summary>
- public class MusicArtist : Folder
+ public class MusicArtist : Folder, IItemByName, IHasMusicGenres, IHasDualAccess
{
+ [IgnoreDataMember]
+ public List<ItemByNameCounts> UserItemCountList { get; set; }
+
+ public bool IsAccessedByName { get; set; }
+
+ public override bool IsFolder
+ {
+ get
+ {
+ return !IsAccessedByName;
+ }
+ }
+
+ protected override IEnumerable<BaseItem> ActualChildren
+ {
+ get
+ {
+ if (IsAccessedByName)
+ {
+ return new List<BaseItem>();
+ }
+
+ return base.ActualChildren;
+ }
+ }
+
+ protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool? recursive = null, bool forceRefreshMetadata = false)
+ {
+ if (IsAccessedByName)
+ {
+ // Should never get in here anyway
+ return Task.FromResult(true);
+ }
+
+ return base.ValidateChildrenInternal(progress, cancellationToken, recursive, forceRefreshMetadata);
+ }
+
+ public override string GetClientTypeName()
+ {
+ if (IsAccessedByName)
+ {
+ //return "Artist";
+ }
+
+ return base.GetClientTypeName();
+ }
+
/// <summary>
/// Gets or sets the last fm image URL.
/// </summary>
@@ -13,13 +67,35 @@ namespace MediaBrowser.Controller.Entities.Audio
public string LastFmImageUrl { get; set; }
public string LastFmImageSize { get; set; }
+ public MusicArtist()
+ {
+ UserItemCountList = new List<ItemByNameCounts>();
+ }
+
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
public override string GetUserDataKey()
{
- return Artist.GetUserDataKey(this);
+ return GetUserDataKey(this);
+ }
+
+ /// <summary>
+ /// Gets the user data key.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>System.String.</returns>
+ public static string GetUserDataKey(BaseItem item)
+ {
+ var id = item.GetProviderId(MetadataProviders.Musicbrainz);
+
+ if (!string.IsNullOrEmpty(id))
+ {
+ return "Artist-Musicbrainz-" + id;
+ }
+
+ return "Artist-" + item.Name;
}
}
}
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
index ec2995fb2f..b54e14f2da 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
@@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities.Audio
{
public MusicGenre()
{
- UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
+ UserItemCountList = new List<ItemByNameCounts>();
}
/// <summary>
@@ -25,6 +25,6 @@ namespace MediaBrowser.Controller.Entities.Audio
}
[IgnoreDataMember]
- public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
+ public List<ItemByNameCounts> UserItemCountList { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index a6178536c6..4f7889f975 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization;
@@ -38,10 +37,8 @@ namespace MediaBrowser.Controller.Entities
Tags = new List<string>();
ThemeSongIds = new List<Guid>();
ThemeVideoIds = new List<Guid>();
- LocalTrailerIds = new List<Guid>();
LockedFields = new List<MetadataFields>();
Taglines = new List<string>();
- RemoteTrailers = new List<MediaUrl>();
ImageSources = new List<ImageSourceInfo>();
}
@@ -88,30 +85,12 @@ namespace MediaBrowser.Controller.Entities
public Guid Id { get; set; }
/// <summary>
- /// Gets or sets the budget.
- /// </summary>
- /// <value>The budget.</value>
- public double? Budget { get; set; }
-
- /// <summary>
/// Gets or sets the taglines.
/// </summary>
/// <value>The taglines.</value>
public List<string> Taglines { get; set; }
/// <summary>
- /// Gets or sets the revenue.
- /// </summary>
- /// <value>The revenue.</value>
- public double? Revenue { get; set; }
-
- /// <summary>
- /// Gets or sets the trailer URL.
- /// </summary>
- /// <value>The trailer URL.</value>
- public List<MediaUrl> RemoteTrailers { get; set; }
-
- /// <summary>
/// Return the id that should be used to key display prefs for this item.
/// Default is based on the type for everything except actual generic folders.
/// </summary>
@@ -139,6 +118,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the type of the location.
/// </summary>
/// <value>The type of the location.</value>
+ [IgnoreDataMember]
public virtual LocationType LocationType
{
get
@@ -483,6 +463,22 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public Folder Parent { get; set; }
+ [IgnoreDataMember]
+ public IEnumerable<Folder> Parents
+ {
+ get
+ {
+ var parent = Parent;
+
+ while (parent != null)
+ {
+ yield return parent;
+
+ parent = parent.Parent;
+ }
+ }
+ }
+
/// <summary>
/// When the item first debuted. For movies this could be premiere date, episodes would be first aired
/// </summary>
@@ -630,11 +626,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The original run time ticks.</value>
public long? OriginalRunTimeTicks { get; set; }
/// <summary>
- /// Gets or sets the aspect ratio.
- /// </summary>
- /// <value>The aspect ratio.</value>
- public string AspectRatio { get; set; }
- /// <summary>
/// Gets or sets the production year.
/// </summary>
/// <value>The production year.</value>
@@ -655,7 +646,6 @@ namespace MediaBrowser.Controller.Entities
public List<Guid> ThemeSongIds { get; set; }
public List<Guid> ThemeVideoIds { get; set; }
- public List<Guid> LocalTrailerIds { get; set; }
[IgnoreDataMember]
public virtual string OfficialRatingForComparison
@@ -898,7 +888,11 @@ namespace MediaBrowser.Controller.Entities
themeVideosChanged = await RefreshThemeVideos(cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false);
- localTrailersChanged = await RefreshLocalTrailers(cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false);
+ var hasTrailers = this as IHasTrailers;
+ if (hasTrailers != null)
+ {
+ localTrailersChanged = await RefreshLocalTrailers(hasTrailers, cancellationToken, forceSave, forceRefresh, allowSlowProviders).ConfigureAwait(false);
+ }
}
cancellationToken.ThrowIfCancellationRequested();
@@ -918,18 +912,18 @@ namespace MediaBrowser.Controller.Entities
return changed;
}
- private async Task<bool> RefreshLocalTrailers(CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true)
+ private async Task<bool> RefreshLocalTrailers(IHasTrailers item, CancellationToken cancellationToken, bool forceSave = false, bool forceRefresh = false, bool allowSlowProviders = true)
{
var newItems = LoadLocalTrailers().ToList();
var newItemIds = newItems.Select(i => i.Id).ToList();
- var itemsChanged = !LocalTrailerIds.SequenceEqual(newItemIds);
+ var itemsChanged = !item.LocalTrailerIds.SequenceEqual(newItemIds);
var tasks = newItems.Select(i => i.RefreshMetadata(cancellationToken, forceSave, forceRefresh, allowSlowProviders, resetResolveArgs: false));
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
- LocalTrailerIds = newItemIds;
+ item.LocalTrailerIds = newItemIds;
return itemsChanged || results.Contains(true);
}
@@ -1134,6 +1128,11 @@ namespace MediaBrowser.Controller.Entities
return changed;
}
+ public virtual string GetClientTypeName()
+ {
+ return GetType().Name;
+ }
+
/// <summary>
/// Determines if the item is considered new based on user settings
/// </summary>
@@ -1187,6 +1186,7 @@ namespace MediaBrowser.Controller.Entities
if (existing != null)
{
existing.Type = PersonType.GuestStar;
+ existing.SortOrder = person.SortOrder ?? existing.SortOrder;
return;
}
}
@@ -1203,23 +1203,35 @@ namespace MediaBrowser.Controller.Entities
else
{
// Was there, if no role and we have one - fill it in
- if (string.IsNullOrWhiteSpace(existing.Role) && !string.IsNullOrWhiteSpace(person.Role)) existing.Role = person.Role;
+ if (string.IsNullOrWhiteSpace(existing.Role) && !string.IsNullOrWhiteSpace(person.Role))
+ {
+ existing.Role = person.Role;
+ }
+
+ existing.SortOrder = person.SortOrder ?? existing.SortOrder;
}
}
else
{
+ var existing = People.FirstOrDefault(p =>
+ string.Equals(p.Name, person.Name, StringComparison.OrdinalIgnoreCase) &&
+ string.Equals(p.Type, person.Type, StringComparison.OrdinalIgnoreCase));
+
// Check for dupes based on the combination of Name and Type
- if (!People.Any(p => string.Equals(p.Name, person.Name, StringComparison.OrdinalIgnoreCase) && string.Equals(p.Type, person.Type, StringComparison.OrdinalIgnoreCase)))
+ if (existing == null)
{
People.Add(person);
}
+ else
+ {
+ existing.SortOrder = person.SortOrder ?? existing.SortOrder;
+ }
}
}
/// <summary>
/// Adds the tagline.
/// </summary>
- /// <param name="item">The item.</param>
/// <param name="tagline">The tagline.</param>
/// <exception cref="System.ArgumentNullException">tagline</exception>
public void AddTagline(string tagline)
@@ -1737,5 +1749,14 @@ namespace MediaBrowser.Controller.Entities
// See if we can avoid a file system lookup by looking for the file in ResolveArgs
return metaFileEntry == null ? FileSystem.GetLastWriteTimeUtc(imagePath) : FileSystem.GetLastWriteTimeUtc(metaFileEntry);
}
+
+ /// <summary>
+ /// Gets the file system path to delete when the item is to be deleted
+ /// </summary>
+ /// <returns></returns>
+ public virtual IEnumerable<string> GetDeletePaths()
+ {
+ return new[] { Path };
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs
index d189f4e71b..2a64bd3a41 100644
--- a/MediaBrowser.Controller/Entities/Extensions.cs
+++ b/MediaBrowser.Controller/Entities/Extensions.cs
@@ -16,7 +16,7 @@ namespace MediaBrowser.Controller.Entities
/// <param name="url">The URL.</param>
/// <param name="isDirectLink">if set to <c>true</c> [is direct link].</param>
/// <exception cref="System.ArgumentNullException">url</exception>
- public static void AddTrailerUrl(this BaseItem item, string url, bool isDirectLink)
+ public static void AddTrailerUrl(this IHasTrailers item, string url, bool isDirectLink)
{
if (string.IsNullOrWhiteSpace(url))
{
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 8dbc981938..e8b5831813 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -90,7 +90,7 @@ namespace MediaBrowser.Controller.Entities
item.Id = item.Path.GetMBId(item.GetType());
}
- if (_children.Any(i => i.Id == item.Id))
+ if (ActualChildren.Any(i => i.Id == item.Id))
{
throw new ArgumentException(string.Format("A child with the Id {0} already exists.", item.Id));
}
@@ -108,14 +108,14 @@ namespace MediaBrowser.Controller.Entities
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
- await ItemRepository.SaveChildren(Id, _children.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
+ await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
}
protected void AddChildrenInternal(IEnumerable<BaseItem> children)
{
lock (_childrenSyncLock)
{
- var newChildren = _children.ToList();
+ var newChildren = ActualChildren.ToList();
newChildren.AddRange(children);
_children = newChildren;
}
@@ -124,7 +124,7 @@ namespace MediaBrowser.Controller.Entities
{
lock (_childrenSyncLock)
{
- var newChildren = _children.ToList();
+ var newChildren = ActualChildren.ToList();
newChildren.Add(child);
_children = newChildren;
}
@@ -134,7 +134,7 @@ namespace MediaBrowser.Controller.Entities
{
lock (_childrenSyncLock)
{
- _children = _children.Except(children).ToList();
+ _children = ActualChildren.Except(children).ToList();
}
}
@@ -519,7 +519,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// The children
/// </summary>
- private IReadOnlyList<BaseItem> _children = new List<BaseItem>();
+ private IReadOnlyList<BaseItem> _children;
/// <summary>
/// The _children sync lock
/// </summary>
@@ -532,15 +532,10 @@ namespace MediaBrowser.Controller.Entities
{
get
{
- return _children;
+ return _children ?? (_children = LoadChildrenInternal());
}
}
- public void LoadSavedChildren()
- {
- _children = LoadChildrenInternal();
- }
-
/// <summary>
/// thread-safe access to the actual children of this folder - without regard to user
/// </summary>
@@ -758,7 +753,7 @@ namespace MediaBrowser.Controller.Entities
AddChildrenInternal(newItems);
- await ItemRepository.SaveChildren(Id, _children.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
+ await ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken).ConfigureAwait(false);
//force the indexes to rebuild next time
if (IndexCache != null)
@@ -1007,8 +1002,7 @@ namespace MediaBrowser.Controller.Entities
return result;
}
- var initialCount = _children.Count;
- var list = new List<BaseItem>(initialCount);
+ var list = new List<BaseItem>();
AddChildrenToList(user, includeLinkedChildren, list, false, null);
@@ -1038,16 +1032,13 @@ namespace MediaBrowser.Controller.Entities
}
}
- if (recursive)
+ if (recursive && child.IsFolder)
{
- var folder = child as Folder;
+ var folder = (Folder)child;
- if (folder != null)
+ if (folder.AddChildrenToList(user, includeLinkedChildren, list, true, filter))
{
- if (folder.AddChildrenToList(user, includeLinkedChildren, list, true, filter))
- {
- hasLinkedChildren = true;
- }
+ hasLinkedChildren = true;
}
}
}
@@ -1073,7 +1064,6 @@ namespace MediaBrowser.Controller.Entities
return hasLinkedChildren;
}
- private int _lastRecursiveCount;
/// <summary>
/// Gets allowed recursive children of an item
/// </summary>
@@ -1101,13 +1091,10 @@ namespace MediaBrowser.Controller.Entities
throw new ArgumentNullException("user");
}
- var initialCount = _lastRecursiveCount == 0 ? _children.Count : _lastRecursiveCount;
- var list = new List<BaseItem>(initialCount);
+ var list = new List<BaseItem>();
var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, true, filter);
- _lastRecursiveCount = list.Count;
-
return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list;
}
@@ -1127,8 +1114,7 @@ namespace MediaBrowser.Controller.Entities
/// <returns>IEnumerable{BaseItem}.</returns>
public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter)
{
- var initialCount = _lastRecursiveCount == 0 ? _children.Count : _lastRecursiveCount;
- var list = new List<BaseItem>(initialCount);
+ var list = new List<BaseItem>();
AddChildrenToList(list, true, filter);
@@ -1150,14 +1136,11 @@ namespace MediaBrowser.Controller.Entities
list.Add(child);
}
- if (recursive)
+ if (recursive && child.IsFolder)
{
- var folder = child as Folder;
+ var folder = (Folder)child;
- if (folder != null)
- {
- folder.AddChildrenToList(list, true, filter);
- }
+ folder.AddChildrenToList(list, true, filter);
}
}
}
diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs
index e8374c2743..e15b7e4c9d 100644
--- a/MediaBrowser.Controller/Entities/Game.cs
+++ b/MediaBrowser.Controller/Entities/Game.cs
@@ -4,16 +4,26 @@ using System.Collections.Generic;
namespace MediaBrowser.Controller.Entities
{
- public class Game : BaseItem, IHasSoundtracks
+ public class Game : BaseItem, IHasSoundtracks, IHasTrailers
{
public List<Guid> SoundtrackIds { get; set; }
-
+
public Game()
{
MultiPartGameFiles = new List<string>();
SoundtrackIds = new List<Guid>();
+ RemoteTrailers = new List<MediaUrl>();
+ LocalTrailerIds = new List<Guid>();
}
+ public List<Guid> LocalTrailerIds { get; set; }
+
+ /// <summary>
+ /// Gets or sets the remote trailers.
+ /// </summary>
+ /// <value>The remote trailers.</value>
+ public List<MediaUrl> RemoteTrailers { get; set; }
+
/// <summary>
/// Gets the type of the media.
/// </summary>
@@ -84,5 +94,15 @@ namespace MediaBrowser.Controller.Entities
}
return base.GetUserDataKey();
}
+
+ public override IEnumerable<string> GetDeletePaths()
+ {
+ if (!IsInMixedFolder)
+ {
+ return new[] { System.IO.Path.GetDirectoryName(Path) };
+ }
+
+ return base.GetDeletePaths();
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs
index 0c877782e6..ffe62ba03f 100644
--- a/MediaBrowser.Controller/Entities/GameGenre.cs
+++ b/MediaBrowser.Controller/Entities/GameGenre.cs
@@ -9,7 +9,7 @@ namespace MediaBrowser.Controller.Entities
{
public GameGenre()
{
- UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
+ UserItemCountList = new List<ItemByNameCounts>();
}
/// <summary>
@@ -22,6 +22,6 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
- public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
+ public List<ItemByNameCounts> UserItemCountList { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs
index 71fa057206..0fa49639bf 100644
--- a/MediaBrowser.Controller/Entities/Genre.cs
+++ b/MediaBrowser.Controller/Entities/Genre.cs
@@ -1,7 +1,7 @@
-using System.Runtime.Serialization;
-using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Dto;
using System;
using System.Collections.Generic;
+using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities
{
@@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities
{
public Genre()
{
- UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
+ UserItemCountList = new List<ItemByNameCounts>();
}
/// <summary>
@@ -25,6 +25,6 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
- public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
+ public List<ItemByNameCounts> UserItemCountList { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Entities/IHasAspectRatio.cs b/MediaBrowser.Controller/Entities/IHasAspectRatio.cs
new file mode 100644
index 0000000000..5aecf4eac1
--- /dev/null
+++ b/MediaBrowser.Controller/Entities/IHasAspectRatio.cs
@@ -0,0 +1,14 @@
+namespace MediaBrowser.Controller.Entities
+{
+ /// <summary>
+ /// Interface IHasAspectRatio
+ /// </summary>
+ public interface IHasAspectRatio
+ {
+ /// <summary>
+ /// Gets or sets the aspect ratio.
+ /// </summary>
+ /// <value>The aspect ratio.</value>
+ string AspectRatio { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Entities/IHasBudget.cs b/MediaBrowser.Controller/Entities/IHasBudget.cs
new file mode 100644
index 0000000000..f697715c16
--- /dev/null
+++ b/MediaBrowser.Controller/Entities/IHasBudget.cs
@@ -0,0 +1,18 @@
+
+namespace MediaBrowser.Controller.Entities
+{
+ public interface IHasBudget
+ {
+ /// <summary>
+ /// Gets or sets the budget.
+ /// </summary>
+ /// <value>The budget.</value>
+ double? Budget { get; set; }
+
+ /// <summary>
+ /// Gets or sets the revenue.
+ /// </summary>
+ /// <value>The revenue.</value>
+ double? Revenue { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Entities/IHasTrailers.cs b/MediaBrowser.Controller/Entities/IHasTrailers.cs
new file mode 100644
index 0000000000..47779064b4
--- /dev/null
+++ b/MediaBrowser.Controller/Entities/IHasTrailers.cs
@@ -0,0 +1,21 @@
+using MediaBrowser.Model.Entities;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Entities
+{
+ public interface IHasTrailers
+ {
+ /// <summary>
+ /// Gets or sets the remote trailers.
+ /// </summary>
+ /// <value>The remote trailers.</value>
+ List<MediaUrl> RemoteTrailers { get; set; }
+
+ /// <summary>
+ /// Gets or sets the local trailer ids.
+ /// </summary>
+ /// <value>The local trailer ids.</value>
+ List<Guid> LocalTrailerIds { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Entities/IItemByName.cs b/MediaBrowser.Controller/Entities/IItemByName.cs
index 7284bf101d..1e83c7466e 100644
--- a/MediaBrowser.Controller/Entities/IItemByName.cs
+++ b/MediaBrowser.Controller/Entities/IItemByName.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Model.Dto;
using System;
using System.Collections.Generic;
+using System.Linq;
namespace MediaBrowser.Controller.Entities
{
@@ -9,26 +10,37 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public interface IItemByName
{
- Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
+ List<ItemByNameCounts> UserItemCountList { get; set; }
}
- public static class IItemByNameExtensions
+ public interface IHasDualAccess : IItemByName
{
- public static ItemByNameCounts GetItemByNameCounts(this IItemByName item, User user)
+ bool IsAccessedByName { get; }
+ }
+
+ public static class ItemByNameExtensions
+ {
+ public static ItemByNameCounts GetItemByNameCounts(this IItemByName item, Guid userId)
{
- if (user == null)
+ if (userId == Guid.Empty)
{
- throw new ArgumentNullException("user");
+ throw new ArgumentNullException("userId");
}
- ItemByNameCounts counts;
+ return item.UserItemCountList.FirstOrDefault(i => i.UserId == userId);
+ }
+
+ public static void SetItemByNameCounts(this IItemByName item, Guid userId, ItemByNameCounts counts)
+ {
+ var current = item.UserItemCountList.FirstOrDefault(i => i.UserId == userId);
- if (item.UserItemCounts.TryGetValue(user.Id, out counts))
+ if (current != null)
{
- return counts;
+ item.UserItemCountList.Remove(current);
}
- return null;
+ counts.UserId = userId;
+ item.UserItemCountList.Add(counts);
}
}
}
diff --git a/MediaBrowser.Controller/Entities/IndexFolder.cs b/MediaBrowser.Controller/Entities/IndexFolder.cs
index 35c11ef5ca..57e4a35d3f 100644
--- a/MediaBrowser.Controller/Entities/IndexFolder.cs
+++ b/MediaBrowser.Controller/Entities/IndexFolder.cs
@@ -40,7 +40,6 @@ namespace MediaBrowser.Controller.Entities
IndexName = indexName;
Parent = parent;
- LoadSavedChildren();
}
/// <summary>
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index e52ece502b..4a6221ee98 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -1,10 +1,26 @@
-
+using System;
+using MediaBrowser.Model.Entities;
+using System.Collections.Generic;
+
namespace MediaBrowser.Controller.Entities.Movies
{
/// <summary>
/// Class BoxSet
/// </summary>
- public class BoxSet : Folder
+ public class BoxSet : Folder, IHasTrailers
{
+ public BoxSet()
+ {
+ RemoteTrailers = new List<MediaUrl>();
+ LocalTrailerIds = new List<Guid>();
+ }
+
+ public List<Guid> LocalTrailerIds { get; set; }
+
+ /// <summary>
+ /// Gets or sets the remote trailers.
+ /// </summary>
+ /// <value>The remote trailers.</value>
+ public List<MediaUrl> RemoteTrailers { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs
index eef348f61c..473ea4996d 100644
--- a/MediaBrowser.Controller/Entities/Movies/Movie.cs
+++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs
@@ -11,7 +11,7 @@ namespace MediaBrowser.Controller.Entities.Movies
/// <summary>
/// Class Movie
/// </summary>
- public class Movie : Video, IHasCriticRating, IHasSoundtracks
+ public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasTrailers
{
public List<Guid> SpecialFeatureIds { get; set; }
@@ -21,8 +21,26 @@ namespace MediaBrowser.Controller.Entities.Movies
{
SpecialFeatureIds = new List<Guid>();
SoundtrackIds = new List<Guid>();
+ RemoteTrailers = new List<MediaUrl>();
+ LocalTrailerIds = new List<Guid>();
}
+ public List<Guid> LocalTrailerIds { get; set; }
+
+ public List<MediaUrl> RemoteTrailers { get; set; }
+
+ /// <summary>
+ /// Gets or sets the budget.
+ /// </summary>
+ /// <value>The budget.</value>
+ public double? Budget { get; set; }
+
+ /// <summary>
+ /// Gets or sets the revenue.
+ /// </summary>
+ /// <value>The revenue.</value>
+ public double? Revenue { get; set; }
+
/// <summary>
/// Gets or sets the critic rating.
/// </summary>
diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs
index 207f76efda..68ad4630a5 100644
--- a/MediaBrowser.Controller/Entities/MusicVideo.cs
+++ b/MediaBrowser.Controller/Entities/MusicVideo.cs
@@ -4,7 +4,7 @@ using System;
namespace MediaBrowser.Controller.Entities
{
- public class MusicVideo : Video, IHasArtist, IHasMusicGenres
+ public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasBudget
{
/// <summary>
/// Gets or sets the artist.
@@ -19,6 +19,18 @@ namespace MediaBrowser.Controller.Entities
public string Album { get; set; }
/// <summary>
+ /// Gets or sets the budget.
+ /// </summary>
+ /// <value>The budget.</value>
+ public double? Budget { get; set; }
+
+ /// <summary>
+ /// Gets or sets the revenue.
+ /// </summary>
+ /// <value>The revenue.</value>
+ public double? Revenue { get; set; }
+
+ /// <summary>
/// Determines whether the specified name has artist.
/// </summary>
/// <param name="name">The name.</param>
diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs
index e5cf48ad08..243861da76 100644
--- a/MediaBrowser.Controller/Entities/Person.cs
+++ b/MediaBrowser.Controller/Entities/Person.cs
@@ -1,7 +1,7 @@
-using System.Runtime.Serialization;
-using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Dto;
using System;
using System.Collections.Generic;
+using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities
{
@@ -12,11 +12,11 @@ namespace MediaBrowser.Controller.Entities
{
public Person()
{
- UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
+ UserItemCountList = new List<ItemByNameCounts>();
}
[IgnoreDataMember]
- public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
+ public List<ItemByNameCounts> UserItemCountList { get; set; }
/// <summary>
/// Gets the user data key.
@@ -50,6 +50,12 @@ namespace MediaBrowser.Controller.Entities
public string Type { get; set; }
/// <summary>
+ /// Gets or sets the sort order - ascending
+ /// </summary>
+ /// <value>The sort order.</value>
+ public int? SortOrder { get; set; }
+
+ /// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>A <see cref="System.String" /> that represents this instance.</returns>
diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs
index bbe96a88b9..7bc17549f3 100644
--- a/MediaBrowser.Controller/Entities/Studio.cs
+++ b/MediaBrowser.Controller/Entities/Studio.cs
@@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Entities
{
public Studio()
{
- UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
+ UserItemCountList = new List<ItemByNameCounts>();
}
/// <summary>
@@ -25,6 +25,6 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
- public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
+ public List<ItemByNameCounts> UserItemCountList { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs
index c68ba0ad1f..e9f250d2a4 100644
--- a/MediaBrowser.Controller/Entities/TV/Episode.cs
+++ b/MediaBrowser.Controller/Entities/TV/Episode.cs
@@ -50,6 +50,33 @@ namespace MediaBrowser.Controller.Entities.TV
get { return true; }
}
+ [IgnoreDataMember]
+ public int? AiredSeasonNumber
+ {
+ get
+ {
+ return AirsAfterSeasonNumber ?? AirsBeforeSeasonNumber ?? PhysicalSeasonNumber;
+ }
+ }
+
+ [IgnoreDataMember]
+ public int? PhysicalSeasonNumber
+ {
+ get
+ {
+ var value = ParentIndexNumber;
+
+ if (value.HasValue)
+ {
+ return value;
+ }
+
+ var season = Parent as Season;
+
+ return season != null ? season.IndexNumber : null;
+ }
+ }
+
/// <summary>
/// We roll up into series
/// </summary>
@@ -59,7 +86,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
get
{
- return Season;
+ return FindParent<Season>();
}
}
@@ -152,20 +179,6 @@ namespace MediaBrowser.Controller.Entities.TV
}
/// <summary>
- /// The _season
- /// </summary>
- private Season _season;
- /// <summary>
- /// This Episode's Season Instance
- /// </summary>
- /// <value>The season.</value>
- [IgnoreDataMember]
- public Season Season
- {
- get { return _season ?? (_season = FindParent<Season>()); }
- }
-
- /// <summary>
/// This is the ending episode number for double episodes.
/// </summary>
/// <value>The index number.</value>
@@ -221,5 +234,46 @@ namespace MediaBrowser.Controller.Entities.TV
{
get { return LocationType == Model.Entities.LocationType.Virtual && IsUnaired; }
}
+
+ [IgnoreDataMember]
+ public Guid? SeasonId
+ {
+ get
+ {
+ // First see if the parent is a Season
+ var season = Parent as Season;
+
+ if (season != null)
+ {
+ return season.Id;
+ }
+
+ var seasonNumber = ParentIndexNumber;
+
+ // Parent is a Series
+ if (seasonNumber.HasValue)
+ {
+ var series = Parent as Series;
+
+ if (series != null)
+ {
+ season = series.Children.OfType<Season>()
+ .FirstOrDefault(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber.Value);
+
+ if (season != null)
+ {
+ return season.Id;
+ }
+ }
+ }
+
+ return null;
+ }
+ }
+
+ public override IEnumerable<string> GetDeletePaths()
+ {
+ return new[] { Path };
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs
index 97a09b7b55..78e0b8bc4a 100644
--- a/MediaBrowser.Controller/Entities/TV/Season.cs
+++ b/MediaBrowser.Controller/Entities/TV/Season.cs
@@ -1,9 +1,9 @@
-using System.Linq;
-using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization;
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities.TV
@@ -94,6 +94,22 @@ namespace MediaBrowser.Controller.Entities.TV
get { return _series ?? (_series = FindParent<Series>()); }
}
+ [IgnoreDataMember]
+ public string SeriesPath
+ {
+ get
+ {
+ var series = Series;
+
+ if (series != null)
+ {
+ return series.Path;
+ }
+
+ return System.IO.Path.GetDirectoryName(Path);
+ }
+ }
+
/// <summary>
/// Our rating comes from our series
/// </summary>
@@ -149,16 +165,34 @@ namespace MediaBrowser.Controller.Entities.TV
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
}
+ private IEnumerable<Episode> GetEpisodes()
+ {
+ var series = Series;
+
+ if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
+ {
+ var seasonNumber = IndexNumber;
+
+ if (seasonNumber.HasValue)
+ {
+ return series.RecursiveChildren.OfType<Episode>()
+ .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value);
+ }
+ }
+
+ return Children.OfType<Episode>();
+ }
+
[IgnoreDataMember]
public bool IsMissingSeason
{
- get { return LocationType == Model.Entities.LocationType.Virtual && Children.OfType<Episode>().All(i => i.IsMissingEpisode); }
+ get { return LocationType == Model.Entities.LocationType.Virtual && GetEpisodes().All(i => i.IsMissingEpisode); }
}
[IgnoreDataMember]
public bool IsUnaired
{
- get { return Children.OfType<Episode>().All(i => i.IsUnaired); }
+ get { return GetEpisodes().All(i => i.IsUnaired); }
}
[IgnoreDataMember]
@@ -170,7 +204,13 @@ namespace MediaBrowser.Controller.Entities.TV
[IgnoreDataMember]
public bool IsMissingOrVirtualUnaired
{
- get { return LocationType == Model.Entities.LocationType.Virtual && Children.OfType<Episode>().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); }
+ get { return LocationType == Model.Entities.LocationType.Virtual && GetEpisodes().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); }
+ }
+
+ [IgnoreDataMember]
+ public bool IsSpecialSeason
+ {
+ get { return (IndexNumber ?? -1) == 0; }
}
}
}
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs
index 02ea50c6b5..b4a3fc811f 100644
--- a/MediaBrowser.Controller/Entities/TV/Series.cs
+++ b/MediaBrowser.Controller/Entities/TV/Series.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities.TV
@@ -11,7 +12,7 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// Class Series
/// </summary>
- public class Series : Folder, IHasSoundtracks
+ public class Series : Folder, IHasSoundtracks, IHasTrailers
{
public List<Guid> SpecialFeatureIds { get; set; }
public List<Guid> SoundtrackIds { get; set; }
@@ -24,8 +25,14 @@ namespace MediaBrowser.Controller.Entities.TV
SpecialFeatureIds = new List<Guid>();
SoundtrackIds = new List<Guid>();
+ RemoteTrailers = new List<MediaUrl>();
+ LocalTrailerIds = new List<Guid>();
}
+ public List<Guid> LocalTrailerIds { get; set; }
+
+ public List<MediaUrl> RemoteTrailers { get; set; }
+
/// <summary>
/// Gets or sets the status.
/// </summary>
@@ -94,5 +101,14 @@ namespace MediaBrowser.Controller.Entities.TV
return args;
}
+
+ [IgnoreDataMember]
+ public bool ContainsEpisodesWithoutSeasonFolders
+ {
+ get
+ {
+ return Children.OfType<Video>().Any();
+ }
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs
index 26814ad40b..77efe8e8c1 100644
--- a/MediaBrowser.Controller/Entities/Trailer.cs
+++ b/MediaBrowser.Controller/Entities/Trailer.cs
@@ -8,7 +8,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Class Trailer
/// </summary>
- public class Trailer : Video, IHasCriticRating, IHasSoundtracks
+ public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasTrailers
{
public List<Guid> SoundtrackIds { get; set; }
@@ -17,8 +17,25 @@ namespace MediaBrowser.Controller.Entities
RemoteTrailers = new List<MediaUrl>();
Taglines = new List<string>();
SoundtrackIds = new List<Guid>();
+ LocalTrailerIds = new List<Guid>();
}
+ public List<Guid> LocalTrailerIds { get; set; }
+
+ public List<MediaUrl> RemoteTrailers { get; set; }
+
+ /// <summary>
+ /// Gets or sets the budget.
+ /// </summary>
+ /// <value>The budget.</value>
+ public double? Budget { get; set; }
+
+ /// <summary>
+ /// Gets or sets the revenue.
+ /// </summary>
+ /// <value>The revenue.</value>
+ public double? Revenue { get; set; }
+
/// <summary>
/// Gets or sets the critic rating.
/// </summary>
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index e900dd77e9..9b02571b00 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Class Video
/// </summary>
- public class Video : BaseItem, IHasMediaStreams
+ public class Video : BaseItem, IHasMediaStreams, IHasAspectRatio
{
public bool IsMultiPart { get; set; }
@@ -66,6 +66,12 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
+ /// Gets or sets the aspect ratio.
+ /// </summary>
+ /// <value>The aspect ratio.</value>
+ public string AspectRatio { get; set; }
+
+ /// <summary>
/// Should be overridden to return the proper folder where metadata lives
/// </summary>
/// <value>The meta location.</value>
@@ -252,5 +258,17 @@ namespace MediaBrowser.Controller.Entities
}).ToList();
}
+ public override IEnumerable<string> GetDeletePaths()
+ {
+ if (!IsInMixedFolder)
+ {
+ if (VideoType == VideoType.VideoFile || VideoType == VideoType.Iso)
+ {
+ return new[] { System.IO.Path.GetDirectoryName(Path) };
+ }
+ }
+
+ return base.GetDeletePaths();
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs
index d0f4577183..cd50a1c60c 100644
--- a/MediaBrowser.Controller/Entities/Year.cs
+++ b/MediaBrowser.Controller/Entities/Year.cs
@@ -12,11 +12,11 @@ namespace MediaBrowser.Controller.Entities
{
public Year()
{
- UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
+ UserItemCountList = new List<ItemByNameCounts>();
}
[IgnoreDataMember]
- public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
+ public List<ItemByNameCounts> UserItemCountList { get; set; }
/// <summary>
/// Gets the user data key.
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index 0a89c0df88..338edd5684 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -60,7 +60,7 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="name">The name.</param>
/// <returns>Task{Artist}.</returns>
- Artist GetArtist(string name);
+ MusicArtist GetArtist(string name);
/// <summary>
/// Gets a Studio
@@ -302,5 +302,18 @@ namespace MediaBrowser.Controller.Library
/// <param name="updateType">Type of the update.</param>
/// <returns>Task.</returns>
Task SaveMetadata(BaseItem item, ItemUpdateType updateType);
+
+ /// <summary>
+ /// Gets all artists.
+ /// </summary>
+ /// <returns>IEnumerable{System.String}.</returns>
+ IEnumerable<string> GetAllArtists();
+
+ /// <summary>
+ /// Gets all artists.
+ /// </summary>
+ /// <param name="items">The items.</param>
+ /// <returns>IEnumerable{System.String}.</returns>
+ IEnumerable<string> GetAllArtists(IEnumerable<BaseItem> items);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs
index 7a5722746e..65308bd100 100644
--- a/MediaBrowser.Controller/Library/TVUtils.cs
+++ b/MediaBrowser.Controller/Library/TVUtils.cs
@@ -257,7 +257,7 @@ namespace MediaBrowser.Controller.Library
if (match != null)
{
- return ParseEpisodeNumber(match.Value);
+ return ParseEpisodeNumber(match.Groups["epnumber"].Value);
}
}
diff --git a/MediaBrowser.Controller/LiveTv/Channel.cs b/MediaBrowser.Controller/LiveTv/Channel.cs
new file mode 100644
index 0000000000..8097cea1de
--- /dev/null
+++ b/MediaBrowser.Controller/LiveTv/Channel.cs
@@ -0,0 +1,73 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.LiveTv;
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+ public class Channel : BaseItem, IItemByName
+ {
+ public Channel()
+ {
+ UserItemCountList = new List<ItemByNameCounts>();
+ }
+
+ /// <summary>
+ /// Gets the user data key.
+ /// </summary>
+ /// <returns>System.String.</returns>
+ public override string GetUserDataKey()
+ {
+ return "Channel-" + Name;
+ }
+
+ [IgnoreDataMember]
+ public List<ItemByNameCounts> UserItemCountList { get; set; }
+
+ /// <summary>
+ /// Gets or sets the number.
+ /// </summary>
+ /// <value>The number.</value>
+ public string ChannelNumber { get; set; }
+
+ /// <summary>
+ /// Get or sets the Id.
+ /// </summary>
+ /// <value>The id of the channel.</value>
+ public string ChannelId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the service.
+ /// </summary>
+ /// <value>The name of the service.</value>
+ public string ServiceName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the type of the channel.
+ /// </summary>
+ /// <value>The type of the channel.</value>
+ public ChannelType ChannelType { get; set; }
+
+ protected override string CreateSortName()
+ {
+ double number = 0;
+
+ if (!string.IsNullOrEmpty(ChannelNumber))
+ {
+ double.TryParse(ChannelNumber, out number);
+ }
+
+ return number.ToString("000-") + (Name ?? string.Empty);
+ }
+
+ public override string MediaType
+ {
+ get
+ {
+ return ChannelType == ChannelType.Radio ? Model.Entities.MediaType.Audio : Model.Entities.MediaType.Video;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs
index 721c1e40a8..27fc596303 100644
--- a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs
+++ b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs
@@ -26,12 +26,6 @@ namespace MediaBrowser.Controller.LiveTv
public string Id { get; set; }
/// <summary>
- /// Gets or sets the name of the service.
- /// </summary>
- /// <value>The name of the service.</value>
- public string ServiceName { get; set; }
-
- /// <summary>
/// Gets or sets the type of the channel.
/// </summary>
/// <value>The type of the channel.</value>
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index 62bfdf3e58..4e73fc109f 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -1,6 +1,8 @@
-using System.Threading.Tasks;
-using MediaBrowser.Model.LiveTv;
+using MediaBrowser.Model.LiveTv;
+using MediaBrowser.Model.Querying;
using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
namespace MediaBrowser.Controller.LiveTv
{
@@ -16,16 +18,92 @@ namespace MediaBrowser.Controller.LiveTv
IReadOnlyList<ILiveTvService> Services { get; }
/// <summary>
+ /// Schedules the recording.
+ /// </summary>
+ /// <param name="programId">The program identifier.</param>
+ /// <returns>Task.</returns>
+ Task ScheduleRecording(string programId);
+
+ /// <summary>
+ /// Deletes the recording.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <returns>Task.</returns>
+ Task DeleteRecording(string id);
+
+ /// <summary>
+ /// Cancels the timer.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <returns>Task.</returns>
+ Task CancelTimer(string id);
+
+ /// <summary>
/// Adds the parts.
/// </summary>
/// <param name="services">The services.</param>
void AddParts(IEnumerable<ILiveTvService> services);
/// <summary>
- /// Gets the channel info dto.
+ /// Gets the channels.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <returns>IEnumerable{Channel}.</returns>
+ QueryResult<ChannelInfoDto> GetChannels(ChannelQuery query);
+
+ /// <summary>
+ /// Gets the recording.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{RecordingInfoDto}.</returns>
+ Task<RecordingInfoDto> GetRecording(string id, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the timer.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{TimerInfoDto}.</returns>
+ Task<TimerInfoDto> GetTimer(string id, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the recordings.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>QueryResult{RecordingInfoDto}.</returns>
+ Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the timers.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{QueryResult{TimerInfoDto}}.</returns>
+ Task<QueryResult<TimerInfoDto>> GetTimers(TimerQuery query, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the channel.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <returns>Channel.</returns>
+ Channel GetChannel(string id);
+
+ /// <summary>
+ /// Gets the channel.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <param name="userId">The user identifier.</param>
+ /// <returns>Channel.</returns>
+ ChannelInfoDto GetChannelInfoDto(string id, string userId);
+
+ /// <summary>
+ /// Gets the programs.
/// </summary>
- /// <param name="info">The info.</param>
- /// <returns>ChannelInfoDto.</returns>
- ChannelInfoDto GetChannelInfoDto(ChannelInfo info);
+ /// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>IEnumerable{ProgramInfo}.</returns>
+ Task<QueryResult<ProgramInfoDto>> GetPrograms(ProgramQuery query, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs
index 5c019ae8c4..a6c60d468d 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs
@@ -1,4 +1,4 @@
-using MediaBrowser.Model.LiveTv;
+using MediaBrowser.Common.Net;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -24,19 +24,88 @@ namespace MediaBrowser.Controller.LiveTv
Task<IEnumerable<ChannelInfo>> GetChannelsAsync(CancellationToken cancellationToken);
/// <summary>
+ /// Cancels the timer asynchronous.
+ /// </summary>
+ /// <param name="timerId">The timer identifier.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task CancelTimerAsync(string timerId, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Deletes the recording asynchronous.
+ /// </summary>
+ /// <param name="recordingId">The recording identifier.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task DeleteRecordingAsync(string recordingId, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Creates the timer asynchronous.
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task CreateTimerAsync(TimerInfo info, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Creates the series timer asynchronous.
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task CreateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Updates the series timer asynchronous.
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task UpdateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the channel image asynchronous.
+ /// </summary>
+ /// <param name="channelId">The channel identifier.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{Stream}.</returns>
+ Task<ImageResponseInfo> GetChannelImageAsync(string channelId, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the program image asynchronous.
+ /// </summary>
+ /// <param name="programId">The program identifier.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{ImageResponseInfo}.</returns>
+ Task<ImageResponseInfo> GetProgramImageAsync(string programId, CancellationToken cancellationToken);
+
+ /// <summary>
/// Gets the recordings asynchronous.
/// </summary>
- /// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{RecordingInfo}}.</returns>
- Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(RecordingQuery query, CancellationToken cancellationToken);
+ Task<IEnumerable<RecordingInfo>> GetRecordingsAsync(CancellationToken cancellationToken);
/// <summary>
- /// Gets the channel guides.
+ /// Gets the recordings asynchronous.
+ /// </summary>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{IEnumerable{RecordingInfo}}.</returns>
+ Task<IEnumerable<TimerInfo>> GetTimersAsync(CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the series timers asynchronous.
+ /// </summary>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{IEnumerable{SeriesTimerInfo}}.</returns>
+ Task<IEnumerable<SeriesTimerInfo>> GetSeriesTimersAsync(CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the programs asynchronous.
/// </summary>
- /// <param name="channelIdList">The channel identifier list.</param>
+ /// <param name="channelId">The channel identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{IEnumerable{ChannelGuide}}.</returns>
- Task<IEnumerable<ChannelGuide>> GetChannelGuidesAsync(IEnumerable<string> channelIdList, CancellationToken cancellationToken);
+ /// <returns>Task{IEnumerable{ProgramInfo}}.</returns>
+ Task<IEnumerable<ProgramInfo>> GetProgramsAsync(string channelId, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/LiveTv/ImageResponseInfo.cs b/MediaBrowser.Controller/LiveTv/ImageResponseInfo.cs
new file mode 100644
index 0000000000..d454a1ef8d
--- /dev/null
+++ b/MediaBrowser.Controller/LiveTv/ImageResponseInfo.cs
@@ -0,0 +1,19 @@
+using System.IO;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+ public class ImageResponseInfo
+ {
+ /// <summary>
+ /// Gets or sets the stream.
+ /// </summary>
+ /// <value>The stream.</value>
+ public Stream Stream { get; set; }
+
+ /// <summary>
+ /// Gets or sets the type of the MIME.
+ /// </summary>
+ /// <value>The type of the MIME.</value>
+ public string MimeType { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/LiveTv/ProgramInfo.cs b/MediaBrowser.Controller/LiveTv/ProgramInfo.cs
new file mode 100644
index 0000000000..cf5cdb94c9
--- /dev/null
+++ b/MediaBrowser.Controller/LiveTv/ProgramInfo.cs
@@ -0,0 +1,98 @@
+using MediaBrowser.Model.LiveTv;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+ public class ProgramInfo
+ {
+ /// <summary>
+ /// Id of the program.
+ /// </summary>
+ public string Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the channel identifier.
+ /// </summary>
+ /// <value>The channel identifier.</value>
+ public string ChannelId { get; set; }
+
+ /// <summary>
+ /// Name of the program
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the official rating.
+ /// </summary>
+ /// <value>The official rating.</value>
+ public string OfficialRating { get; set; }
+
+ /// <summary>
+ /// Description of the progam.
+ /// </summary>
+ public string Description { get; set; }
+
+ /// <summary>
+ /// The start date of the program, in UTC.
+ /// </summary>
+ public DateTime StartDate { get; set; }
+
+ /// <summary>
+ /// The end date of the program, in UTC.
+ /// </summary>
+ public DateTime EndDate { get; set; }
+
+ /// <summary>
+ /// Gets or sets the aspect ratio.
+ /// </summary>
+ /// <value>The aspect ratio.</value>
+ public string AspectRatio { get; set; }
+
+ /// <summary>
+ /// Genre of the program.
+ /// </summary>
+ public List<string> Genres { get; set; }
+
+ /// <summary>
+ /// Gets or sets the quality.
+ /// </summary>
+ /// <value>The quality.</value>
+ public ProgramVideoQuality Quality { get; set; }
+
+ /// <summary>
+ /// Gets or sets the original air date.
+ /// </summary>
+ /// <value>The original air date.</value>
+ public DateTime? OriginalAirDate { get; set; }
+
+ /// <summary>
+ /// Gets or sets the audio.
+ /// </summary>
+ /// <value>The audio.</value>
+ public ProgramAudio Audio { get; set; }
+
+ /// <summary>
+ /// Gets or sets the community rating.
+ /// </summary>
+ /// <value>The community rating.</value>
+ public float? CommunityRating { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is repeat.
+ /// </summary>
+ /// <value><c>true</c> if this instance is repeat; otherwise, <c>false</c>.</value>
+ public bool IsRepeat { get; set; }
+
+ /// <summary>
+ /// Gets or sets the episode title.
+ /// </summary>
+ /// <value>The episode title.</value>
+ public string EpisodeTitle { get; set; }
+
+ public ProgramInfo()
+ {
+ Genres = new List<string>();
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/LiveTv/RecordingInfo.cs b/MediaBrowser.Controller/LiveTv/RecordingInfo.cs
new file mode 100644
index 0000000000..2c8e8cb464
--- /dev/null
+++ b/MediaBrowser.Controller/LiveTv/RecordingInfo.cs
@@ -0,0 +1,102 @@
+using MediaBrowser.Model.LiveTv;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+ public class RecordingInfo
+ {
+ /// <summary>
+ /// Id of the recording.
+ /// </summary>
+ public string Id { get; set; }
+
+ /// <summary>
+ /// ChannelId of the recording.
+ /// </summary>
+ public string ChannelId { get; set; }
+
+ /// <summary>
+ /// ChannelName of the recording.
+ /// </summary>
+ public string ChannelName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the type of the channel.
+ /// </summary>
+ /// <value>The type of the channel.</value>
+ public ChannelType ChannelType { get; set; }
+
+ /// <summary>
+ /// Name of the recording.
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the path.
+ /// </summary>
+ /// <value>The path.</value>
+ public string Path { get; set; }
+
+ /// <summary>
+ /// Description of the recording.
+ /// </summary>
+ public string Description { get; set; }
+
+ /// <summary>
+ /// The start date of the recording, in UTC.
+ /// </summary>
+ public DateTime StartDate { get; set; }
+
+ /// <summary>
+ /// The end date of the recording, in UTC.
+ /// </summary>
+ public DateTime EndDate { get; set; }
+
+ /// <summary>
+ /// Gets or sets the program identifier.
+ /// </summary>
+ /// <value>The program identifier.</value>
+ public string ProgramId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the status.
+ /// </summary>
+ /// <value>The status.</value>
+ public RecordingStatus Status { get; set; }
+
+ /// <summary>
+ /// Genre of the program.
+ /// </summary>
+ public List<string> Genres { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is repeat.
+ /// </summary>
+ /// <value><c>true</c> if this instance is repeat; otherwise, <c>false</c>.</value>
+ public bool IsRepeat { get; set; }
+
+ /// <summary>
+ /// Gets or sets the episode title.
+ /// </summary>
+ /// <value>The episode title.</value>
+ public string EpisodeTitle { get; set; }
+
+ /// <summary>
+ /// Gets or sets the official rating.
+ /// </summary>
+ /// <value>The official rating.</value>
+ public string OfficialRating { get; set; }
+
+ /// <summary>
+ /// Gets or sets the community rating.
+ /// </summary>
+ /// <value>The community rating.</value>
+ public float? CommunityRating { get; set; }
+
+ public RecordingInfo()
+ {
+ Genres = new List<string>();
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/LiveTv/SeriesTimerInfo.cs b/MediaBrowser.Controller/LiveTv/SeriesTimerInfo.cs
new file mode 100644
index 0000000000..44594882cd
--- /dev/null
+++ b/MediaBrowser.Controller/LiveTv/SeriesTimerInfo.cs
@@ -0,0 +1,85 @@
+using MediaBrowser.Model.LiveTv;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+ public class SeriesTimerInfo
+ {
+ /// <summary>
+ /// Id of the recording.
+ /// </summary>
+ public string Id { get; set; }
+
+ /// <summary>
+ /// ChannelId of the recording.
+ /// </summary>
+ public string ChannelId { get; set; }
+
+ /// <summary>
+ /// ChannelName of the recording.
+ /// </summary>
+ public string ChannelName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the program identifier.
+ /// </summary>
+ /// <value>The program identifier.</value>
+ public string ProgramId { get; set; }
+
+ /// <summary>
+ /// Name of the recording.
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Description of the recording.
+ /// </summary>
+ public string Description { get; set; }
+
+ /// <summary>
+ /// The start date of the recording, in UTC.
+ /// </summary>
+ public DateTime StartDate { get; set; }
+
+ /// <summary>
+ /// The end date of the recording, in UTC.
+ /// </summary>
+ public DateTime EndDate { get; set; }
+
+ /// <summary>
+ /// Gets or sets the pre padding seconds.
+ /// </summary>
+ /// <value>The pre padding seconds.</value>
+ public int PrePaddingSeconds { get; set; }
+
+ /// <summary>
+ /// Gets or sets the post padding seconds.
+ /// </summary>
+ /// <value>The post padding seconds.</value>
+ public int PostPaddingSeconds { get; set; }
+
+ /// <summary>
+ /// Gets or sets the type of the recurrence.
+ /// </summary>
+ /// <value>The type of the recurrence.</value>
+ public RecurrenceType RecurrenceType { get; set; }
+
+ /// <summary>
+ /// Gets or sets the days.
+ /// </summary>
+ /// <value>The days.</value>
+ public List<DayOfWeek> Days { get; set; }
+
+ /// <summary>
+ /// Gets or sets the priority.
+ /// </summary>
+ /// <value>The priority.</value>
+ public int Priority { get; set; }
+
+ public SeriesTimerInfo()
+ {
+ Days = new List<DayOfWeek>();
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/LiveTv/TimerInfo.cs b/MediaBrowser.Controller/LiveTv/TimerInfo.cs
new file mode 100644
index 0000000000..3df0b8ccab
--- /dev/null
+++ b/MediaBrowser.Controller/LiveTv/TimerInfo.cs
@@ -0,0 +1,73 @@
+using MediaBrowser.Model.LiveTv;
+using System;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+ public class TimerInfo
+ {
+ /// <summary>
+ /// Id of the recording.
+ /// </summary>
+ public string Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the series timer identifier.
+ /// </summary>
+ /// <value>The series timer identifier.</value>
+ public string SeriesTimerId { get; set; }
+
+ /// <summary>
+ /// ChannelId of the recording.
+ /// </summary>
+ public string ChannelId { get; set; }
+
+ /// <summary>
+ /// ChannelName of the recording.
+ /// </summary>
+ public string ChannelName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the program identifier.
+ /// </summary>
+ /// <value>The program identifier.</value>
+ public string ProgramId { get; set; }
+
+ /// <summary>
+ /// Name of the recording.
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Description of the recording.
+ /// </summary>
+ public string Description { get; set; }
+
+ /// <summary>
+ /// The start date of the recording, in UTC.
+ /// </summary>
+ public DateTime StartDate { get; set; }
+
+ /// <summary>
+ /// The end date of the recording, in UTC.
+ /// </summary>
+ public DateTime EndDate { get; set; }
+
+ /// <summary>
+ /// Gets or sets the status.
+ /// </summary>
+ /// <value>The status.</value>
+ public RecordingStatus Status { get; set; }
+
+ /// <summary>
+ /// Gets or sets the pre padding seconds.
+ /// </summary>
+ /// <value>The pre padding seconds.</value>
+ public int PrePaddingSeconds { get; set; }
+
+ /// <summary>
+ /// Gets or sets the post padding seconds.
+ /// </summary>
+ /// <value>The post padding seconds.</value>
+ public int PostPaddingSeconds { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index f2837a1f1d..2beb3588ed 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -89,8 +89,11 @@
<Compile Include="Entities\GameGenre.cs" />
<Compile Include="Entities\GameSystem.cs" />
<Compile Include="Entities\IByReferenceItem.cs" />
+ <Compile Include="Entities\IHasAspectRatio.cs" />
+ <Compile Include="Entities\IHasBudget.cs" />
<Compile Include="Entities\IHasCriticRating.cs" />
<Compile Include="Entities\IHasSoundtracks.cs" />
+ <Compile Include="Entities\IHasTrailers.cs" />
<Compile Include="Entities\IItemByName.cs" />
<Compile Include="Entities\ILibraryItem.cs" />
<Compile Include="Entities\ImageSourceInfo.cs" />
@@ -103,18 +106,24 @@
<Compile Include="Library\ItemUpdateType.cs" />
<Compile Include="Library\IUserDataManager.cs" />
<Compile Include="Library\UserDataSaveEventArgs.cs" />
+ <Compile Include="LiveTv\Channel.cs" />
<Compile Include="LiveTv\ChannelInfo.cs" />
<Compile Include="LiveTv\ILiveTvManager.cs" />
<Compile Include="LiveTv\ILiveTvService.cs" />
+ <Compile Include="LiveTv\ImageResponseInfo.cs" />
+ <Compile Include="LiveTv\ProgramInfo.cs" />
+ <Compile Include="LiveTv\RecordingInfo.cs" />
+ <Compile Include="LiveTv\SeriesTimerInfo.cs" />
+ <Compile Include="LiveTv\TimerInfo.cs" />
<Compile Include="Localization\ILocalizationManager.cs" />
<Compile Include="Notifications\INotificationsRepository.cs" />
<Compile Include="Notifications\NotificationUpdateEventArgs.cs" />
<Compile Include="Providers\IDynamicInfoProvider.cs" />
<Compile Include="Providers\IImageProvider.cs" />
+ <Compile Include="Providers\NameParser.cs" />
<Compile Include="Session\ISessionManager.cs" />
<Compile Include="Drawing\ImageExtensions.cs" />
<Compile Include="Entities\AggregateFolder.cs" />
- <Compile Include="Entities\Audio\Artist.cs" />
<Compile Include="Entities\Audio\Audio.cs" />
<Compile Include="Entities\Audio\MusicAlbum.cs" />
<Compile Include="Entities\Audio\MusicArtist.cs" />
diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
index 9fdbbf3b7e..617e4fd819 100644
--- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
+++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
@@ -69,6 +69,12 @@ namespace MediaBrowser.Controller.Providers
item.People.Clear();
item.Tags.Clear();
+ var hasTrailers = item as IHasTrailers;
+ if (hasTrailers != null)
+ {
+ hasTrailers.RemoteTrailers.Clear();
+ }
+
//Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken);
Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken);
}
@@ -161,10 +167,14 @@ namespace MediaBrowser.Controller.Providers
case "Budget":
{
var text = reader.ReadElementContentAsString();
- double value;
- if (double.TryParse(text, NumberStyles.Any, _usCulture, out value))
+ var hasBudget = item as IHasBudget;
+ if (hasBudget != null)
{
- item.Budget = value;
+ double value;
+ if (double.TryParse(text, NumberStyles.Any, _usCulture, out value))
+ {
+ hasBudget.Budget = value;
+ }
}
break;
@@ -173,10 +183,14 @@ namespace MediaBrowser.Controller.Providers
case "Revenue":
{
var text = reader.ReadElementContentAsString();
- double value;
- if (double.TryParse(text, NumberStyles.Any, _usCulture, out value))
+ var hasBudget = item as IHasBudget;
+ if (hasBudget != null)
{
- item.Revenue = value;
+ double value;
+ if (double.TryParse(text, NumberStyles.Any, _usCulture, out value))
+ {
+ hasBudget.Revenue = value;
+ }
}
break;
@@ -375,9 +389,10 @@ namespace MediaBrowser.Controller.Providers
{
var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
+ var hasAspectRatio = item as IHasAspectRatio;
+ if (!string.IsNullOrWhiteSpace(val) && hasAspectRatio != null)
{
- item.AspectRatio = val;
+ hasAspectRatio.AspectRatio = val;
}
break;
}
@@ -474,9 +489,26 @@ namespace MediaBrowser.Controller.Providers
{
var val = reader.ReadElementContentAsString();
- if (!string.IsNullOrWhiteSpace(val))
+ var hasTrailers = item as IHasTrailers;
+ if (hasTrailers != null)
{
- item.AddTrailerUrl(val, false);
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ hasTrailers.AddTrailerUrl(val, false);
+ }
+ }
+ break;
+ }
+
+ case "Trailers":
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ var hasTrailers = item as IHasTrailers;
+ if (hasTrailers != null)
+ {
+ FetchDataFromTrailersNode(subtree, hasTrailers);
+ }
}
break;
}
@@ -921,6 +953,35 @@ namespace MediaBrowser.Controller.Providers
}
}
+ private void FetchDataFromTrailersNode(XmlReader reader, IHasTrailers item)
+ {
+ reader.MoveToContent();
+
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Trailer":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.AddTrailerUrl(val, false);
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ }
+
protected async Task FetchChaptersFromXmlNode(BaseItem item, XmlReader reader, IItemRepository repository, CancellationToken cancellationToken)
{
var runtime = item.RunTimeTicks ?? 0;
@@ -1071,9 +1132,10 @@ namespace MediaBrowser.Controller.Providers
/// <returns>IEnumerable{PersonInfo}.</returns>
private IEnumerable<PersonInfo> GetPersonsFromXmlNode(XmlReader reader)
{
- var names = new List<string>();
+ var name = string.Empty;
var type = "Actor"; // If type is not specified assume actor
var role = string.Empty;
+ int? sortOrder = null;
reader.MoveToContent();
@@ -1084,7 +1146,7 @@ namespace MediaBrowser.Controller.Providers
switch (reader.Name)
{
case "Name":
- names.AddRange(SplitNames(reader.ReadElementContentAsString()));
+ name = reader.ReadElementContentAsString() ?? string.Empty;
break;
case "Type":
@@ -1108,6 +1170,20 @@ namespace MediaBrowser.Controller.Providers
}
break;
}
+ case "SortOrder":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int intVal;
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out intVal))
+ {
+ sortOrder = intVal;
+ }
+ }
+ break;
+ }
default:
reader.Skip();
@@ -1116,7 +1192,15 @@ namespace MediaBrowser.Controller.Providers
}
}
- return names.Select(n => new PersonInfo { Name = n.Trim(), Role = role, Type = type });
+ var personInfo = new PersonInfo
+ {
+ Name = name.Trim(),
+ Role = role,
+ Type = type,
+ SortOrder = sortOrder
+ };
+
+ return new[] { personInfo };
}
/// <summary>
diff --git a/MediaBrowser.Controller/Providers/NameParser.cs b/MediaBrowser.Controller/Providers/NameParser.cs
new file mode 100644
index 0000000000..726f0e60e3
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/NameParser.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Text.RegularExpressions;
+
+namespace MediaBrowser.Controller.Providers
+{
+ public static class NameParser
+ {
+ static readonly Regex[] NameMatches = new[] {
+ new Regex(@"(?<name>.*)\((?<year>\d{4})\)"), // matches "My Movie (2001)" and gives us the name and the year
+ new Regex(@"(?<name>.*)(\.(?<year>\d{4})(\.|$)).*$"),
+ new Regex(@"(?<name>.*)") // last resort matches the whole string as the name
+ };
+
+
+ /// <summary>
+ /// Parses the name.
+ /// </summary>
+ /// <param name="name">The name.</param>
+ /// <param name="justName">Name of the just.</param>
+ /// <param name="year">The year.</param>
+ public static void ParseName(string name, out string justName, out int? year)
+ {
+ justName = null;
+ year = null;
+ foreach (var re in NameMatches)
+ {
+ Match m = re.Match(name);
+ if (m.Success)
+ {
+ justName = m.Groups["name"].Value.Trim();
+ string y = m.Groups["year"] != null ? m.Groups["year"].Value : null;
+ int temp;
+ year = Int32.TryParse(y, out temp) ? temp : (int?)null;
+ break;
+ }
+ }
+ }
+ }
+}