فهرست منبع

update windows ffmpeg

Luke Pulverenti 9 سال پیش
والد
کامیت
99084edabe
31فایلهای تغییر یافته به همراه330 افزوده شده و 101 حذف شده
  1. 6 2
      MediaBrowser.Api/ApiEntryPoint.cs
  2. 18 2
      MediaBrowser.Api/LiveTv/LiveTvService.cs
  3. 0 1
      MediaBrowser.Api/Movies/MoviesService.cs
  4. 4 1
      MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
  5. 2 1
      MediaBrowser.Api/UserLibrary/ItemsService.cs
  6. 0 6
      MediaBrowser.Controller/Entities/Audio/Audio.cs
  7. 9 0
      MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
  8. 9 0
      MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
  9. 11 0
      MediaBrowser.Controller/Entities/BaseItem.cs
  10. 33 16
      MediaBrowser.Controller/Entities/Folder.cs
  11. 2 0
      MediaBrowser.Controller/Entities/IHasMetadata.cs
  12. 2 0
      MediaBrowser.Controller/Entities/InternalItemsQuery.cs
  13. 0 6
      MediaBrowser.Controller/Entities/MusicVideo.cs
  14. 9 0
      MediaBrowser.Controller/Entities/TV/Season.cs
  15. 9 0
      MediaBrowser.Controller/Entities/TV/Series.cs
  16. 0 5
      MediaBrowser.Controller/Entities/UserRootFolder.cs
  17. 9 0
      MediaBrowser.Controller/Playlists/Playlist.cs
  18. 3 0
      MediaBrowser.Model/LiveTv/ProgramQuery.cs
  19. 8 1
      MediaBrowser.Model/LiveTv/RecommendedProgramQuery.cs
  20. 57 4
      MediaBrowser.Providers/Manager/MetadataService.cs
  21. 22 7
      MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs
  22. 10 23
      MediaBrowser.Server.Implementations/Dto/DtoService.cs
  23. 11 3
      MediaBrowser.Server.Implementations/Library/LibraryManager.cs
  24. 16 2
      MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
  25. 6 4
      MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
  26. 58 4
      MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
  27. 4 4
      MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs
  28. 0 2
      MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
  29. 12 5
      MediaBrowser.ServerApplication/Native/WindowsApp.cs
  30. 0 1
      MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id
  31. 0 1
      MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id

+ 6 - 2
MediaBrowser.Api/ApiEntryPoint.cs

