diff options
| author | Luke <luke.pulverenti@gmail.com> | 2017-07-23 02:12:16 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-07-23 02:12:16 -0400 |
| commit | 5ec9d4e9fe4b3e5109ca1abf6c1ffdb87fd2d4dd (patch) | |
| tree | e49cc827583b6dffeabb142af5fae889b1a09581 /Emby.Dlna | |
| parent | e99bc61d53f393dc475e265e3b5bc8c19b186594 (diff) | |
| parent | 0d1b5ad733e6f1bbf6d730e723969495dda99016 (diff) | |
Merge pull request #2767 from MediaBrowser/beta
Beta
Diffstat (limited to 'Emby.Dlna')
| -rw-r--r-- | Emby.Dlna/ContentDirectory/ControlHandler.cs | 356 | ||||
| -rw-r--r-- | Emby.Dlna/Didl/DidlBuilder.cs | 40 | ||||
| -rw-r--r-- | Emby.Dlna/Eventing/EventManager.cs | 60 | ||||
| -rw-r--r-- | Emby.Dlna/PlayTo/PlaylistItemFactory.cs | 5 | ||||
| -rw-r--r-- | Emby.Dlna/Profiles/LgTvProfile.cs | 9 | ||||
| -rw-r--r-- | Emby.Dlna/Profiles/Xml/LG Smart TV.xml | 3 | ||||
| -rw-r--r-- | Emby.Dlna/Service/BaseService.cs | 8 |
7 files changed, 443 insertions, 38 deletions
diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index e93ee5990d..9345a1df71 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -26,6 +26,7 @@ using System.Xml; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Playlists; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Xml; @@ -482,6 +483,12 @@ namespace Emby.Dlna.ContentDirectory return GetMusicArtistItems(item, null, user, sort, startIndex, limit); } + var collectionFolder = item as ICollectionFolder; + if (collectionFolder != null && string.Equals(CollectionType.Music, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase)) + { + return GetMusicFolders(item, user, stubType, sort, startIndex, limit); + } + if (stubType.HasValue) { if (stubType.Value == StubType.People) @@ -518,7 +525,7 @@ namespace Emby.Dlna.ContentDirectory StartIndex = startIndex, User = user, IsMissing = false, - PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows, CollectionType.Music }, + PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows }, ExcludeItemTypes = new[] { typeof(Game).Name, typeof(Book).Name }, IsPlaceHolder = false, DtoOptions = GetDtoOptions() @@ -531,6 +538,278 @@ namespace Emby.Dlna.ContentDirectory return ToResult(queryResult); } + private QueryResult<ServerItem> GetMusicFolders(BaseItem item, User user, StubType? stubType, SortCriteria sort, int? startIndex, int? limit) + { + var query = new InternalItemsQuery(user) + { + StartIndex = startIndex, + Limit = limit + }; + SetSorting(query, sort, false); + + if (stubType.HasValue && stubType.Value == StubType.Latest) + { + return GetMusicLatest(item, user, query); + } + + if (stubType.HasValue && stubType.Value == StubType.Playlists) + { + return GetMusicPlaylists(item, user, query); + } + + if (stubType.HasValue && stubType.Value == StubType.Albums) + { + return GetMusicAlbums(item, user, query); + } + + if (stubType.HasValue && stubType.Value == StubType.Artists) + { + return GetMusicArtists(item, user, query); + } + + if (stubType.HasValue && stubType.Value == StubType.AlbumArtists) + { + return GetMusicAlbumArtists(item, user, query); + } + + if (stubType.HasValue && stubType.Value == StubType.FavoriteAlbums) + { + return GetFavoriteAlbums(item, user, query); + } + + if (stubType.HasValue && stubType.Value == StubType.FavoriteArtists) + { + return GetFavoriteArtists(item, user, query); + } + + if (stubType.HasValue && stubType.Value == StubType.FavoriteSongs) + { + return GetFavoriteSongs(item, user, query); + } + + if (stubType.HasValue && stubType.Value == StubType.Songs) + { + return GetMusicSongs(item, user, query); + } + + if (stubType.HasValue && stubType.Value == StubType.Genres) + { + return GetMusicGenres(item, user, query); + } + + var list = new List<ServerItem>(); + + list.Add(new ServerItem(item) + { + StubType = StubType.Latest + }); + + list.Add(new ServerItem(item) + { + StubType = StubType.Playlists + }); + + list.Add(new ServerItem(item) + { + StubType = StubType.Albums + }); + + list.Add(new ServerItem(item) + { + StubType = StubType.AlbumArtists + }); + + list.Add(new ServerItem(item) + { + StubType = StubType.Artists + }); + + list.Add(new ServerItem(item) + { + StubType = StubType.Songs + }); + + list.Add(new ServerItem(item) + { + StubType = StubType.Genres + }); + + list.Add(new ServerItem(item) + { + StubType = StubType.FavoriteArtists + }); + + list.Add(new ServerItem(item) + { + StubType = StubType.FavoriteAlbums + }); + + list.Add(new ServerItem(item) + { + StubType = StubType.FavoriteSongs + }); + + return new QueryResult<ServerItem> + { + Items = list.ToArray(), + TotalRecordCount = list.Count + }; + } + + private QueryResult<ServerItem> GetMusicAlbums(BaseItem parent, User user, InternalItemsQuery query) + { + query.Recursive = true; + query.Parent = parent; + query.SetUser(user); + + query.IncludeItemTypes = new[] { typeof(MusicAlbum).Name }; + + var result = _libraryManager.GetItemsResult(query); + + return ToResult(result); + } + + private QueryResult<ServerItem> GetMusicSongs(BaseItem parent, User user, InternalItemsQuery query) + { + query.Recursive = true; + query.Parent = parent; + query.SetUser(user); + + query.IncludeItemTypes = new[] { typeof(Audio).Name }; + + var result = _libraryManager.GetItemsResult(query); + + return ToResult(result); + } + + private QueryResult<ServerItem> GetFavoriteSongs(BaseItem parent, User user, InternalItemsQuery query) + { + query.Recursive = true; + query.Parent = parent; + query.SetUser(user); + query.IsFavorite = true; + query.IncludeItemTypes = new[] { typeof(Audio).Name }; + + var result = _libraryManager.GetItemsResult(query); + + return ToResult(result); + } + + private QueryResult<ServerItem> GetFavoriteAlbums(BaseItem parent, User user, InternalItemsQuery query) + { + query.Recursive = true; + query.Parent = parent; + query.SetUser(user); + query.IsFavorite = true; + query.IncludeItemTypes = new[] { typeof(MusicAlbum).Name }; + + var result = _libraryManager.GetItemsResult(query); + + return ToResult(result); + } + + private QueryResult<ServerItem> GetMusicGenres(BaseItem parent, User user, InternalItemsQuery query) + { + var genresResult = _libraryManager.GetMusicGenres(new InternalItemsQuery(user) + { + AncestorIds = new[] { parent.Id.ToString("N") }, + StartIndex = query.StartIndex, + Limit = query.Limit + }); + + var result = new QueryResult<BaseItem> + { + TotalRecordCount = genresResult.TotalRecordCount, + Items = genresResult.Items.Select(i => i.Item1).ToArray() + }; + + return ToResult(result); + } + + private QueryResult<ServerItem> GetMusicAlbumArtists(BaseItem parent, User user, InternalItemsQuery query) + { + var artists = _libraryManager.GetAlbumArtists(new InternalItemsQuery(user) + { + AncestorIds = new[] { parent.Id.ToString("N") }, + StartIndex = query.StartIndex, + Limit = query.Limit + }); + + var result = new QueryResult<BaseItem> + { + TotalRecordCount = artists.TotalRecordCount, + Items = artists.Items.Select(i => i.Item1).ToArray() + }; + + return ToResult(result); + } + + private QueryResult<ServerItem> GetMusicArtists(BaseItem parent, User user, InternalItemsQuery query) + { + var artists = _libraryManager.GetArtists(new InternalItemsQuery(user) + { + AncestorIds = new[] { parent.Id.ToString("N") }, + StartIndex = query.StartIndex, + Limit = query.Limit + }); + + var result = new QueryResult<BaseItem> + { + TotalRecordCount = artists.TotalRecordCount, + Items = artists.Items.Select(i => i.Item1).ToArray() + }; + + return ToResult(result); + } + + private QueryResult<ServerItem> GetFavoriteArtists(BaseItem parent, User user, InternalItemsQuery query) + { + var artists = _libraryManager.GetArtists(new InternalItemsQuery(user) + { + AncestorIds = new[] { parent.Id.ToString("N") }, + StartIndex = query.StartIndex, + Limit = query.Limit, + IsFavorite = true + }); + + var result = new QueryResult<BaseItem> + { + TotalRecordCount = artists.TotalRecordCount, + Items = artists.Items.Select(i => i.Item1).ToArray() + }; + + return ToResult(result); + } + + private QueryResult<ServerItem> GetMusicPlaylists(BaseItem parent, User user, InternalItemsQuery query) + { + query.Parent = null; + query.IncludeItemTypes = new[] { typeof(Playlist).Name }; + query.SetUser(user); + query.Recursive = true; + + var result = _libraryManager.GetItemsResult(query); + + return ToResult(result); + } + + private QueryResult<ServerItem> GetMusicLatest(BaseItem parent, User user, InternalItemsQuery query) + { + query.SortBy = new string[] { }; + + var items = _userViewManager.GetLatestItems(new LatestItemsQuery + { + UserId = user.Id.ToString("N"), + Limit = 50, + IncludeItemTypes = new[] { typeof(Audio).Name }, + ParentId = parent == null ? null : parent.Id.ToString("N"), + GroupItems = true + + }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToList(); + + return ToResult(items); + } + private QueryResult<ServerItem> GetMusicArtistItems(BaseItem item, Guid? parentId, User user, SortCriteria sort, int? startIndex, int? limit) { var query = new InternalItemsQuery(user) @@ -571,6 +850,19 @@ namespace Emby.Dlna.ContentDirectory return ToResult(result); } + private QueryResult<ServerItem> ToResult(List<BaseItem> result) + { + var serverItems = result + .Select(i => new ServerItem(i)) + .ToArray(); + + return new QueryResult<ServerItem> + { + TotalRecordCount = result.Count, + Items = serverItems + }; + } + private QueryResult<ServerItem> ToResult(QueryResult<BaseItem> result) { var serverItems = result @@ -660,6 +952,56 @@ namespace Emby.Dlna.ContentDirectory stubType = StubType.People; id = id.Split(new[] { '_' }, 2)[1]; } + else if (id.StartsWith("latest_", StringComparison.OrdinalIgnoreCase)) + { + stubType = StubType.Latest; + id = id.Split(new[] { '_' }, 2)[1]; + } + else if (id.StartsWith("playlists_", StringComparison.OrdinalIgnoreCase)) + { + stubType = StubType.Playlists; + id = id.Split(new[] { '_' }, 2)[1]; + } + else if (id.StartsWith("Albums_", StringComparison.OrdinalIgnoreCase)) + { + stubType = StubType.Albums; + id = id.Split(new[] { '_' }, 2)[1]; + } + else if (id.StartsWith("AlbumArtists_", StringComparison.OrdinalIgnoreCase)) + { + stubType = StubType.AlbumArtists; + id = id.Split(new[] { '_' }, 2)[1]; + } + else if (id.StartsWith("Artists_", StringComparison.OrdinalIgnoreCase)) + { + stubType = StubType.Artists; + id = id.Split(new[] { '_' }, 2)[1]; + } + else if (id.StartsWith("Genres_", StringComparison.OrdinalIgnoreCase)) + { + stubType = StubType.Genres; + id = id.Split(new[] { '_' }, 2)[1]; + } + else if (id.StartsWith("Songs_", StringComparison.OrdinalIgnoreCase)) + { + stubType = StubType.Songs; + id = id.Split(new[] { '_' }, 2)[1]; + } + else if (id.StartsWith("FavoriteAlbums_", StringComparison.OrdinalIgnoreCase)) + { + stubType = StubType.FavoriteAlbums; + id = id.Split(new[] { '_' }, 2)[1]; + } + else if (id.StartsWith("FavoriteArtists_", StringComparison.OrdinalIgnoreCase)) + { + stubType = StubType.FavoriteArtists; + id = id.Split(new[] { '_' }, 2)[1]; + } + else if (id.StartsWith("FavoriteSongs_", StringComparison.OrdinalIgnoreCase)) + { + stubType = StubType.FavoriteSongs; + id = id.Split(new[] { '_' }, 2)[1]; + } if (Guid.TryParse(id, out itemId)) { @@ -696,6 +1038,16 @@ namespace Emby.Dlna.ContentDirectory public enum StubType { Folder = 0, - People = 1 + People = 1, + Latest = 2, + Playlists = 3, + Albums = 4, + AlbumArtists = 5, + Artists = 6, + Songs = 7, + Genres = 8, + FavoriteSongs = 9, + FavoriteArtists = 10, + FavoriteAlbums = 11 } } diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index 3344bfcfe3..d2a160cf78 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -399,6 +399,46 @@ namespace Emby.Dlna.Didl } return _localization.GetLocalizedString("HeaderPeople"); } + if (itemStubType.HasValue && itemStubType.Value == StubType.Latest) + { + return _localization.GetLocalizedString("ViewTypeMusicLatest"); + } + if (itemStubType.HasValue && itemStubType.Value == StubType.Playlists) + { + return _localization.GetLocalizedString("ViewTypeMusicPlaylists"); + } + if (itemStubType.HasValue && itemStubType.Value == StubType.AlbumArtists) + { + return _localization.GetLocalizedString("ViewTypeMusicAlbumArtists"); + } + if (itemStubType.HasValue && itemStubType.Value == StubType.Albums) + { + return _localization.GetLocalizedString("ViewTypeMusicAlbums"); + } + if (itemStubType.HasValue && itemStubType.Value == StubType.Artists) + { + return _localization.GetLocalizedString("ViewTypeMusicArtists"); + } + if (itemStubType.HasValue && itemStubType.Value == StubType.Songs) + { + return _localization.GetLocalizedString("ViewTypeMusicSongs"); + } + if (itemStubType.HasValue && itemStubType.Value == StubType.Genres) + { + return _localization.GetLocalizedString("ViewTypeTvGenres"); + } + if (itemStubType.HasValue && itemStubType.Value == StubType.FavoriteAlbums) + { + return _localization.GetLocalizedString("ViewTypeMusicFavoriteAlbums"); + } + if (itemStubType.HasValue && itemStubType.Value == StubType.FavoriteArtists) + { + return _localization.GetLocalizedString("ViewTypeMusicFavoriteArtists"); + } + if (itemStubType.HasValue && itemStubType.Value == StubType.FavoriteSongs) + { + return _localization.GetLocalizedString("ViewTypeMusicFavoriteSongs"); + } var episode = item as Episode; var season = context as Season; diff --git a/Emby.Dlna/Eventing/EventManager.cs b/Emby.Dlna/Eventing/EventManager.cs index cf2c8d9956..0516585ae0 100644 --- a/Emby.Dlna/Eventing/EventManager.cs +++ b/Emby.Dlna/Eventing/EventManager.cs @@ -26,32 +26,34 @@ namespace Emby.Dlna.Eventing _logger = logger; } - public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, int? timeoutSeconds) + public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string requestedTimeoutString) { - var timeout = timeoutSeconds ?? 300; - var subscription = GetSubscription(subscriptionId, true); - _logger.Debug("Renewing event subscription for {0} with timeout of {1} to {2}", - subscription.NotificationType, - timeout, - subscription.CallbackUrl); + // Remove logging for now because some devices are sending this very frequently + // TODO re-enable with dlna debug logging setting + //_logger.Debug("Renewing event subscription for {0} with timeout of {1} to {2}", + // subscription.NotificationType, + // timeout, + // subscription.CallbackUrl); - subscription.TimeoutSeconds = timeout; + subscription.TimeoutSeconds = ParseTimeout(requestedTimeoutString) ?? 300; subscription.SubscriptionTime = DateTime.UtcNow; - return GetEventSubscriptionResponse(subscriptionId, timeout); + return GetEventSubscriptionResponse(subscriptionId, requestedTimeoutString, subscription.TimeoutSeconds); } - public EventSubscriptionResponse CreateEventSubscription(string notificationType, int? timeoutSeconds, string callbackUrl) + public EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl) { - var timeout = timeoutSeconds ?? 300; + var timeout = ParseTimeout(requestedTimeoutString) ?? 300; var id = "uuid:" + Guid.NewGuid().ToString("N"); - _logger.Debug("Creating event subscription for {0} with timeout of {1} to {2}", - notificationType, - timeout, - callbackUrl); + // Remove logging for now because some devices are sending this very frequently + // TODO re-enable with dlna debug logging setting + //_logger.Debug("Creating event subscription for {0} with timeout of {1} to {2}", + // notificationType, + // timeout, + // callbackUrl); _subscriptions.TryAdd(id, new EventSubscription { @@ -61,7 +63,25 @@ namespace Emby.Dlna.Eventing TimeoutSeconds = timeout }); - return GetEventSubscriptionResponse(id, timeout); + return GetEventSubscriptionResponse(id, requestedTimeoutString, timeout); + } + + private int? ParseTimeout(string header) + { + if (!string.IsNullOrEmpty(header)) + { + // Starts with SECOND- + header = header.Split('-').Last(); + + int val; + + if (int.TryParse(header, NumberStyles.Any, _usCulture, out val)) + { + return val; + } + } + + return null; } public EventSubscriptionResponse CancelEventSubscription(string subscriptionId) @@ -73,22 +93,22 @@ namespace Emby.Dlna.Eventing return new EventSubscriptionResponse { - Content = "\r\n", + Content = string.Empty, ContentType = "text/plain" }; } private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private EventSubscriptionResponse GetEventSubscriptionResponse(string subscriptionId, int timeoutSeconds) + private EventSubscriptionResponse GetEventSubscriptionResponse(string subscriptionId, string requestedTimeoutString, int timeoutSeconds) { var response = new EventSubscriptionResponse { - Content = "\r\n", + Content = string.Empty, ContentType = "text/plain" }; response.Headers["SID"] = subscriptionId; - response.Headers["TIMEOUT"] = "SECOND-" + timeoutSeconds.ToString(_usCulture); + response.Headers["TIMEOUT"] = string.IsNullOrWhiteSpace(requestedTimeoutString) ? ("SECOND-" + timeoutSeconds.ToString(_usCulture)) : requestedTimeoutString; return response; } diff --git a/Emby.Dlna/PlayTo/PlaylistItemFactory.cs b/Emby.Dlna/PlayTo/PlaylistItemFactory.cs index 3eb2bc1d5c..d31dc155e9 100644 --- a/Emby.Dlna/PlayTo/PlaylistItemFactory.cs +++ b/Emby.Dlna/PlayTo/PlaylistItemFactory.cs @@ -56,8 +56,9 @@ namespace Emby.Dlna.PlayTo if (profile.Container.Length > 0) { // Check container type - var mediaContainer = Path.GetExtension(mediaPath); - if (!profile.GetContainers().Any(i => string.Equals("." + i.TrimStart('.'), mediaContainer, StringComparison.OrdinalIgnoreCase))) + var mediaContainer = (Path.GetExtension(mediaPath) ?? string.Empty).TrimStart('.'); + + if (!profile.SupportsContainer(mediaContainer)) { return false; } diff --git a/Emby.Dlna/Profiles/LgTvProfile.cs b/Emby.Dlna/Profiles/LgTvProfile.cs index 71f684ec48..f81fb1ee79 100644 --- a/Emby.Dlna/Profiles/LgTvProfile.cs +++ b/Emby.Dlna/Profiles/LgTvProfile.cs @@ -53,14 +53,7 @@ namespace Emby.Dlna.Profiles { new DirectPlayProfile { - Container = "ts", - VideoCodec = "h264", - AudioCodec = "aac,ac3,mp3,dca,dts", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mkv", + Container = "ts,mpegts,avi,mkv", VideoCodec = "h264", AudioCodec = "aac,ac3,mp3,dca,dts", Type = DlnaProfileType.Video diff --git a/Emby.Dlna/Profiles/Xml/LG Smart TV.xml b/Emby.Dlna/Profiles/Xml/LG Smart TV.xml index a61fefcc8b..92e02799ed 100644 --- a/Emby.Dlna/Profiles/Xml/LG Smart TV.xml +++ b/Emby.Dlna/Profiles/Xml/LG Smart TV.xml @@ -35,8 +35,7 @@ <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <XmlRootAttributes /> <DirectPlayProfiles> - <DirectPlayProfile container="ts" audioCodec="aac,ac3,mp3,dca,dts" videoCodec="h264" type="Video" /> - <DirectPlayProfile container="mkv" audioCodec="aac,ac3,mp3,dca,dts" videoCodec="h264" type="Video" /> + <DirectPlayProfile container="ts,mpegts,avi,mkv" audioCodec="aac,ac3,mp3,dca,dts" videoCodec="h264" type="Video" /> <DirectPlayProfile container="mp4,m4v" audioCodec="aac,ac3,mp3,dca,dts" videoCodec="h264,mpeg4" type="Video" /> <DirectPlayProfile container="mp3" type="Audio" /> <DirectPlayProfile container="jpeg" type="Photo" /> diff --git a/Emby.Dlna/Service/BaseService.cs b/Emby.Dlna/Service/BaseService.cs index 574d749588..ddc37da095 100644 --- a/Emby.Dlna/Service/BaseService.cs +++ b/Emby.Dlna/Service/BaseService.cs @@ -24,14 +24,14 @@ namespace Emby.Dlna.Service return EventManager.CancelEventSubscription(subscriptionId); } - public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, int? timeoutSeconds) + public EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string timeoutString) { - return EventManager.RenewEventSubscription(subscriptionId, timeoutSeconds); + return EventManager.RenewEventSubscription(subscriptionId, timeoutString); } - public EventSubscriptionResponse CreateEventSubscription(string notificationType, int? timeoutSeconds, string callbackUrl) + public EventSubscriptionResponse CreateEventSubscription(string notificationType, string timeoutString, string callbackUrl) { - return EventManager.CreateEventSubscription(notificationType, timeoutSeconds, callbackUrl); + return EventManager.CreateEventSubscription(notificationType, timeoutString, callbackUrl); } } } |
