aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
authorhatharry <hatharry@hotmail.com>2016-08-29 01:27:43 +1200
committerhatharry <hatharry@hotmail.com>2016-08-29 01:27:43 +1200
commitcabf2cdc1be4c06714ac6bcf835a19d2f652a6e2 (patch)
treed375b8a41e9fd40a2569ceea6b02e4f8237db797 /MediaBrowser.Controller
parente564b54686029a90595e1bb4277f87490763e183 (diff)
parentc974641a352685b2e6595dd7b291843c8e6364ac (diff)
Merge branch 'dev' of https://github.com/hatharry/Emby.git
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Channels/Channel.cs5
-rw-r--r--MediaBrowser.Controller/Channels/ChannelMediaInfo.cs6
-rw-r--r--MediaBrowser.Controller/Dto/DtoOptions.cs4
-rw-r--r--MediaBrowser.Controller/Dto/IDtoService.cs21
-rw-r--r--MediaBrowser.Controller/Entities/AggregateFolder.cs61
-rw-r--r--MediaBrowser.Controller/Entities/Audio/Audio.cs9
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs57
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicGenre.cs51
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs53
-rw-r--r--MediaBrowser.Controller/Entities/Book.cs2
-rw-r--r--MediaBrowser.Controller/Entities/CollectionFolder.cs74
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs68
-rw-r--r--MediaBrowser.Controller/Entities/Game.cs2
-rw-r--r--MediaBrowser.Controller/Entities/GameGenre.cs50
-rw-r--r--MediaBrowser.Controller/Entities/Genre.cs51
-rw-r--r--MediaBrowser.Controller/Entities/IHasImages.cs3
-rw-r--r--MediaBrowser.Controller/Entities/IHasMetadata.cs13
-rw-r--r--MediaBrowser.Controller/Entities/IItemByName.cs3
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs2
-rw-r--r--MediaBrowser.Controller/Entities/InternalPeopleQuery.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs36
-rw-r--r--MediaBrowser.Controller/Entities/Movies/Movie.cs10
-rw-r--r--MediaBrowser.Controller/Entities/MusicVideo.cs1
-rw-r--r--MediaBrowser.Controller/Entities/Person.cs66
-rw-r--r--MediaBrowser.Controller/Entities/Photo.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Studio.cs51
-rw-r--r--MediaBrowser.Controller/Entities/TV/Episode.cs46
-rw-r--r--MediaBrowser.Controller/Entities/TV/Season.cs70
-rw-r--r--MediaBrowser.Controller/Entities/TV/Series.cs223
-rw-r--r--MediaBrowser.Controller/Entities/Trailer.cs12
-rw-r--r--MediaBrowser.Controller/Entities/User.cs2
-rw-r--r--MediaBrowser.Controller/Entities/UserRootFolder.cs42
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs83
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs27
-rw-r--r--MediaBrowser.Controller/Entities/Year.cs43
-rw-r--r--MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs24
-rw-r--r--MediaBrowser.Controller/IServerApplicationPaths.cs2
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs26
-rw-r--r--MediaBrowser.Controller/Library/ItemResolveArgs.cs9
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs5
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvProgram.cs1
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs1
-rw-r--r--MediaBrowser.Controller/LiveTv/TimerEventInfo.cs8
-rw-r--r--MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs8
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj1
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs3
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs3
-rw-r--r--MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs7
-rw-r--r--MediaBrowser.Controller/Net/IAsyncStreamSource.cs18
-rw-r--r--MediaBrowser.Controller/Net/IHttpResultFactory.cs2
-rw-r--r--MediaBrowser.Controller/Persistence/IItemRepository.cs7
-rw-r--r--MediaBrowser.Controller/Playlists/Playlist.cs12
-rw-r--r--MediaBrowser.Controller/Providers/BaseItemXmlParser.cs9
-rw-r--r--MediaBrowser.Controller/Providers/DirectoryService.cs28
-rw-r--r--MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs3
-rw-r--r--MediaBrowser.Controller/Session/ISessionManager.cs12
-rw-r--r--MediaBrowser.Controller/Sync/ISyncManager.cs2
-rw-r--r--MediaBrowser.Controller/Sync/ISyncRepository.cs5
-rw-r--r--MediaBrowser.Controller/Sync/SyncedItemProgress.cs2
59 files changed, 1037 insertions, 412 deletions
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index 718a0d878..e0b7204b8 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -57,10 +57,7 @@ namespace MediaBrowser.Controller.Channels
catch
{
// Already logged at lower levels
- return new QueryResult<BaseItem>
- {
-
- };
+ return new QueryResult<BaseItem>();
}
}
diff --git a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
index 9424568b4..1216ae352 100644
--- a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
+++ b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
@@ -83,8 +83,7 @@ namespace MediaBrowser.Controller.Channels
{
var list = new List<MediaStream>();
- if (!string.IsNullOrWhiteSpace(info.VideoCodec) &&
- !string.IsNullOrWhiteSpace(info.AudioCodec))
+ if (!string.IsNullOrWhiteSpace(info.VideoCodec))
{
list.Add(new MediaStream
{
@@ -99,7 +98,10 @@ namespace MediaBrowser.Controller.Channels
BitRate = info.VideoBitrate,
AverageFrameRate = info.Framerate
});
+ }
+ if (!string.IsNullOrWhiteSpace(info.AudioCodec))
+ {
list.Add(new MediaStream
{
Type = MediaStreamType.Audio,
diff --git a/MediaBrowser.Controller/Dto/DtoOptions.cs b/MediaBrowser.Controller/Dto/DtoOptions.cs
index d627cc67a..e69b64948 100644
--- a/MediaBrowser.Controller/Dto/DtoOptions.cs
+++ b/MediaBrowser.Controller/Dto/DtoOptions.cs
@@ -19,12 +19,16 @@ namespace MediaBrowser.Controller.Dto
public bool EnableImages { get; set; }
public bool AddProgramRecordingInfo { get; set; }
public string DeviceId { get; set; }
+ public bool EnableUserData { get; set; }
+ public bool AddCurrentProgram { get; set; }
public DtoOptions()
{
Fields = new List<ItemFields>();
ImageTypeLimit = int.MaxValue;
EnableImages = true;
+ EnableUserData = true;
+ AddCurrentProgram = true;
Fields = Enum.GetNames(typeof (ItemFields))
.Select(i => (ItemFields) Enum.Parse(typeof (ItemFields), i, true))
diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs
index e4aa466df..a6f807ce9 100644
--- a/MediaBrowser.Controller/Dto/IDtoService.cs
+++ b/MediaBrowser.Controller/Dto/IDtoService.cs
@@ -1,9 +1,9 @@
-using System;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using System.Collections.Generic;
using System.Threading.Tasks;
+using MediaBrowser.Controller.Sync;
namespace MediaBrowser.Controller.Dto
{
@@ -44,14 +44,6 @@ namespace MediaBrowser.Controller.Dto
BaseItemDto GetBaseItemDto(BaseItem item, List<ItemFields> fields, User user = null, BaseItem owner = null);
/// <summary>
- /// Fills the synchronize information.
- /// </summary>
- /// <param name="tuples">The tuples.</param>
- /// <param name="options">The options.</param>
- /// <param name="user">The user.</param>
- void FillSyncInfo(IEnumerable<Tuple<BaseItem, BaseItemDto>> tuples, DtoOptions options, User user);
-
- /// <summary>
/// Gets the base item dto.
/// </summary>
/// <param name="item">The item.</param>
@@ -89,11 +81,8 @@ namespace MediaBrowser.Controller.Dto
/// <summary>
/// Gets the item by name dto.
/// </summary>
- /// <param name="item">The item.</param>
- /// <param name="options">The options.</param>
- /// <param name="taggedItems">The tagged items.</param>
- /// <param name="user">The user.</param>
- /// <returns>BaseItemDto.</returns>
- BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem> taggedItems, User user = null);
+ BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem> taggedItems, Dictionary<string, SyncedItemProgress> syncProgress, User user = null);
+
+ Dictionary<string, SyncedItemProgress> GetSyncedItemProgress(DtoOptions options);
}
}
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs
index 588a65e98..efc450248 100644
--- a/MediaBrowser.Controller/Entities/AggregateFolder.cs
+++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs
@@ -5,6 +5,8 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using System.Threading;
+using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Controller.Providers;
@@ -67,6 +69,31 @@ namespace MediaBrowser.Controller.Entities
return CreateResolveArgs(directoryService, true).FileSystemChildren;
}
+ private List<Guid> _childrenIds = null;
+ private readonly object _childIdsLock = new object();
+ protected override IEnumerable<BaseItem> LoadChildren()
+ {
+ lock (_childIdsLock)
+ {
+ if (_childrenIds == null || _childrenIds.Count == 0)
+ {
+ var list = base.LoadChildren().ToList();
+ _childrenIds = list.Select(i => i.Id).ToList();
+ return list;
+ }
+
+ return _childrenIds.Select(LibraryManager.GetItemById).Where(i => i != null).ToList();
+ }
+ }
+
+ private void ClearCache()
+ {
+ lock (_childIdsLock)
+ {
+ _childrenIds = null;
+ }
+ }
+
private bool _requiresRefresh;
public override bool RequiresRefresh()
{
@@ -76,7 +103,7 @@ namespace MediaBrowser.Controller.Entities
{
var locations = PhysicalLocations.ToList();
- var newLocations = CreateResolveArgs(new DirectoryService(BaseItem.FileSystem), false).PhysicalLocations.ToList();
+ var newLocations = CreateResolveArgs(new DirectoryService(Logger, FileSystem), false).PhysicalLocations.ToList();
if (!locations.SequenceEqual(newLocations))
{
@@ -89,6 +116,8 @@ namespace MediaBrowser.Controller.Entities
public override bool BeforeMetadataRefresh()
{
+ ClearCache();
+
var changed = base.BeforeMetadataRefresh() || _requiresRefresh;
_requiresRefresh = false;
return changed;
@@ -96,9 +125,11 @@ namespace MediaBrowser.Controller.Entities
private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService, bool setPhysicalLocations)
{
+ ClearCache();
+
var path = ContainingFolderPath;
- var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths , directoryService)
+ var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService)
{
FileInfo = FileSystem.GetDirectoryInfo(path),
Path = path,
@@ -135,7 +166,22 @@ namespace MediaBrowser.Controller.Entities
return args;
}
-
+
+ protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
+ {
+ return base.GetNonCachedChildren(directoryService).Concat(_virtualChildren);
+ }
+
+ protected override async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
+ {
+ ClearCache();
+
+ await base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService)
+ .ConfigureAwait(false);
+
+ ClearCache();
+ }
+
/// <summary>
/// Adds the virtual child.
/// </summary>
@@ -152,15 +198,6 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
- /// Get the children of this folder from the actual file system
- /// </summary>
- /// <returns>IEnumerable{BaseItem}.</returns>
- protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
- {
- return base.GetNonCachedChildren(directoryService).Concat(_virtualChildren);
- }
-
- /// <summary>
/// Finds the virtual child.
/// </summary>
/// <param name="id">The id.</param>
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 1897511af..1af55a389 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -5,9 +5,11 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.MediaInfo;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Channels;
namespace MediaBrowser.Controller.Entities.Audio
@@ -47,7 +49,7 @@ namespace MediaBrowser.Controller.Entities.Audio
}
[IgnoreDataMember]
- public override bool EnableForceSaveOnDateModifiedChange
+ public override bool EnableRefreshOnDateModifiedChange
{
get { return true; }
}
@@ -266,6 +268,11 @@ namespace MediaBrowser.Controller.Entities.Audio
Size = i.Size
};
+ if (info.Protocol == MediaProtocol.File)
+ {
+ info.ETag = i.DateModified.Ticks.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N");
+ }
+
if (string.IsNullOrEmpty(info.Container))
{
if (!string.IsNullOrWhiteSpace(i.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual)
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index 6790a1bcf..81d1deaa2 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -169,13 +169,9 @@ namespace MediaBrowser.Controller.Entities.Audio
list.Add("Artist-" + (item.Name ?? string.Empty).RemoveDiacritics());
return list;
}
-
- public override string PresentationUniqueKey
+ public override string CreatePresentationUniqueKey()
{
- get
- {
- return "Artist-" + (Name ?? string.Empty).RemoveDiacritics();
- }
+ return "Artist-" + (Name ?? string.Empty).RemoveDiacritics();
}
protected override bool GetBlockUnratedValue(UserPolicy config)
{
@@ -274,5 +270,54 @@ namespace MediaBrowser.Controller.Entities.Audio
return false;
}
}
+
+ public static string GetPath(string name, bool normalizeName = true)
+ {
+ // Trim the period at the end because windows will have a hard time with that
+ var validName = normalizeName ?
+ FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
+ name;
+
+ return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.ArtistsPath, validName);
+ }
+
+ private string GetRebasedPath()
+ {
+ return GetPath(System.IO.Path.GetFileName(Path), false);
+ }
+
+ public override bool RequiresRefresh()
+ {
+ if (IsAccessedByName)
+ {
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
+ return true;
+ }
+ }
+ return base.RequiresRefresh();
+ }
+
+ /// <summary>
+ /// This is called before any metadata refresh and returns true or false indicating if changes were made
+ /// </summary>
+ public override bool BeforeMetadataRefresh()
+ {
+ var hasChanges = base.BeforeMetadataRefresh();
+
+ if (IsAccessedByName)
+ {
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Path = newPath;
+ hasChanges = true;
+ }
+ }
+
+ return hasChanges;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
index 798bc79fb..bd991d9f4 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
@@ -18,13 +18,9 @@ namespace MediaBrowser.Controller.Entities.Audio
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
return list;
}
-
- public override string PresentationUniqueKey
+ public override string CreatePresentationUniqueKey()
{
- get
- {
- return GetUserDataKeys()[0];
- }
+ return GetUserDataKeys()[0];
}
[IgnoreDataMember]
@@ -96,5 +92,48 @@ namespace MediaBrowser.Controller.Entities.Audio
return LibraryManager.GetItemList(query);
}
+
+ public static string GetPath(string name, bool normalizeName = true)
+ {
+ // Trim the period at the end because windows will have a hard time with that
+ var validName = normalizeName ?
+ FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
+ name;
+
+ return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.MusicGenrePath, validName);
+ }
+
+ private string GetRebasedPath()
+ {
+ return GetPath(System.IO.Path.GetFileName(Path), false);
+ }
+
+ public override bool RequiresRefresh()
+ {
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
+ return true;
+ }
+ return base.RequiresRefresh();
+ }
+
+ /// <summary>
+ /// This is called before any metadata refresh and returns true or false indicating if changes were made
+ /// </summary>
+ public override bool BeforeMetadataRefresh()
+ {
+ var hasChanges = base.BeforeMetadataRefresh();
+
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Path = newPath;
+ hasChanges = true;
+ }
+
+ return hasChanges;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index c7a6b75ff..55aaf04ff 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -281,6 +281,20 @@ namespace MediaBrowser.Controller.Entities
}
}
+ public Task UpdateIsOffline(bool newValue)
+ {
+ var item = this;
+
+ if (item.IsOffline != newValue)
+ {
+ item.IsOffline = newValue;
+ // this is creating too many repeated db updates
+ //return item.UpdateToRepository(ItemUpdateType.None, CancellationToken.None);
+ }
+
+ return Task.FromResult(true);
+ }
+
/// <summary>
/// Gets or sets the type of the location.
/// </summary>
@@ -290,10 +304,10 @@ namespace MediaBrowser.Controller.Entities
{
get
{
- if (IsOffline)
- {
- return LocationType.Offline;
- }
+ //if (IsOffline)
+ //{
+ // return LocationType.Offline;
+ //}
if (string.IsNullOrWhiteSpace(Path))
{
@@ -455,7 +469,7 @@ namespace MediaBrowser.Controller.Entities
public DateTime DateLastRefreshed { get; set; }
[IgnoreDataMember]
- public virtual bool EnableForceSaveOnDateModifiedChange
+ public virtual bool EnableRefreshOnDateModifiedChange
{
get { return false; }
}
@@ -767,6 +781,9 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public string OfficialRating { get; set; }
+ [IgnoreDataMember]
+ public int InheritedParentalRatingValue { get; set; }
+
/// <summary>
/// Gets or sets the critic rating.
/// </summary>
@@ -951,7 +968,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => !i.IsDirectory && string.Equals(FileSystem.GetFileNameWithoutExtension(i), ThemeSongFilename, StringComparison.OrdinalIgnoreCase))
);
- return LibraryManager.ResolvePaths(files, directoryService, null)
+ return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions())
.OfType<Audio.Audio>()
.Select(audio =>
{
@@ -981,7 +998,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => string.Equals(i.Name, ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
.SelectMany(i => directoryService.GetFiles(i.FullName));
- return LibraryManager.ResolvePaths(files, directoryService, null)
+ return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions())
.OfType<Video>()
.Select(item =>
{
@@ -1003,7 +1020,7 @@ namespace MediaBrowser.Controller.Entities
public Task RefreshMetadata(CancellationToken cancellationToken)
{
- return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(FileSystem)), cancellationToken);
+ return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(Logger, FileSystem)), cancellationToken);
}
/// <summary>
@@ -1194,10 +1211,17 @@ namespace MediaBrowser.Controller.Entities
get { return null; }
}
+ public virtual string CreatePresentationUniqueKey()
+ {
+ return Id.ToString("N");
+ }
+
[IgnoreDataMember]
- public virtual string PresentationUniqueKey
+ public string PresentationUniqueKey { get; set; }
+
+ public string GetPresentationUniqueKey()
{
- get { return Id.ToString("N"); }
+ return PresentationUniqueKey ?? CreatePresentationUniqueKey();
}
public virtual bool RequiresRefresh()
@@ -2206,6 +2230,15 @@ namespace MediaBrowser.Controller.Entities
}
}
+ [IgnoreDataMember]
+ public virtual bool StopRefreshIfLocalMetadataFound
+ {
+ get
+ {
+ return true;
+ }
+ }
+
public virtual IEnumerable<Guid> GetIdsForAncestorQuery()
{
return new[] { Id };
diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs
index 59ab95437..56f9fa784 100644
--- a/MediaBrowser.Controller/Entities/Book.cs
+++ b/MediaBrowser.Controller/Entities/Book.cs
@@ -35,7 +35,7 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
- public override bool EnableForceSaveOnDateModifiedChange
+ public override bool EnableRefreshOnDateModifiedChange
{
get { return true; }
}
diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index 35dfd52e9..597ecf973 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -3,11 +3,15 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
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;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Serialization;
using MoreLinq;
namespace MediaBrowser.Controller.Entities
@@ -18,6 +22,8 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class CollectionFolder : Folder, ICollectionFolder
{
+ public static IXmlSerializer XmlSerializer { get; set; }
+
public CollectionFolder()
{
PhysicalLocationsList = new List<string>();
@@ -39,6 +45,72 @@ namespace MediaBrowser.Controller.Entities
public string CollectionType { get; set; }
+ private static readonly Dictionary<string, LibraryOptions> LibraryOptions = new Dictionary<string, LibraryOptions>();
+ public LibraryOptions GetLibraryOptions()
+ {
+ lock (LibraryOptions)
+ {
+ LibraryOptions options;
+ if (!LibraryOptions.TryGetValue(Path, out options))
+ {
+ options = LoadLibraryOptions();
+ LibraryOptions[Path] = options;
+ }
+
+ return options;
+ }
+ }
+
+ private LibraryOptions LoadLibraryOptions()
+ {
+ try
+ {
+ var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(Path)) as LibraryOptions;
+
+ if (result == null)
+ {
+ return new LibraryOptions();
+ }
+
+ return result;
+ }
+ catch (FileNotFoundException)
+ {
+ return new LibraryOptions();
+ }
+ catch (DirectoryNotFoundException)
+ {
+ return new LibraryOptions();
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error loading library options", ex);
+
+ return new LibraryOptions();
+ }
+ }
+
+ private static string GetLibraryOptionsPath(string path)
+ {
+ return System.IO.Path.Combine(path, "options.xml");
+ }
+
+ public void UpdateLibraryOptions(LibraryOptions options)
+ {
+ SaveLibraryOptions(Path, options);
+ }
+
+ public static void SaveLibraryOptions(string path, LibraryOptions options)
+ {
+ lock (LibraryOptions)
+ {
+ LibraryOptions[path] = options;
+
+ options.SchemaVersion = 1;
+ XmlSerializer.SerializeToFile(options, GetLibraryOptionsPath(path));
+ }
+ }
+
/// <summary>
/// Allow different display preferences for each collection folder
/// </summary>
@@ -82,7 +154,7 @@ namespace MediaBrowser.Controller.Entities
{
var locations = PhysicalLocations.ToList();
- var newLocations = CreateResolveArgs(new DirectoryService(BaseItem.FileSystem), false).PhysicalLocations.ToList();
+ var newLocations = CreateResolveArgs(new DirectoryService(Logger, FileSystem), false).PhysicalLocations.ToList();
if (!locations.SequenceEqual(newLocations))
{
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 0397e9a88..bf47ada0d 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Common.Progress;
-using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
@@ -14,6 +13,8 @@ using System.Threading;
using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Model.Channels;
namespace MediaBrowser.Controller.Entities
@@ -273,13 +274,14 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
protected virtual IEnumerable<BaseItem> LoadChildren()
{
+ //Logger.Debug("Loading children from {0} {1} {2}", GetType().Name, Id, Path);
//just load our children from the repo - the library will be validated and maintained in other processes
return GetCachedChildren();
}
public Task ValidateChildren(IProgress<double> progress, CancellationToken cancellationToken)
{
- return ValidateChildren(progress, cancellationToken, new MetadataRefreshOptions(new DirectoryService(FileSystem)));
+ return ValidateChildren(progress, cancellationToken, new MetadataRefreshOptions(new DirectoryService(Logger, FileSystem)));
}
/// <summary>
@@ -373,7 +375,7 @@ namespace MediaBrowser.Controller.Entities
if (currentChildren.TryGetValue(child.Id, out currentChild) && IsValidFromResolver(currentChild, child))
{
- await UpdateIsOffline(currentChild, false).ConfigureAwait(false);
+ await currentChild.UpdateIsOffline(false).ConfigureAwait(false);
validChildren.Add(currentChild);
continue;
@@ -402,7 +404,7 @@ namespace MediaBrowser.Controller.Entities
else if (!string.IsNullOrEmpty(item.Path) && IsPathOffline(item.Path))
{
- await UpdateIsOffline(item, true).ConfigureAwait(false);
+ await item.UpdateIsOffline(true).ConfigureAwait(false);
}
else
{
@@ -459,17 +461,6 @@ namespace MediaBrowser.Controller.Entities
progress.Report(100);
}
- private Task UpdateIsOffline(BaseItem item, bool newValue)
- {
- if (item.IsOffline != newValue)
- {
- item.IsOffline = newValue;
- return item.UpdateToRepository(ItemUpdateType.None, CancellationToken.None);
- }
-
- return Task.FromResult(true);
- }
-
private async Task RefreshMetadataRecursive(MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken)
{
var children = ActualChildren.ToList();
@@ -643,8 +634,9 @@ namespace MediaBrowser.Controller.Entities
protected virtual IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
{
var collectionType = LibraryManager.GetContentType(this);
+ var libraryOptions = LibraryManager.GetLibraryOptions(this);
- return LibraryManager.ResolvePaths(GetFileSystemChildren(directoryService), directoryService, this, collectionType);
+ return LibraryManager.ResolvePaths(GetFileSystemChildren(directoryService), directoryService, this, libraryOptions, collectionType);
}
/// <summary>
@@ -699,7 +691,7 @@ namespace MediaBrowser.Controller.Entities
items = GetRecursiveChildren(user, query);
}
- return PostFilterAndSort(items, query);
+ return PostFilterAndSort(items, query, true, true);
}
if (!(this is UserRootFolder) && !(this is AggregateFolder))
@@ -883,6 +875,15 @@ namespace MediaBrowser.Controller.Entities
return true;
}
+ if (query.IsPlayed.HasValue)
+ {
+ if (query.IncludeItemTypes.Length == 1 && query.IncludeItemTypes.Contains(typeof(Series).Name))
+ {
+ Logger.Debug("Query requires post-filtering due to IsPlayed");
+ return true;
+ }
+ }
+
return false;
}
@@ -890,8 +891,16 @@ namespace MediaBrowser.Controller.Entities
{
if (query.ItemIds.Length > 0)
{
- var specificItems = query.ItemIds.Select(LibraryManager.GetItemById).Where(i => i != null).ToList();
- return Task.FromResult(PostFilterAndSort(specificItems, query));
+ var result = LibraryManager.GetItemsResult(query);
+
+ if (query.SortBy.Length == 0)
+ {
+ var ids = query.ItemIds.ToList();
+
+ // Try to preserve order
+ result.Items = result.Items.OrderBy(i => ids.IndexOf(i.Id.ToString("N"))).ToArray();
+ }
+ return Task.FromResult(result);
}
return GetItemsInternal(query);
@@ -919,10 +928,7 @@ namespace MediaBrowser.Controller.Entities
catch
{
// Already logged at lower levels
- return new QueryResult<BaseItem>
- {
-
- };
+ return new QueryResult<BaseItem>();
}
}
@@ -950,12 +956,12 @@ namespace MediaBrowser.Controller.Entities
: GetChildren(user, true).Where(filter);
}
- return PostFilterAndSort(items, query);
+ return PostFilterAndSort(items, query, true, true);
}
- protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
+ protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query, bool collapseBoxSetItems, bool enableSorting)
{
- return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager, ConfigurationManager);
+ return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager, ConfigurationManager, collapseBoxSetItems, enableSorting);
}
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
@@ -1419,7 +1425,7 @@ namespace MediaBrowser.Controller.Entities
itemDto.RecursiveItemCount = allItemsQueryResult.TotalRecordCount;
}
- double recursiveItemCount = allItemsQueryResult.TotalRecordCount;
+ var recursiveItemCount = allItemsQueryResult.TotalRecordCount;
double unplayedCount = unplayedQueryResult.TotalRecordCount;
if (recursiveItemCount > 0)
@@ -1429,6 +1435,14 @@ namespace MediaBrowser.Controller.Entities
dto.Played = dto.PlayedPercentage.Value >= 100;
dto.UnplayedItemCount = unplayedQueryResult.TotalRecordCount;
}
+
+ if (itemDto != null)
+ {
+ if (this is Season || this is MusicAlbum)
+ {
+ itemDto.ChildCount = recursiveItemCount;
+ }
+ }
}
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs
index 54386a179..24910498f 100644
--- a/MediaBrowser.Controller/Entities/Game.cs
+++ b/MediaBrowser.Controller/Entities/Game.cs
@@ -34,7 +34,7 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
- public override bool EnableForceSaveOnDateModifiedChange
+ public override bool EnableRefreshOnDateModifiedChange
{
get { return true; }
}
diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs
index 45e766c0f..6448828fb 100644
--- a/MediaBrowser.Controller/Entities/GameGenre.cs
+++ b/MediaBrowser.Controller/Entities/GameGenre.cs
@@ -16,12 +16,9 @@ namespace MediaBrowser.Controller.Entities
return list;
}
- public override string PresentationUniqueKey
+ public override string CreatePresentationUniqueKey()
{
- get
- {
- return GetUserDataKeys()[0];
- }
+ return GetUserDataKeys()[0];
}
/// <summary>
@@ -87,5 +84,48 @@ namespace MediaBrowser.Controller.Entities
return false;
}
}
+
+ public static string GetPath(string name, bool normalizeName = true)
+ {
+ // Trim the period at the end because windows will have a hard time with that
+ var validName = normalizeName ?
+ FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
+ name;
+
+ return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.GameGenrePath, validName);
+ }
+
+ private string GetRebasedPath()
+ {
+ return GetPath(System.IO.Path.GetFileName(Path), false);
+ }
+
+ public override bool RequiresRefresh()
+ {
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
+ return true;
+ }
+ return base.RequiresRefresh();
+ }
+
+ /// <summary>
+ /// This is called before any metadata refresh and returns true or false indicating if changes were made
+ /// </summary>
+ public override bool BeforeMetadataRefresh()
+ {
+ var hasChanges = base.BeforeMetadataRefresh();
+
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Path = newPath;
+ hasChanges = true;
+ }
+
+ return hasChanges;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs
index cc5aebb2a..1736ba8c7 100644
--- a/MediaBrowser.Controller/Entities/Genre.cs
+++ b/MediaBrowser.Controller/Entities/Genre.cs
@@ -19,13 +19,9 @@ namespace MediaBrowser.Controller.Entities
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
return list;
}
-
- public override string PresentationUniqueKey
+ public override string CreatePresentationUniqueKey()
{
- get
- {
- return GetUserDataKeys()[0];
- }
+ return GetUserDataKeys()[0];
}
/// <summary>
@@ -91,5 +87,48 @@ namespace MediaBrowser.Controller.Entities
return false;
}
}
+
+ public static string GetPath(string name, bool normalizeName = true)
+ {
+ // Trim the period at the end because windows will have a hard time with that
+ var validName = normalizeName ?
+ FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
+ name;
+
+ return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.GenrePath, validName);
+ }
+
+ private string GetRebasedPath()
+ {
+ return GetPath(System.IO.Path.GetFileName(Path), false);
+ }
+
+ public override bool RequiresRefresh()
+ {
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
+ return true;
+ }
+ return base.RequiresRefresh();
+ }
+
+ /// <summary>
+ /// This is called before any metadata refresh and returns true or false indicating if changes were made
+ /// </summary>
+ public override bool BeforeMetadataRefresh()
+ {
+ var hasChanges = base.BeforeMetadataRefresh();
+
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Path = newPath;
+ hasChanges = true;
+ }
+
+ return hasChanges;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/IHasImages.cs b/MediaBrowser.Controller/Entities/IHasImages.cs
index 226748098..a38b7394d 100644
--- a/MediaBrowser.Controller/Entities/IHasImages.cs
+++ b/MediaBrowser.Controller/Entities/IHasImages.cs
@@ -1,5 +1,4 @@
-using System;
-using MediaBrowser.Controller.Providers;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Threading;
diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs
index 378c4a390..cf2f7db64 100644
--- a/MediaBrowser.Controller/Entities/IHasMetadata.cs
+++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs
@@ -32,7 +32,7 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value>The date last refreshed.</value>
DateTime DateLastRefreshed { get; set; }
-
+
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// </summary>
@@ -52,6 +52,15 @@ namespace MediaBrowser.Controller.Entities
bool RequiresRefresh();
- bool EnableForceSaveOnDateModifiedChange { get; }
+ bool EnableRefreshOnDateModifiedChange { get; }
+
+ string PresentationUniqueKey { get; set; }
+
+ string GetPresentationUniqueKey();
+ string CreatePresentationUniqueKey();
+ bool StopRefreshIfLocalMetadataFound { get; }
+
+ int? GetInheritedParentalRatingValue();
+ int InheritedParentalRatingValue { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Entities/IItemByName.cs b/MediaBrowser.Controller/Entities/IItemByName.cs
index 2ac4af1af..b69c8bdfc 100644
--- a/MediaBrowser.Controller/Entities/IItemByName.cs
+++ b/MediaBrowser.Controller/Entities/IItemByName.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
namespace MediaBrowser.Controller.Entities
{
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index 69cab5ec5..deea63112 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -37,6 +37,7 @@ namespace MediaBrowser.Controller.Entities
public string[] Genres { get; set; }
public string[] Keywords { get; set; }
+ public bool? IsSpecialSeason { get; set; }
public bool? IsMissing { get; set; }
public bool? IsUnaired { get; set; }
public bool? IsVirtualUnaired { get; set; }
@@ -50,6 +51,7 @@ namespace MediaBrowser.Controller.Entities
public string PresentationUniqueKey { get; set; }
public string Path { get; set; }
+ public string PathNotStartsWith { get; set; }
public string Name { get; set; }
public string SlugName { get; set; }
diff --git a/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs b/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs
index 05d23d986..2ba6842ca 100644
--- a/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs
@@ -11,11 +11,13 @@ namespace MediaBrowser.Controller.Entities
public int? MaxListOrder { get; set; }
public Guid AppearsInItemId { get; set; }
public string NameContains { get; set; }
+ public SourceType[] SourceTypes { get; set; }
public InternalPeopleQuery()
{
PersonTypes = new List<string>();
ExcludePersonTypes = new List<string>();
+ SourceTypes = new SourceType[] { };
}
}
}
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index 4effc162e..6d5278f1f 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -62,6 +62,26 @@ namespace MediaBrowser.Controller.Entities.Movies
return UnratedItem.Movie;
}
+ protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
+ {
+ if (IsLegacyBoxSet)
+ {
+ return base.GetNonCachedChildren(directoryService);
+ }
+ return new List<BaseItem>();
+ }
+
+ protected override IEnumerable<BaseItem> LoadChildren()
+ {
+ if (IsLegacyBoxSet)
+ {
+ return base.LoadChildren();
+ }
+
+ // Save a trip to the database
+ return new List<BaseItem>();
+ }
+
[IgnoreDataMember]
public override bool IsPreSorted
{
@@ -76,7 +96,21 @@ namespace MediaBrowser.Controller.Entities.Movies
{
get
{
- return true;
+ if (IsLegacyBoxSet)
+ {
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ [IgnoreDataMember]
+ private bool IsLegacyBoxSet
+ {
+ get
+ {
+ return !FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, Path);
}
}
diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs
index c7a833c58..f0270497c 100644
--- a/MediaBrowser.Controller/Entities/Movies/Movie.cs
+++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs
@@ -179,5 +179,15 @@ namespace MediaBrowser.Controller.Entities.Movies
return list;
}
+
+ [IgnoreDataMember]
+ public override bool StopRefreshIfLocalMetadataFound
+ {
+ get
+ {
+ // Need people id's from internet metadata
+ return false;
+ }
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs
index 7119828e2..8b749b7a5 100644
--- a/MediaBrowser.Controller/Entities/MusicVideo.cs
+++ b/MediaBrowser.Controller/Entities/MusicVideo.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Runtime.Serialization;
diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs
index 8ef0d70bf..f21bc0a71 100644
--- a/MediaBrowser.Controller/Entities/Person.cs
+++ b/MediaBrowser.Controller/Entities/Person.cs
@@ -26,13 +26,9 @@ namespace MediaBrowser.Controller.Entities
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
return list;
}
-
- public override string PresentationUniqueKey
+ public override string CreatePresentationUniqueKey()
{
- get
- {
- return GetUserDataKeys()[0];
- }
+ return GetUserDataKeys()[0];
}
public PersonLookupInfo GetLookupInfo()
@@ -126,6 +122,64 @@ namespace MediaBrowser.Controller.Entities
return false;
}
}
+
+ public static string GetPath(string name, bool normalizeName = true)
+ {
+ // Trim the period at the end because windows will have a hard time with that
+ var validFilename = normalizeName ?
+ FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
+ name;
+
+ string subFolderPrefix = null;
+
+ foreach (char c in validFilename)
+ {
+ if (char.IsLetterOrDigit(c))
+ {
+ subFolderPrefix = c.ToString();
+ break;
+ }
+ }
+
+ var path = ConfigurationManager.ApplicationPaths.PeoplePath;
+
+ return string.IsNullOrEmpty(subFolderPrefix) ?
+ System.IO.Path.Combine(path, validFilename) :
+ System.IO.Path.Combine(path, subFolderPrefix, validFilename);
+ }
+
+ private string GetRebasedPath()
+ {
+ return GetPath(System.IO.Path.GetFileName(Path), false);
+ }
+
+ public override bool RequiresRefresh()
+ {
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
+ return true;
+ }
+ return base.RequiresRefresh();
+ }
+
+ /// <summary>
+ /// This is called before any metadata refresh and returns true or false indicating if changes were made
+ /// </summary>
+ public override bool BeforeMetadataRefresh()
+ {
+ var hasChanges = base.BeforeMetadataRefresh();
+
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Path = newPath;
+ hasChanges = true;
+ }
+
+ return hasChanges;
+ }
}
/// <summary>
diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs
index 804ea04a5..965616eb5 100644
--- a/MediaBrowser.Controller/Entities/Photo.cs
+++ b/MediaBrowser.Controller/Entities/Photo.cs
@@ -52,7 +52,7 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
- public override bool EnableForceSaveOnDateModifiedChange
+ public override bool EnableRefreshOnDateModifiedChange
{
get { return true; }
}
diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs
index 762798b55..04b09b744 100644
--- a/MediaBrowser.Controller/Entities/Studio.cs
+++ b/MediaBrowser.Controller/Entities/Studio.cs
@@ -18,13 +18,9 @@ namespace MediaBrowser.Controller.Entities
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
return list;
}
-
- public override string PresentationUniqueKey
+ public override string CreatePresentationUniqueKey()
{
- get
- {
- return GetUserDataKeys()[0];
- }
+ return GetUserDataKeys()[0];
}
/// <summary>
@@ -89,5 +85,48 @@ namespace MediaBrowser.Controller.Entities
return false;
}
}
+
+ public static string GetPath(string name, bool normalizeName = true)
+ {
+ // Trim the period at the end because windows will have a hard time with that
+ var validName = normalizeName ?
+ FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
+ name;
+
+ return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.StudioPath, validName);
+ }
+
+ private string GetRebasedPath()
+ {
+ return GetPath(System.IO.Path.GetFileName(Path), false);
+ }
+
+ public override bool RequiresRefresh()
+ {
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
+ return true;
+ }
+ return base.RequiresRefresh();
+ }
+
+ /// <summary>
+ /// This is called before any metadata refresh and returns true or false indicating if changes were made
+ /// </summary>
+ public override bool BeforeMetadataRefresh()
+ {
+ var hasChanges = base.BeforeMetadataRefresh();
+
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Path = newPath;
+ hasChanges = true;
+ }
+
+ return hasChanges;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs
index 726390f65..1a02043d6 100644
--- a/MediaBrowser.Controller/Entities/TV/Episode.cs
+++ b/MediaBrowser.Controller/Entities/TV/Episode.cs
@@ -135,7 +135,11 @@ namespace MediaBrowser.Controller.Entities.TV
[IgnoreDataMember]
public Series Series
{
- get { return FindParent<Series>(); }
+ get
+ {
+ var seriesId = SeriesId ?? FindSeriesId();
+ return seriesId.HasValue ? (LibraryManager.GetItemById(seriesId.Value) as Series) : null;
+ }
}
[IgnoreDataMember]
@@ -143,24 +147,8 @@ namespace MediaBrowser.Controller.Entities.TV
{
get
{
- var season = FindParent<Season>();
-
- // Episodes directly in series folder
- if (season == null)
- {
- var series = Series;
-
- if (series != null && ParentIndexNumber.HasValue)
- {
- var findNumber = ParentIndexNumber.Value;
-
- season = series.Children
- .OfType<Season>()
- .FirstOrDefault(i => i.IndexNumber.HasValue && i.IndexNumber.Value == findNumber);
- }
- }
-
- return season;
+ var seasonId = SeasonId ?? FindSeasonId();
+ return seasonId.HasValue ? (LibraryManager.GetItemById(seasonId.Value) as Season) : null;
}
}
@@ -193,7 +181,23 @@ namespace MediaBrowser.Controller.Entities.TV
public Guid? FindSeasonId()
{
- var season = Season;
+ var season = FindParent<Season>();
+
+ // Episodes directly in series folder
+ if (season == null)
+ {
+ var series = Series;
+
+ if (series != null && ParentIndexNumber.HasValue)
+ {
+ var findNumber = ParentIndexNumber.Value;
+
+ season = series.Children
+ .OfType<Season>()
+ .FirstOrDefault(i => i.IndexNumber.HasValue && i.IndexNumber.Value == findNumber);
+ }
+ }
+
return season == null ? (Guid?)null : season.Id;
}
@@ -263,7 +267,7 @@ namespace MediaBrowser.Controller.Entities.TV
public Guid? FindSeriesId()
{
- var series = Series;
+ var series = FindParent<Series>();
return series == null ? (Guid?)null : series.Id;
}
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs
index ee01c60b1..65b7c9955 100644
--- a/MediaBrowser.Controller/Entities/TV/Season.cs
+++ b/MediaBrowser.Controller/Entities/TV/Season.cs
@@ -1,6 +1,5 @@
using System;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Users;
using MoreLinq;
@@ -86,7 +85,11 @@ namespace MediaBrowser.Controller.Entities.TV
public override int GetChildCount(User user)
{
- return GetChildren(user, true).Count();
+ Logger.Debug("Season {0} getting child cound", (Path ?? Name));
+ var result = GetChildren(user, true).Count();
+ Logger.Debug("Season {0} child cound: ", result);
+
+ return result;
}
/// <summary>
@@ -96,7 +99,11 @@ namespace MediaBrowser.Controller.Entities.TV
[IgnoreDataMember]
public Series Series
{
- get { return FindParent<Series>(); }
+ get
+ {
+ var seriesId = SeriesId ?? FindSeriesId();
+ return seriesId.HasValue ? (LibraryManager.GetItemById(seriesId.Value) as Series) : null;
+ }
}
[IgnoreDataMember]
@@ -115,22 +122,18 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
- [IgnoreDataMember]
- public override string PresentationUniqueKey
+ public override string CreatePresentationUniqueKey()
{
- get
+ if (IndexNumber.HasValue)
{
- if (IndexNumber.HasValue)
+ var series = Series;
+ if (series != null)
{
- var series = Series;
- if (series != null)
- {
- return series.PresentationUniqueKey + "-" + (IndexNumber ?? 0).ToString("000");
- }
+ return series.PresentationUniqueKey + "-" + (IndexNumber ?? 0).ToString("000");
}
-
- return base.PresentationUniqueKey;
}
+
+ return base.CreatePresentationUniqueKey();
}
/// <summary>
@@ -142,24 +145,6 @@ namespace MediaBrowser.Controller.Entities.TV
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
}
- [IgnoreDataMember]
- public bool IsMissingSeason
- {
- get { return (IsVirtualItem) && !IsUnaired; }
- }
-
- [IgnoreDataMember]
- public bool IsVirtualUnaired
- {
- get { return (IsVirtualItem) && IsUnaired; }
- }
-
- [IgnoreDataMember]
- public bool IsSpecialSeason
- {
- get { return (IndexNumber ?? -1) == 0; }
- }
-
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
{
if (query.User == null)
@@ -171,10 +156,15 @@ namespace MediaBrowser.Controller.Entities.TV
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
+ var id = Guid.NewGuid().ToString("N");
+
+ Logger.Debug("Season.GetItemsInternal entering GetEpisodes. Request id: " + id);
var items = GetEpisodes(user).Where(filter);
- var result = PostFilterAndSort(items, query);
+ Logger.Debug("Season.GetItemsInternal entering PostFilterAndSort. Request id: " + id);
+ var result = PostFilterAndSort(items, query, false, false);
+ Logger.Debug("Season.GetItemsInternal complete. Request id: " + id);
return Task.FromResult(result);
}
@@ -185,19 +175,17 @@ namespace MediaBrowser.Controller.Entities.TV
/// <returns>IEnumerable{Episode}.</returns>
public IEnumerable<Episode> GetEpisodes(User user)
{
- var config = user.Configuration;
-
- return GetEpisodes(Series, user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
+ return GetEpisodes(Series, user);
}
- public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
+ public IEnumerable<Episode> GetEpisodes(Series series, User user)
{
- return GetEpisodes(series, user, includeMissingEpisodes, includeVirtualUnairedEpisodes, null);
+ return GetEpisodes(series, user, null);
}
- public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
+ public IEnumerable<Episode> GetEpisodes(Series series, User user, IEnumerable<Episode> allSeriesEpisodes)
{
- return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes, allSeriesEpisodes);
+ return series.GetSeasonEpisodes(user, this, allSeriesEpisodes);
}
public IEnumerable<Episode> GetEpisodes()
@@ -257,7 +245,7 @@ namespace MediaBrowser.Controller.Entities.TV
public Guid? FindSeriesId()
{
- var series = Series;
+ var series = FindParent<Series>();
return series == null ? (Guid?)null : series.Id;
}
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs
index ad35b3d36..4915cfedc 100644
--- a/MediaBrowser.Controller/Entities/TV/Series.cs
+++ b/MediaBrowser.Controller/Entities/TV/Series.cs
@@ -96,19 +96,29 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
- [IgnoreDataMember]
- public override string PresentationUniqueKey
+ public override string CreatePresentationUniqueKey()
{
- get
+ var userdatakeys = GetUserDataKeys();
+
+ if (userdatakeys.Count > 1)
{
- var userdatakeys = GetUserDataKeys();
+ return AddLibrariesToPresentationUniqueKey(userdatakeys[0]);
+ }
+ return base.CreatePresentationUniqueKey();
+ }
- if (userdatakeys.Count > 1)
- {
- return userdatakeys[0];
- }
- return base.PresentationUniqueKey;
+ private string AddLibrariesToPresentationUniqueKey(string key)
+ {
+ var folders = LibraryManager.GetCollectionFolders(this)
+ .Select(i => i.Id.ToString("N"))
+ .ToArray();
+
+ if (folders.Length == 0)
+ {
+ return key;
}
+
+ return key + "-" + string.Join("-", folders);
}
private static string GetUniqueSeriesKey(BaseItem series)
@@ -117,7 +127,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
return series.Id.ToString("N");
}
- return series.PresentationUniqueKey;
+ return series.GetPresentationUniqueKey();
}
public override int GetChildCount(User user)
@@ -197,7 +207,30 @@ namespace MediaBrowser.Controller.Entities.TV
{
var config = user.Configuration;
- return GetSeasons(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
+ var seriesKey = GetUniqueSeriesKey(this);
+
+ Logger.Debug("GetSeasons SeriesKey: {0}", seriesKey);
+ var query = new InternalItemsQuery(user)
+ {
+ AncestorWithPresentationUniqueKey = seriesKey,
+ IncludeItemTypes = new[] {typeof (Season).Name},
+ SortBy = new[] {ItemSortBy.SortName}
+ };
+
+ if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes)
+ {
+ query.IsVirtualItem = false;
+ }
+ else if (!config.DisplayMissingEpisodes)
+ {
+ query.IsMissing = false;
+ }
+ else if (!config.DisplayUnairedEpisodes)
+ {
+ query.IsVirtualUnaired = false;
+ }
+
+ return LibraryManager.GetItemList(query).Cast<Season>();
}
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
@@ -227,55 +260,43 @@ namespace MediaBrowser.Controller.Entities.TV
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
var items = GetSeasons(user).Where(filter);
- var result = PostFilterAndSort(items, query);
+ var result = PostFilterAndSort(items, query, false, true);
return Task.FromResult(result);
}
- public IEnumerable<Season> GetSeasons(User user, bool includeMissingSeasons, bool includeVirtualUnaired)
+ public IEnumerable<Episode> GetEpisodes(User user)
{
- IEnumerable<Season> seasons;
+ var seriesKey = GetUniqueSeriesKey(this);
+ Logger.Debug("GetEpisodes seriesKey: {0}", seriesKey);
- seasons = LibraryManager.GetItemList(new InternalItemsQuery(user)
+ var query = new InternalItemsQuery(user)
{
- AncestorWithPresentationUniqueKey = GetUniqueSeriesKey(this),
- IncludeItemTypes = new[] { typeof(Season).Name },
- SortBy = new[] { ItemSortBy.SortName }
-
- }).Cast<Season>();
-
- if (!includeMissingSeasons)
+ AncestorWithPresentationUniqueKey = seriesKey,
+ IncludeItemTypes = new[] {typeof (Episode).Name, typeof (Season).Name},
+ SortBy = new[] {ItemSortBy.SortName}
+ };
+ var config = user.Configuration;
+ if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes)
{
- seasons = seasons.Where(i => !(i.IsMissingSeason));
+ query.IsVirtualItem = false;
}
- if (!includeVirtualUnaired)
+ else if (!config.DisplayMissingEpisodes)
{
- seasons = seasons.Where(i => !i.IsVirtualUnaired);
+ query.IsMissing = false;
}
-
- return seasons;
- }
-
- public IEnumerable<Episode> GetEpisodes(User user)
- {
- var config = user.Configuration;
-
- return GetEpisodes(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
- }
-
- public IEnumerable<Episode> GetEpisodes(User user, bool includeMissing, bool includeVirtualUnaired)
- {
- var allItems = LibraryManager.GetItemList(new InternalItemsQuery(user)
+ else if (!config.DisplayUnairedEpisodes)
{
- AncestorWithPresentationUniqueKey = GetUniqueSeriesKey(this),
- IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name },
- SortBy = new[] { ItemSortBy.SortName }
+ query.IsVirtualUnaired = false;
+ }
- }).ToList();
+ var allItems = LibraryManager.GetItemList(query).ToList();
+
+ Logger.Debug("GetEpisodes return {0} items from database", allItems.Count);
var allSeriesEpisodes = allItems.OfType<Episode>().ToList();
var allEpisodes = allItems.OfType<Season>()
- .SelectMany(i => i.GetEpisodes(this, user, includeMissing, includeVirtualUnaired, allSeriesEpisodes))
+ .SelectMany(i => i.GetEpisodes(this, user, allSeriesEpisodes))
.Reverse()
.ToList();
@@ -352,78 +373,68 @@ namespace MediaBrowser.Controller.Entities.TV
progress.Report(100);
}
- public IEnumerable<Episode> GetEpisodes(User user, Season season)
- {
- var config = user.Configuration;
-
- return GetEpisodes(user, season, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
- }
-
private IEnumerable<Episode> GetAllEpisodes(User user)
{
- return LibraryManager.GetItemList(new InternalItemsQuery(user)
+ Logger.Debug("Series.GetAllEpisodes entering GetItemList");
+
+ var result = LibraryManager.GetItemList(new InternalItemsQuery(user)
{
AncestorWithPresentationUniqueKey = GetUniqueSeriesKey(this),
IncludeItemTypes = new[] { typeof(Episode).Name },
SortBy = new[] { ItemSortBy.SortName }
- }).Cast<Episode>();
- }
+ }).Cast<Episode>().ToList();
- public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
- {
- IEnumerable<Episode> episodes = GetAllEpisodes(user);
+ Logger.Debug("Series.GetAllEpisodes returning {0} episodes", result.Count);
- return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
+ return result;
}
- public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
+ public IEnumerable<Episode> GetSeasonEpisodes(User user, Season parentSeason)
{
- if (allSeriesEpisodes == null)
+ var seriesKey = GetUniqueSeriesKey(this);
+ Logger.Debug("GetSeasonEpisodes seriesKey: {0}", seriesKey);
+
+ var query = new InternalItemsQuery(user)
{
- return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes);
+ AncestorWithPresentationUniqueKey = seriesKey,
+ IncludeItemTypes = new[] { typeof(Episode).Name },
+ SortBy = new[] { ItemSortBy.SortName }
+ };
+ var config = user.Configuration;
+ if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes)
+ {
+ query.IsVirtualItem = false;
}
-
- var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons);
-
- if (!includeMissingEpisodes)
+ else if (!config.DisplayMissingEpisodes)
{
- episodes = episodes.Where(i => !i.IsMissingEpisode);
+ query.IsMissing = false;
}
- if (!includeVirtualUnairedEpisodes)
+ else if (!config.DisplayUnairedEpisodes)
{
- episodes = episodes.Where(i => !i.IsVirtualUnaired);
+ query.IsVirtualUnaired = false;
}
- var sortBy = (parentSeason.IndexNumber ?? -1) == 0 ? ItemSortBy.SortName : ItemSortBy.AiredEpisodeOrder;
+ var allItems = LibraryManager.GetItemList(query).OfType<Episode>();
- return LibraryManager.Sort(episodes, user, new[] { sortBy }, SortOrder.Ascending)
- .Cast<Episode>();
+ return GetSeasonEpisodes(user, parentSeason, allItems);
}
- /// <summary>
- /// Filters the episodes by season.
- /// </summary>
- public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials)
+ public IEnumerable<Episode> GetSeasonEpisodes(User user, Season parentSeason, IEnumerable<Episode> allSeriesEpisodes)
{
- if (!includeSpecials || seasonNumber < 1)
+ if (allSeriesEpisodes == null)
{
- return episodes.Where(i => (i.ParentIndexNumber ?? -1) == seasonNumber);
+ Logger.Debug("GetSeasonEpisodes allSeriesEpisodes is null");
+ return GetSeasonEpisodes(user, parentSeason);
}
- return episodes.Where(i =>
- {
- var episode = i;
-
- if (episode != null)
- {
- var currentSeasonNumber = episode.AiredSeasonNumber;
+ Logger.Debug("GetSeasonEpisodes FilterEpisodesBySeason");
+ var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons);
- return currentSeasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber;
- }
+ var sortBy = (parentSeason.IndexNumber ?? -1) == 0 ? ItemSortBy.SortName : ItemSortBy.AiredEpisodeOrder;
- return false;
- });
+ return LibraryManager.Sort(episodes, user, new[] { sortBy }, SortOrder.Ascending)
+ .Cast<Episode>();
}
/// <summary>
@@ -454,6 +465,32 @@ namespace MediaBrowser.Controller.Entities.TV
});
}
+ /// <summary>
+ /// Filters the episodes by season.
+ /// </summary>
+ public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials)
+ {
+ if (!includeSpecials || seasonNumber < 1)
+ {
+ return episodes.Where(i => (i.ParentIndexNumber ?? -1) == seasonNumber);
+ }
+
+ return episodes.Where(i =>
+ {
+ var episode = i;
+
+ if (episode != null)
+ {
+ var currentSeasonNumber = episode.AiredSeasonNumber;
+
+ return currentSeasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber;
+ }
+
+ return false;
+ });
+ }
+
+
protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Series);
@@ -509,5 +546,15 @@ namespace MediaBrowser.Controller.Entities.TV
return list;
}
+
+ [IgnoreDataMember]
+ public override bool StopRefreshIfLocalMetadataFound
+ {
+ get
+ {
+ // Need people id's from internet metadata
+ return false;
+ }
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs
index eab5ab679..306ce35ec 100644
--- a/MediaBrowser.Controller/Entities/Trailer.cs
+++ b/MediaBrowser.Controller/Entities/Trailer.cs
@@ -2,9 +2,7 @@
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using System.Collections.Generic;
-using System.Globalization;
using System.Runtime.Serialization;
-using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.Entities
@@ -126,5 +124,15 @@ namespace MediaBrowser.Controller.Entities
return list;
}
+
+ [IgnoreDataMember]
+ public override bool StopRefreshIfLocalMetadataFound
+ {
+ get
+ {
+ // Need people id's from internet metadata
+ return false;
+ }
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs
index 5c68308f5..46da469fa 100644
--- a/MediaBrowser.Controller/Entities/User.cs
+++ b/MediaBrowser.Controller/Entities/User.cs
@@ -213,7 +213,7 @@ namespace MediaBrowser.Controller.Entities
Name = newName;
- return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(FileSystem))
+ return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(Logger, FileSystem))
{
ReplaceAllMetadata = true,
ImageRefreshMode = ImageRefreshMode.FullRefresh,
diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs
index 8e6f11c2c..aff1f5e28 100644
--- a/MediaBrowser.Controller/Entities/UserRootFolder.cs
+++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs
@@ -1,6 +1,5 @@
using System.Runtime.Serialization;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying;
using System;
@@ -8,7 +7,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Controller.Library;
namespace MediaBrowser.Controller.Entities
{
@@ -18,6 +16,31 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class UserRootFolder : Folder
{
+ private List<Guid> _childrenIds = null;
+ private readonly object _childIdsLock = new object();
+ protected override IEnumerable<BaseItem> LoadChildren()
+ {
+ lock (_childIdsLock)
+ {
+ if (_childrenIds == null)
+ {
+ var list = base.LoadChildren().ToList();
+ _childrenIds = list.Select(i => i.Id).ToList();
+ return list;
+ }
+
+ return _childrenIds.Select(LibraryManager.GetItemById).Where(i => i != null).ToList();
+ }
+ }
+
+ private void ClearCache()
+ {
+ lock (_childIdsLock)
+ {
+ _childrenIds = null;
+ }
+ }
+
protected override async Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
{
if (query.Recursive)
@@ -35,7 +58,7 @@ namespace MediaBrowser.Controller.Entities
var user = query.User;
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
- return PostFilterAndSort(result.Where(filter), query);
+ return PostFilterAndSort(result.Where(filter), query, true, true);
}
public override int GetChildCount(User user)
@@ -71,6 +94,8 @@ namespace MediaBrowser.Controller.Entities
public override bool BeforeMetadataRefresh()
{
+ ClearCache();
+
var hasChanges = base.BeforeMetadataRefresh();
if (string.Equals("default", Name, StringComparison.OrdinalIgnoreCase))
@@ -82,11 +107,22 @@ namespace MediaBrowser.Controller.Entities
return hasChanges;
}
+ protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
+ {
+ ClearCache();
+
+ return base.GetNonCachedChildren(directoryService);
+ }
+
protected override async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
{
+ ClearCache();
+
await base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService)
.ConfigureAwait(false);
+ ClearCache();
+
// Not the best way to handle this, but it solves an issue
// CollectionFolders aren't always getting saved after changes
// This means that grabbing the item by Id may end up returning the old one
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index e2228bcaf..9f3acc3fc 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Controller.Channels;
-using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@@ -14,12 +13,10 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Model.Configuration;
using MoreLinq;
namespace MediaBrowser.Controller.Entities
@@ -427,7 +424,7 @@ namespace MediaBrowser.Controller.Entities
query.SortBy = new string[] { };
- return PostFilterAndSort(items, parent, null, query);
+ return PostFilterAndSort(items, parent, null, query, false, true);
}
private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query)
@@ -783,7 +780,7 @@ namespace MediaBrowser.Controller.Entities
{
items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager));
- return PostFilterAndSort(items, queryParent, null, query, _libraryManager, _config);
+ return PostFilterAndSort(items, queryParent, null, query, _libraryManager, _config, true, true);
}
public static bool FilterItem(BaseItem item, InternalItemsQuery query)
@@ -794,9 +791,11 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
BaseItem queryParent,
int? totalRecordLimit,
- InternalItemsQuery query)
+ InternalItemsQuery query,
+ bool collapseBoxSetItems,
+ bool enableSorting)
{
- return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager, _config);
+ return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager, _config, collapseBoxSetItems, enableSorting);
}
public static QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
@@ -804,7 +803,9 @@ namespace MediaBrowser.Controller.Entities
int? totalRecordLimit,
InternalItemsQuery query,
ILibraryManager libraryManager,
- IServerConfigurationManager configurationManager)
+ IServerConfigurationManager configurationManager,
+ bool collapseBoxSetItems,
+ bool enableSorting)
{
var user = query.User;
@@ -813,7 +814,10 @@ namespace MediaBrowser.Controller.Entities
query.IsVirtualUnaired,
query.IsUnaired);
- items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user, configurationManager);
+ if (collapseBoxSetItems)
+ {
+ items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user, configurationManager);
+ }
// This must be the last filter
if (!string.IsNullOrEmpty(query.AdjacentTo))
@@ -821,7 +825,7 @@ namespace MediaBrowser.Controller.Entities
items = FilterForAdjacency(items, query.AdjacentTo);
}
- return Sort(items, totalRecordLimit, query, libraryManager);
+ return SortAndPage(items, totalRecordLimit, query, libraryManager, enableSorting);
}
public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
@@ -1096,8 +1100,6 @@ namespace MediaBrowser.Controller.Entities
bool? isVirtualUnaired,
bool? isUnaired)
{
- items = FilterVirtualSeasons(items, isMissing, isVirtualUnaired, isUnaired);
-
if (isMissing.HasValue)
{
var val = isMissing.Value;
@@ -1143,65 +1145,14 @@ namespace MediaBrowser.Controller.Entities
return items;
}
- private static IEnumerable<BaseItem> FilterVirtualSeasons(
- IEnumerable<BaseItem> items,
- bool? isMissing,
- bool? isVirtualUnaired,
- bool? isUnaired)
- {
- if (isMissing.HasValue)
- {
- var val = isMissing.Value;
- items = items.Where(i =>
- {
- var e = i as Season;
- if (e != null)
- {
- return (e.IsMissingSeason) == val;
- }
- return true;
- });
- }
-
- if (isUnaired.HasValue)
- {
- var val = isUnaired.Value;
- items = items.Where(i =>
- {
- var e = i as Season;
- if (e != null)
- {
- return e.IsUnaired == val;
- }
- return true;
- });
- }
-
- if (isVirtualUnaired.HasValue)
- {
- var val = isVirtualUnaired.Value;
- items = items.Where(i =>
- {
- var e = i as Season;
- if (e != null)
- {
- return e.IsVirtualUnaired == val;
- }
- return true;
- });
- }
-
- return items;
- }
-
- public static QueryResult<BaseItem> Sort(IEnumerable<BaseItem> items,
+ public static QueryResult<BaseItem> SortAndPage(IEnumerable<BaseItem> items,
int? totalRecordLimit,
InternalItemsQuery query,
- ILibraryManager libraryManager)
+ ILibraryManager libraryManager, bool enableSorting)
{
var user = query.User;
- items = items.DistinctBy(i => i.PresentationUniqueKey, StringComparer.OrdinalIgnoreCase);
+ items = items.DistinctBy(i => i.GetPresentationUniqueKey(), StringComparer.OrdinalIgnoreCase);
if (query.SortBy.Length > 0)
{
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index eba1e466a..8809f155c 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -12,6 +12,7 @@ using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Channels;
namespace MediaBrowser.Controller.Entities
@@ -44,24 +45,23 @@ namespace MediaBrowser.Controller.Entities
}
}
- [IgnoreDataMember]
- public override string PresentationUniqueKey
+ public override string CreatePresentationUniqueKey()
{
- get
+ if (!string.IsNullOrWhiteSpace(PrimaryVersionId))
{
- if (!string.IsNullOrWhiteSpace(PrimaryVersionId))
- {
- return PrimaryVersionId;
- }
-
- return base.PresentationUniqueKey;
+ return PrimaryVersionId;
}
+
+ return base.CreatePresentationUniqueKey();
}
[IgnoreDataMember]
- public override bool EnableForceSaveOnDateModifiedChange
+ public override bool EnableRefreshOnDateModifiedChange
{
- get { return true; }
+ get
+ {
+ return VideoType == VideoType.VideoFile || VideoType == VideoType.Iso;
+ }
}
public int? TotalBitrate { get; set; }
@@ -612,6 +612,11 @@ namespace MediaBrowser.Controller.Entities
SupportsDirectStream = i.VideoType == VideoType.VideoFile
};
+ if (info.Protocol == MediaProtocol.File)
+ {
+ info.ETag = i.DateModified.Ticks.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N");
+ }
+
if (i.IsShortcut)
{
info.Path = i.ShortcutPath;
diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs
index db896f1fc..4197ea93e 100644
--- a/MediaBrowser.Controller/Entities/Year.cs
+++ b/MediaBrowser.Controller/Entities/Year.cs
@@ -112,5 +112,48 @@ namespace MediaBrowser.Controller.Entities
return false;
}
}
+
+ public static string GetPath(string name, bool normalizeName = true)
+ {
+ // Trim the period at the end because windows will have a hard time with that
+ var validName = normalizeName ?
+ FileSystem.GetValidFilename(name).Trim().TrimEnd('.') :
+ name;
+
+ return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.YearPath, validName);
+ }
+
+ private string GetRebasedPath()
+ {
+ return GetPath(System.IO.Path.GetFileName(Path), false);
+ }
+
+ public override bool RequiresRefresh()
+ {
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
+ return true;
+ }
+ return base.RequiresRefresh();
+ }
+
+ /// <summary>
+ /// This is called before any metadata refresh and returns true or false indicating if changes were made
+ /// </summary>
+ public override bool BeforeMetadataRefresh()
+ {
+ var hasChanges = base.BeforeMetadataRefresh();
+
+ var newPath = GetRebasedPath();
+ if (!string.Equals(Path, newPath, StringComparison.Ordinal))
+ {
+ Path = newPath;
+ hasChanges = true;
+ }
+
+ return hasChanges;
+ }
}
}
diff --git a/MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs b/MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs
index daa670d83..9a5b96a24 100644
--- a/MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs
+++ b/MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs
@@ -1,5 +1,7 @@
-using MediaBrowser.Model.FileOrganization;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.FileOrganization;
using MediaBrowser.Model.Querying;
+using System;
using System.Threading;
using System.Threading.Tasks;
@@ -7,6 +9,11 @@ namespace MediaBrowser.Controller.FileOrganization
{
public interface IFileOrganizationService
{
+ event EventHandler<GenericEventArgs<FileOrganizationResult>> ItemAdded;
+ event EventHandler<GenericEventArgs<FileOrganizationResult>> ItemUpdated;
+ event EventHandler<GenericEventArgs<FileOrganizationResult>> ItemRemoved;
+ event EventHandler LogReset;
+
/// <summary>
/// Processes the new files.
/// </summary>
@@ -81,5 +88,20 @@ namespace MediaBrowser.Controller.FileOrganization
/// <param name="ItemName">Item name.</param>
/// <param name="matchString">The match string to delete.</param>
void DeleteSmartMatchEntry(string ItemName, string matchString);
+
+ /// <summary>
+ /// Attempts to add a an item to the list of currently processed items.
+ /// </summary>
+ /// <param name="result">The result item.</param>
+ /// <param name="fullClientRefresh">Passing true will notify the client to reload all items, otherwise only a single item will be refreshed.</param>
+ /// <returns>True if the item was added, False if the item is already contained in the list.</returns>
+ bool AddToInProgressList(FileOrganizationResult result, bool fullClientRefresh);
+
+ /// <summary>
+ /// Removes an item from the list of currently processed items.
+ /// </summary>
+ /// <param name="result">The result item.</param>
+ /// <returns>True if the item was removed, False if the item was not contained in the list.</returns>
+ bool RemoveFromInprogressList(FileOrganizationResult result);
}
}
diff --git a/MediaBrowser.Controller/IServerApplicationPaths.cs b/MediaBrowser.Controller/IServerApplicationPaths.cs
index c07934d0b..c89a60a6f 100644
--- a/MediaBrowser.Controller/IServerApplicationPaths.cs
+++ b/MediaBrowser.Controller/IServerApplicationPaths.cs
@@ -106,5 +106,7 @@ namespace MediaBrowser.Controller
/// </summary>
/// <value>The internal metadata path.</value>
string InternalMetadataPath { get; }
+
+ string ArtistsPath { get; }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index ad38b9ea5..0862e3eaf 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -11,6 +11,8 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
namespace MediaBrowser.Controller.Library
@@ -32,15 +34,11 @@ namespace MediaBrowser.Controller.Library
/// <summary>
/// Resolves a set of files into a list of BaseItem
/// </summary>
- /// <param name="files">The files.</param>
- /// <param name="directoryService">The directory service.</param>
- /// <param name="parent">The parent.</param>
- /// <param name="collectionType">Type of the collection.</param>
- /// <returns>List{``0}.</returns>
IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files,
IDirectoryService directoryService,
- Folder parent, string
- collectionType = null);
+ Folder parent,
+ LibraryOptions libraryOptions,
+ string collectionType = null);
/// <summary>
/// Gets the root folder.
@@ -397,6 +395,9 @@ namespace MediaBrowser.Controller.Library
/// <returns><c>true</c> if [is audio file] [the specified path]; otherwise, <c>false</c>.</returns>
bool IsAudioFile(string path);
+ bool IsAudioFile(string path, LibraryOptions libraryOptions);
+ bool IsVideoFile(string path, LibraryOptions libraryOptions);
+
/// <summary>
/// Gets the season number from path.
/// </summary>
@@ -453,6 +454,8 @@ namespace MediaBrowser.Controller.Library
/// <returns>IEnumerable&lt;Folder&gt;.</returns>
IEnumerable<Folder> GetCollectionFolders(BaseItem item);
+ LibraryOptions GetLibraryOptions(BaseItem item);
+
/// <summary>
/// Gets the people.
/// </summary>
@@ -475,12 +478,6 @@ namespace MediaBrowser.Controller.Library
List<Person> GetPeopleItems(InternalPeopleQuery query);
/// <summary>
- /// Gets all people names.
- /// </summary>
- /// <returns>List&lt;System.String&gt;.</returns>
- List<PersonInfo> GetAllPeople();
-
- /// <summary>
/// Updates the people.
/// </summary>
/// <param name="item">The item.</param>
@@ -557,7 +554,7 @@ namespace MediaBrowser.Controller.Library
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
bool IgnoreFile(FileSystemMetadata file, BaseItem parent);
- void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, bool refreshLibrary);
+ void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, LibraryOptions options, bool refreshLibrary);
void RemoveVirtualFolder(string name, bool refreshLibrary);
void AddMediaPath(string virtualFolderName, string path);
void RemoveMediaPath(string virtualFolderName, string path);
@@ -568,5 +565,6 @@ namespace MediaBrowser.Controller.Library
QueryResult<Tuple<BaseItem, ItemCounts>> GetStudios(InternalItemsQuery query);
QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query);
QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query);
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetAllArtists(InternalItemsQuery query);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs
index ea3199b31..ec0ac325b 100644
--- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs
+++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs
@@ -5,6 +5,8 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using CommonIO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Library
{
@@ -51,6 +53,13 @@ namespace MediaBrowser.Controller.Library
}
}
+ public LibraryOptions LibraryOptions { get; set; }
+
+ public LibraryOptions GetLibraryOptions()
+ {
+ return LibraryOptions ?? (LibraryOptions = (Parent == null ? new LibraryOptions() : BaseItem.LibraryManager.GetLibraryOptions(Parent)));
+ }
+
/// <summary>
/// Gets or sets the file system dictionary.
/// </summary>
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index fe69b38cb..ed64127c3 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -331,12 +331,11 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="user">The user.</param>
/// <returns>Task.</returns>
Task AddInfoToProgramDto(List<Tuple<BaseItem,BaseItemDto>> programs, List<ItemFields> fields, User user = null);
+
/// <summary>
/// Saves the tuner host.
/// </summary>
- /// <param name="info">The information.</param>
- /// <returns>Task.</returns>
- Task<TunerHostInfo> SaveTunerHost(TunerHostInfo info);
+ Task<TunerHostInfo> SaveTunerHost(TunerHostInfo info, bool dataSourceChanged = true);
/// <summary>
/// Saves the listing provider.
/// </summary>
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
index 74c993248..c7f47b825 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.LiveTv;
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
index a8c737673..f4dba070d 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
diff --git a/MediaBrowser.Controller/LiveTv/TimerEventInfo.cs b/MediaBrowser.Controller/LiveTv/TimerEventInfo.cs
index 0e1a05475..642dee3af 100644
--- a/MediaBrowser.Controller/LiveTv/TimerEventInfo.cs
+++ b/MediaBrowser.Controller/LiveTv/TimerEventInfo.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Controller.LiveTv
+namespace MediaBrowser.Controller.LiveTv
{
public class TimerEventInfo
{
diff --git a/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs b/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs
index da0527eea..c1d1c413e 100644
--- a/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs
+++ b/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Controller.LiveTv
+namespace MediaBrowser.Controller.LiveTv
{
public class TunerChannelMapping
{
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 0462117cb..e7eaa1dc0 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -236,6 +236,7 @@
<Compile Include="Net\IAuthorizationContext.cs" />
<Compile Include="Net\IAuthService.cs" />
<Compile Include="Net\IHasAuthorization.cs" />
+ <Compile Include="Net\IAsyncStreamSource.cs" />
<Compile Include="Net\IHasResultFactory.cs" />
<Compile Include="Net\IHasSession.cs" />
<Compile Include="Net\IHttpResultFactory.cs" />
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
index 44b741755..844fafcde 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
@@ -1,5 +1,4 @@
-using System.Linq;
-using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Dlna;
namespace MediaBrowser.Controller.MediaEncoding
{
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index c8a8caa91..7fdbf020c 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.MediaInfo;
using System;
-using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Dlna;
@@ -134,5 +133,7 @@ namespace MediaBrowser.Controller.MediaEncoding
Task Init();
Task UpdateEncoderPath(string path, string pathType);
+ bool SupportsEncoder(string encoder);
+ bool IsDefaultEncoderPath { get; }
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
index 66a9fa60b..96a3753e1 100644
--- a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
+++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
@@ -36,8 +36,13 @@ namespace MediaBrowser.Controller.MediaEncoding
return new[] {videoPath};
}
- public static List<string> GetPlayableStreamFiles(IFileSystem fileSystem, string rootPath, IEnumerable<string> filenames)
+ private static List<string> GetPlayableStreamFiles(IFileSystem fileSystem, string rootPath, List<string> filenames)
{
+ if (filenames.Count == 0)
+ {
+ return new List<string>();
+ }
+
var allFiles = fileSystem
.GetFilePaths(rootPath, true)
.ToList();
diff --git a/MediaBrowser.Controller/Net/IAsyncStreamSource.cs b/MediaBrowser.Controller/Net/IAsyncStreamSource.cs
new file mode 100644
index 000000000..0f41f60a5
--- /dev/null
+++ b/MediaBrowser.Controller/Net/IAsyncStreamSource.cs
@@ -0,0 +1,18 @@
+using ServiceStack.Web;
+using System.IO;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Net
+{
+ /// <summary>
+ /// Interface IAsyncStreamSource
+ /// Enables asynchronous writing to http resonse streams
+ /// </summary>
+ public interface IAsyncStreamSource
+ {
+ /// <summary>
+ /// Asynchronously write to the response stream.
+ /// </summary>
+ Task WriteToAsync(Stream responseStream);
+ }
+}
diff --git a/MediaBrowser.Controller/Net/IHttpResultFactory.cs b/MediaBrowser.Controller/Net/IHttpResultFactory.cs
index 49d4614d8..8fdb1ce37 100644
--- a/MediaBrowser.Controller/Net/IHttpResultFactory.cs
+++ b/MediaBrowser.Controller/Net/IHttpResultFactory.cs
@@ -28,7 +28,7 @@ namespace MediaBrowser.Controller.Net
/// <returns>System.Object.</returns>
object GetResult(object content, string contentType, IDictionary<string,string> responseHeaders = null);
- object GetAsyncStreamWriter(Func<Stream,Task> streamWriter, IDictionary<string, string> responseHeaders = null);
+ object GetAsyncStreamWriter(IAsyncStreamSource streamSource);
/// <summary>
/// Gets the optimized result.
diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs
index 78138999c..87937869d 100644
--- a/MediaBrowser.Controller/Persistence/IItemRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs
@@ -169,6 +169,13 @@ namespace MediaBrowser.Controller.Persistence
QueryResult<Tuple<BaseItem, ItemCounts>> GetStudios(InternalItemsQuery query);
QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query);
QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query);
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetAllArtists(InternalItemsQuery query);
+
+ List<string> GetGameGenreNames();
+ List<string> GetMusicGenreNames();
+ List<string> GetStudioNames();
+ List<string> GetGenreNames();
+ List<string> GetAllArtistNames();
}
}
diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs
index 5ffe3d5da..654b97d7d 100644
--- a/MediaBrowser.Controller/Playlists/Playlist.cs
+++ b/MediaBrowser.Controller/Playlists/Playlist.cs
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading.Tasks;
+using MediaBrowser.Controller.Providers;
namespace MediaBrowser.Controller.Playlists
{
@@ -58,11 +59,22 @@ namespace MediaBrowser.Controller.Playlists
return true;
}
+ protected override IEnumerable<BaseItem> LoadChildren()
+ {
+ // Save a trip to the database
+ return new List<BaseItem>();
+ }
+
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
{
return GetPlayableItems(user).Result;
}
+ protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
+ {
+ return new List<BaseItem>();
+ }
+
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
{
var items = GetPlayableItems(user).Result;
diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
index a783910e3..c0912708c 100644
--- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
+++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
@@ -724,6 +724,15 @@ namespace MediaBrowser.Controller.Providers
}
break;
}
+ case "TvMazeId":
+ {
+ var id = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(id))
+ {
+ item.SetProviderId(MetadataProviders.TvMaze, id);
+ }
+ break;
+ }
case "AudioDbArtistId":
{
var id = reader.ReadElementContentAsString();
diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs
index e7e3323c2..ee2b28c60 100644
--- a/MediaBrowser.Controller/Providers/DirectoryService.cs
+++ b/MediaBrowser.Controller/Providers/DirectoryService.cs
@@ -16,13 +16,16 @@ namespace MediaBrowser.Controller.Providers
private readonly ConcurrentDictionary<string, Dictionary<string, FileSystemMetadata>> _cache =
new ConcurrentDictionary<string, Dictionary<string, FileSystemMetadata>>(StringComparer.OrdinalIgnoreCase);
- public DirectoryService(ILogger logger, IFileSystem fileSystem)
+ private readonly ConcurrentDictionary<string, FileSystemMetadata> _fileCache =
+ new ConcurrentDictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase);
+
+ public DirectoryService(ILogger logger, IFileSystem fileSystem)
{
_logger = logger;
_fileSystem = fileSystem;
}
- public DirectoryService(IFileSystem fileSystem)
+ public DirectoryService(IFileSystem fileSystem)
: this(new NullLogger(), fileSystem)
{
}
@@ -100,20 +103,19 @@ namespace MediaBrowser.Controller.Providers
public FileSystemMetadata GetFile(string path)
{
- var directory = Path.GetDirectoryName(path);
-
- if (string.IsNullOrWhiteSpace(directory))
+ FileSystemMetadata file;
+ if (!_fileCache.TryGetValue(path, out file))
{
- _logger.Debug("Parent path is null for {0}", path);
- return null;
- }
-
- var dict = GetFileSystemDictionary(directory, false);
+ file = _fileSystem.GetFileInfo(path);
- FileSystemMetadata entry;
- dict.TryGetValue(path, out entry);
+ if (file != null)
+ {
+ _fileCache.TryAdd(path, file);
+ }
+ }
- return entry;
+ return file;
+ //return _fileSystem.GetFileInfo(path);
}
public IEnumerable<FileSystemMetadata> GetDirectories(string path)
diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
index 9427b2afd..87c3b36a2 100644
--- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
+++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
@@ -1,5 +1,6 @@
using System.Linq;
using CommonIO;
+using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.Providers
@@ -19,7 +20,7 @@ namespace MediaBrowser.Controller.Providers
public bool ForceSave { get; set; }
public MetadataRefreshOptions(IFileSystem fileSystem)
- : this(new DirectoryService(fileSystem))
+ : this(new DirectoryService(new NullLogger(), fileSystem))
{
}
diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs
index 6659d1553..387195245 100644
--- a/MediaBrowser.Controller/Session/ISessionManager.cs
+++ b/MediaBrowser.Controller/Session/ISessionManager.cs
@@ -172,15 +172,21 @@ namespace MediaBrowser.Controller.Session
Task SendPlaystateCommand(string controllingSessionId, string sessionId, PlaystateRequest command, CancellationToken cancellationToken);
/// <summary>
- /// Sends the message to user sessions.
+ /// Sends the message to admin sessions.
/// </summary>
/// <typeparam name="T"></typeparam>
- /// <param name="userId">The user identifier.</param>
/// <param name="name">The name.</param>
/// <param name="data">The data.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task SendMessageToUserSessions<T>(string userId, string name, T data, CancellationToken cancellationToken);
+ Task SendMessageToAdminSessions<T>(string name, T data, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Sends the message to user sessions.
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <returns>Task.</returns>
+ Task SendMessageToUserSessions<T>(List<string> userIds, string name, T data, CancellationToken cancellationToken);
/// <summary>
/// Sends the message to user device sessions.
diff --git a/MediaBrowser.Controller/Sync/ISyncManager.cs b/MediaBrowser.Controller/Sync/ISyncManager.cs
index 8eb934eaa..fbcb549ad 100644
--- a/MediaBrowser.Controller/Sync/ISyncManager.cs
+++ b/MediaBrowser.Controller/Sync/ISyncManager.cs
@@ -151,7 +151,7 @@ namespace MediaBrowser.Controller.Sync
/// </summary>
/// <param name="query">The query.</param>
/// <returns>QueryResult&lt;System.String&gt;.</returns>
- QueryResult<SyncedItemProgress> GetSyncedItemProgresses(SyncJobItemQuery query);
+ Dictionary<string, SyncedItemProgress> GetSyncedItemProgresses(SyncJobItemQuery query);
/// <summary>
/// Reports the synchronize job item transfer beginning.
diff --git a/MediaBrowser.Controller/Sync/ISyncRepository.cs b/MediaBrowser.Controller/Sync/ISyncRepository.cs
index 2af09dbaa..8e9b2bf77 100644
--- a/MediaBrowser.Controller/Sync/ISyncRepository.cs
+++ b/MediaBrowser.Controller/Sync/ISyncRepository.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Querying;
+using System.Collections.Generic;
+using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Sync;
using System.Threading.Tasks;
@@ -74,6 +75,6 @@ namespace MediaBrowser.Controller.Sync
/// </summary>
/// <param name="query">The query.</param>
/// <returns>QueryResult&lt;System.String&gt;.</returns>
- QueryResult<SyncedItemProgress> GetSyncedItemProgresses(SyncJobItemQuery query);
+ Dictionary<string, SyncedItemProgress> GetSyncedItemProgresses(SyncJobItemQuery query);
}
}
diff --git a/MediaBrowser.Controller/Sync/SyncedItemProgress.cs b/MediaBrowser.Controller/Sync/SyncedItemProgress.cs
index edb42eb0f..0fd929eb1 100644
--- a/MediaBrowser.Controller/Sync/SyncedItemProgress.cs
+++ b/MediaBrowser.Controller/Sync/SyncedItemProgress.cs
@@ -4,7 +4,7 @@ namespace MediaBrowser.Controller.Sync
{
public class SyncedItemProgress
{
- public string ItemId { get; set; }
+ public double Progress { get; set; }
public SyncJobItemStatus Status { get; set; }
}
}