@@ -488,13 +488,17 @@ namespace MediaBrowser.Api
                 {
                     try
                     {
-                        Logger.Info("Killing ffmpeg process for {0}", job.Path);
+                        Logger.Info("Stopping ffmpeg process with q command for {0}", job.Path);
 
                         //process.Kill();
                         process.StandardInput.WriteLine("q");
 
                         // Need to wait because killing is asynchronous
-                        process.WaitForExit(5000);
+                        if (!process.WaitForExit(5000))
+                        {
+                            Logger.Info("Killing ffmpeg process for {0}", job.Path);
+                            process.Kill();
+                        }
                     }
                     catch (Exception ex)
                     {

+ 18 - 2
MediaBrowser.Api/LiveTv/LiveTvService.cs

@@ -254,6 +254,8 @@ namespace MediaBrowser.Api.LiveTv
         [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
         public bool? EnableImages { get; set; }
 
+        public bool EnableTotalRecordCount { get; set; }
+
         [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
         public int? ImageTypeLimit { get; set; }
 
@@ -266,12 +268,24 @@ namespace MediaBrowser.Api.LiveTv
         /// <value>The fields.</value>
         [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
         public string Fields { get; set; }
+
+        public GetPrograms()
+        {
+            EnableTotalRecordCount = true;
+        }
     }
 
     [Route("/LiveTv/Programs/Recommended", "GET", Summary = "Gets available live tv epgs..")]
     [Authenticated]
     public class GetRecommendedPrograms : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
     {
+        public bool EnableTotalRecordCount { get; set; }
+
+        public GetRecommendedPrograms()
+        {
+            EnableTotalRecordCount = true;
+        }
+
         [ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
         public string UserId { get; set; }
 
@@ -662,7 +676,8 @@ namespace MediaBrowser.Api.LiveTv
             {
                 ChannelIds = (request.ChannelIds ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToArray(),
                 UserId = request.UserId,
-                HasAired = request.HasAired
+                HasAired = request.HasAired,
+                EnableTotalRecordCount = request.EnableTotalRecordCount
             };
 
             if (!string.IsNullOrEmpty(request.MinStartDate))
@@ -709,7 +724,8 @@ namespace MediaBrowser.Api.LiveTv
                 HasAired = request.HasAired,
                 IsMovie = request.IsMovie,
                 IsKids = request.IsKids,
-                IsSports = request.IsSports
+                IsSports = request.IsSports,
+                EnableTotalRecordCount = request.EnableTotalRecordCount
             };
 
             var result = await _liveTvManager.GetRecommendedPrograms(query, GetDtoOptions(request), CancellationToken.None).ConfigureAwait(false);

+ 0 - 1
MediaBrowser.Api/Movies/MoviesService.cs

@@ -196,7 +196,6 @@ namespace MediaBrowser.Api.Movies
 
             var parentIds = new string[] { };
             var list = _libraryManager.GetItemList(query, parentIds)
-                .DistinctBy(i => i.PresentationUniqueKey, StringComparer.OrdinalIgnoreCase)
                 .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
                 .ToList();
 

+ 4 - 1
MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs

@@ -12,6 +12,7 @@ namespace MediaBrowser.Api.UserLibrary
         protected BaseItemsRequest()
         {
             EnableImages = true;
+            EnableTotalRecordCount = true;
         }
 
         /// <summary>
@@ -104,7 +105,9 @@ namespace MediaBrowser.Api.UserLibrary
 
         [ApiMember(Name = "IsInBoxSet", Description = "Optional filter by items that are in boxsets, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
         public bool? IsInBoxSet { get; set; }
-        
+
+        public bool EnableTotalRecordCount { get; set; }
+
         /// <summary>
         /// Skips over a given number of items within the results. Use for paging.
         /// </summary>

+ 2 - 1
MediaBrowser.Api/UserLibrary/ItemsService.cs

@@ -230,7 +230,8 @@ namespace MediaBrowser.Api.UserLibrary
                 ParentId = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId),
                 ParentIndexNumber = request.ParentIndexNumber,
                 AiredDuringSeason = request.AiredDuringSeason,
-                AlbumArtistStartsWithOrGreater = request.AlbumArtistStartsWithOrGreater
+                AlbumArtistStartsWithOrGreater = request.AlbumArtistStartsWithOrGreater,
+                EnableTotalRecordCount = request.EnableTotalRecordCount
             };
 
             if (!string.IsNullOrWhiteSpace(request.Ids))

+ 0 - 6
MediaBrowser.Controller/Entities/Audio/Audio.cs

@@ -40,12 +40,6 @@ namespace MediaBrowser.Controller.Entities.Audio
 
         public List<string> AlbumArtists { get; set; }
 
-        /// <summary>
-        /// Gets or sets the album.
-        /// </summary>
-        /// <value>The album.</value>
-        public string Album { get; set; }
-
         [IgnoreDataMember]
         public bool IsThemeMedia
         {

+ 9 - 0
MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs

@@ -48,6 +48,15 @@ namespace MediaBrowser.Controller.Entities.Audio
             }
         }
 
+        [IgnoreDataMember]
+        public override bool SupportsCumulativeRunTimeTicks
+        {
+            get
+            {
+                return true;
+            }
+        }
+
         [IgnoreDataMember]
         public List<string> AllArtists
         {

+ 9 - 0
MediaBrowser.Controller/Entities/Audio/MusicArtist.cs

@@ -34,6 +34,15 @@ namespace MediaBrowser.Controller.Entities.Audio
             }
         }
 
+        [IgnoreDataMember]
+        public override bool SupportsCumulativeRunTimeTicks
+        {
+            get
+            {
+                return true;
+            }
+        }
+
         [IgnoreDataMember]
         public override bool SupportsAddingToPlaylist
         {

+ 11 - 0
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -69,6 +69,12 @@ namespace MediaBrowser.Controller.Entities
 
         public List<ItemImageInfo> ImageInfos { get; set; }
 
+        /// <summary>
+        /// Gets or sets the album.
+        /// </summary>
+        /// <value>The album.</value>
+        public string Album { get; set; }
+
         /// <summary>
         /// Gets or sets the channel identifier.
         /// </summary>
@@ -1175,6 +1181,11 @@ namespace MediaBrowser.Controller.Entities
             get { return Id.ToString("N"); }
         }
 
+        public virtual bool RequiresRefresh()
+        {
+            return false;
+        }
+
         private string _userDataKey;
         /// <summary>
         /// Gets the user data key.

+ 33 - 16
MediaBrowser.Controller/Entities/Folder.cs

@@ -28,6 +28,9 @@ namespace MediaBrowser.Controller.Entities
         public List<Guid> ThemeSongIds { get; set; }
         public List<Guid> ThemeVideoIds { get; set; }
 
+        [IgnoreDataMember]
+        public DateTime? DateLastMediaAdded { get; set; }
+
         public Folder()
         {
             LinkedChildren = new List<LinkedChild>();
@@ -55,6 +58,36 @@ namespace MediaBrowser.Controller.Entities
             }
         }
 
+        [IgnoreDataMember]
+        public virtual bool SupportsCumulativeRunTimeTicks
+        {
+            get
+            {
+                return false;
+            }
+        }
+
+        [IgnoreDataMember]
+        public virtual bool SupportsDateLastMediaAdded
+        {
+            get
+            {
+                return false;
+            }
+        }
+
+        public override bool RequiresRefresh()
+        {
+            var baseResult = base.RequiresRefresh();
+
+            if (SupportsCumulativeRunTimeTicks && !RunTimeTicks.HasValue)
+            {
+                baseResult = true;
+            }
+
+            return baseResult;
+        }
+
         [IgnoreDataMember]
         public override string FileNameWithoutExtension
         {
@@ -789,11 +822,6 @@ namespace MediaBrowser.Controller.Entities
                     Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
                     return true;
                 }
-                if (query.SortBy.Contains(ItemSortBy.Album, StringComparer.OrdinalIgnoreCase))
-                {
-                    Logger.Debug("Query requires post-filtering due to ItemSortBy.Album");
-                    return true;
-                }
                 if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
                 {
                     Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
@@ -809,11 +837,6 @@ namespace MediaBrowser.Controller.Entities
                     Logger.Debug("Query requires post-filtering due to ItemSortBy.Budget");
                     return true;
                 }
-                if (query.SortBy.Contains(ItemSortBy.DateLastContentAdded, StringComparer.OrdinalIgnoreCase))
-                {
-                    Logger.Debug("Query requires post-filtering due to ItemSortBy.DateLastContentAdded");
-                    return true;
-                }
                 if (query.SortBy.Contains(ItemSortBy.GameSystem, StringComparer.OrdinalIgnoreCase))
                 {
                     Logger.Debug("Query requires post-filtering due to ItemSortBy.GameSystem");
@@ -1086,12 +1109,6 @@ namespace MediaBrowser.Controller.Entities
                 return true;
             }
 
-            if (query.AlbumNames.Length > 0)
-            {
-                Logger.Debug("Query requires post-filtering due to AlbumNames");
-                return true;
-            }
-
             if (query.ArtistNames.Length > 0)
             {
                 Logger.Debug("Query requires post-filtering due to ArtistNames");

+ 2 - 0
MediaBrowser.Controller/Entities/IHasMetadata.cs

@@ -49,5 +49,7 @@ namespace MediaBrowser.Controller.Entities
         /// </summary>
         /// <value><c>true</c> if [supports people]; otherwise, <c>false</c>.</value>
         bool SupportsPeople { get; }
+
+        bool RequiresRefresh();
     }
 }

+ 2 - 0
MediaBrowser.Controller/Entities/InternalItemsQuery.cs

@@ -137,10 +137,12 @@ namespace MediaBrowser.Controller.Entities
         public string AncestorWithPresentationUniqueKey { get; set; }
 
         public bool GroupByPresentationUniqueKey { get; set; }
+        public bool EnableTotalRecordCount { get; set; }
 
         public InternalItemsQuery()
         {
             GroupByPresentationUniqueKey = true;
+            EnableTotalRecordCount = true;
 
             AlbumNames = new string[] { };
             ArtistNames = new string[] { };

+ 0 - 6
MediaBrowser.Controller/Entities/MusicVideo.cs

@@ -9,12 +9,6 @@ namespace MediaBrowser.Controller.Entities
 {
     public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasProductionLocations, IHasBudget, IHasLookupInfo<MusicVideoInfo>
     {
-        /// <summary>
-        /// Gets or sets the album.
-        /// </summary>
-        /// <value>The album.</value>
-        public string Album { get; set; }
-
         /// <summary>
         /// Gets or sets the budget.
         /// </summary>

+ 9 - 0
MediaBrowser.Controller/Entities/TV/Season.cs

@@ -32,6 +32,15 @@ namespace MediaBrowser.Controller.Entities.TV
             }
         }
 
+        [IgnoreDataMember]
+        public override bool SupportsDateLastMediaAdded
+        {
+            get
+            {
+                return true;
+            }
+        }
+
         [IgnoreDataMember]
         public override Guid? DisplayParentId
         {

+ 9 - 0
MediaBrowser.Controller/Entities/TV/Series.cs

@@ -48,6 +48,15 @@ namespace MediaBrowser.Controller.Entities.TV
             }
         }
 
+        [IgnoreDataMember]
+        public override bool SupportsDateLastMediaAdded
+        {
+            get
+            {
+                return true;
+            }
+        }
+
         public bool DisplaySpecialsWithSeasons { get; set; }
 
         public List<Guid> LocalTrailerIds { get; set; }

+ 0 - 5
MediaBrowser.Controller/Entities/UserRootFolder.cs

@@ -102,10 +102,5 @@ namespace MediaBrowser.Controller.Entities
                 LibraryManager.RegisterItem(item);
             }
         }
