diff options
| author | Tavares André <tavares_and@hotmail.com> | 2015-05-07 19:12:56 +0200 |
|---|---|---|
| committer | Tavares André <tavares_and@hotmail.com> | 2015-05-07 19:12:56 +0200 |
| commit | 48e7ca87254969f98abbedcfc46985fc1ea955c0 (patch) | |
| tree | c1084f29f6529d4bf5524fdab7a723686a379b2d | |
| parent | f2b800181252b6fd0bb3b51925d1dcb0623f21d2 (diff) | |
| parent | 63dc2512c5d272dbc3cb1515beb175e9b3572440 (diff) | |
Merge branch 'dev' of https://github.com/MediaBrowser/MediaBrowser into dev
Conflicts:
MediaBrowser.Server.Implementations/Localization/Server/server.json
97 files changed, 1071 insertions, 1145 deletions
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 7da11a405..639c1f54b 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -648,10 +648,8 @@ namespace MediaBrowser.Api.Images var serverFormats = _imageProcessor.GetSupportedImageOutputFormats(); - var clientFormats = GetClientSupportedFormats(); - if (serverFormats.Contains(ImageFormat.Webp) && - clientFormats.Contains(ImageFormat.Webp)) + GetClientSupportedFormats().Contains(ImageFormat.Webp)) { return ImageFormat.Webp; } diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index f89a70340..269f4cb20 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -617,36 +617,14 @@ namespace MediaBrowser.Api.Library : (Folder)_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); - var originalItem = item; - while (GetThemeSongIds(item).Count == 0 && request.InheritFromParent && item.Parent != null) { item = item.Parent; } - var themeSongIds = GetThemeSongIds(item); - - if (themeSongIds.Count == 0 && request.InheritFromParent) - { - var album = originalItem as MusicAlbum; - - if (album != null) - { - var linkedItemWithThemes = album.SoundtrackIds - .Select(i => _libraryManager.GetItemById(i)) - .FirstOrDefault(i => GetThemeSongIds(i).Count > 0); - - if (linkedItemWithThemes != null) - { - themeSongIds = GetThemeSongIds(linkedItemWithThemes); - item = linkedItemWithThemes; - } - } - } - var dtoOptions = GetDtoOptions(request); - var dtos = themeSongIds.Select(_libraryManager.GetItemById) + var dtos = GetThemeSongIds(item).Select(_libraryManager.GetItemById) .OrderBy(i => i.SortName) .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)); @@ -682,41 +660,14 @@ namespace MediaBrowser.Api.Library : (Folder)_libraryManager.RootFolder) : _libraryManager.GetItemById(request.Id); - var originalItem = item; - while (GetThemeVideoIds(item).Count == 0 && request.InheritFromParent && item.Parent != null) { item = item.Parent; } - var themeVideoIds = GetThemeVideoIds(item); - - if (themeVideoIds.Count == 0 && request.InheritFromParent) - { - var album = originalItem as MusicAlbum; - - if (album == null) - { - album = originalItem.Parents.OfType<MusicAlbum>().FirstOrDefault(); - } - - if (album != null) - { - var linkedItemWithThemes = album.SoundtrackIds - .Select(i => _libraryManager.GetItemById(i)) - .FirstOrDefault(i => GetThemeVideoIds(i).Count > 0); - - if (linkedItemWithThemes != null) - { - themeVideoIds = GetThemeVideoIds(linkedItemWithThemes); - item = linkedItemWithThemes; - } - } - } - var dtoOptions = GetDtoOptions(request); - var dtos = themeVideoIds.Select(_libraryManager.GetItemById) + var dtos = GetThemeVideoIds(item).Select(_libraryManager.GetItemById) .OrderBy(i => i.SortName) .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)); diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index db94e37f4..34fb29b94 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -23,6 +23,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Api.Playback { @@ -68,12 +69,14 @@ namespace MediaBrowser.Api.Playback protected ISubtitleEncoder SubtitleEncoder { get; private set; } protected IMediaSourceManager MediaSourceManager { get; private set; } protected IZipClient ZipClient { get; private set; } + protected IJsonSerializer JsonSerializer { get; private set; } /// <summary> /// Initializes a new instance of the <see cref="BaseStreamingService" /> class. /// </summary> - protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient) + protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer) { + JsonSerializer = jsonSerializer; ZipClient = zipClient; MediaSourceManager = mediaSourceManager; DeviceManager = deviceManager; @@ -598,7 +601,7 @@ namespace MediaBrowser.Api.Playback var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); - filters.Add(string.Format("scale=trunc(min(iw\\,{0})/2)*2:trunc(min((iw/dar)\\,{1})/2)*2", maxWidthParam, maxHeightParam)); + filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam)); } // If a fixed width was requested @@ -618,7 +621,7 @@ namespace MediaBrowser.Api.Playback } // If a max width was requested - else if (request.MaxWidth.HasValue && (!request.MaxHeight.HasValue || state.VideoStream == null)) + else if (request.MaxWidth.HasValue) { var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); @@ -626,35 +629,13 @@ namespace MediaBrowser.Api.Playback } // If a max height was requested - else if (request.MaxHeight.HasValue && (!request.MaxWidth.HasValue || state.VideoStream == null)) + else if (request.MaxHeight.HasValue) { var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); filters.Add(string.Format("scale=trunc(oh*a*2)/2:min(ih\\,{0})", maxHeightParam)); } - else if (request.MaxWidth.HasValue || - request.MaxHeight.HasValue || - request.Width.HasValue || - request.Height.HasValue) - { - if (state.VideoStream != null) - { - // Need to perform calculations manually - - // Try to account for bad media info - var currentHeight = state.VideoStream.Height ?? request.MaxHeight ?? request.Height ?? 0; - var currentWidth = state.VideoStream.Width ?? request.MaxWidth ?? request.Width ?? 0; - - var outputSize = DrawingUtils.Resize(currentWidth, currentHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight); - - var manualWidthParam = outputSize.Width.ToString(UsCulture); - var manualHeightParam = outputSize.Height.ToString(UsCulture); - - filters.Add(string.Format("scale=trunc({0}/2)*2:trunc({1}/2)*2", manualWidthParam, manualHeightParam)); - } - } - if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase)) { filters[filters.Count - 1] += ":flags=fast_bilinear"; @@ -1027,7 +1008,7 @@ namespace MediaBrowser.Api.Playback // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true); - var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(Request.AbsoluteUri + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); + var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(Request.AbsoluteUri + Environment.NewLine + Environment.NewLine + JsonSerializer.SerializeToString(state.MediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); await state.LogFileStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false); process.Exited += (sender, args) => OnFfMpegProcessExited(process, transcodingJob, state); diff --git a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs index 0692c4863..1a90dbb53 100644 --- a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs +++ b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs @@ -8,6 +8,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Net; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Serialization; using ServiceStack; using System; using System.Collections.Generic; @@ -53,7 +54,7 @@ namespace MediaBrowser.Api.Playback.Dash public class MpegDashService : BaseHlsService { - public MpegDashService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient) + public MpegDashService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer) { NetworkManager = networkManager; } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 78dee4c44..b10c02e17 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -13,6 +13,7 @@ using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Api.Playback.Hls { @@ -21,7 +22,7 @@ namespace MediaBrowser.Api.Playback.Hls /// </summary> public abstract class BaseHlsService : BaseStreamingService { - protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient) + protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer) { } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 4f938dc41..1f6bc242d 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -10,6 +10,7 @@ using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Serialization; using ServiceStack; using System; using System.Collections.Generic; @@ -61,7 +62,7 @@ namespace MediaBrowser.Api.Playback.Hls public class DynamicHlsService : BaseHlsService { - public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient) + public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer) { NetworkManager = networkManager; } diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 8e2854c5e..626df59f2 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Serialization; using ServiceStack; using System; @@ -40,7 +41,7 @@ namespace MediaBrowser.Api.Playback.Hls /// </summary> public class VideoHlsService : BaseHlsService { - public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient) + public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer) { } diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs index fee501159..67a9cab58 100644 --- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs +++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs @@ -8,6 +8,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Serialization; using ServiceStack; using System.Collections.Generic; @@ -31,7 +32,7 @@ namespace MediaBrowser.Api.Playback.Progressive /// </summary> public class AudioService : BaseProgressiveStreamingService { - public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, imageProcessor, httpClient) + public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, imageProcessor, httpClient) { } diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 8ed17ca17..835f3357e 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -10,6 +10,7 @@ using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Net; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Serialization; using ServiceStack.Web; using System; using System.Collections.Generic; @@ -27,7 +28,7 @@ namespace MediaBrowser.Api.Playback.Progressive protected readonly IImageProcessor ImageProcessor; protected readonly IHttpClient HttpClient; - protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient) + protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer) { ImageProcessor = imageProcessor; HttpClient = httpClient; diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 0ded108b1..27482c50c 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -7,6 +7,7 @@ using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Serialization; using ServiceStack; using System; using System.IO; @@ -61,7 +62,7 @@ namespace MediaBrowser.Api.Playback.Progressive /// </summary> public class VideoService : BaseProgressiveStreamingService { - public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, imageProcessor, httpClient) + public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer, imageProcessor, httpClient) { } diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index 967cf54a6..e603ea373 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -58,11 +58,8 @@ </Reference> <Reference Include="SimpleInjector, Version=2.7.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\SimpleInjector.2.7.0\lib\net45\SimpleInjector.dll</HintPath> - </Reference> - <Reference Include="SimpleInjector.Diagnostics, Version=2.7.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\SimpleInjector.2.7.0\lib\net45\SimpleInjector.Diagnostics.dll</HintPath> + <HintPath>..\packages\SimpleInjector.2.8.0\lib\net45\SimpleInjector.dll</HintPath> + <Private>True</Private> </Reference> <Reference Include="System" /> <Reference Include="System.Core" /> diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs index 0fd4e2787..c27dfd68d 100644 --- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs +++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs @@ -6,16 +6,29 @@ using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; +using System.Threading; namespace MediaBrowser.Common.Implementations.Networking { public abstract class BaseNetworkManager { protected ILogger Logger { get; private set; } + private Timer _clearCacheTimer; protected BaseNetworkManager(ILogger logger) { Logger = logger; + + // Can't use network change events due to a crash in Linux + _clearCacheTimer = new Timer(ClearCacheTimerCallback, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); + } + + private void ClearCacheTimerCallback(object state) + { + lock (_localIpAddressSyncLock) + { + _localIpAddresses = null; + } } private volatile List<string> _localIpAddresses; @@ -36,7 +49,6 @@ namespace MediaBrowser.Common.Implementations.Networking var addresses = GetLocalIpAddressesInternal().ToList(); _localIpAddresses = addresses; - BindEvents(); return addresses; } @@ -46,35 +58,6 @@ namespace MediaBrowser.Common.Implementations.Networking return _localIpAddresses; } - private void BindEvents() - { - NetworkChange.NetworkAddressChanged -= NetworkChange_NetworkAddressChanged; - NetworkChange.NetworkAvailabilityChanged -= NetworkChange_NetworkAvailabilityChanged; - - NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged; - NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged; - } - - void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e) - { - Logger.Debug("NetworkAvailabilityChanged fired. Resetting cached network info."); - - lock (_localIpAddressSyncLock) - { - _localIpAddresses = null; - } - } - - void NetworkChange_NetworkAddressChanged(object sender, EventArgs e) - { - Logger.Debug("NetworkAddressChanged fired. Resetting cached network info."); - - lock (_localIpAddressSyncLock) - { - _localIpAddresses = null; - } - } - private IEnumerable<string> GetLocalIpAddressesInternal() { var list = GetIPsDefault() diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config index 56cb78031..e57c874f2 100644 --- a/MediaBrowser.Common.Implementations/packages.config +++ b/MediaBrowser.Common.Implementations/packages.config @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <packages> <package id="NLog" version="3.2.1" targetFramework="net45" /> - <package id="SimpleInjector" version="2.7.0" targetFramework="net45" /> + <package id="SimpleInjector" version="2.8.0" targetFramework="net45" /> </packages> diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 100633d7f..623329ca6 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -52,34 +52,6 @@ namespace MediaBrowser.Controller.Entities.Audio /// <value><c>true</c> if this instance has embedded image; otherwise, <c>false</c>.</value> public bool HasEmbeddedImage { get; set; } - /// <summary> - /// Override this to true if class should be grouped under a container in indicies - /// The container class should be defined via IndexContainer - /// </summary> - /// <value><c>true</c> if [group in index]; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool GroupInIndex - { - get - { - return true; - } - } - - /// <summary> - /// Override this to return the folder that should be used to construct a container - /// for this item in an index. GroupInIndex should be true as well. - /// </summary> - /// <value>The index container.</value> - [IgnoreDataMember] - public override Folder IndexContainer - { - get - { - return LatestItemsIndexContainer ?? new MusicAlbum { Name = "Unknown Album" }; - } - } - [IgnoreDataMember] protected override bool SupportsOwnedItems { @@ -94,7 +66,7 @@ namespace MediaBrowser.Controller.Entities.Audio { get { - return Parents.OfType<MusicAlbum>().FirstOrDefault(); + return AlbumEntity; } } @@ -148,6 +120,12 @@ namespace MediaBrowser.Controller.Entities.Audio /// <value>The album.</value> public string Album { get; set; } + [IgnoreDataMember] + public MusicAlbum AlbumEntity + { + get { return FindParent<MusicAlbum>(); } + } + /// <summary> /// Gets the type of the media. /// </summary> @@ -177,7 +155,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// <returns>System.String.</returns> protected override string CreateUserDataKey() { - var parent = FindParent<MusicAlbum>(); + var parent = AlbumEntity; if (parent != null) { diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index dc3f13b01..c060f53a6 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -2,7 +2,6 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Users; -using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; @@ -14,11 +13,8 @@ namespace MediaBrowser.Controller.Entities.Audio /// </summary> public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo> { - public List<Guid> SoundtrackIds { get; set; } - public MusicAlbum() { - SoundtrackIds = new List<Guid>(); Artists = new List<string>(); AlbumArtists = new List<string>(); } @@ -77,49 +73,6 @@ namespace MediaBrowser.Controller.Entities.Audio return Tracks; } - /// <summary> - /// Songs will group into us so don't also include us in the index - /// </summary> - /// <value><c>true</c> if [include in index]; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool IncludeInIndex - { - get - { - return false; - } - } - - /// <summary> - /// Override this to true if class should be grouped under a container in indicies - /// The container class should be defined via IndexContainer - /// </summary> - /// <value><c>true</c> if [group in index]; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool GroupInIndex - { - get - { - return true; - } - } - - /// <summary> - /// The unknwon artist - /// </summary> - private static readonly MusicArtist UnknwonArtist = new MusicArtist { Name = "<Unknown>" }; - - /// <summary> - /// Override this to return the folder that should be used to construct a container - /// for this item in an index. GroupInIndex should be true as well. - /// </summary> - /// <value>The index container.</value> - [IgnoreDataMember] - public override Folder IndexContainer - { - get { return Parent as MusicArtist ?? UnknwonArtist; } - } - public List<string> Artists { get; set; } /// <summary> diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 3313f45fd..8b6cbdc93 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -906,38 +906,6 @@ namespace MediaBrowser.Controller.Entities /// <value>The provider ids.</value> public Dictionary<string, string> ProviderIds { get; set; } - /// <summary> - /// Override this to false if class should be ignored for indexing purposes - /// </summary> - /// <value><c>true</c> if [include in index]; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public virtual bool IncludeInIndex - { - get { return true; } - } - - /// <summary> - /// Override this to true if class should be grouped under a container in indicies - /// The container class should be defined via IndexContainer - /// </summary> - /// <value><c>true</c> if [group in index]; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public virtual bool GroupInIndex - { - get { return false; } - } - - /// <summary> - /// Override this to return the folder that should be used to construct a container - /// for this item in an index. GroupInIndex should be true as well. - /// </summary> - /// <value>The index container.</value> - [IgnoreDataMember] - public virtual Folder IndexContainer - { - get { return null; } - } - [IgnoreDataMember] public virtual Folder LatestItemsIndexContainer { diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index c8408365d..8f5b8f6cf 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -45,16 +45,6 @@ namespace MediaBrowser.Controller.Entities.TV /// <value>The index number.</value> public int? IndexNumberEnd { get; set; } - /// <summary> - /// We want to group into series not show individually in an index - /// </summary> - /// <value><c>true</c> if [group in index]; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool GroupInIndex - { - get { return true; } - } - [IgnoreDataMember] protected override bool SupportsOwnedItems { @@ -91,19 +81,6 @@ namespace MediaBrowser.Controller.Entities.TV } } - /// <summary> - /// We roll up into series - /// </summary> - /// <value>The index container.</value> - [IgnoreDataMember] - public override Folder IndexContainer - { - get - { - return Season; - } - } - [IgnoreDataMember] public override Folder LatestItemsIndexContainer { diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index a99b8c659..cfd6b46e0 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Controller.Localization; -using MediaBrowser.Controller.Providers; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Users; @@ -15,20 +14,6 @@ namespace MediaBrowser.Controller.Entities.TV /// </summary> public class Season : Folder, IHasSeries, IHasLookupInfo<SeasonInfo> { - - /// <summary> - /// Seasons are just containers - /// </summary> - /// <value><c>true</c> if [include in index]; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool IncludeInIndex - { - get - { - return false; - } - } - [IgnoreDataMember] public override bool SupportsAddingToPlaylist { @@ -50,33 +35,6 @@ namespace MediaBrowser.Controller.Entities.TV get { return Series ?? Parent; } } - /// <summary> - /// We want to group into our Series - /// </summary> - /// <value><c>true</c> if [group in index]; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool GroupInIndex - { - get - { - return true; - } - } - - /// <summary> - /// Override this to return the folder that should be used to construct a container - /// for this item in an index. GroupInIndex should be true as well. - /// </summary> - /// <value>The index container.</value> - [IgnoreDataMember] - public override Folder IndexContainer - { - get - { - return Series; - } - } - // Genre, Rating and Stuido will all be the same protected override IEnumerable<string> GetIndexByOptions() { diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 4696afeb6..2663d19e8 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -95,19 +95,6 @@ namespace MediaBrowser.Controller.Entities.TV } /// <summary> - /// Series aren't included directly in indices - Their Episodes will roll up to them - /// </summary> - /// <value><c>true</c> if [include in index]; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool IncludeInIndex - { - get - { - return false; - } - } - - /// <summary> /// Gets the user data key. /// </summary> /// <returns>System.String.</returns> diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs index bdc8beb98..62756e4c4 100644 --- a/MediaBrowser.Dlna/DlnaManager.cs +++ b/MediaBrowser.Dlna/DlnaManager.cs @@ -544,7 +544,9 @@ namespace MediaBrowser.Dlna new DirectTvProfile(), new DishHopperJoeyProfile(), new DefaultProfile(), - new PopcornHourProfile() + new PopcornHourProfile(), + new VlcProfile(), + new BubbleUpnpProfile() }; foreach (var item in list) diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj index b4e93ed68..204872e7b 100644 --- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj +++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj @@ -77,10 +77,12 @@ <Compile Include="Common\DeviceService.cs" /> <Compile Include="Didl\DidlBuilder.cs" /> <Compile Include="PlayTo\PlayToController.cs" /> + <Compile Include="Profiles\BubbleUpnpProfile.cs" /> <Compile Include="Profiles\DefaultProfile.cs" /> <Compile Include="Profiles\DirectTvProfile.cs" /> <Compile Include="Profiles\DishHopperJoeyProfile.cs" /> <Compile Include="Profiles\PopcornHourProfile.cs" /> + <Compile Include="Profiles\VlcProfile.cs" /> <Compile Include="Ssdp\DeviceDiscoveryInfo.cs" /> <Compile Include="Ssdp\Extensions.cs" /> <Compile Include="PlayTo\PlaybackProgressEventArgs.cs" /> @@ -204,6 +206,10 @@ <EmbeddedResource Include="Images\people480.jpg" /> <EmbeddedResource Include="Images\people480.png" /> </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Profiles\Xml\BubbleUPnp.xml" /> + <EmbeddedResource Include="Profiles\Xml\Vlc.xml" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. diff --git a/MediaBrowser.Dlna/PlayTo/Device.cs b/MediaBrowser.Dlna/PlayTo/Device.cs index 00cb34be3..c41aa73a9 100644 --- a/MediaBrowser.Dlna/PlayTo/Device.cs +++ b/MediaBrowser.Dlna/PlayTo/Device.cs @@ -296,7 +296,7 @@ namespace MediaBrowser.Dlna.PlayTo } var post = AvCommands.BuildPost(command, service.ServiceType, url, dictionary); - await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header) + await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header: header) .ConfigureAwait(false); await Task.Delay(50).ConfigureAwait(false); @@ -463,10 +463,10 @@ namespace MediaBrowser.Dlna.PlayTo if (service == null) { - throw new InvalidOperationException("Unable to find service"); + return; } - var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType), true) .ConfigureAwait(false); if (result == null || result.Document == null) @@ -496,10 +496,10 @@ namespace MediaBrowser.Dlna.PlayTo if (service == null) { - throw new InvalidOperationException("Unable to find service"); + return; } - var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType), true) .ConfigureAwait(false); if (result == null || result.Document == null) @@ -521,7 +521,7 @@ namespace MediaBrowser.Dlna.PlayTo if (service == null) return null; - var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType), false) .ConfigureAwait(false); if (result == null || result.Document == null) @@ -558,7 +558,7 @@ namespace MediaBrowser.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType), false) .ConfigureAwait(false); if (result == null || result.Document == null) @@ -589,7 +589,7 @@ namespace MediaBrowser.Dlna.PlayTo throw new InvalidOperationException("Unable to find service"); } - var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType)) + var result = await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, RendererCommands.BuildPost(command, service.ServiceType), false) .ConfigureAwait(false); if (result == null || result.Document == null) diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index 5aa8c1f9c..cf21211f4 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -768,8 +768,11 @@ namespace MediaBrowser.Dlna.PlayTo await _device.SetAvTransport(newItem.StreamUrl, GetDlnaHeaders(newItem), newItem.Didl).ConfigureAwait(false); - if (newItem.StreamInfo.IsDirectStream) + if (newItem.StreamInfo.IsDirectStream && newPosition > 0) { + // This is rather arbitrary, but give the player time to start playing + await Task.Delay(2000).ConfigureAwait(false); + await _device.Seek(TimeSpan.FromTicks(newPosition)).ConfigureAwait(false); } } diff --git a/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs b/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs index f0689751c..39d3a8d07 100644 --- a/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs +++ b/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs @@ -1,7 +1,7 @@ -using System; -using MediaBrowser.Common.Net; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Dlna.Common; +using System; using System.Globalization; using System.IO; using System.Text; @@ -28,9 +28,10 @@ namespace MediaBrowser.Dlna.PlayTo DeviceService service, string command, string postData, + bool logRequest = true, string header = null) { - var response = await PostSoapDataAsync(NormalizeServiceUrl(baseUrl, service.ControlUrl), "\"" + service.ServiceType + "#" + command + "\"", postData, header) + var response = await PostSoapDataAsync(NormalizeServiceUrl(baseUrl, service.ControlUrl), "\"" + service.ServiceType + "#" + command + "\"", postData, header, logRequest) .ConfigureAwait(false); using (var stream = response.Content) @@ -69,7 +70,6 @@ namespace MediaBrowser.Dlna.PlayTo { Url = url, UserAgent = USERAGENT, - LogRequest = _config.GetDlnaConfiguration().EnableDebugLogging, LogErrorResponseBody = true }; @@ -87,7 +87,6 @@ namespace MediaBrowser.Dlna.PlayTo { Url = url, UserAgent = USERAGENT, - LogRequest = _config.GetDlnaConfiguration().EnableDebugLogging, LogErrorResponseBody = true }; @@ -105,7 +104,8 @@ namespace MediaBrowser.Dlna.PlayTo private Task<HttpResponseInfo> PostSoapDataAsync(string url, string soapAction, string postData, - string header = null) + string header, + bool logRequest) { if (!soapAction.StartsWith("\"")) soapAction = "\"" + soapAction + "\""; @@ -114,7 +114,7 @@ namespace MediaBrowser.Dlna.PlayTo { Url = url, UserAgent = USERAGENT, - LogRequest = _config.GetDlnaConfiguration().EnableDebugLogging, + LogRequest = logRequest || _config.GetDlnaConfiguration().EnableDebugLogging, LogErrorResponseBody = true }; diff --git a/MediaBrowser.Dlna/Profiles/BubbleUpnpProfile.cs b/MediaBrowser.Dlna/Profiles/BubbleUpnpProfile.cs new file mode 100644 index 000000000..a9af85346 --- /dev/null +++ b/MediaBrowser.Dlna/Profiles/BubbleUpnpProfile.cs @@ -0,0 +1,76 @@ +using System.Xml.Serialization; +using MediaBrowser.Model.Dlna; + +namespace MediaBrowser.Dlna.Profiles +{ + [XmlRoot("Profile")] + public class BubbleUpnpProfile : DefaultProfile + { + public BubbleUpnpProfile() + { + Name = "BubbleUPnp"; + + TimelineOffsetSeconds = 5; + + Identification = new DeviceIdentification + { + ModelName = "BubbleUPnp", + + Headers = new[] + { + new HttpHeaderInfo {Name = "User-Agent", Value = "BubbleUPnp", Match = HeaderMatchType.Substring} + } + }; + + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio, + AudioCodec = "mp3" + }, + new TranscodingProfile + { + Container = "ts", + Type = DlnaProfileType.Video, + VideoCodec = "h264", + AudioCodec = "aac" + }, + new TranscodingProfile + { + Container = "jpeg", + Type = DlnaProfileType.Photo + } + }; + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Container = "avi,mpeg,mkv,ts,mp4,mov,m4v,asf,webm,ogg,ogv,iso", + Type = DlnaProfileType.Video + }, + + new DirectPlayProfile + { + Container = "mp3,flac,asf,off,oga,aac", + Type = DlnaProfileType.Audio + }, + + new DirectPlayProfile + { + Type = DlnaProfileType.Photo, + + Container = "jpeg,png,gif,bmp,tiff" + } + }; + + ResponseProfiles = new ResponseProfile[] { }; + + ContainerProfiles = new ContainerProfile[] { }; + + CodecProfiles = new CodecProfile[] { }; + } + } +} diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs index 71f877232..3bd425cb3 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs @@ -47,6 +47,7 @@ namespace MediaBrowser.Dlna.Profiles "http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000"; EnableSingleAlbumArtLimit = true; + EnableAlbumArtInDidl = true; TranscodingProfiles = new[] { @@ -293,6 +294,12 @@ namespace MediaBrowser.Dlna.Profiles Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.Height, Value = "1080" + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.VideoFramerate, + Value = "30" } } }, diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs index 0b157ae33..de4f1d2b6 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs @@ -44,6 +44,7 @@ namespace MediaBrowser.Dlna.Profiles ManufacturerUrl = "http://www.microsoft.com/"; SonyAggregationFlags = "10"; EnableSingleAlbumArtLimit = true; + EnableAlbumArtInDidl = true; TranscodingProfiles = new[] { @@ -310,6 +311,12 @@ namespace MediaBrowser.Dlna.Profiles Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.Height, Value = "1080" + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.VideoFramerate, + Value = "30" } } }, diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs index 0d974cbc0..5a5fb9e94 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs @@ -44,6 +44,7 @@ namespace MediaBrowser.Dlna.Profiles ManufacturerUrl = "http://www.microsoft.com/"; SonyAggregationFlags = "10"; EnableSingleAlbumArtLimit = true; + EnableAlbumArtInDidl = true; TranscodingProfiles = new[] { @@ -250,6 +251,12 @@ namespace MediaBrowser.Dlna.Profiles Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.Height, Value = "1080" + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.VideoFramerate, + Value = "30" } } }, diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs index ac4cb2131..74a07f389 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs @@ -44,6 +44,7 @@ namespace MediaBrowser.Dlna.Profiles ManufacturerUrl = "http://www.microsoft.com/"; SonyAggregationFlags = "10"; EnableSingleAlbumArtLimit = true; + EnableAlbumArtInDidl = true; TranscodingProfiles = new[] { @@ -284,6 +285,12 @@ namespace MediaBrowser.Dlna.Profiles Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.Height, Value = "1080" + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.VideoFramerate, + Value = "30" } } } diff --git a/MediaBrowser.Dlna/Profiles/VlcProfile.cs b/MediaBrowser.Dlna/Profiles/VlcProfile.cs new file mode 100644 index 000000000..5b3f7c0d1 --- /dev/null +++ b/MediaBrowser.Dlna/Profiles/VlcProfile.cs @@ -0,0 +1,76 @@ +using System.Xml.Serialization; +using MediaBrowser.Model.Dlna; + +namespace MediaBrowser.Dlna.Profiles +{ + [XmlRoot("Profile")] + public class VlcProfile : DefaultProfile + { + public VlcProfile() + { + Name = "Vlc"; + + TimelineOffsetSeconds = 5; + + Identification = new DeviceIdentification + { + ModelName = "Vlc", + + Headers = new[] + { + new HttpHeaderInfo {Name = "User-Agent", Value = "vlc", Match = HeaderMatchType.Substring} + } + }; + + TranscodingProfiles = new[] + { + new TranscodingProfile + { + Container = "mp3", + Type = DlnaProfileType.Audio, + AudioCodec = "mp3" + }, + new TranscodingProfile + { + Container = "ts", + Type = DlnaProfileType.Video, + VideoCodec = "h264", + AudioCodec = "aac" + }, + new TranscodingProfile + { + Container = "jpeg", + Type = DlnaProfileType.Photo + } + }; + + DirectPlayProfiles = new[] + { + new DirectPlayProfile + { + Container = "avi,mpeg,mkv,ts,mp4,mov,m4v,asf,webm,ogg,ogv,iso", + Type = DlnaProfileType.Video + }, + + new DirectPlayProfile + { + Container = "mp3,flac,asf,off,oga,aac", + Type = DlnaProfileType.Audio + }, + + new DirectPlayProfile + { + Type = DlnaProfileType.Photo, + + Container = "jpeg,png,gif,bmp,tiff" + } + }; + + ResponseProfiles = new ResponseProfile[] { }; + + ContainerProfiles = new ContainerProfile[] { }; + + CodecProfiles = new CodecProfile[] { }; + } + } +} diff --git a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs index a26c43911..ab8d5ea72 100644 --- a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs +++ b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs @@ -11,7 +11,6 @@ namespace MediaBrowser.Dlna.Profiles Name = "WDTV Live"; TimelineOffsetSeconds = 5; - IgnoreTranscodeByteRangeRequests = true; Identification = new DeviceIdentification { diff --git a/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml b/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml new file mode 100644 index 000000000..d65b55f2e --- /dev/null +++ b/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml @@ -0,0 +1,50 @@ +<?xml version="1.0"?> +<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <Name>BubbleUPnp</Name> + <Identification> + <ModelName>BubbleUPnp</ModelName> + <Headers> + <HttpHeaderInfo name="User-Agent" value="BubbleUPnp" match="Substring" /> + </Headers> + </Identification> + <FriendlyName>Emby</FriendlyName> + <Manufacturer>Emby</Manufacturer> + <ManufacturerUrl>http://emby.media/</ManufacturerUrl> + <ModelName>Emby</ModelName> + <ModelDescription>Emby</ModelDescription> + <ModelNumber>Emby</ModelNumber> + <ModelUrl>http://emby.media/</ModelUrl> + <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> + <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> + <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> + <AlbumArtPn>JPEG_SM</AlbumArtPn> + <MaxAlbumArtWidth>480</MaxAlbumArtWidth> + <MaxAlbumArtHeight>480</MaxAlbumArtHeight> + <MaxIconWidth>48</MaxIconWidth> + <MaxIconHeight>48</MaxIconHeight> + <MaxStreamingBitrate>8000000</MaxStreamingBitrate> + <MaxStaticBitrate>8000000</MaxStaticBitrate> + <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate> + <MusicSyncBitrate>128000</MusicSyncBitrate> + <XDlnaDoc>DMS-1.50</XDlnaDoc> + <ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo> + <TimelineOffsetSeconds>5</TimelineOffsetSeconds> + <RequiresPlainVideoItems>false</RequiresPlainVideoItems> + <RequiresPlainFolders>false</RequiresPlainFolders> + <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar> + <XmlRootAttributes /> + <DirectPlayProfiles> + <DirectPlayProfile container="avi,mpeg,mkv,ts,mp4,mov,m4v,asf,webm,ogg,ogv,iso" type="Video" /> + <DirectPlayProfile container="mp3,flac,asf,off,oga,aac" type="Audio" /> + <DirectPlayProfile container="jpeg,png,gif,bmp,tiff" type="Photo" /> + </DirectPlayProfiles> + <TranscodingProfiles> + <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" /> + <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" /> + <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" /> + </TranscodingProfiles> + <ContainerProfiles /> + <CodecProfiles /> + <ResponseProfiles /> + <SubtitleProfiles /> +</Profile>
\ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Default.xml b/MediaBrowser.Dlna/Profiles/Xml/Default.xml index 3c1fbfb1b..1c611d47a 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Default.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Default.xml @@ -8,7 +8,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml index 2fde80008..4f8a0eac5 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml @@ -13,7 +13,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml b/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml index 7876ccc7c..4595b57e0 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml @@ -14,7 +14,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml b/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml index 21f2b1ad5..50bc43f7c 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml @@ -15,7 +15,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Generic Device.xml b/MediaBrowser.Dlna/Profiles/Xml/Generic Device.xml new file mode 100644 index 000000000..1c611d47a --- /dev/null +++ b/MediaBrowser.Dlna/Profiles/Xml/Generic Device.xml @@ -0,0 +1,43 @@ +<?xml version="1.0"?> +<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <Name>Generic Device</Name> + <FriendlyName>Emby</FriendlyName> + <Manufacturer>Emby</Manufacturer> + <ManufacturerUrl>http://emby.media/</ManufacturerUrl> + <ModelName>Emby</ModelName> + <ModelDescription>Emby</ModelDescription> + <ModelNumber>Emby</ModelNumber> + <ModelUrl>http://emby.media/</ModelUrl> + <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> + <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> + <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> + <AlbumArtPn>JPEG_SM</AlbumArtPn> + <MaxAlbumArtWidth>480</MaxAlbumArtWidth> + <MaxAlbumArtHeight>480</MaxAlbumArtHeight> + <MaxIconWidth>48</MaxIconWidth> + <MaxIconHeight>48</MaxIconHeight> + <MaxStreamingBitrate>8000000</MaxStreamingBitrate> + <MaxStaticBitrate>8000000</MaxStaticBitrate> + <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate> + <MusicSyncBitrate>128000</MusicSyncBitrate> + <XDlnaDoc>DMS-1.50</XDlnaDoc> + <ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo> + <TimelineOffsetSeconds>0</TimelineOffsetSeconds> + <RequiresPlainVideoItems>false</RequiresPlainVideoItems> + <RequiresPlainFolders>false</RequiresPlainFolders> + <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar> + <XmlRootAttributes /> + <DirectPlayProfiles> + <DirectPlayProfile container="mp3,wma" type="Audio" /> + <DirectPlayProfile container="avi,mp4" type="Video" /> + </DirectPlayProfiles> + <TranscodingProfiles> + <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" /> + <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" /> + <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" /> + </TranscodingProfiles> + <ContainerProfiles /> + <CodecProfiles /> + <ResponseProfiles /> + <SubtitleProfiles /> +</Profile>
\ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml index a2fc002e5..919fa5a40 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml @@ -14,7 +14,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml index a273586bd..1dc942873 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml @@ -12,7 +12,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml b/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml index e92b99830..4896402a0 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml @@ -14,7 +14,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml index dcc06abb3..a2203e4ce 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml @@ -15,7 +15,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml b/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml index 2df2da98b..b02f37986 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml @@ -8,7 +8,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml index d8d2a0b2b..91c2325cf 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml @@ -14,7 +14,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>true</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml index e4959c0c7..f5ec1a31e 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml @@ -14,7 +14,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>3.0</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml index b46b94c1d..6a732f869 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml @@ -16,7 +16,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>3.0</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml index 19cb5670a..7afc8183d 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml @@ -15,8 +15,7 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>3.0</ModelNumber> <ModelUrl>http://www.microsoft.com/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> - <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> + <EnableAlbumArtInDidl>true</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> <AlbumArtPn>JPEG_TN</AlbumArtPn> @@ -79,6 +78,7 @@ <Conditions> <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" /> <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" /> + <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" /> </Conditions> </CodecProfile> <CodecProfile type="VideoAudio" codec="ac3"> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml index 78c99d366..7400600e2 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml @@ -15,8 +15,7 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>3.0</ModelNumber> <ModelUrl>http://www.microsoft.com/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> - <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> + <EnableAlbumArtInDidl>true</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> <AlbumArtPn>JPEG_TN</AlbumArtPn> @@ -82,6 +81,7 @@ <Conditions> <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" /> <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" /> + <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" /> </Conditions> </CodecProfile> <CodecProfile type="VideoAudio" codec="ac3"> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml index 4f849b731..b8e3d6d30 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml @@ -15,8 +15,7 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>3.0</ModelNumber> <ModelUrl>http://www.microsoft.com/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> - <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> + <EnableAlbumArtInDidl>true</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> <AlbumArtPn>JPEG_TN</AlbumArtPn> @@ -67,6 +66,7 @@ <Conditions> <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" /> <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" /> + <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" /> </Conditions> </CodecProfile> <CodecProfile type="VideoAudio" codec="ac3"> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml index e074b8389..5733d9d0b 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml @@ -15,8 +15,7 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>3.0</ModelNumber> <ModelUrl>http://www.microsoft.com/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> - <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> + <EnableAlbumArtInDidl>true</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> <AlbumArtPn>JPEG_TN</AlbumArtPn> @@ -72,6 +71,7 @@ <Conditions> <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" /> <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" /> + <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" /> </Conditions> </CodecProfile> </CodecProfiles> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml index e90d1bc0f..4b21dc195 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml @@ -15,7 +15,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>true</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml b/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml new file mode 100644 index 000000000..fd4b77f55 --- /dev/null +++ b/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml @@ -0,0 +1,50 @@ +<?xml version="1.0"?> +<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <Name>Vlc</Name> + <Identification> + <ModelName>Vlc</ModelName> + <Headers> + <HttpHeaderInfo name="User-Agent" value="vlc" match="Substring" /> + </Headers> + </Identification> + <FriendlyName>Emby</FriendlyName> + <Manufacturer>Emby</Manufacturer> + <ManufacturerUrl>http://emby.media/</ManufacturerUrl> + <ModelName>Emby</ModelName> + <ModelDescription>Emby</ModelDescription> + <ModelNumber>Emby</ModelNumber> + <ModelUrl>http://emby.media/</ModelUrl> + <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> + <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> + <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> + <AlbumArtPn>JPEG_SM</AlbumArtPn> + <MaxAlbumArtWidth>480</MaxAlbumArtWidth> + <MaxAlbumArtHeight>480</MaxAlbumArtHeight> + <MaxIconWidth>48</MaxIconWidth> + <MaxIconHeight>48</MaxIconHeight> + <MaxStreamingBitrate>8000000</MaxStreamingBitrate> + <MaxStaticBitrate>8000000</MaxStaticBitrate> + <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate> + <MusicSyncBitrate>128000</MusicSyncBitrate> + <XDlnaDoc>DMS-1.50</XDlnaDoc> + <ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo> + <TimelineOffsetSeconds>5</TimelineOffsetSeconds> + <RequiresPlainVideoItems>false</RequiresPlainVideoItems> + <RequiresPlainFolders>false</RequiresPlainFolders> + <EnableMSMediaReceiverRegistrar>false</EnableMSMediaReceiverRegistrar> + <XmlRootAttributes /> + <DirectPlayProfiles> + <DirectPlayProfile container="avi,mpeg,mkv,ts,mp4,mov,m4v,asf,webm,ogg,ogv,iso" type="Video" /> + <DirectPlayProfile container="mp3,flac,asf,off,oga,aac" type="Audio" /> + <DirectPlayProfile container="jpeg,png,gif,bmp,tiff" type="Photo" /> + </DirectPlayProfiles> + <TranscodingProfiles> + <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" /> + <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" /> + <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" /> + </TranscodingProfiles> + <ContainerProfiles /> + <CodecProfiles /> + <ResponseProfiles /> + <SubtitleProfiles /> +</Profile>
\ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml index 3d7e745f8..a2ab33b4e 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml @@ -15,7 +15,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>true</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml index ae0f53edb..69d091e47 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml @@ -15,7 +15,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>12.0</ModelNumber> <ModelUrl>http://www.microsoft.com/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml index d22356646..1aa2b9198 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml @@ -15,7 +15,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml index 1418e63bd..c2095cf83 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml @@ -14,7 +14,6 @@ <ModelDescription>Emby</ModelDescription> <ModelNumber>Emby</ModelNumber> <ModelUrl>http://emby.media/</ModelUrl> - <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests> <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl> <EnableSingleAlbumArtLimit>false</EnableSingleAlbumArtLimit> <SupportedMediaTypes>Audio</SupportedMediaTypes> diff --git a/MediaBrowser.Dlna/Service/BaseControlHandler.cs b/MediaBrowser.Dlna/Service/BaseControlHandler.cs index a17182a7e..a65520d65 100644 --- a/MediaBrowser.Dlna/Service/BaseControlHandler.cs +++ b/MediaBrowser.Dlna/Service/BaseControlHandler.cs @@ -27,14 +27,16 @@ namespace MediaBrowser.Dlna.Service { try { - if (Config.GetDlnaConfiguration().EnableDebugLogging) + var enableDebugLogging = Config.GetDlnaConfiguration().EnableDebugLogging; + + if (enableDebugLogging) { LogRequest(request); } var response = ProcessControlRequestInternal(request); - if (Config.GetDlnaConfiguration().EnableDebugLogging) + if (enableDebugLogging) { LogResponse(response); } diff --git a/MediaBrowser.Dlna/Ssdp/Datagram.cs b/MediaBrowser.Dlna/Ssdp/Datagram.cs index ae79ab44f..4a0bb6f48 100644 --- a/MediaBrowser.Dlna/Ssdp/Datagram.cs +++ b/MediaBrowser.Dlna/Ssdp/Datagram.cs @@ -12,13 +12,15 @@ namespace MediaBrowser.Dlna.Ssdp public EndPoint FromEndPoint { get; private set; } public string Message { get; private set; } public bool IgnoreBindFailure { get; private set; } + public bool EnableDebugLogging { get; private set; } private readonly ILogger _logger; - public Datagram(EndPoint toEndPoint, EndPoint fromEndPoint, ILogger logger, string message, bool ignoreBindFailure) + public Datagram(EndPoint toEndPoint, EndPoint fromEndPoint, ILogger logger, string message, bool ignoreBindFailure, bool enableDebugLogging) { Message = message; _logger = logger; + EnableDebugLogging = enableDebugLogging; IgnoreBindFailure = ignoreBindFailure; FromEndPoint = fromEndPoint; ToEndPoint = toEndPoint; @@ -37,8 +39,13 @@ namespace MediaBrowser.Dlna.Ssdp { client.Bind(FromEndPoint); } - catch + catch (Exception ex) { + if (EnableDebugLogging) + { + _logger.ErrorException("Error binding datagram socket", ex); + } + if (!IgnoreBindFailure) throw; } } @@ -51,7 +58,7 @@ namespace MediaBrowser.Dlna.Ssdp } catch (Exception ex) { - if (!IgnoreBindFailure) + if (!IgnoreBindFailure || EnableDebugLogging) { _logger.ErrorException("Error sending Datagram to {0} from {1}: " + Message, ex, ToEndPoint, FromEndPoint == null ? "" : FromEndPoint.ToString()); } @@ -62,8 +69,12 @@ namespace MediaBrowser.Dlna.Ssdp { client.Close(); } - catch (Exception) + catch (Exception ex) { + if (EnableDebugLogging) + { + _logger.ErrorException("Error closing datagram socket", ex); + } } } }, null); diff --git a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs index 3dd482e64..94342bf31 100644 --- a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs +++ b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs @@ -1,5 +1,4 @@ using MediaBrowser.Common.Events; -using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dlna; @@ -143,7 +142,10 @@ namespace MediaBrowser.Dlna.Ssdp args.EndPoint = endPoint; args.LocalIp = localIp; - TryCreateDevice(args); + if (!_ssdpHandler.IsSelfNotification(args)) + { + TryCreateDevice(args); + } } } @@ -203,18 +205,25 @@ namespace MediaBrowser.Dlna.Ssdp string nts; args.Headers.TryGetValue("NTS", out nts); + if (String.Equals(nts, "ssdp:byebye", StringComparison.OrdinalIgnoreCase)) + { + if (String.Equals(args.Method, "NOTIFY", StringComparison.OrdinalIgnoreCase)) + { + if (!_disposed) + { + EventHelper.FireEventIfNotNull(DeviceLeft, this, args, _logger); + } + } + + return; + } + string usn; if (!args.Headers.TryGetValue("USN", out usn)) usn = string.Empty; string nt; if (!args.Headers.TryGetValue("NT", out nt)) nt = string.Empty; - // Ignore when a device is indicating it's shutting down - if (string.Equals(nts, "ssdp:byebye", StringComparison.OrdinalIgnoreCase)) - { - return; - } - // Need to be able to download device description string location; if (!args.Headers.TryGetValue("Location", out location) || diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs index 5b3746aeb..28ea5ad6c 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs @@ -67,7 +67,7 @@ namespace MediaBrowser.Dlna.Ssdp } return String.Format( - "{0}{1}/{2}.{3} UPnP/1.0 DLNADOC/1.5 MediaBrowser/{4}", + "{0}{1}/{2}.{3} UPnP/1.0 DLNADOC/1.5 Emby/{4}", pstring, IntPtr.Size * 8, os.Version.Major, @@ -88,24 +88,21 @@ namespace MediaBrowser.Dlna.Ssdp private async void OnMessageReceived(SsdpMessageEventArgs args) { - if (string.Equals(args.Method, "M-SEARCH", StringComparison.OrdinalIgnoreCase)) - { - var headers = args.Headers; + var headers = args.Headers; + string st; + if (string.Equals(args.Method, "M-SEARCH", StringComparison.OrdinalIgnoreCase) && headers.TryGetValue("st", out st)) + { TimeSpan delay = GetSearchDelay(headers); - + if (_config.GetDlnaConfiguration().EnableDebugLogging) { _logger.Debug("Delaying search response by {0} seconds", delay.TotalSeconds); } - + await Task.Delay(delay).ConfigureAwait(false); - string st; - if (headers.TryGetValue("st", out st)) - { - RespondToSearch(args.EndPoint, st); - } + RespondToSearch(args.EndPoint, st); } EventHelper.FireEventIfNotNull(MessageReceived, this, args, _logger); @@ -166,9 +163,11 @@ namespace MediaBrowser.Dlna.Ssdp var msg = new SsdpMessageBuilder().BuildMessage(header, values); var queued = false; + var enableDebugLogging = _config.GetDlnaConfiguration().EnableDebugLogging; + for (var i = 0; i < sendCount; i++) { - var dgram = new Datagram(endpoint, localAddress, _logger, msg, ignoreBindFailure); + var dgram = new Datagram(endpoint, localAddress, _logger, msg, ignoreBindFailure, enableDebugLogging); if (_messageQueue.Count == 0) { @@ -212,10 +211,9 @@ namespace MediaBrowser.Dlna.Ssdp private void RespondToSearch(EndPoint endpoint, string deviceType) { - if (_config.GetDlnaConfiguration().EnableDebugLogging) - { - _logger.Debug("RespondToSearch"); - } + var enableDebugLogging = _config.GetDlnaConfiguration().EnableDebugLogging; + + var isLogged = false; const string header = "HTTP/1.1 200 OK"; @@ -224,6 +222,15 @@ namespace MediaBrowser.Dlna.Ssdp if (string.Equals(deviceType, "ssdp:all", StringComparison.OrdinalIgnoreCase) || string.Equals(deviceType, d.Type, StringComparison.OrdinalIgnoreCase)) { + if (!isLogged) + { + if (enableDebugLogging) + { + _logger.Debug("Responding to search from {0} for {1}", endpoint, deviceType); + } + isLogged = true; + } + var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); values["CACHE-CONTROL"] = "max-age = 600"; @@ -238,7 +245,7 @@ namespace MediaBrowser.Dlna.Ssdp SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0), true, 1); //SendDatagram(header, values, endpoint, null, true); - if (_config.GetDlnaConfiguration().EnableDebugLogging) + if (enableDebugLogging) { _logger.Debug("{1} - Responded to a {0} request to {2}", d.Type, endpoint, d.Address.ToString()); } @@ -316,7 +323,9 @@ namespace MediaBrowser.Dlna.Ssdp var received = (byte[])result.AsyncState; - if (_config.GetDlnaConfiguration().EnableDebugLogging) + var enableDebugLogging = _config.GetDlnaConfiguration().EnableDebugLogging; + + if (enableDebugLogging) { _logger.Debug(Encoding.ASCII.GetString(received)); } @@ -324,7 +333,12 @@ namespace MediaBrowser.Dlna.Ssdp var args = SsdpHelper.ParseSsdpResponse(received); args.EndPoint = endpoint; - if (_config.GetDlnaConfiguration().EnableDebugLogging) + if (IsSelfNotification(args)) + { + return; + } + + if (enableDebugLogging) { var headerTexts = args.Headers.Select(i => string.Format("{0}={1}", i.Key, i.Value)); var headerText = string.Join(",", headerTexts.ToArray()); @@ -345,6 +359,44 @@ namespace MediaBrowser.Dlna.Ssdp } } + internal bool IsSelfNotification(SsdpMessageEventArgs args) + { + // Avoid responding to self search messages + //string serverId; + //if (args.Headers.TryGetValue("X-EMBYSERVERID", out serverId) && + // string.Equals(serverId, _appHost.SystemId, StringComparison.OrdinalIgnoreCase)) + //{ + // return true; + //} + + string server; + args.Headers.TryGetValue("SERVER", out server); + + if (string.Equals(server, _serverSignature, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + return false; + //string usn; + //args.Headers.TryGetValue("USN", out usn); + + //if (string.IsNullOrWhiteSpace(usn)) + //{ + // return false; + //} + + //_logger.Debug("IsSelfNotification test: " + usn); + + //return RegisteredDevices.Any(i => + //{ + // var isSameDevice = string.Equals(usn, i.USN, StringComparison.OrdinalIgnoreCase) || + // i.USN.IndexOf(usn, StringComparison.OrdinalIgnoreCase) != 1 || + // usn.IndexOf(i.USN, StringComparison.OrdinalIgnoreCase) != 1; + + // return isSameDevice; + //}); + } + public void Dispose() { _config.NamedConfigurationUpdated -= _config_ConfigurationUpdated; @@ -399,17 +451,19 @@ namespace MediaBrowser.Dlna.Ssdp private void NotifyAll() { - if (_config.GetDlnaConfiguration().EnableDebugLogging) + var enableDebugLogging = _config.GetDlnaConfiguration().EnableDebugLogging; + + if (enableDebugLogging) { _logger.Debug("Sending alive notifications"); } foreach (var d in RegisteredDevices) { - NotifyDevice(d, "alive", 1); + NotifyDevice(d, "alive", 1, enableDebugLogging); } } - private void NotifyDevice(UpnpDevice dev, string type, int sendCount) + private void NotifyDevice(UpnpDevice dev, string type, int sendCount, bool logMessage) { const string header = "NOTIFY * HTTP/1.1"; @@ -424,7 +478,7 @@ namespace MediaBrowser.Dlna.Ssdp values["NT"] = dev.Type; values["USN"] = dev.USN; - if (_config.GetDlnaConfiguration().EnableDebugLogging) + if (logMessage) { _logger.Debug("{0} said {1}", dev.USN, type); } @@ -457,7 +511,7 @@ namespace MediaBrowser.Dlna.Ssdp foreach (var d in dl.ToList()) { - NotifyDevice(d, "byebye", 2); + NotifyDevice(d, "byebye", 2, true); } _logger.Debug("Unregistered mount {0}", uuid); @@ -468,13 +522,15 @@ namespace MediaBrowser.Dlna.Ssdp private int _aliveNotifierIntervalMs; private void ReloadAliveNotifier() { - if (!_config.GetDlnaConfiguration().BlastAliveMessages) + var config = _config.GetDlnaConfiguration(); + + if (!config.BlastAliveMessages) { DisposeNotificationTimer(); return; } - var intervalMs = _config.GetDlnaConfiguration().BlastAliveMessageIntervalSeconds * 1000; + var intervalMs = config.BlastAliveMessageIntervalSeconds * 1000; if (_notificationTimer == null || _aliveNotifierIntervalMs != intervalMs) { diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index c30ceb62d..e25537362 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -840,7 +840,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); - filters.Add(string.Format("scale=trunc(min(iw\\,{0})/2)*2:trunc(min((iw/dar)\\,{1})/2)*2", maxWidthParam, maxHeightParam)); + filters.Add(string.Format("scale=trunc(min(max(iw\\,ih*dar)\\,min({0}\\,{1}*dar))/2)*2:trunc(min(max(iw/dar\\,ih)\\,min({0}/dar\\,{1}))/2)*2", maxWidthParam, maxHeightParam)); } // If a fixed width was requested @@ -860,7 +860,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } // If a max width was requested - else if (request.MaxWidth.HasValue && (!request.MaxHeight.HasValue || state.VideoStream == null)) + else if (request.MaxWidth.HasValue) { var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture); @@ -868,35 +868,13 @@ namespace MediaBrowser.MediaEncoding.Encoder } // If a max height was requested - else if (request.MaxHeight.HasValue && (!request.MaxWidth.HasValue || state.VideoStream == null)) + else if (request.MaxHeight.HasValue) { var maxHeightParam = request.MaxHeight.Value.ToString(UsCulture); filters.Add(string.Format("scale=trunc(oh*a*2)/2:min(ih\\,{0})", maxHeightParam)); } - else if (request.MaxWidth.HasValue || - request.MaxHeight.HasValue || - request.Width.HasValue || - request.Height.HasValue) - { - if (state.VideoStream != null) - { - // Need to perform calculations manually - - // Try to account for bad media info - var currentHeight = state.VideoStream.Height ?? request.MaxHeight ?? request.Height ?? 0; - var currentWidth = state.VideoStream.Width ?? request.MaxWidth ?? request.Width ?? 0; - - var outputSize = DrawingUtils.Resize(currentWidth, currentHeight, request.Width, request.Height, request.MaxWidth, request.MaxHeight); - - var manualWidthParam = outputSize.Width.ToString(UsCulture); - var manualHeightParam = outputSize.Height.ToString(UsCulture); - - filters.Add(string.Format("scale=trunc({0}/2)*2:trunc({1}/2)*2", manualWidthParam, manualHeightParam)); - } - } - var output = string.Empty; if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index a01f37f91..4d5b669e2 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -199,82 +199,83 @@ namespace MediaBrowser.MediaEncoding.Encoder await _ffProbeResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - var processWrapper = new ProcessWrapper(process, this); - - try - { - StartProcess(processWrapper); - } - catch (Exception ex) + using (var processWrapper = new ProcessWrapper(process, this)) { - _ffProbeResourcePool.Release(); + try + { + StartProcess(processWrapper); + } + catch (Exception ex) + { + _ffProbeResourcePool.Release(); - _logger.ErrorException("Error starting ffprobe", ex); + _logger.ErrorException("Error starting ffprobe", ex); - throw; - } + throw; + } - try - { - process.BeginErrorReadLine(); + try + { + process.BeginErrorReadLine(); - var result = _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream); + var result = _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream); - if (result != null) - { - if (result.streams != null) + if (result != null) { - // Normalize aspect ratio if invalid - foreach (var stream in result.streams) + if (result.streams != null) { - if (string.Equals(stream.display_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)) - { - stream.display_aspect_ratio = string.Empty; - } - if (string.Equals(stream.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)) + // Normalize aspect ratio if invalid + foreach (var stream in result.streams) { - stream.sample_aspect_ratio = string.Empty; + if (string.Equals(stream.display_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)) + { + stream.display_aspect_ratio = string.Empty; + } + if (string.Equals(stream.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase)) + { + stream.sample_aspect_ratio = string.Empty; + } } } - } - var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); + var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); - if (extractKeyFrameInterval && mediaInfo.RunTimeTicks.HasValue) - { - foreach (var stream in mediaInfo.MediaStreams) + if (extractKeyFrameInterval && mediaInfo.RunTimeTicks.HasValue) { - if (stream.Type == MediaStreamType.Video && string.Equals(stream.Codec, "h264", StringComparison.OrdinalIgnoreCase)) + foreach (var stream in mediaInfo.MediaStreams) { - try - { - //stream.KeyFrames = await GetKeyFrames(inputPath, stream.Index, cancellationToken) - // .ConfigureAwait(false); - } - catch (OperationCanceledException) - { - - } - catch (Exception ex) + if (stream.Type == MediaStreamType.Video && string.Equals(stream.Codec, "h264", StringComparison.OrdinalIgnoreCase)) { - _logger.ErrorException("Error getting key frame interval", ex); + try + { + //stream.KeyFrames = await GetKeyFrames(inputPath, stream.Index, cancellationToken) + // .ConfigureAwait(false); + } + catch (OperationCanceledException) + { + + } + catch (Exception ex) + { + _logger.ErrorException("Error getting key frame interval", ex); + } } } } - } - return mediaInfo; + return mediaInfo; + } } - } - catch - { - StopProcess(processWrapper, 100, true); + catch + { + StopProcess(processWrapper, 100, true); - throw; - } - finally - { - _ffProbeResourcePool.Release(); + throw; + } + finally + { + _ffProbeResourcePool.Release(); + } } throw new ApplicationException(string.Format("FFProbe failed for {0}", inputPath)); @@ -307,31 +308,32 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - var processWrapper = new ProcessWrapper(process, this); - - StartProcess(processWrapper); + using (var processWrapper = new ProcessWrapper(process, this)) + { + StartProcess(processWrapper); - var lines = new List<int>(); + var lines = new List<int>(); - try - { - process.BeginErrorReadLine(); + try + { + process.BeginErrorReadLine(); - await StartReadingOutput(process.StandardOutput.BaseStream, lines, 120000, cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - if (cancellationToken.IsCancellationRequested) + await StartReadingOutput(process.StandardOutput.BaseStream, lines, 120000, cancellationToken).ConfigureAwait(false); + } + catch (OperationCanceledException) { - throw; + if (cancellationToken.IsCancellationRequested) + { + throw; + } + } + finally + { + StopProcess(processWrapper, 100, true); } - } - finally - { - StopProcess(processWrapper, 100, true); - } - return lines; + return lines; + } } private async Task StartReadingOutput(Stream source, List<int> lines, int timeoutMs, CancellationToken cancellationToken) @@ -490,51 +492,53 @@ namespace MediaBrowser.MediaEncoding.Encoder await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - var processWrapper = new ProcessWrapper(process, this); - bool ranToCompletion; + using (var processWrapper = new ProcessWrapper(process, this)) + { + bool ranToCompletion; - var memoryStream = new MemoryStream(); + var memoryStream = new MemoryStream(); - try - { - StartProcess(processWrapper); + try + { + StartProcess(processWrapper); #pragma warning disable 4014 - // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback - process.StandardOutput.BaseStream.CopyToAsync(memoryStream); + // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback + process.StandardOutput.BaseStream.CopyToAsync(memoryStream); #pragma warning restore 4014 - // MUST read both stdout and stderr asynchronously or a deadlock may occurr - process.BeginErrorReadLine(); + // MUST read both stdout and stderr asynchronously or a deadlock may occurr + process.BeginErrorReadLine(); - ranToCompletion = process.WaitForExit(10000); + ranToCompletion = process.WaitForExit(10000); - if (!ranToCompletion) + if (!ranToCompletion) + { + StopProcess(processWrapper, 1000, false); + } + + } + finally { - StopProcess(processWrapper, 1000, false); + resourcePool.Release(); } - } - finally - { - resourcePool.Release(); - } + var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1; - var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1; + if (exitCode == -1 || memoryStream.Length == 0) + { + memoryStream.Dispose(); - if (exitCode == -1 || memoryStream.Length == 0) - { - memoryStream.Dispose(); + var msg = string.Format("ffmpeg image extraction failed for {0}", inputPath); - var msg = string.Format("ffmpeg image extraction failed for {0}", inputPath); + _logger.Error(msg); - _logger.Error(msg); + throw new ApplicationException(msg); + } - throw new ApplicationException(msg); + memoryStream.Position = 0; + return memoryStream; } - - memoryStream.Position = 0; - return memoryStream; } public string GetTimeParameter(long ticks) @@ -603,55 +607,56 @@ namespace MediaBrowser.MediaEncoding.Encoder bool ranToCompletion = false; - var processWrapper = new ProcessWrapper(process, this); - - try + using (var processWrapper = new ProcessWrapper(process, this)) { - StartProcess(processWrapper); + try + { + StartProcess(processWrapper); - // Need to give ffmpeg enough time to make all the thumbnails, which could be a while, - // but we still need to detect if the process hangs. - // Making the assumption that as long as new jpegs are showing up, everything is good. + // Need to give ffmpeg enough time to make all the thumbnails, which could be a while, + // but we still need to detect if the process hangs. + // Making the assumption that as long as new jpegs are showing up, everything is good. - bool isResponsive = true; - int lastCount = 0; + bool isResponsive = true; + int lastCount = 0; - while (isResponsive) - { - if (process.WaitForExit(30000)) + while (isResponsive) { - ranToCompletion = true; - break; - } + if (process.WaitForExit(30000)) + { + ranToCompletion = true; + break; + } + + cancellationToken.ThrowIfCancellationRequested(); - cancellationToken.ThrowIfCancellationRequested(); + var jpegCount = Directory.GetFiles(targetDirectory) + .Count(i => string.Equals(Path.GetExtension(i), ".jpg", StringComparison.OrdinalIgnoreCase)); - var jpegCount = Directory.GetFiles(targetDirectory) - .Count(i => string.Equals(Path.GetExtension(i), ".jpg", StringComparison.OrdinalIgnoreCase)); + isResponsive = (jpegCount > lastCount); + lastCount = jpegCount; + } - isResponsive = (jpegCount > lastCount); - lastCount = jpegCount; + if (!ranToCompletion) + { + StopProcess(processWrapper, 1000, false); + } } - - if (!ranToCompletion) + finally { - StopProcess(processWrapper, 1000, false); + resourcePool.Release(); } - } - finally - { - resourcePool.Release(); - } - var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1; + var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1; - if (exitCode == -1) - { - var msg = string.Format("ffmpeg image extraction failed for {0}", inputArgument); + if (exitCode == -1) + { + var msg = string.Format("ffmpeg image extraction failed for {0}", inputArgument); - _logger.Error(msg); + _logger.Error(msg); - throw new ApplicationException(msg); + throw new ApplicationException(msg); + } } } @@ -781,7 +786,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - private class ProcessWrapper + private class ProcessWrapper : IDisposable { public readonly Process Process; public bool HasExited; @@ -810,6 +815,25 @@ namespace MediaBrowser.MediaEncoding.Encoder process.Dispose(); } + + private bool _disposed; + private readonly object _syncLock = new object(); + public void Dispose() + { + lock (_syncLock) + { + if (!_disposed) + { + if (Process != null) + { + Process.Exited -= Process_Exited; + Process.Dispose(); + } + } + + _disposed = true; + } + } } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index 26d4a7650..49eed9ee5 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -1,8 +1,6 @@ using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dlna; diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 8a3a2a3e4..2833e7167 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -158,7 +158,7 @@ namespace MediaBrowser.Model.Configuration /// different directories and files. /// </summary> /// <value>The file watcher delay.</value> - public int RealtimeMonitorDelay { get; set; } + public int RealtimeLibraryMonitorDelay { get; set; } /// <summary> /// Gets or sets a value indicating whether [enable dashboard response caching]. @@ -233,7 +233,7 @@ namespace MediaBrowser.Model.Configuration // 5 minutes MinResumeDurationSeconds = 300; - RealtimeMonitorDelay = 30; + RealtimeLibraryMonitorDelay = 40; EnableInternetProviders = true; FindInternetTrailers = true; @@ -261,8 +261,6 @@ namespace MediaBrowser.Model.Configuration "Chromecast", "iOS", "Unknown app", - "MediaPortal", - "Media Portal", "iPad", "iPhone", "Windows Phone" diff --git a/MediaBrowser.Model/Dlna/CodecProfile.cs b/MediaBrowser.Model/Dlna/CodecProfile.cs index c2d36dc79..7200f648c 100644 --- a/MediaBrowser.Model/Dlna/CodecProfile.cs +++ b/MediaBrowser.Model/Dlna/CodecProfile.cs @@ -14,6 +14,9 @@ namespace MediaBrowser.Model.Dlna [XmlAttribute("codec")] public string Codec { get; set; } + [XmlAttribute("container")] + public string Container { get; set; } + public CodecProfile() { Conditions = new ProfileCondition[] {}; @@ -29,8 +32,30 @@ namespace MediaBrowser.Model.Dlna return list; } - public bool ContainsCodec(string codec) + public List<string> GetContainers() + { + List<string> list = new List<string>(); + foreach (string i in (Container ?? string.Empty).Split(',')) + { + if (!string.IsNullOrEmpty(i)) list.Add(i); + } + return list; + } + + private bool ContainsContainer(string container) + { + List<string> containers = GetContainers(); + + return containers.Count == 0 || ListHelper.ContainsIgnoreCase(containers, container ?? string.Empty); + } + + public bool ContainsCodec(string codec, string container) { + if (!ContainsContainer(container)) + { + return false; + } + List<string> codecs = GetCodecs(); return codecs.Count == 0 || ListHelper.ContainsIgnoreCase(codecs, codec); diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index 3a798e3fe..62463d196 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -1,4 +1,5 @@ using MediaBrowser.Model.MediaInfo; +using System; using System.Collections.Generic; namespace MediaBrowser.Model.Dlna @@ -164,7 +165,7 @@ namespace MediaBrowser.Model.Dlna if (mediaProfile != null && !string.IsNullOrEmpty(mediaProfile.OrgPn)) { - orgPnValues.Add(mediaProfile.OrgPn); + orgPnValues.AddRange(mediaProfile.OrgPn.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)); } else { diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index a78724bf2..752b4d179 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -34,7 +34,6 @@ namespace MediaBrowser.Model.Dlna public string ModelNumber { get; set; } public string ModelUrl { get; set; } public string SerialNumber { get; set; } - public bool IgnoreTranscodeByteRangeRequests { get; set; } public bool EnableAlbumArtInDidl { get; set; } public bool EnableSingleAlbumArtLimit { get; set; } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 715752d05..8400b204f 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -131,7 +131,7 @@ namespace MediaBrowser.Model.Dlna List<ProfileCondition> conditions = new List<ProfileCondition>(); foreach (CodecProfile i in options.Profile.CodecProfiles) { - if (i.Type == CodecType.Audio && i.ContainsCodec(audioCodec)) + if (i.Type == CodecType.Audio && i.ContainsCodec(audioCodec, item.Container)) { foreach (ProfileCondition c in i.Conditions) { @@ -206,7 +206,7 @@ namespace MediaBrowser.Model.Dlna List<CodecProfile> audioCodecProfiles = new List<CodecProfile>(); foreach (CodecProfile i in options.Profile.CodecProfiles) { - if (i.Type == CodecType.Audio && i.ContainsCodec(transcodingProfile.AudioCodec)) + if (i.Type == CodecType.Audio && i.ContainsCodec(transcodingProfile.AudioCodec, transcodingProfile.Container)) { audioCodecProfiles.Add(i); } @@ -423,7 +423,7 @@ namespace MediaBrowser.Model.Dlna List<ProfileCondition> videoTranscodingConditions = new List<ProfileCondition>(); foreach (CodecProfile i in options.Profile.CodecProfiles) { - if (i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec)) + if (i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec, transcodingProfile.Container)) { foreach (ProfileCondition c in i.Conditions) { @@ -437,7 +437,7 @@ namespace MediaBrowser.Model.Dlna List<ProfileCondition> audioTranscodingConditions = new List<ProfileCondition>(); foreach (CodecProfile i in options.Profile.CodecProfiles) { - if (i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec)) + if (i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec, transcodingProfile.Container)) { foreach (ProfileCondition c in i.Conditions) { @@ -600,7 +600,7 @@ namespace MediaBrowser.Model.Dlna conditions = new List<ProfileCondition>(); foreach (CodecProfile i in profile.CodecProfiles) { - if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec)) + if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec, container)) { foreach (ProfileCondition c in i.Conditions) { @@ -635,7 +635,7 @@ namespace MediaBrowser.Model.Dlna conditions = new List<ProfileCondition>(); foreach (CodecProfile i in profile.CodecProfiles) { - if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec)) + if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec, container)) { foreach (ProfileCondition c in i.Conditions) { diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index fc47b0259..92fc1c2a8 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -38,13 +38,16 @@ namespace MediaBrowser.Providers.Manager { var hasChanges = false; - var images = providers.OfType<ILocalImageFileProvider>() - .SelectMany(i => i.GetImages(item, directoryService)) - .ToList(); - - if (MergeImages(item, images)) + if (!(item is Photo)) { - hasChanges = true; + var images = providers.OfType<ILocalImageFileProvider>() + .SelectMany(i => i.GetImages(item, directoryService)) + .ToList(); + + if (MergeImages(item, images)) + { + hasChanges = true; + } } return hasChanges; @@ -419,19 +422,14 @@ namespace MediaBrowser.Providers.Manager var changed = false; var newImages = images.Where(i => i.Type == type).ToList(); - if (newImages.Count > 0) - { - var newImageFileInfos = images.Where(i => i.Type == type) + + var newImageFileInfos = newImages .Select(i => i.FileInfo) .ToList(); - if (newImageFileInfos.Count > 0) - { - if (item.AddImages(type, newImageFileInfos)) - { - changed = true; - } - } + if (item.AddImages(type, newImageFileInfos)) + { + changed = true; } return changed; diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index 99be102f8..bd83862a8 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -93,7 +93,7 @@ namespace MediaBrowser.Providers.MediaInfo private string GetAudioImagePath(Audio item) { - var album = item.Parent as MusicAlbum; + var album = item.AlbumEntity; var filename = item.Album ?? string.Empty; filename += string.Join(",", item.Artists.ToArray()); diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs index cbd3f0af0..68601b6b2 100644 --- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; using MediaBrowser.Model.Providers; using System; using System.Collections.Generic; @@ -29,12 +30,14 @@ namespace MediaBrowser.Providers.TV private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _config; private readonly IHttpClient _httpClient; + private readonly ILogger _logger; - public TvdbEpisodeProvider(IFileSystem fileSystem, IServerConfigurationManager config, IHttpClient httpClient) + public TvdbEpisodeProvider(IFileSystem fileSystem, IServerConfigurationManager config, IHttpClient httpClient, ILogger logger) { _fileSystem = fileSystem; _config = config; _httpClient = httpClient; + _logger = logger; Current = this; } @@ -100,7 +103,8 @@ namespace MediaBrowser.Providers.TV try { - result.Item = FetchEpisodeData(searchInfo, identity, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken); + result.Item = FetchEpisodeData(searchInfo, identity, seriesDataPath, searchInfo.SeriesProviderIds, + cancellationToken); result.HasMetadata = result.Item != null; } catch (FileNotFoundException) @@ -112,6 +116,10 @@ namespace MediaBrowser.Providers.TV // Don't fail the provider because this will just keep on going and going. } } + else + { + _logger.Debug("No series identity found for {0}", searchInfo.Name); + } return result; } @@ -265,7 +273,6 @@ namespace MediaBrowser.Providers.TV FetchMainEpisodeInfo(episode, file, cancellationToken); usingAbsoluteData = true; - success = true; } var end = identity.IndexNumberEnd ?? episodeNumber; @@ -298,7 +305,7 @@ namespace MediaBrowser.Providers.TV episodeNumber++; } - return success ? episode : null; + return episode; } private readonly CultureInfo _usCulture = new CultureInfo("en-US"); diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 402bd4d98..1b55f47d5 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1193,7 +1193,7 @@ namespace MediaBrowser.Server.Implementations.Dto { dto.Album = audio.Album; - var albumParent = audio.FindParent<MusicAlbum>(); + var albumParent = audio.AlbumEntity; if (albumParent != null) { @@ -1208,15 +1208,6 @@ namespace MediaBrowser.Server.Implementations.Dto //} } - var album = item as MusicAlbum; - - if (album != null) - { - dto.SoundtrackIds = album.SoundtrackIds - .Select(i => i.ToString("N")) - .ToArray(); - } - var hasArtist = item as IHasArtist; if (hasArtist != null) { diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index d501d1210..2d4770fac 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -84,7 +84,7 @@ namespace MediaBrowser.Server.Implementations.IO // This is an arbitraty amount of time, but delay it because file system writes often trigger events after RemoveTempIgnore has been called. // Seeing long delays in some situations, especially over the network. // Seeing delays up to 40 seconds, but not going to ignore changes for that long. - await Task.Delay(1500).ConfigureAwait(false); + await Task.Delay(5000).ConfigureAwait(false); string val; _tempIgnoredPaths.TryRemove(path, out val); @@ -437,11 +437,11 @@ namespace MediaBrowser.Server.Implementations.IO { if (_updateTimer == null) { - _updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeMonitorDelay), TimeSpan.FromMilliseconds(-1)); + _updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeLibraryMonitorDelay), TimeSpan.FromMilliseconds(-1)); } else { - _updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeMonitorDelay), TimeSpan.FromMilliseconds(-1)); + _updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeLibraryMonitorDelay), TimeSpan.FromMilliseconds(-1)); } } } @@ -560,7 +560,7 @@ namespace MediaBrowser.Server.Implementations.IO /// <returns>Task.</returns> private async Task ProcessPathChanges(List<string> paths) { - var itemsToRefresh = paths.Select(Path.GetDirectoryName) + var itemsToRefresh = paths .Select(GetAffectedBaseItem) .Where(item => item != null) .Distinct() diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 02e1795f3..5012f2479 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -281,10 +281,10 @@ namespace MediaBrowser.Server.Implementations.Library if (newValue >= maxCount) { - _logger.Debug("Disabling user {0} due to {1} unsuccessful login attempts.", user.Name, newValue.ToString(CultureInfo.InvariantCulture)); - user.Policy.IsDisabled = true; + //_logger.Debug("Disabling user {0} due to {1} unsuccessful login attempts.", user.Name, newValue.ToString(CultureInfo.InvariantCulture)); + //user.Policy.IsDisabled = true; - fireLockout = true; + //fireLockout = true; } await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false); diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json index ea141645c..2dff86fce 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json @@ -387,7 +387,6 @@ "ButtonSignOut": "Sign Out", "ButtonMyProfile": "My Profile", "ButtonMyPreferences": "My Preferences", - "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.", "LabelInstallingPackage": "Installing {0}", "LabelPackageInstallCompleted": "{0} installation completed.", "LabelPackageInstallFailed": "{0} installation failed.", diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index c15e520e2..ad6b159e7 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -440,7 +440,7 @@ "HeaderVideo": "Video", "HeaderRuntime": "Runtime", "HeaderCommunityRating": "Community rating", - "HeaderPasswordReset": "Password Reset", + "HeaderPasswordReset": "Password Reset", "HeaderParentalRating": "Parental rating", "HeaderReleaseDate": "Release date", "HeaderDateAdded": "Date added", @@ -766,5 +766,10 @@ "SyncJobItemStatusRemovedFromDevice": "Removed from device", "SyncJobItemStatusCancelled": "Cancelled", "LabelProfile": "Profile:", - "LabelBitrateMbps": "Bitrate (Mbps):" + "LabelBitrateMbps": "Bitrate (Mbps):", + "EmbyIntroDownloadMessage": "To download and install Emby Server visit {0}.", + "ButtonNewServer": "New Server", + "ButtonSignInWithConnect": "Sign in with Emby Connect", + "HeaderNewServer": "New Server", + "MyDevice": "My Device" } diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index caff2426a..368d11646 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -882,7 +882,7 @@ "MessageNoSubtitleSearchResultsFound": "No search results founds.", "TabDisplay": "Display", "TabLanguages": "Languages", - "TabWebClient": "Web Client", + "TabAppSettings": "App Settings", "LabelEnableThemeSongs": "Enable theme songs", "LabelEnableBackdrops": "Enable backdrops", "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.", @@ -1436,10 +1436,17 @@ "LabelSelectViewStyles": "Enable enhanced presentations for:", "LabelSelectViewStylesHelp": "If enabled, views will be built with metadata to offer categories such as Suggestions, Latest, Genres, and more. If disabled, they'll be displayed with simple folders.", "TabPhotos": "Photos", - "TabVideos": "Videos", - "OptionReportList": "List View", - "OptionReportStatistics": "Statistics", - "OptionReportGrouping": "Grouping", - "OptionReportExport": "Report Export", - "OptionReportColumns": "Report Columns" + "TabVideos": "Videos", + "HeaderWelcomeToEmby": "Welcome to Emby", + "EmbyIntroMessage": "With Emby you can easily stream videos, music and photos to smart phones, tablets and other devices from your Emby Server.", + "ButtonSkip": "Skip", + "TextConnectToServerManually": "Connect to server manually", + "ButtonSignInWithConnect": "Sign in with Emby Connect", + "ButtonConnect": "Connect", + "LabelServerHost": "Host:", + "LabelServerHostHelp": "192.168.1.100 or https://myserver.com", + "LabelServerPort": "Port:", + "HeaderNewServer": "New Server", + "ButtonChangeServer": "Change Server", + "HeaderConnectToServer": "Connect to Server" } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 9e7810c76..572aa3a12 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -48,9 +48,8 @@ <Reference Include="Interfaces.IO"> <HintPath>..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll</HintPath> </Reference> - <Reference Include="MediaBrowser.Naming, Version=1.0.5509.27636, Culture=neutral, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\MediaBrowser.Naming.1.0.0.34\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath> + <Reference Include="MediaBrowser.Naming"> + <HintPath>..\packages\MediaBrowser.Naming.1.0.0.35\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath> </Reference> <Reference Include="Mono.Nat, Version=1.2.24.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> @@ -226,6 +225,7 @@ <Compile Include="Localization\LocalizationManager.cs" /> <Compile Include="Logging\PatternsLogger.cs" /> <Compile Include="MediaEncoder\EncodingManager.cs" /> + <Compile Include="Persistence\BaseSqliteRepository.cs" /> <Compile Include="Sorting\StartDateComparer.cs" /> <Compile Include="Sync\SyncHelper.cs" /> <Compile Include="Sync\SyncJobOptions.cs" /> @@ -242,7 +242,6 @@ <Compile Include="Persistence\SqliteMediaStreamsRepository.cs" /> <Compile Include="Notifications\SqliteNotificationsRepository.cs" /> <Compile Include="Persistence\SqliteProviderInfoRepository.cs" /> - <Compile Include="Persistence\SqliteShrinkMemoryTimer.cs" /> <Compile Include="Persistence\TypeMapper.cs" /> <Compile Include="Photos\BaseDynamicImageProvider.cs" /> <Compile Include="Playlists\ManualPlaylistsFolder.cs" /> diff --git a/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs new file mode 100644 index 000000000..15d76fb60 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Persistence/BaseSqliteRepository.cs @@ -0,0 +1,56 @@ +using MediaBrowser.Model.Logging; +using System; +using System.Threading; + +namespace MediaBrowser.Server.Implementations.Persistence +{ + public abstract class BaseSqliteRepository : IDisposable + { + protected readonly SemaphoreSlim WriteLock = new SemaphoreSlim(1, 1); + protected ILogger Logger; + + protected BaseSqliteRepository(ILogManager logManager) + { + Logger = logManager.GetLogger(GetType().Name); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private readonly object _disposeLock = new object(); + + /// <summary> + /// Releases unmanaged and - optionally - managed resources. + /// </summary> + /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> + protected virtual void Dispose(bool dispose) + { + if (dispose) + { + try + { + lock (_disposeLock) + { + WriteLock.Wait(); + + CloseConnection(); + } + } + catch (Exception ex) + { + Logger.ErrorException("Error disposing database", ex); + } + } + } + + protected virtual void DisposeInternal() + { + + } + + protected abstract void CloseConnection(); + } +} diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteChapterRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteChapterRepository.cs index 77b993205..075ef4239 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteChapterRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteChapterRepository.cs @@ -32,8 +32,6 @@ namespace MediaBrowser.Server.Implementations.Persistence _logger = logManager.GetLogger(GetType().Name); } - private SqliteShrinkMemoryTimer _shrinkMemoryTimer; - /// <summary> /// Opens the connection to the database /// </summary> @@ -54,8 +52,6 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.RunQueries(queries, _logger); PrepareStatements(); - - _shrinkMemoryTimer = new SqliteShrinkMemoryTimer(_connection, _writeLock, _logger); } /// <summary> @@ -286,12 +282,6 @@ namespace MediaBrowser.Server.Implementations.Persistence { lock (_disposeLock) { - if (_shrinkMemoryTimer != null) - { - _shrinkMemoryTimer.Dispose(); - _shrinkMemoryTimer = null; - } - if (_connection != null) { if (_connection.IsOpen()) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs index 3dfa74727..c9ab43e63 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs @@ -16,11 +16,15 @@ namespace MediaBrowser.Server.Implementations.Persistence /// <summary> /// Class SQLiteDisplayPreferencesRepository /// </summary> - public class SqliteDisplayPreferencesRepository : IDisplayPreferencesRepository + public class SqliteDisplayPreferencesRepository : BaseSqliteRepository, IDisplayPreferencesRepository { private IDbConnection _connection; - private readonly ILogger _logger; + public SqliteDisplayPreferencesRepository(ILogManager logManager, IJsonSerializer jsonSerializer, IApplicationPaths appPaths) : base(logManager) + { + _jsonSerializer = jsonSerializer; + _appPaths = appPaths; + } /// <summary> /// Gets the name of the repository @@ -44,36 +48,6 @@ namespace MediaBrowser.Server.Implementations.Persistence /// </summary> private readonly IApplicationPaths _appPaths; - private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1); - - /// <summary> - /// Initializes a new instance of the <see cref="SqliteDisplayPreferencesRepository" /> class. - /// </summary> - /// <param name="appPaths">The app paths.</param> - /// <param name="jsonSerializer">The json serializer.</param> - /// <param name="logManager">The log manager.</param> - /// <exception cref="System.ArgumentNullException"> - /// jsonSerializer - /// or - /// appPaths - /// </exception> - public SqliteDisplayPreferencesRepository(IApplicationPaths appPaths, IJsonSerializer jsonSerializer, ILogManager logManager) - { - if (jsonSerializer == null) - { - throw new ArgumentNullException("jsonSerializer"); - } - if (appPaths == null) - { - throw new ArgumentNullException("appPaths"); - } - - _jsonSerializer = jsonSerializer; - _appPaths = appPaths; - - _logger = logManager.GetLogger(GetType().Name); - } - /// <summary> /// Opens the connection to the database /// </summary> @@ -82,7 +56,7 @@ namespace MediaBrowser.Server.Implementations.Persistence { var dbFile = Path.Combine(_appPaths.DataPath, "displaypreferences.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); + _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); string[] queries = { @@ -95,7 +69,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "pragma shrink_memory" }; - _connection.RunQueries(queries, _logger); + _connection.RunQueries(queries, Logger); } /// <summary> @@ -122,7 +96,7 @@ namespace MediaBrowser.Server.Implementations.Persistence var serialized = _jsonSerializer.SerializeToBytes(displayPreferences); - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); IDbTransaction transaction = null; @@ -157,7 +131,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } catch (Exception e) { - _logger.ErrorException("Failed to save display preferences:", e); + Logger.ErrorException("Failed to save display preferences:", e); if (transaction != null) { @@ -173,7 +147,7 @@ namespace MediaBrowser.Server.Implementations.Persistence transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } @@ -194,7 +168,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cancellationToken.ThrowIfCancellationRequested(); - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); IDbTransaction transaction = null; @@ -235,7 +209,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } catch (Exception e) { - _logger.ErrorException("Failed to save display preferences:", e); + Logger.ErrorException("Failed to save display preferences:", e); if (transaction != null) { @@ -251,7 +225,7 @@ namespace MediaBrowser.Server.Implementations.Persistence transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } @@ -322,45 +296,17 @@ namespace MediaBrowser.Server.Implementations.Persistence } } - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() + protected override void CloseConnection() { - Dispose(true); - GC.SuppressFinalize(this); - } - - private readonly object _disposeLock = new object(); - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) + if (_connection != null) { - try + if (_connection.IsOpen()) { - lock (_disposeLock) - { - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } - - _connection.Dispose(); - _connection = null; - } - } - } - catch (Exception ex) - { - _logger.ErrorException("Error disposing database", ex); + _connection.Close(); } + + _connection.Dispose(); + _connection = null; } } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs index 5d5855bf8..2d5aad04d 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs @@ -14,14 +14,10 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Persistence { - public class SqliteFileOrganizationRepository : IFileOrganizationRepository, IDisposable + public class SqliteFileOrganizationRepository : BaseSqliteRepository, IFileOrganizationRepository, IDisposable { private IDbConnection _connection; - private readonly ILogger _logger; - - private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1); - private SqliteShrinkMemoryTimer _shrinkMemoryTimer; private readonly IServerApplicationPaths _appPaths; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); @@ -30,11 +26,9 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _deleteResultCommand; private IDbCommand _deleteAllCommand; - public SqliteFileOrganizationRepository(ILogManager logManager, IServerApplicationPaths appPaths) + public SqliteFileOrganizationRepository(ILogManager logManager, IServerApplicationPaths appPaths) : base(logManager) { _appPaths = appPaths; - - _logger = logManager.GetLogger(GetType().Name); } /// <summary> @@ -45,7 +39,7 @@ namespace MediaBrowser.Server.Implementations.Persistence { var dbFile = Path.Combine(_appPaths.DataPath, "fileorganization.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); + _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); string[] queries = { @@ -58,11 +52,9 @@ namespace MediaBrowser.Server.Implementations.Persistence "pragma shrink_memory" }; - _connection.RunQueries(queries, _logger); + _connection.RunQueries(queries, Logger); PrepareStatements(); - - _shrinkMemoryTimer = new SqliteShrinkMemoryTimer(_connection, _writeLock, _logger); } private void PrepareStatements() @@ -103,7 +95,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cancellationToken.ThrowIfCancellationRequested(); - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); IDbTransaction transaction = null; @@ -145,7 +137,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } catch (Exception e) { - _logger.ErrorException("Failed to save FileOrganizationResult:", e); + Logger.ErrorException("Failed to save FileOrganizationResult:", e); if (transaction != null) { @@ -161,7 +153,7 @@ namespace MediaBrowser.Server.Implementations.Persistence transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } @@ -172,7 +164,7 @@ namespace MediaBrowser.Server.Implementations.Persistence throw new ArgumentNullException("id"); } - await _writeLock.WaitAsync().ConfigureAwait(false); + await WriteLock.WaitAsync().ConfigureAwait(false); IDbTransaction transaction = null; @@ -199,7 +191,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } catch (Exception e) { - _logger.ErrorException("Failed to delete FileOrganizationResult:", e); + Logger.ErrorException("Failed to delete FileOrganizationResult:", e); if (transaction != null) { @@ -215,13 +207,13 @@ namespace MediaBrowser.Server.Implementations.Persistence transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } public async Task DeleteAll() { - await _writeLock.WaitAsync().ConfigureAwait(false); + await WriteLock.WaitAsync().ConfigureAwait(false); IDbTransaction transaction = null; @@ -246,7 +238,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } catch (Exception e) { - _logger.ErrorException("Failed to delete results", e); + Logger.ErrorException("Failed to delete results", e); if (transaction != null) { @@ -262,7 +254,7 @@ namespace MediaBrowser.Server.Implementations.Persistence transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } @@ -423,51 +415,17 @@ namespace MediaBrowser.Server.Implementations.Persistence return result; } - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - private readonly object _disposeLock = new object(); - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) + protected override void CloseConnection() { - if (dispose) + if (_connection != null) { - try - { - lock (_disposeLock) - { - if (_shrinkMemoryTimer != null) - { - _shrinkMemoryTimer.Dispose(); - _shrinkMemoryTimer = null; - } - - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } - - _connection.Dispose(); - _connection = null; - } - } - } - catch (Exception ex) + if (_connection.IsOpen()) { - _logger.ErrorException("Error disposing database", ex); + _connection.Close(); } + + _connection.Dispose(); + _connection = null; } } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index e063d44dc..c5a9db87b 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -130,12 +130,8 @@ namespace MediaBrowser.Server.Implementations.Persistence _mediaStreamsRepository.Initialize(); _chapterRepository.Initialize(); - - _shrinkMemoryTimer = new SqliteShrinkMemoryTimer(_connection, _writeLock, _logger); } - private SqliteShrinkMemoryTimer _shrinkMemoryTimer; - /// <summary> /// The _write lock /// </summary> @@ -430,12 +426,6 @@ namespace MediaBrowser.Server.Implementations.Persistence { lock (_disposeLock) { - if (_shrinkMemoryTimer != null) - { - _shrinkMemoryTimer.Dispose(); - _shrinkMemoryTimer = null; - } - _writeLock.Wait(); if (_connection != null) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs index 293da3f0f..994397624 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs @@ -1,5 +1,4 @@ -using System.Globalization; -using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System; @@ -21,8 +20,6 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _deleteStreamsCommand; private IDbCommand _saveStreamCommand; - private SqliteShrinkMemoryTimer _shrinkMemoryTimer; - public SqliteMediaStreamsRepository(IDbConnection connection, ILogManager logManager) { _connection = connection; @@ -64,8 +61,6 @@ namespace MediaBrowser.Server.Implementations.Persistence AddRefFramesCommand(); PrepareStatements(); - - _shrinkMemoryTimer = new SqliteShrinkMemoryTimer(_connection, _writeLock, _logger); } private void AddPixelFormatColumnCommand() @@ -563,12 +558,6 @@ namespace MediaBrowser.Server.Implementations.Persistence { lock (_disposeLock) { - if (_shrinkMemoryTimer != null) - { - _shrinkMemoryTimer.Dispose(); - _shrinkMemoryTimer = null; - } - if (_connection != null) { if (_connection.IsOpen()) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs index 743d8fed6..bce33e834 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs @@ -1,33 +1,28 @@ -using System.Text; -using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Logging; using System; using System.Data; using System.IO; using System.Linq; +using System.Text; using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Persistence { - public class SqliteProviderInfoRepository : IProviderRepository + public class SqliteProviderInfoRepository : BaseSqliteRepository, IProviderRepository { private IDbConnection _connection; - private readonly ILogger _logger; - private IDbCommand _saveStatusCommand; private readonly IApplicationPaths _appPaths; - public SqliteProviderInfoRepository(IApplicationPaths appPaths, ILogManager logManager) + public SqliteProviderInfoRepository(ILogManager logManager, IApplicationPaths appPaths) : base(logManager) { _appPaths = appPaths; - _logger = logManager.GetLogger(GetType().Name); } - private SqliteShrinkMemoryTimer _shrinkMemoryTimer; - /// <summary> /// Gets the name of the repository /// </summary> @@ -48,7 +43,7 @@ namespace MediaBrowser.Server.Implementations.Persistence { var dbFile = Path.Combine(_appPaths.DataPath, "refreshinfo.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); + _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); string[] queries = { @@ -61,13 +56,11 @@ namespace MediaBrowser.Server.Implementations.Persistence "pragma shrink_memory" }; - _connection.RunQueries(queries, _logger); + _connection.RunQueries(queries, Logger); AddItemDateModifiedCommand(); PrepareStatements(); - - _shrinkMemoryTimer = new SqliteShrinkMemoryTimer(_connection, _writeLock, _logger); } private static readonly string[] StatusColumns = @@ -113,15 +106,10 @@ namespace MediaBrowser.Server.Implementations.Persistence builder.AppendLine("alter table MetadataStatus"); builder.AppendLine("add column ItemDateModified DateTime NULL"); - _connection.RunQueries(new[] { builder.ToString() }, _logger); + _connection.RunQueries(new[] { builder.ToString() }, Logger); } /// <summary> - /// The _write lock - /// </summary> - private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1); - - /// <summary> /// Prepares the statements. /// </summary> private void PrepareStatements() @@ -227,7 +215,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cancellationToken.ThrowIfCancellationRequested(); - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); IDbTransaction transaction = null; @@ -264,7 +252,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } catch (Exception e) { - _logger.ErrorException("Failed to save provider info:", e); + Logger.ErrorException("Failed to save provider info:", e); if (transaction != null) { @@ -280,55 +268,21 @@ namespace MediaBrowser.Server.Implementations.Persistence transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - private readonly object _disposeLock = new object(); - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) + protected override void CloseConnection() { - if (dispose) + if (_connection != null) { - try + if (_connection.IsOpen()) { - lock (_disposeLock) - { - if (_shrinkMemoryTimer != null) - { - _shrinkMemoryTimer.Dispose(); - _shrinkMemoryTimer = null; - } - - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } - - _connection.Dispose(); - _connection = null; - } - } - } - catch (Exception ex) - { - _logger.ErrorException("Error disposing database", ex); + _connection.Close(); } + + _connection.Dispose(); + _connection = null; } } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteShrinkMemoryTimer.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteShrinkMemoryTimer.cs deleted file mode 100644 index b5a0c10b1..000000000 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteShrinkMemoryTimer.cs +++ /dev/null @@ -1,84 +0,0 @@ -using MediaBrowser.Model.Logging; -using System; -using System.Data; -using System.Threading; - -namespace MediaBrowser.Server.Implementations.Persistence -{ - class SqliteShrinkMemoryTimer : IDisposable - { - private Timer _shrinkMemoryTimer; - - private readonly SemaphoreSlim _writeLock; - private readonly ILogger _logger; - private readonly IDbConnection _connection; - - public SqliteShrinkMemoryTimer(IDbConnection connection, SemaphoreSlim writeLock, ILogger logger) - { - _connection = connection; - _writeLock = writeLock; - _logger = logger; - - _shrinkMemoryTimer = new Timer(TimerCallback, null, TimeSpan.FromMinutes(30), TimeSpan.FromMinutes(10)); - } - - private async void TimerCallback(object state) - { - await _writeLock.WaitAsync(CancellationToken.None).ConfigureAwait(false); - - IDbTransaction transaction = null; - - try - { - transaction = _connection.BeginTransaction(); - - using (var cmd = _connection.CreateCommand()) - { - cmd.Transaction = transaction; - cmd.CommandText = "pragma shrink_memory"; - cmd.ExecuteNonQuery(); - } - - transaction.Commit(); - } - catch (OperationCanceledException) - { - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - catch (Exception e) - { - _logger.ErrorException("Failed to save items:", e); - - if (transaction != null) - { - transaction.Rollback(); - } - - throw; - } - finally - { - if (transaction != null) - { - transaction.Dispose(); - } - - _writeLock.Release(); - } - } - - public void Dispose() - { - if (_shrinkMemoryTimer != null) - { - _shrinkMemoryTimer.Dispose(); - _shrinkMemoryTimer = null; - } - } - } -} diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs index 0f0488168..8b86d19a2 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs @@ -11,13 +11,15 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Persistence { - public class SqliteUserDataRepository : IUserDataRepository + public class SqliteUserDataRepository : BaseSqliteRepository, IUserDataRepository { - private readonly ILogger _logger; - - private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1); - private IDbConnection _connection; + private readonly IApplicationPaths _appPaths; + + public SqliteUserDataRepository(ILogManager logManager, IApplicationPaths appPaths) : base(logManager) + { + _appPaths = appPaths; + } /// <summary> /// Gets the name of the repository @@ -32,32 +34,6 @@ namespace MediaBrowser.Server.Implementations.Persistence } /// <summary> - /// The _app paths - /// </summary> - private readonly IApplicationPaths _appPaths; - - /// <summary> - /// Initializes a new instance of the <see cref="SqliteUserDataRepository" /> class. - /// </summary> - /// <param name="appPaths">The app paths.</param> - /// <param name="logManager">The log manager.</param> - /// <exception cref="System.ArgumentNullException">jsonSerializer - /// or - /// appPaths</exception> - public SqliteUserDataRepository(IApplicationPaths appPaths, ILogManager logManager) - { - if (appPaths == null) - { - throw new ArgumentNullException("appPaths"); - } - - _appPaths = appPaths; - _logger = logManager.GetLogger(GetType().Name); - } - - private SqliteShrinkMemoryTimer _shrinkMemoryTimer; - - /// <summary> /// Opens the connection to the database /// </summary> /// <returns>Task.</returns> @@ -65,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Persistence { var dbFile = Path.Combine(_appPaths.DataPath, "userdata_v2.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); + _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); string[] queries = { @@ -79,9 +55,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "pragma shrink_memory" }; - _connection.RunQueries(queries, _logger); - - _shrinkMemoryTimer = new SqliteShrinkMemoryTimer(_connection, _writeLock, _logger); + _connection.RunQueries(queries, Logger); } /// <summary> @@ -143,7 +117,7 @@ namespace MediaBrowser.Server.Implementations.Persistence { cancellationToken.ThrowIfCancellationRequested(); - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); IDbTransaction transaction = null; @@ -182,7 +156,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } catch (Exception e) { - _logger.ErrorException("Failed to save user data:", e); + Logger.ErrorException("Failed to save user data:", e); if (transaction != null) { @@ -198,7 +172,7 @@ namespace MediaBrowser.Server.Implementations.Persistence transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } @@ -213,7 +187,7 @@ namespace MediaBrowser.Server.Implementations.Persistence { cancellationToken.ThrowIfCancellationRequested(); - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); IDbTransaction transaction = null; @@ -257,7 +231,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } catch (Exception e) { - _logger.ErrorException("Failed to save user data:", e); + Logger.ErrorException("Failed to save user data:", e); if (transaction != null) { @@ -273,7 +247,7 @@ namespace MediaBrowser.Server.Implementations.Persistence transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } @@ -379,51 +353,17 @@ namespace MediaBrowser.Server.Implementations.Persistence return userData; } - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - private readonly object _disposeLock = new object(); - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) + protected override void CloseConnection() { - if (dispose) + if (_connection != null) { - try + if (_connection.IsOpen()) { - lock (_disposeLock) - { - if (_shrinkMemoryTimer != null) - { - _shrinkMemoryTimer.Dispose(); - _shrinkMemoryTimer = null; - } - - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } - - _connection.Dispose(); - _connection = null; - } - } - } - catch (Exception ex) - { - _logger.ErrorException("Error disposing database", ex); + _connection.Close(); } + + _connection.Dispose(); + _connection = null; } } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs index d97a55ae6..ad784ae5d 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs @@ -15,14 +15,17 @@ namespace MediaBrowser.Server.Implementations.Persistence /// <summary> /// Class SQLiteUserRepository /// </summary> - public class SqliteUserRepository : IUserRepository + public class SqliteUserRepository : BaseSqliteRepository, IUserRepository { - private readonly ILogger _logger; - - private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1); - private IDbConnection _connection; private readonly IServerApplicationPaths _appPaths; + private readonly IJsonSerializer _jsonSerializer; + + public SqliteUserRepository(ILogManager logManager, IServerApplicationPaths appPaths, IJsonSerializer jsonSerializer) : base(logManager) + { + _appPaths = appPaths; + _jsonSerializer = jsonSerializer; + } /// <summary> /// Gets the name of the repository @@ -37,32 +40,6 @@ namespace MediaBrowser.Server.Implementations.Persistence } /// <summary> - /// Gets the json serializer. - /// </summary> - /// <value>The json serializer.</value> - private readonly IJsonSerializer _jsonSerializer; - - /// <summary> - /// Initializes a new instance of the <see cref="SqliteUserRepository" /> class. - /// </summary> - /// <param name="jsonSerializer">The json serializer.</param> - /// <param name="logManager">The log manager.</param> - /// <param name="appPaths">The app paths.</param> - /// <exception cref="System.ArgumentNullException">appPaths</exception> - public SqliteUserRepository(IJsonSerializer jsonSerializer, ILogManager logManager, IServerApplicationPaths appPaths) - { - if (jsonSerializer == null) - { - throw new ArgumentNullException("jsonSerializer"); - } - - _jsonSerializer = jsonSerializer; - _appPaths = appPaths; - - _logger = logManager.GetLogger(GetType().Name); - } - - /// <summary> /// Opens the connection to the database /// </summary> /// <returns>Task.</returns> @@ -70,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Persistence { var dbFile = Path.Combine(_appPaths.DataPath, "users.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false); + _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); string[] queries = { @@ -84,7 +61,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "pragma shrink_memory" }; - _connection.RunQueries(queries, _logger); + _connection.RunQueries(queries, Logger); } /// <summary> @@ -107,8 +84,8 @@ namespace MediaBrowser.Server.Implementations.Persistence cancellationToken.ThrowIfCancellationRequested(); - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); - + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); + IDbTransaction transaction = null; try @@ -139,7 +116,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } catch (Exception e) { - _logger.ErrorException("Failed to save user:", e); + Logger.ErrorException("Failed to save user:", e); if (transaction != null) { @@ -155,7 +132,7 @@ namespace MediaBrowser.Server.Implementations.Persistence transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } @@ -199,7 +176,7 @@ namespace MediaBrowser.Server.Implementations.Persistence cancellationToken.ThrowIfCancellationRequested(); - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); IDbTransaction transaction = null; @@ -231,7 +208,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } catch (Exception e) { - _logger.ErrorException("Failed to delete user:", e); + Logger.ErrorException("Failed to delete user:", e); if (transaction != null) { @@ -247,49 +224,21 @@ namespace MediaBrowser.Server.Implementations.Persistence transaction.Dispose(); } - _writeLock.Release(); + WriteLock.Release(); } } - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - private readonly object _disposeLock = new object(); - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) + protected override void CloseConnection() { - if (dispose) + if (_connection != null) { - try - { - lock (_disposeLock) - { - if (_connection != null) - { - if (_connection.IsOpen()) - { - _connection.Close(); - } - - _connection.Dispose(); - _connection = null; - } - } - } - catch (Exception ex) + if (_connection.IsOpen()) { - _logger.ErrorException("Error disposing database", ex); + _connection.Close(); } + + _connection.Dispose(); + _connection = null; } } } diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index be71a6408..bd22a8a70 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -191,6 +191,8 @@ namespace MediaBrowser.Server.Implementations.Photos throw new ArgumentException("Unexpected image type"); } + private const int MaxImageAgeDays = 7; + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) { if (!Supports(item)) @@ -198,6 +200,11 @@ namespace MediaBrowser.Server.Implementations.Photos return false; } + if (item is UserView) + { + return HasChanged(item, ImageType.Primary) || HasChanged(item, ImageType.Thumb); + } + var items = GetItemsWithImages(item).Result; var cacheKey = GetConfigurationCacheKey(items, item.Name); @@ -216,7 +223,6 @@ namespace MediaBrowser.Server.Implementations.Photos } var currentPathCacheKey = (Path.GetFileNameWithoutExtension(image.Path) ?? string.Empty).Split('_').LastOrDefault(); - if (string.Equals(cacheKey, currentPathCacheKey, StringComparison.OrdinalIgnoreCase)) { return false; @@ -226,6 +232,27 @@ namespace MediaBrowser.Server.Implementations.Photos return true; } + protected bool HasChanged(IHasImages item, ImageType type) + { + var image = item.GetImageInfo(type, 0); + + if (image != null) + { + if (!FileSystem.ContainsSubPath(item.GetInternalMetadataPath(), image.Path)) + { + return false; + } + + var age = DateTime.UtcNow - image.DateModified; + if (age.TotalDays <= MaxImageAgeDays) + { + return false; + } + } + + return true; + } + protected List<BaseItem> GetFinalItems(List<BaseItem> items) { return GetFinalItems(items, 4); @@ -234,7 +261,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected virtual List<BaseItem> GetFinalItems(List<BaseItem> items, int limit) { // Rotate the images once every x days - var random = DateTime.Now.DayOfYear % 7; + var random = DateTime.Now.DayOfYear % MaxImageAgeDays; return items .OrderBy(i => (random + "" + items.IndexOf(i)).GetMD5()) diff --git a/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs index 8c142b646..f04c0bf77 100644 --- a/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs @@ -11,7 +11,8 @@ namespace MediaBrowser.Server.Implementations.Photos { //public class PhotoAlbumImageProvider : BaseDynamicImageProvider<PhotoAlbum> //{ - // public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor) + // public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) + // : base(fileSystem, providerManager, applicationPaths, imageProcessor) // { // } diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 112778ec8..757e6938a 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -1550,7 +1550,7 @@ namespace MediaBrowser.Server.Implementations.Session if (info.PrimaryImageTag == null) { - var album = audio.Parents.OfType<MusicAlbum>().FirstOrDefault(); + var album = audio.AlbumEntity; if (album != null && album.HasImage(ImageType.Primary)) { diff --git a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs index 93a9bc8f6..930762696 100644 --- a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs @@ -21,13 +21,11 @@ namespace MediaBrowser.Server.Implementations.UserViews public class DynamicImageProvider : BaseDynamicImageProvider<UserView> { private readonly IUserManager _userManager; - private readonly ILibraryManager _libraryManager; - public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, IUserManager userManager, ILibraryManager libraryManager) + public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, IUserManager userManager) : base(fileSystem, providerManager, applicationPaths, imageProcessor) { _userManager = userManager; - _libraryManager = libraryManager; } public override IEnumerable<ImageType> GetSupportedImages(IHasImages item) @@ -122,7 +120,7 @@ namespace MediaBrowser.Server.Implementations.UserViews var audio = i as Audio; if (audio != null) { - var album = audio.FindParent<MusicAlbum>(); + var album = audio.AlbumEntity; if (album != null && album.HasImage(ImageType.Primary)) { return album; diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 7fb369106..0b81c1866 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Interfaces.IO" version="1.0.0.5" targetFramework="net45" />
- <package id="MediaBrowser.Naming" version="1.0.0.34" targetFramework="net45" />
+ <package id="MediaBrowser.Naming" version="1.0.0.35" targetFramework="net45" />
<package id="Mono.Nat" version="1.2.24.0" targetFramework="net45" />
<package id="morelinq" version="1.1.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
- <package id="SocketHttpListener" version="1.0.0.5" targetFramework="net45" />
+ <package id="SocketHttpListener" version="1.0.0.6" targetFramework="net45" />
</packages>
\ No newline at end of file diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index c9a2d3f22..4c25c968c 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -392,13 +392,13 @@ namespace MediaBrowser.Server.Startup.Common UserRepository = await GetUserRepository().ConfigureAwait(false); RegisterSingleInstance(UserRepository); - DisplayPreferencesRepository = new SqliteDisplayPreferencesRepository(ApplicationPaths, JsonSerializer, LogManager); + DisplayPreferencesRepository = new SqliteDisplayPreferencesRepository(LogManager, JsonSerializer, ApplicationPaths); RegisterSingleInstance(DisplayPreferencesRepository); ItemRepository = new SqliteItemRepository(ApplicationPaths, JsonSerializer, LogManager); RegisterSingleInstance(ItemRepository); - ProviderRepository = new SqliteProviderInfoRepository(ApplicationPaths, LogManager); + ProviderRepository = new SqliteProviderInfoRepository(LogManager, ApplicationPaths); RegisterSingleInstance(ProviderRepository); FileOrganizationRepository = await GetFileOrganizationRepository().ConfigureAwait(false); @@ -614,7 +614,7 @@ namespace MediaBrowser.Server.Startup.Common /// <returns>Task{IUserRepository}.</returns> private async Task<IUserRepository> GetUserRepository() { - var repo = new SqliteUserRepository(JsonSerializer, LogManager, ApplicationPaths); + var repo = new SqliteUserRepository(LogManager, ApplicationPaths, JsonSerializer); await repo.Initialize().ConfigureAwait(false); @@ -704,7 +704,7 @@ namespace MediaBrowser.Server.Startup.Common /// <returns>Task.</returns> private async Task ConfigureUserDataRepositories() { - var repo = new SqliteUserDataRepository(ApplicationPaths, LogManager); + var repo = new SqliteUserDataRepository(LogManager, ApplicationPaths); await repo.Initialize().ConfigureAwait(false); diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index dcafa9417..119e92cd1 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -52,6 +52,7 @@ namespace MediaBrowser.WebDashboard.Api [Route("/dashboard/Package", "GET")] public class GetDashboardPackage { + public string Mode { get; set; } } /// <summary> @@ -134,7 +135,7 @@ namespace MediaBrowser.WebDashboard.Api { var page = ServerEntryPoint.Instance.PluginConfigurationPages.First(p => p.Name.Equals(request.Name, StringComparison.OrdinalIgnoreCase)); - return ResultFactory.GetStaticResult(Request, page.Plugin.Version.ToString().GetMD5(), null, null, MimeTypes.GetMimeType("page.html"), () => GetPackageCreator().ModifyHtml(page.GetHtmlStream(), null, false)); + return ResultFactory.GetStaticResult(Request, page.Plugin.Version.ToString().GetMD5(), null, null, MimeTypes.GetMimeType("page.html"), () => GetPackageCreator().ModifyHtml(page.GetHtmlStream(), null, null, false)); } /// <summary> @@ -252,7 +253,7 @@ namespace MediaBrowser.WebDashboard.Api var minify = _serverConfigurationManager.Configuration.EnableDashboardResourceMinification; return GetPackageCreator() - .GetResource(path, localizationCulture, _appHost.ApplicationVersion.ToString(), minify); + .GetResource(path, null, localizationCulture, _appHost.ApplicationVersion.ToString(), minify); } private PackageCreator GetPackageCreator() @@ -292,38 +293,40 @@ namespace MediaBrowser.WebDashboard.Api var appVersion = DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture); - await DumpHtml(creator.DashboardUIPath, path, culture, appVersion); - await DumpJs(creator.DashboardUIPath, path, culture, appVersion); + var mode = request.Mode; - await DumpFile("scripts/all.js", Path.Combine(path, "scripts", "all.js"), culture, appVersion).ConfigureAwait(false); - await DumpFile("css/all.css", Path.Combine(path, "css", "all.css"), culture, appVersion).ConfigureAwait(false); + await DumpHtml(creator.DashboardUIPath, path, mode, culture, appVersion); + await DumpJs(creator.DashboardUIPath, path, mode, culture, appVersion); + + await DumpFile("scripts/all.js", Path.Combine(path, "scripts", "all.js"), mode, culture, appVersion).ConfigureAwait(false); + await DumpFile("css/all.css", Path.Combine(path, "css", "all.css"), mode, culture, appVersion).ConfigureAwait(false); return ""; } - private async Task DumpHtml(string source, string destination, string culture, string appVersion) + private async Task DumpHtml(string source, string destination, string mode, string culture, string appVersion) { foreach (var file in Directory.GetFiles(source, "*.html", SearchOption.TopDirectoryOnly)) { var filename = Path.GetFileName(file); - await DumpFile(filename, Path.Combine(destination, filename), culture, appVersion).ConfigureAwait(false); + await DumpFile(filename, Path.Combine(destination, filename), mode, culture, appVersion).ConfigureAwait(false); } } - private async Task DumpJs(string source, string destination, string culture, string appVersion) + private async Task DumpJs(string source, string mode, string destination, string culture, string appVersion) { foreach (var file in Directory.GetFiles(source, "*.js", SearchOption.TopDirectoryOnly)) { var filename = Path.GetFileName(file); - await DumpFile("scripts/" + filename, Path.Combine(destination, "scripts", filename), culture, appVersion).ConfigureAwait(false); + await DumpFile("scripts/" + filename, Path.Combine(destination, "scripts", filename), mode, culture, appVersion).ConfigureAwait(false); } } - private async Task DumpFile(string resourceVirtualPath, string destinationFilePath, string culture, string appVersion) + private async Task DumpFile(string resourceVirtualPath, string destinationFilePath, string mode, string culture, string appVersion) { - using (var stream = await GetPackageCreator().GetResource(resourceVirtualPath, culture, appVersion, true).ConfigureAwait(false)) + using (var stream = await GetPackageCreator().GetResource(resourceVirtualPath, mode, culture, appVersion, true).ConfigureAwait(false)) { using (var fs = _fileSystem.GetFileStream(destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)) { diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs index 6e03bd674..a1d47f0d2 100644 --- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs +++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs @@ -32,8 +32,10 @@ namespace MediaBrowser.WebDashboard.Api } public async Task<Stream> GetResource(string path, + string mode, string localizationCulture, - string appVersion, bool enableMinification) + string appVersion, + bool enableMinification) { var isHtml = IsHtml(path); @@ -41,7 +43,7 @@ namespace MediaBrowser.WebDashboard.Api if (path.Equals("scripts/all.js", StringComparison.OrdinalIgnoreCase)) { - resourceStream = await GetAllJavascript(localizationCulture, appVersion, enableMinification).ConfigureAwait(false); + resourceStream = await GetAllJavascript(mode, localizationCulture, appVersion, enableMinification).ConfigureAwait(false); } else if (path.Equals("css/all.css", StringComparison.OrdinalIgnoreCase)) { @@ -58,7 +60,7 @@ namespace MediaBrowser.WebDashboard.Api // jQuery ajax doesn't seem to handle if-modified-since correctly if (isHtml) { - resourceStream = await ModifyHtml(resourceStream, localizationCulture, enableMinification).ConfigureAwait(false); + resourceStream = await ModifyHtml(resourceStream, mode, localizationCulture, enableMinification).ConfigureAwait(false); } } @@ -106,10 +108,11 @@ namespace MediaBrowser.WebDashboard.Api /// Modifies the HTML by adding common meta tags, css and js. /// </summary> /// <param name="sourceStream">The source stream.</param> + /// <param name="mode">The mode.</param> /// <param name="localizationCulture">The localization culture.</param> /// <param name="enableMinification">if set to <c>true</c> [enable minification].</param> /// <returns>Task{Stream}.</returns> - public async Task<Stream> ModifyHtml(Stream sourceStream, string localizationCulture, bool enableMinification) + public async Task<Stream> ModifyHtml(Stream sourceStream, string mode, string localizationCulture, bool enableMinification) { using (sourceStream) { @@ -155,7 +158,7 @@ namespace MediaBrowser.WebDashboard.Api var version = GetType().Assembly.GetName().Version; - html = html.Replace("<head>", "<head>" + GetMetaTags() + GetCommonCss(version) + GetCommonJavascript(version)); + html = html.Replace("<head>", "<head>" + GetMetaTags(mode) + GetCommonCss(mode, version) + GetCommonJavascript(mode, version)); var bytes = Encoding.UTF8.GetBytes(html); @@ -172,12 +175,19 @@ namespace MediaBrowser.WebDashboard.Api /// Gets the meta tags. /// </summary> /// <returns>System.String.</returns> - private static string GetMetaTags() + private static string GetMetaTags(string mode) { var sb = new StringBuilder(); + if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase)) + { + sb.Append("<meta http-equiv=\"Content-Security-Policy\" content=\"default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'\">"); + } + sb.Append("<meta http-equiv=\"X-UA-Compatibility\" content=\"IE=Edge\">"); - sb.Append("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\">"); + sb.Append("<meta name=\"format-detection\" content=\"telephone=no\">"); + sb.Append("<meta name=\"msapplication-tap-highlight\" content=\"no\">"); + sb.Append("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no\">"); sb.Append("<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">"); sb.Append("<meta name=\"mobile-web-app-capable\" content=\"yes\">"); sb.Append("<meta name=\"application-name\" content=\"Emby\">"); @@ -200,11 +210,12 @@ namespace MediaBrowser.WebDashboard.Api /// <summary> /// Gets the common CSS. /// </summary> + /// <param name="mode">The mode.</param> /// <param name="version">The version.</param> /// <returns>System.String.</returns> - private string GetCommonCss(Version version) + private string GetCommonCss(string mode, Version version) { - var versionString = "?v=" + version; + var versionString = !string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase) ? "?v=" + version : string.Empty; var files = new[] { @@ -223,20 +234,26 @@ namespace MediaBrowser.WebDashboard.Api /// <summary> /// Gets the common javascript. /// </summary> + /// <param name="mode">The mode.</param> /// <param name="version">The version.</param> /// <returns>System.String.</returns> - private string GetCommonJavascript(Version version) + private string GetCommonJavascript(string mode, Version version) { var builder = new StringBuilder(); - var versionString = "?v=" + version; + var versionString = !string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase) ? "?v=" + version : string.Empty; - var files = new[] - { - "scripts/all.js" + versionString, - "thirdparty/swipebox-master/js/jquery.swipebox.min.js" + versionString + var files = new List<string> + { + "scripts/all.js" + versionString, + "thirdparty/swipebox-master/js/jquery.swipebox.min.js" + versionString }; + if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase)) + { + files.Insert(0, "cordova.js"); + } + var tags = files.Select(s => string.Format("<script src=\"{0}\"></script>", s)).ToArray(); builder.Append(string.Join(string.Empty, tags)); @@ -248,7 +265,7 @@ namespace MediaBrowser.WebDashboard.Api /// Gets a stream containing all concatenated javascript /// </summary> /// <returns>Task{Stream}.</returns> - private async Task<Stream> GetAllJavascript(string culture, string version, bool enableMinification) + private async Task<Stream> GetAllJavascript(string mode, string culture, string version, bool enableMinification) { var memoryStream = new MemoryStream(); var newLineBytes = Encoding.UTF8.GetBytes(Environment.NewLine); @@ -264,9 +281,18 @@ namespace MediaBrowser.WebDashboard.Api await AppendResource(memoryStream, "thirdparty/jstree3.0.8/jstree.js", newLineBytes).ConfigureAwait(false); + await AppendResource(memoryStream, "thirdparty/fastclick.js", newLineBytes).ConfigureAwait(false); + await AppendResource(memoryStream, "thirdparty/headroom.js", newLineBytes).ConfigureAwait(false); + await AppendLocalization(memoryStream, culture).ConfigureAwait(false); await memoryStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false); + if (!string.IsNullOrWhiteSpace(mode)) + { + var appModeBytes = Encoding.UTF8.GetBytes(string.Format("window.appMode='{0}';", mode)); + await memoryStream.WriteAsync(appModeBytes, 0, appModeBytes.Length).ConfigureAwait(false); + } + // Write the version string for the dashboard comparison function var versionString = string.Format("window.dashboardVersion='{0}';", version); var versionBytes = Encoding.UTF8.GetBytes(versionString); @@ -276,7 +302,7 @@ namespace MediaBrowser.WebDashboard.Api var builder = new StringBuilder(); - foreach (var file in new[] + var apiClientFiles = new[] { "thirdparty/apiclient/logger.js", "thirdparty/apiclient/md5.js", @@ -289,10 +315,20 @@ namespace MediaBrowser.WebDashboard.Api "thirdparty/apiclient/events.js", "thirdparty/apiclient/deferred.js", "thirdparty/apiclient/apiclient.js", - "thirdparty/apiclient/connectservice.js", - "thirdparty/apiclient/serverdiscovery.js", - "thirdparty/apiclient/connectionmanager.js" - }) + "thirdparty/apiclient/connectservice.js" + }.ToList(); + + if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase)) + { + apiClientFiles.Add("thirdparty/apiclient/cordova/serverdiscovery.js"); + } + else + { + apiClientFiles.Add("thirdparty/apiclient/serverdiscovery.js"); + } + apiClientFiles.Add("thirdparty/apiclient/connectionmanager.js"); + + foreach (var file in apiClientFiles) { using (var fs = _fileSystem.GetFileStream(GetDashboardResourcePath(file), FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true)) { diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 00debc459..4f029c26a 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -90,10 +90,13 @@ <Content Include="dashboard-ui\css\images\clients\androidtv-tile.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\css\images\empty.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\css\images\kids\bg.jpg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\css\images\server.png">
+ <Content Include="dashboard-ui\css\images\logo536.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\images\splash.jpg">
@@ -216,6 +219,9 @@ <Content Include="dashboard-ui\thirdparty\apiclient\connectservice.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\thirdparty\apiclient\cordova\serverdiscovery.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\thirdparty\apiclient\deferred.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -996,6 +1002,9 @@ <Content Include="dashboard-ui\thirdparty\cast_sender.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\thirdparty\fastclick.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\thirdparty\fontawesome\css\font-awesome.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -1005,6 +1014,9 @@ <Content Include="dashboard-ui\thirdparty\fontawesome\fonts\fontawesome-webfont.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\thirdparty\headroom.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\thirdparty\jquery-2.1.1.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 497c1e070..f2d46de3e 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -14,7 +14,7 @@ <dependencies> <dependency id="MediaBrowser.Common" version="3.0.622" /> <dependency id="NLog" version="3.2.1" /> - <dependency id="SimpleInjector" version="2.7.0" /> + <dependency id="SimpleInjector" version="2.8.0" /> </dependencies> </metadata> <files> |
