diff --git a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs index b6ee3d434..a8e778751 100644 --- a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs +++ b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs @@ -1,194 +1,41 @@ -namespace MediaBrowser.Dlna.Channels +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Channels; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Dlna.ContentDirectory; +using MediaBrowser.Dlna.PlayTo; +using MediaBrowser.Model.Channels; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.Dlna.Channels { - //public class DlnaChannelFactory : IChannelFactory, IDisposable + //public class DlnaChannel : IChannel, IDisposable //{ - // private readonly IServerConfigurationManager _config; // private readonly ILogger _logger; // private readonly IHttpClient _httpClient; - - // private readonly IDeviceDiscovery _deviceDiscovery; - - // private readonly SemaphoreSlim _syncLock = new SemaphoreSlim(1, 1); + // private readonly IServerConfigurationManager _config; // private List _servers = new List(); - // public static DlnaChannelFactory Instance; - + // private readonly IDeviceDiscovery _deviceDiscovery; + // private readonly SemaphoreSlim _syncLock = new SemaphoreSlim(1, 1); // private Func> _localServersLookup; - // public DlnaChannelFactory(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger, IDeviceDiscovery deviceDiscovery) + // public static DlnaChannel Current; + + // public DlnaChannel(ILogger logger, IHttpClient httpClient, IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config) // { - // _config = config; - // _httpClient = httpClient; // _logger = logger; + // _httpClient = httpClient; // _deviceDiscovery = deviceDiscovery; - // Instance = this; - // } - - // internal void Start(Func> localServersLookup) - // { - // _localServersLookup = localServersLookup; - - // //deviceDiscovery.DeviceDiscovered += deviceDiscovery_DeviceDiscovered; - // _deviceDiscovery.DeviceLeft += deviceDiscovery_DeviceLeft; - // } - - // async void deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e) - // { - // string usn; - // if (!e.Headers.TryGetValue("USN", out usn)) usn = string.Empty; - - // string nt; - // if (!e.Headers.TryGetValue("NT", out nt)) nt = string.Empty; - - // string location; - // if (!e.Headers.TryGetValue("Location", out location)) location = string.Empty; - - // if (!IsValid(nt, usn)) - // { - // return; - // } - - // if (_localServersLookup != null) - // { - // if (_localServersLookup().Any(i => usn.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1)) - // { - // // Don't add the local Dlna server to this - // return; - // } - // } - - // if (GetExistingServers(usn).Any()) - // { - // return; - // } - - // await _syncLock.WaitAsync().ConfigureAwait(false); - - // try - // { - // if (GetExistingServers(usn).Any()) - // { - // return; - // } - - // var device = await Device.CreateuPnpDeviceAsync(new Uri(location), _httpClient, _config, _logger) - // .ConfigureAwait(false); - - // if (!_servers.Any(i => string.Equals(i.Properties.UUID, device.Properties.UUID, StringComparison.OrdinalIgnoreCase))) - // { - // _servers.Add(device); - // } - // } - // catch (Exception ex) - // { - - // } - // finally - // { - // _syncLock.Release(); - // } - // } - - // async void deviceDiscovery_DeviceLeft(object sender, SsdpMessageEventArgs e) - // { - // string usn; - // if (!e.Headers.TryGetValue("USN", out usn)) usn = String.Empty; - - // string nt; - // if (!e.Headers.TryGetValue("NT", out nt)) nt = String.Empty; - - // if (!IsValid(nt, usn)) - // { - // return; - // } - - // if (!GetExistingServers(usn).Any()) - // { - // return; - // } - - // await _syncLock.WaitAsync().ConfigureAwait(false); - - // try - // { - // var list = _servers.ToList(); - - // foreach (var device in GetExistingServers(usn).ToList()) - // { - // list.Remove(device); - // } - - // _servers = list; - // } - // finally - // { - // _syncLock.Release(); - // } - // } - - // private bool IsValid(string nt, string usn) - // { - // // It has to report that it's a media renderer - // if (usn.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 && - // nt.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 && - // usn.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1 && - // nt.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1) - // { - // return false; - // } - - // return true; - // } - - // private IEnumerable GetExistingServers(string usn) - // { - // return _servers - // .Where(i => usn.IndexOf(i.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1); - // } - - // public IEnumerable GetChannels() - // { - // //if (_servers.Count > 0) - // //{ - // // var service = _servers[0].Properties.Services - // // .FirstOrDefault(i => string.Equals(i.ServiceType, "urn:schemas-upnp-org:service:ContentDirectory:1", StringComparison.OrdinalIgnoreCase)); - - // // var controlUrl = service == null ? null : (_servers[0].Properties.BaseUrl.TrimEnd('/') + "/" + service.ControlUrl.TrimStart('/')); - - // // if (!string.IsNullOrEmpty(controlUrl)) - // // { - // // return new List - // // { - // // new ServerChannel(_servers.ToList(), _httpClient, _logger, controlUrl) - // // }; - // // } - // //} - - // return new List(); - // } - - // public void Dispose() - // { - // if (_deviceDiscovery != null) - // { - // _deviceDiscovery.DeviceDiscovered -= deviceDiscovery_DeviceDiscovered; - // _deviceDiscovery.DeviceLeft -= deviceDiscovery_DeviceLeft; - // } - // } - //} - - //public class ServerChannel : IChannel, IFactoryChannel - //{ - // private readonly IHttpClient _httpClient; - // private readonly ILogger _logger; - // public string ControlUrl { get; set; } - // public List Servers { get; set; } - - // public ServerChannel(IHttpClient httpClient, ILogger logger) - // { - // _httpClient = httpClient; - // _logger = logger; - // Servers = new List(); + // _config = config; + // Current = this; // } // public string Name @@ -221,17 +68,17 @@ // return new InternalChannelFeatures // { // ContentTypes = new List - // { - // ChannelMediaContentType.Song, - // ChannelMediaContentType.Clip - // }, + // { + // ChannelMediaContentType.Song, + // ChannelMediaContentType.Clip + // }, // MediaTypes = new List - // { - // ChannelMediaType.Audio, - // ChannelMediaType.Video, - // ChannelMediaType.Photo - // } + // { + // ChannelMediaType.Audio, + // ChannelMediaType.Video, + // ChannelMediaType.Photo + // } // }; // } @@ -240,85 +87,219 @@ // return true; // } - // public async Task GetChannelItems(InternalChannelItemQuery query, CancellationToken cancellationToken) - // { - // IEnumerable items; - - // if (string.IsNullOrWhiteSpace(query.FolderId)) - // { - // items = Servers.Select(i => new ChannelItemInfo - // { - // FolderType = ChannelFolderType.Container, - // Id = GetServerId(i), - // Name = i.Properties.Name, - // Overview = i.Properties.ModelDescription, - // Type = ChannelItemType.Folder - // }); - // } - // else - // { - // var idParts = query.FolderId.Split('|'); - // var folderId = idParts.Length == 2 ? idParts[1] : null; - - // var result = await new ContentDirectoryBrowser(_httpClient, _logger).Browse(new ContentDirectoryBrowseRequest - // { - // Limit = query.Limit, - // StartIndex = query.StartIndex, - // ParentId = folderId, - // ContentDirectoryUrl = ControlUrl - - // }, cancellationToken).ConfigureAwait(false); - - // items = result.Items.ToList(); - // } - - // var list = items.ToList(); - // var count = list.Count; - - // list = ApplyPaging(list, query).ToList(); - - // return new ChannelItemResult - // { - // Items = list, - // TotalRecordCount = count - // }; - // } - - // private string GetServerId(Device device) - // { - // return device.Properties.UUID.GetMD5().ToString("N"); - // } - - // private IEnumerable ApplyPaging(IEnumerable items, InternalChannelItemQuery query) - // { - // if (query.StartIndex.HasValue) - // { - // items = items.Skip(query.StartIndex.Value); - // } - - // if (query.Limit.HasValue) - // { - // items = items.Take(query.Limit.Value); - // } - - // return items; - // } - // public Task GetChannelImage(ImageType type, CancellationToken cancellationToken) // { - // // TODO: Implement - // return Task.FromResult(new DynamicImageResponse - // { - // HasImage = false - // }); + // throw new NotImplementedException(); // } // public IEnumerable GetSupportedChannelImages() // { // return new List + // { + // ImageType.Primary + // }; + // } + + // public void Start(Func> localServersLookup) + // { + // _localServersLookup = localServersLookup; + + // _deviceDiscovery.DeviceDiscovered -= deviceDiscovery_DeviceDiscovered; + // _deviceDiscovery.DeviceLeft -= deviceDiscovery_DeviceLeft; + + // _deviceDiscovery.DeviceDiscovered += deviceDiscovery_DeviceDiscovered; + // _deviceDiscovery.DeviceLeft += deviceDiscovery_DeviceLeft; + // } + + // public async Task GetChannelItems(InternalChannelItemQuery query, CancellationToken cancellationToken) + // { + // if (string.IsNullOrWhiteSpace(query.FolderId)) // { - // ImageType.Primary - // }; + // return await GetServers(query, cancellationToken).ConfigureAwait(false); + // } + + // return new ChannelItemResult(); + + // //var idParts = query.FolderId.Split('|'); + // //var folderId = idParts.Length == 2 ? idParts[1] : null; + + // //var result = await new ContentDirectoryBrowser(_httpClient, _logger).Browse(new ContentDirectoryBrowseRequest + // //{ + // // Limit = query.Limit, + // // StartIndex = query.StartIndex, + // // ParentId = folderId, + // // ContentDirectoryUrl = ControlUrl + + // //}, cancellationToken).ConfigureAwait(false); + + // //items = result.Items.ToList(); + + // //var list = items.ToList(); + // //var count = list.Count; + + // //list = ApplyPaging(list, query).ToList(); + + // //return new ChannelItemResult + // //{ + // // Items = list, + // // TotalRecordCount = count + // //}; + // } + + // public async Task GetServers(InternalChannelItemQuery query, CancellationToken cancellationToken) + // { + // await _syncLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + // try + // { + // var items = _servers.Select(i => + // { + // var service = i.Properties.Services + // .FirstOrDefault(s => string.Equals(s.ServiceType, "urn:schemas-upnp-org:service:ContentDirectory:1", StringComparison.OrdinalIgnoreCase)); + + // var controlUrl = service == null ? null : (_servers[0].Properties.BaseUrl.TrimEnd('/') + "/" + service.ControlUrl.TrimStart('/')); + + // if (string.IsNullOrWhiteSpace(controlUrl)) + // { + // return null; + // } + + // return new ChannelItemInfo + // { + // Id = i.Properties.UUID, + // Name = i.Properties.Name, + // Type = ChannelItemType.Folder + // }; + + // }).Where(i => i != null).ToList(); + + // return new ChannelItemResult + // { + // TotalRecordCount = items.Count, + // Items = items + // }; + // } + // finally + // { + // _syncLock.Release(); + // } + // } + + // async void deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e) + // { + // string usn; + // if (!e.Headers.TryGetValue("USN", out usn)) usn = string.Empty; + + // string nt; + // if (!e.Headers.TryGetValue("NT", out nt)) nt = string.Empty; + + // string location; + // if (!e.Headers.TryGetValue("Location", out location)) location = string.Empty; + + // if (!IsValid(nt, usn)) + // { + // return; + // } + + // if (_localServersLookup != null) + // { + // if (_localServersLookup().Any(i => usn.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1)) + // { + // // Don't add the local Dlna server to this + // return; + // } + // } + + // await _syncLock.WaitAsync().ConfigureAwait(false); + + // var serverList = _servers.ToList(); + + // try + // { + // if (GetExistingServers(serverList, usn).Any()) + // { + // return; + // } + + // var device = await Device.CreateuPnpDeviceAsync(new Uri(location), _httpClient, _config, _logger) + // .ConfigureAwait(false); + + // if (!serverList.Any(i => string.Equals(i.Properties.UUID, device.Properties.UUID, StringComparison.OrdinalIgnoreCase))) + // { + // serverList.Add(device); + // } + // } + // catch (Exception ex) + // { + + // } + // finally + // { + // _syncLock.Release(); + // } + // } + + // async void deviceDiscovery_DeviceLeft(object sender, SsdpMessageEventArgs e) + // { + // string usn; + // if (!e.Headers.TryGetValue("USN", out usn)) usn = String.Empty; + + // string nt; + // if (!e.Headers.TryGetValue("NT", out nt)) nt = String.Empty; + + // if (!IsValid(nt, usn)) + // { + // return; + // } + + // await _syncLock.WaitAsync().ConfigureAwait(false); + + // try + // { + // var serverList = _servers.ToList(); + + // var matchingServers = GetExistingServers(serverList, usn); + // if (matchingServers.Count > 0) + // { + // foreach (var device in matchingServers) + // { + // serverList.Remove(device); + // } + + // _servers = serverList; + // } + // } + // finally + // { + // _syncLock.Release(); + // } + // } + + // private bool IsValid(string nt, string usn) + // { + // // It has to report that it's a media renderer + // if (usn.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 && + // nt.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 && + // usn.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1 && + // nt.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1) + // { + // return false; + // } + + // return true; + // } + + // private List GetExistingServers(List allDevices, string usn) + // { + // return allDevices + // .Where(i => usn.IndexOf(i.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1) + // .ToList(); + // } + + // public void Dispose() + // { + // _deviceDiscovery.DeviceDiscovered -= deviceDiscovery_DeviceDiscovered; + // _deviceDiscovery.DeviceLeft -= deviceDiscovery_DeviceLeft; // } //} } diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs index a2e9cd60e..22f308979 100644 --- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs +++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs @@ -14,7 +14,9 @@ using MediaBrowser.Dlna.Ssdp; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; +using System.Linq; using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Dlna.Channels; namespace MediaBrowser.Dlna.Main { @@ -167,6 +169,8 @@ namespace MediaBrowser.Dlna.Main try { ((DeviceDiscovery)_deviceDiscovery).Start(_ssdpHandler); + + //DlnaChannel.Current.Start(() => _registeredServerIds.ToList()); } catch (Exception ex) { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 1a95bdf9d..44c69d4c1 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -548,7 +548,8 @@ namespace MediaBrowser.MediaEncoding.Probing private void NormalizeStreamTitle(MediaStream stream) { - if (string.Equals(stream.Title, "sdh", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(stream.Title, "sdh", StringComparison.OrdinalIgnoreCase) || + string.Equals(stream.Title, "cc", StringComparison.OrdinalIgnoreCase)) { stream.Title = null; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index f85be5100..99ab07648 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1383,6 +1383,28 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } + private QueryResult GetEmbyRecordings(RecordingQuery query, User user) + { + var folders = EmbyTV.EmbyTV.Current.GetRecordingFolders() + .SelectMany(i => i.Locations) + .Distinct(StringComparer.OrdinalIgnoreCase) + .Select(i => _libraryManager.FindByPath(i, true)) + .Where(i => i != null) + .Where(i => i.IsVisibleStandalone(user)) + .ToList(); + + var items = _libraryManager.GetItemsResult(new InternalItemsQuery(user) + { + MediaTypes = new[] { MediaType.Video }, + Recursive = true, + AncestorIds = folders.Select(i => i.Id.ToString("N")).ToArray(), + ExcludeLocationTypes = new[] { LocationType.Virtual }, + Limit = Math.Min(10, query.Limit ?? int.MaxValue) + }); + + return items; + } + public async Task> GetInternalRecordings(RecordingQuery query, CancellationToken cancellationToken) { var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId); @@ -1391,6 +1413,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv return new QueryResult(); } + if (user != null && !(query.IsInProgress ?? false)) + { + var initialResult = GetEmbyRecordings(query, user); + if (initialResult.TotalRecordCount > 0) + { + return initialResult; + } + } + await RefreshRecordings(cancellationToken).ConfigureAwait(false); var internalQuery = new InternalItemsQuery(user) @@ -2060,7 +2091,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv }, cancellationToken).ConfigureAwait(false); - var recordings = recordingResult.Items.Cast().ToList(); + var recordings = recordingResult.Items.OfType().ToList(); var groups = new List();