-
-        public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
-        {
-            // Nothing meaninful here and will only waste resources
-        }
     }
 }

+ 9 - 0
MediaBrowser.Controller/Playlists/Playlist.cs

@@ -39,6 +39,15 @@ namespace MediaBrowser.Controller.Playlists
             }
         }
 
+        [IgnoreDataMember]
+        public override bool SupportsCumulativeRunTimeTicks
+        {
+            get
+            {
+                return true;
+            }
+        }
+
         public override bool IsAuthorizedToDelete(User user)
         {
             return true;

+ 3 - 0
MediaBrowser.Model/LiveTv/ProgramQuery.cs

@@ -14,8 +14,11 @@ namespace MediaBrowser.Model.LiveTv
             ChannelIds = new string[] { };
             SortBy = new string[] { };
             Genres = new string[] { };
+            EnableTotalRecordCount = true;
         }
 
+        public bool EnableTotalRecordCount { get; set; }
+
         /// <summary>
         /// Fields to return within the items, in addition to basic information
         /// </summary>

+ 8 - 1
MediaBrowser.Model/LiveTv/RecommendedProgramQuery.cs

@@ -13,7 +13,14 @@ namespace MediaBrowser.Model.LiveTv
         public bool? EnableImages { get; set; }
         public int? ImageTypeLimit { get; set; }
         public ImageType[] EnableImageTypes { get; set; }
-        
+
+        public bool EnableTotalRecordCount { get; set; }
+
+        public RecommendedProgramQuery()
+        {
+            EnableTotalRecordCount = true;
+        }
+
         /// <summary>
         /// Gets or sets the user identifier.
         /// </summary>

+ 57 - 4
MediaBrowser.Providers/Manager/MetadataService.cs

@@ -310,6 +310,11 @@ namespace MediaBrowser.Providers.Manager
                 return true;
             }
 
+            if (item is MusicVideo)
+            {
+                return true;
+            }
+
             return false;
         }
 
@@ -390,7 +395,6 @@ namespace MediaBrowser.Providers.Manager
             return _cachedTask;
         }
 
-        private readonly Task<ItemUpdateType> _cachedResult = Task.FromResult(ItemUpdateType.None);
         /// <summary>
         /// Befores the save.
         /// </summary>
@@ -398,9 +402,58 @@ namespace MediaBrowser.Providers.Manager
         /// <param name="isFullRefresh">if set to <c>true</c> [is full refresh].</param>
         /// <param name="currentUpdateType">Type of the current update.</param>
         /// <returns>ItemUpdateType.</returns>
-        protected virtual Task<ItemUpdateType> BeforeSave(TItemType item, bool isFullRefresh, ItemUpdateType currentUpdateType)
+        protected virtual async Task<ItemUpdateType> BeforeSave(TItemType item, bool isFullRefresh, ItemUpdateType currentUpdateType)
+        {
+            var updateType = ItemUpdateType.None;
+
+            updateType |= SaveCumulativeRunTimeTicks(item, isFullRefresh, currentUpdateType);
+            updateType |= SaveDateLastMediaAdded(item, isFullRefresh, currentUpdateType);
+
+            return updateType;
+        }
+
+        private ItemUpdateType SaveCumulativeRunTimeTicks(TItemType item, bool isFullRefresh, ItemUpdateType currentUpdateType)
+        {
+            var updateType = ItemUpdateType.None;
+
+            if (isFullRefresh || currentUpdateType > ItemUpdateType.None)
+            {
+                var folder = item as Folder;
+                if (folder != null && folder.SupportsCumulativeRunTimeTicks)
+                {
+                    var ticks = folder.GetRecursiveChildren(i => !i.IsFolder).Select(i => i.RunTimeTicks ?? 0).Sum();
+
+                    if (!folder.RunTimeTicks.HasValue || folder.RunTimeTicks.Value != ticks)
+                    {
+                        folder.RunTimeTicks = ticks;
+                        updateType = ItemUpdateType.MetadataEdit;
+                    }
+                }
+            }
+
+            return updateType;
+        }
+
+        private ItemUpdateType SaveDateLastMediaAdded(TItemType item, bool isFullRefresh, ItemUpdateType currentUpdateType)
         {
-            return _cachedResult;
+            var updateType = ItemUpdateType.None;
+
+            if (isFullRefresh || currentUpdateType > ItemUpdateType.None)
+            {
+                var folder = item as Folder;
+                if (folder != null && folder.SupportsDateLastMediaAdded)
+                {
+                    var date = folder.GetRecursiveChildren(i => !i.IsFolder).Select(i => i.DateCreated).Max();
+
+                    if (!folder.DateLastMediaAdded.HasValue || folder.DateLastMediaAdded.Value != date)
+                    {
+                        folder.DateLastMediaAdded = date;
+                        updateType = ItemUpdateType.MetadataEdit;
+                    }
+                }
+            }
+
+            return updateType;
         }
 
         /// <summary>
@@ -420,7 +473,7 @@ namespace MediaBrowser.Providers.Manager
                 : status.DateLastMetadataRefresh ?? default(DateTime);
 
             // Run all if either of these flags are true
-            var runAllProviders = options.ReplaceAllMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || dateLastRefresh == default(DateTime);
+            var runAllProviders = options.ReplaceAllMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || dateLastRefresh == default(DateTime) || item.RequiresRefresh();
 
             if (!runAllProviders)
             {

+ 22 - 7
MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs

@@ -62,12 +62,25 @@ namespace MediaBrowser.Providers.Music
 
         private IEnumerable<RemoteSearchResult> GetResultsFromResponse(XmlDocument doc)
         {
-            var ns = new XmlNamespaceManager(doc.NameTable);
-            ns.AddNamespace("mb", "https://musicbrainz.org/ns/mmd-2.0#");
+            //var ns = new XmlNamespaceManager(doc.NameTable);
+            //ns.AddNamespace("mb", "https://musicbrainz.org/ns/mmd-2.0#");
 
             var list = new List<RemoteSearchResult>();
 
-            var nodes = doc.SelectNodes("//mb:artist-list/mb:artist", ns);
+            var docElem = doc.DocumentElement;
+
+            if (docElem == null)
+            {
+                return list;
+            }
+
+            var artistList = docElem.FirstChild;
+            if (artistList == null)
+            {
+                return list;
+            }
+
+            var nodes = artistList.ChildNodes;
 
             if (nodes != null)
             {
@@ -79,11 +92,13 @@ namespace MediaBrowser.Providers.Music
 
                         string mbzId = node.Attributes["id"].Value;
 
-                        var nameNode = node.SelectSingleNode("//mb:name", ns);
-
-                        if (nameNode != null)
+                        foreach (var child in node.ChildNodes.Cast<XmlNode>())
                         {
-                            name = nameNode.InnerText;
+                            if (string.Equals(child.Name, "name", StringComparison.OrdinalIgnoreCase))
+                            {
+                                name = node.InnerText;
+                                break;
+                            }
                         }
 
                         if (!string.IsNullOrWhiteSpace(mbzId) && !string.IsNullOrWhiteSpace(name))

+ 10 - 23
MediaBrowser.Server.Implementations/Dto/DtoService.cs

@@ -499,6 +499,16 @@ namespace MediaBrowser.Server.Implementations.Dto
                     }
                 }
 
+                if (fields.Contains(ItemFields.CumulativeRunTimeTicks))
+                {
+                    dto.CumulativeRunTimeTicks = dto.RunTimeTicks;
+                }
+
+                if (fields.Contains(ItemFields.DateLastMediaAdded))
+                {
+                    dto.DateLastMediaAdded = folder.DateLastMediaAdded;
+                }
+
                 dto.UserData.Played = dto.UserData.PlayedPercentage.HasValue && dto.UserData.PlayedPercentage.Value >= 100;
             }
 
@@ -1613,9 +1623,7 @@ namespace MediaBrowser.Server.Implementations.Dto
         {
             var recursiveItemCount = 0;
             var unplayed = 0;
-            long runtime = 0;
 
-            DateTime? dateLastMediaAdded = null;
             double totalPercentPlayed = 0;
             double totalSyncPercent = 0;
             var addSyncInfo = fields.Contains(ItemFields.SyncInfo);
@@ -1632,15 +1640,6 @@ namespace MediaBrowser.Server.Implementations.Dto
             // Loop through each recursive child
             foreach (var child in children)
             {
-                if (!dateLastMediaAdded.HasValue)
-                {
-                    dateLastMediaAdded = child.DateCreated;
-                }
-                else
-                {
-                    dateLastMediaAdded = new[] { dateLastMediaAdded.Value, child.DateCreated }.Max();
-                }
-
                 var userdata = _userDataRepository.GetUserData(user, child);
 
                 recursiveItemCount++;
@@ -1669,8 +1668,6 @@ namespace MediaBrowser.Server.Implementations.Dto
                     unplayed++;
                 }
 
-                runtime += child.RunTimeTicks ?? 0;
-
                 if (addSyncInfo)
                 {
                     double percent = 0;
@@ -1709,16 +1706,6 @@ namespace MediaBrowser.Server.Implementations.Dto
                     }
                 }
             }
-
-            if (runtime > 0 && fields.Contains(ItemFields.CumulativeRunTimeTicks))
-            {
-                dto.CumulativeRunTimeTicks = runtime;
-            }
-
-            if (fields.Contains(ItemFields.DateLastMediaAdded))
-            {
-                dto.DateLastMediaAdded = dateLastMediaAdded;
-            }
         }
 
         /// <summary>

+ 11 - 3
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -1354,12 +1354,20 @@ namespace MediaBrowser.Server.Implementations.Library
                 AddUserToQuery(query, query.User);
             }
 
-            var initialResult = ItemRepository.GetItemIds(query);
+            if (query.EnableTotalRecordCount)
+            {
+                var initialResult = ItemRepository.GetItemIds(query);
+
+                return new QueryResult<BaseItem>
+                {
+                    TotalRecordCount = initialResult.TotalRecordCount,
+                    Items = initialResult.Items.Select(GetItemById).Where(i => i != null).ToArray()
+                };
+            }
 
             return new QueryResult<BaseItem>
             {
-                TotalRecordCount = initialResult.TotalRecordCount,
-                Items = initialResult.Items.Select(GetItemById).Where(i => i != null).ToArray()
+                Items = ItemRepository.GetItemIdsList(query).Select(GetItemById).Where(i => i != null).ToArray()
             };
         }
 

+ 16 - 2
MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs

@@ -760,7 +760,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
             if (info.IsMovie)
             {
                 var customRecordingPath = config.MovieRecordingPath;
-                if ((string.IsNullOrWhiteSpace(customRecordingPath) || string.Equals(customRecordingPath, recordPath, StringComparison.OrdinalIgnoreCase)) && config.EnableRecordingSubfolders)
+                var allowSubfolder = true;
+                if (!string.IsNullOrWhiteSpace(customRecordingPath))
+                {
+                    allowSubfolder = string.Equals(customRecordingPath, recordPath, StringComparison.OrdinalIgnoreCase);
+                    recordPath = customRecordingPath;
+                }
+
+                if (allowSubfolder && config.EnableRecordingSubfolders)
                 {
                     recordPath = Path.Combine(recordPath, "Movies");
                 }
@@ -775,7 +782,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
             else if (info.IsSeries)
             {
                 var customRecordingPath = config.SeriesRecordingPath;
-                if ((string.IsNullOrWhiteSpace(customRecordingPath) || string.Equals(customRecordingPath, recordPath, StringComparison.OrdinalIgnoreCase)) && config.EnableRecordingSubfolders)
+                var allowSubfolder = true;
+                if (!string.IsNullOrWhiteSpace(customRecordingPath))
+                {
+                    allowSubfolder = string.Equals(customRecordingPath, recordPath, StringComparison.OrdinalIgnoreCase);
+                    recordPath = customRecordingPath;
+                }
+
+                if (allowSubfolder && config.EnableRecordingSubfolders)
                 {
                     recordPath = Path.Combine(recordPath, "Series");
                 }

+ 6 - 4
MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs

@@ -886,7 +886,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 StartIndex = query.StartIndex,
                 Limit = query.Limit,
                 SortBy = query.SortBy,
-                SortOrder = query.SortOrder ?? SortOrder.Ascending
+                SortOrder = query.SortOrder ?? SortOrder.Ascending,
+                EnableTotalRecordCount = query.EnableTotalRecordCount
             };
 
             if (query.HasAired.HasValue)
@@ -924,7 +925,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
                 IsAiring = query.IsAiring,
                 IsMovie = query.IsMovie,
                 IsSports = query.IsSports,
-                IsKids = query.IsKids
+                IsKids = query.IsKids,
+                EnableTotalRecordCount = query.EnableTotalRecordCount
             };
 
             if (query.HasAired.HasValue)
@@ -1263,11 +1265,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
 
         private async Task CleanDatabaseInternal(List<Guid> currentIdList, string[] validTypes, IProgress<double> progress, CancellationToken cancellationToken)
         {
-            var list = _itemRepo.GetItemIds(new InternalItemsQuery
+            var list = _itemRepo.GetItemIdsList(new InternalItemsQuery
             {
                 IncludeItemTypes = validTypes
 
-            }).Items.ToList();
+            }).ToList();
 
             var numComplete = 0;
 

+ 58 - 4
MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs

@@ -85,7 +85,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
         private IDbCommand _updateInheritedRatingCommand;
         private IDbCommand _updateInheritedTagsCommand;
 
-        public const int LatestSchemaVersion = 76;
+        public const int LatestSchemaVersion = 77;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
@@ -235,6 +235,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
             _connection.AddColumn(Logger, "TypedBaseItems", "SlugName", "Text");
             _connection.AddColumn(Logger, "TypedBaseItems", "OriginalTitle", "Text");
             _connection.AddColumn(Logger, "TypedBaseItems", "PrimaryVersionId", "Text");
+            _connection.AddColumn(Logger, "TypedBaseItems", "DateLastMediaAdded", "DATETIME");
+            _connection.AddColumn(Logger, "TypedBaseItems", "Album", "Text");
+
             _connection.AddColumn(Logger, "UserDataKeys", "Priority", "INT");
 
             string[] postQueries =
@@ -351,7 +354,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
             "TrailerTypes",
             "DateModifiedDuringLastRefresh",
             "OriginalTitle",
-            "PrimaryVersionId"
+            "PrimaryVersionId",
+            "DateLastMediaAdded",
+            "Album"
         };
 
         private readonly string[] _mediaStreamSaveColumns =
@@ -463,7 +468,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 "PresentationUniqueKey",
                 "SlugName",
                 "OriginalTitle",
-                "PrimaryVersionId"
+                "PrimaryVersionId",
+                "DateLastMediaAdded",
+                "Album"
             };
             _saveItemCommand = _connection.CreateCommand();
             _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
@@ -824,6 +831,18 @@ namespace MediaBrowser.Server.Implementations.Persistence
                         _saveItemCommand.GetParameter(index++).Value = null;
                     }
 
+                    var folder = item as Folder;
+                    if (folder != null && folder.DateLastMediaAdded.HasValue)
+                    {
+                        _saveItemCommand.GetParameter(index++).Value = folder.DateLastMediaAdded.Value;
+                    }
+                    else
+                    {
+                        _saveItemCommand.GetParameter(index++).Value = null;
+                    }
+
+                    _saveItemCommand.GetParameter(index++).Value = item.Album;
+
                     _saveItemCommand.Transaction = transaction;
 
                     _saveItemCommand.ExecuteNonQuery();
@@ -1217,6 +1236,17 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 }
             }
 
+            var folder = item as Folder;
+            if (folder != null && !reader.IsDBNull(54))
+            {
+                folder.DateLastMediaAdded = reader.GetDateTime(54).ToUniversalTime();
+            }
+
+            if (!reader.IsDBNull(55))
+            {
+                item.Album = reader.GetString(55);
+            }
+
             return item;
         }
 
@@ -1777,6 +1807,10 @@ namespace MediaBrowser.Server.Implementations.Persistence
             {
                 return new Tuple<string, bool>("played", false);
             }
+            if (string.Equals(name, ItemSortBy.DateLastContentAdded, StringComparison.OrdinalIgnoreCase))
+            {
+                return new Tuple<string, bool>("DateLastMediaAdded", false);
+            }
 
             return new Tuple<string, bool>(name, false);
         }
@@ -2484,7 +2518,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
             if (query.MediaTypes.Length == 1)
             {
                 whereClauses.Add("MediaType=@MediaTypes");
-                cmd.Parameters.Add(cmd, "@MediaTypes", DbType.String).Value = query.MediaTypes[0].ToString();
+                cmd.Parameters.Add(cmd, "@MediaTypes", DbType.String).Value = query.MediaTypes[0];
             }
             if (query.MediaTypes.Length > 1)
             {
@@ -2493,6 +2527,26 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 whereClauses.Add("MediaType in (" + val + ")");
             }
 
+            if (query.AlbumNames.Length > 0)
+            {
+                var clause = "(";
+
+                var index = 0;
+                foreach (var name in query.AlbumNames)
+                {
+                    if (index > 0)
+                    {
+                        clause += " OR ";
+                    }
+                    clause += "Album=@AlbumName" + index;
+                    index++;
+                    cmd.Parameters.Add(cmd, "@AlbumName" + index, DbType.String).Value = name;
+                }
+
+                clause += ")";
+                whereClauses.Add(clause);
+            }
+
             //var enableItemsByName = query.IncludeItemsByName ?? query.IncludeItemTypes.Length > 0;
             var enableItemsByName = query.IncludeItemsByName ?? false;
 

+ 4 - 4
MediaBrowser.Server.Implementations/Sorting/DateLastMediaAddedComparer.cs

@@ -49,10 +49,10 @@ namespace MediaBrowser.Server.Implementations.Sorting
 
             if (folder != null)
             {
-                return folder.GetRecursiveChildren(User, i => !i.IsFolder)
-                    .Select(i => i.DateCreated)
-                    .OrderByDescending(i => i)
-                    .FirstOrDefault();
+                if (folder.DateLastMediaAdded.HasValue)
+                {
+                    return folder.DateLastMediaAdded.Value;
+                }
             }
 
             return x.DateCreated;

+ 0 - 2
MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj

@@ -142,8 +142,6 @@
     <None Include="App.config" />
     <None Include="app.manifest" />
     <EmbeddedResource Include="Native\RegisterServer.bat" />
-    <EmbeddedResource Include="ffmpeg\ffmpegx64.7z" />
-    <EmbeddedResource Include="ffmpeg\ffmpegx86.7z" />
     <None Include="packages.config" />
   </ItemGroup>
   <ItemGroup>

+ 12 - 5
MediaBrowser.ServerApplication/Native/WindowsApp.cs

@@ -158,9 +158,9 @@ namespace MediaBrowser.ServerApplication.Native
 
             info.FFMpegFilename = "ffmpeg.exe";
             info.FFProbeFilename = "ffprobe.exe";
-            info.Version = "20160401";
+            info.Version = "20160508";
             info.ArchiveType = "7z";
-            info.IsEmbedded = true;
+            info.IsEmbedded = false;
             info.DownloadUrls = GetDownloadUrls();
 
             return info;
@@ -212,11 +212,18 @@ namespace MediaBrowser.ServerApplication.Native
             switch (Environment.SystemArchitecture)
             {
                 case Architecture.X86_X64:
-                    return new[] { "MediaBrowser.ServerApplication.ffmpeg.ffmpegx64.7z" };
+                    return new[]
+                    {
+                                "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20160508-win64.7z",
+                                "https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20160508-git-caee88d-win64-static.7z"
+                            };
                 case Architecture.X86:
-                    return new[] { "MediaBrowser.ServerApplication.ffmpeg.ffmpegx86.7z" };
+                    return new[]
+                    {
+                                "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20160508-win32.7z",
+                                "https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20160508-git-caee88d-win32-static.7z"
+                            };
             }
-
             return new string[] { };
         }
     }

+ 0 - 1
MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id

@@ -1 +0,0 @@
-9dc10b022537738edce7eb71aa8dd4adbfee2c7b

+ 0 - 1
MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id

@@ -1 +0,0 @@
-00fa1afa35fbd0a7e97ad7956e42ae17f6882f64