mirror of https://github.com/jellyfin/jellyfin.git
added out of network bitrate limit
This commit is contained in:
parent
6e6ce82cf6
commit
b9c656e859
|
@ -1,5 +1,4 @@
|
||||||
using System.Linq;
|
using MediaBrowser.Common.IO;
|
||||||
using MediaBrowser.Common.IO;
|
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
using MediaBrowser.Model.Drawing;
|
using MediaBrowser.Model.Drawing;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
|
@ -8,6 +7,7 @@ using System.Drawing;
|
||||||
using System.Drawing.Drawing2D;
|
using System.Drawing.Drawing2D;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using ImageFormat = MediaBrowser.Model.Drawing.ImageFormat;
|
using ImageFormat = MediaBrowser.Model.Drawing.ImageFormat;
|
||||||
|
|
||||||
namespace Emby.Drawing.GDI
|
namespace Emby.Drawing.GDI
|
||||||
|
@ -245,5 +245,10 @@ namespace Emby.Drawing.GDI
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "GDI"; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,5 +44,10 @@ namespace Emby.Drawing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
void CreateImageCollage(ImageCollageOptions options);
|
void CreateImageCollage(ImageCollageOptions options);
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name.</value>
|
||||||
|
string Name { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,6 +206,11 @@ namespace Emby.Drawing.ImageMagick
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return "ImageMagick"; }
|
||||||
|
}
|
||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|
|
@ -433,7 +433,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
|
|
||||||
var result = await _liveTvManager.GetPrograms(query, CancellationToken.None).ConfigureAwait(false);
|
var result = await _liveTvManager.GetPrograms(query, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetRecommendedPrograms request)
|
public async Task<object> Get(GetRecommendedPrograms request)
|
||||||
|
@ -450,7 +450,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
|
|
||||||
var result = await _liveTvManager.GetRecommendedPrograms(query, CancellationToken.None).ConfigureAwait(false);
|
var result = await _liveTvManager.GetRecommendedPrograms(query, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Post(GetPrograms request)
|
public object Post(GetPrograms request)
|
||||||
|
@ -473,7 +473,7 @@ namespace MediaBrowser.Api.LiveTv
|
||||||
|
|
||||||
}, CancellationToken.None).ConfigureAwait(false);
|
}, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
return ToOptimizedSerializedResultUsingCache(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetRecording request)
|
public async Task<object> Get(GetRecording request)
|
||||||
|
|
|
@ -1627,7 +1627,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
MediaSourceInfo mediaSource;
|
MediaSourceInfo mediaSource;
|
||||||
if (string.IsNullOrWhiteSpace(request.LiveStreamId))
|
if (string.IsNullOrWhiteSpace(request.LiveStreamId))
|
||||||
{
|
{
|
||||||
var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(request.Id, false, cancellationToken).ConfigureAwait(false)).ToList();
|
var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(request.Id, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false)).ToList();
|
||||||
|
|
||||||
mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
|
mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
|
||||||
? mediaSources.First()
|
? mediaSources.First()
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using MediaBrowser.Controller.Devices;
|
using MediaBrowser.Common.Net;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Devices;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
using MediaBrowser.Controller.Net;
|
using MediaBrowser.Controller.Net;
|
||||||
|
@ -59,23 +61,27 @@ namespace MediaBrowser.Api.Playback
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
private readonly IDeviceManager _deviceManager;
|
private readonly IDeviceManager _deviceManager;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
private readonly IServerConfigurationManager _config;
|
||||||
|
private readonly INetworkManager _networkManager;
|
||||||
|
|
||||||
public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager)
|
public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager)
|
||||||
{
|
{
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
_deviceManager = deviceManager;
|
_deviceManager = deviceManager;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
_config = config;
|
||||||
|
_networkManager = networkManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetPlaybackInfo request)
|
public async Task<object> Get(GetPlaybackInfo request)
|
||||||
{
|
{
|
||||||
var result = await GetPlaybackInfo(request.Id, request.UserId).ConfigureAwait(false);
|
var result = await GetPlaybackInfo(request.Id, request.UserId, new[] { MediaType.Audio, MediaType.Video }).ConfigureAwait(false);
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<object> Get(GetLiveMediaInfo request)
|
public async Task<object> Get(GetLiveMediaInfo request)
|
||||||
{
|
{
|
||||||
var result = await GetPlaybackInfo(request.Id, request.UserId).ConfigureAwait(false);
|
var result = await GetPlaybackInfo(request.Id, request.UserId, new[] { MediaType.Audio, MediaType.Video }).ConfigureAwait(false);
|
||||||
return ToOptimizedResult(result);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,29 +128,38 @@ namespace MediaBrowser.Api.Playback
|
||||||
|
|
||||||
public async Task<object> Post(GetPostedPlaybackInfo request)
|
public async Task<object> Post(GetPostedPlaybackInfo request)
|
||||||
{
|
{
|
||||||
var info = await GetPlaybackInfo(request.Id, request.UserId, request.MediaSourceId, request.LiveStreamId).ConfigureAwait(false);
|
|
||||||
var authInfo = AuthorizationContext.GetAuthorizationInfo(Request);
|
var authInfo = AuthorizationContext.GetAuthorizationInfo(Request);
|
||||||
|
|
||||||
var profile = request.DeviceProfile;
|
var profile = request.DeviceProfile;
|
||||||
if (profile == null)
|
|
||||||
|
var caps = _deviceManager.GetCapabilities(authInfo.DeviceId);
|
||||||
|
if (caps != null)
|
||||||
{
|
{
|
||||||
var caps = _deviceManager.GetCapabilities(authInfo.DeviceId);
|
if (profile == null)
|
||||||
if (caps != null)
|
|
||||||
{
|
{
|
||||||
profile = caps.DeviceProfile;
|
profile = caps.DeviceProfile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var maxBitrate = request.MaxStreamingBitrate;
|
||||||
|
|
||||||
|
if (_config.Configuration.RemoteClientBitrateLimit > 0 && !_networkManager.IsInLocalNetwork(Request.RemoteIp))
|
||||||
|
{
|
||||||
|
maxBitrate = Math.Min(maxBitrate ?? _config.Configuration.RemoteClientBitrateLimit, _config.Configuration.RemoteClientBitrateLimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
var info = await GetPlaybackInfo(request.Id, request.UserId, new[] { MediaType.Audio, MediaType.Video }, request.MediaSourceId, request.LiveStreamId).ConfigureAwait(false);
|
||||||
|
|
||||||
if (profile != null)
|
if (profile != null)
|
||||||
{
|
{
|
||||||
var mediaSourceId = request.MediaSourceId;
|
var mediaSourceId = request.MediaSourceId;
|
||||||
SetDeviceSpecificData(request.Id, info, profile, authInfo, request.MaxStreamingBitrate, request.StartTimeTicks ?? 0, mediaSourceId, request.AudioStreamIndex, request.SubtitleStreamIndex);
|
SetDeviceSpecificData(request.Id, info, profile, authInfo, maxBitrate, request.StartTimeTicks ?? 0, mediaSourceId, request.AudioStreamIndex, request.SubtitleStreamIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToOptimizedResult(info);
|
return ToOptimizedResult(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<PlaybackInfoResponse> GetPlaybackInfo(string id, string userId, string mediaSourceId = null, string liveStreamId = null)
|
private async Task<PlaybackInfoResponse> GetPlaybackInfo(string id, string userId, string[] supportedLiveMediaTypes, string mediaSourceId = null, string liveStreamId = null)
|
||||||
{
|
{
|
||||||
var result = new PlaybackInfoResponse();
|
var result = new PlaybackInfoResponse();
|
||||||
|
|
||||||
|
@ -153,7 +168,7 @@ namespace MediaBrowser.Api.Playback
|
||||||
IEnumerable<MediaSourceInfo> mediaSources;
|
IEnumerable<MediaSourceInfo> mediaSources;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mediaSources = await _mediaSourceManager.GetPlayackMediaSources(id, userId, true, CancellationToken.None).ConfigureAwait(false);
|
mediaSources = await _mediaSourceManager.GetPlayackMediaSources(id, userId, true, supportedLiveMediaTypes, CancellationToken.None).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (PlaybackException ex)
|
catch (PlaybackException ex)
|
||||||
{
|
{
|
||||||
|
|
|
@ -136,11 +136,11 @@ namespace MediaBrowser.Api.Subtitles
|
||||||
_providerManager = providerManager;
|
_providerManager = providerManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetSubtitlePlaylist request)
|
public async Task<object> Get(GetSubtitlePlaylist request)
|
||||||
{
|
{
|
||||||
var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
|
var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
|
||||||
|
|
||||||
var mediaSource = _mediaSourceManager.GetStaticMediaSource(item, request.MediaSourceId, false);
|
var mediaSource = await _mediaSourceManager.GetMediaSource(item, request.MediaSourceId, false).ConfigureAwait(false);
|
||||||
|
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
|
|
||||||
|
|
|
@ -101,12 +101,6 @@ namespace MediaBrowser.Common.Implementations
|
||||||
/// <value>The failed assemblies.</value>
|
/// <value>The failed assemblies.</value>
|
||||||
public List<string> FailedAssemblies { get; protected set; }
|
public List<string> FailedAssemblies { get; protected set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets all types within all running assemblies
|
|
||||||
/// </summary>
|
|
||||||
/// <value>All types.</value>
|
|
||||||
public Type[] AllTypes { get; protected set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all concrete types.
|
/// Gets all concrete types.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -438,9 +432,10 @@ namespace MediaBrowser.Common.Implementations
|
||||||
Logger.Info("Loading {0}", assembly.FullName);
|
Logger.Info("Loading {0}", assembly.FullName);
|
||||||
}
|
}
|
||||||
|
|
||||||
AllTypes = assemblies.SelectMany(GetTypes).ToArray();
|
AllConcreteTypes = assemblies
|
||||||
|
.SelectMany(GetTypes)
|
||||||
AllConcreteTypes = AllTypes.Where(t => t.IsClass && !t.IsAbstract && !t.IsInterface && !t.IsGenericType).ToArray();
|
.Where(t => t.IsClass && !t.IsAbstract && !t.IsInterface && !t.IsGenericType)
|
||||||
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -172,11 +172,11 @@ namespace MediaBrowser.Common.Implementations.Networking
|
||||||
Uri uri;
|
Uri uri;
|
||||||
if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri))
|
if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri))
|
||||||
{
|
{
|
||||||
var host = uri.DnsSafeHost;
|
|
||||||
Logger.Debug("Resolving host {0}", host);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var host = uri.DnsSafeHost;
|
||||||
|
Logger.Debug("Resolving host {0}", host);
|
||||||
|
|
||||||
address = GetIpAddresses(host).FirstOrDefault();
|
address = GetIpAddresses(host).FirstOrDefault();
|
||||||
|
|
||||||
if (address != null)
|
if (address != null)
|
||||||
|
@ -186,9 +186,13 @@ namespace MediaBrowser.Common.Implementations.Networking
|
||||||
return IsInLocalNetworkInternal(address.ToString(), false);
|
return IsInLocalNetworkInternal(address.ToString(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
// Can happen with reverse proxy or IIS url rewriting
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.ErrorException("Error resovling hostname {0}", ex, host);
|
Logger.ErrorException("Error resovling hostname", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,18 +43,10 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <param name="id">The identifier.</param>
|
/// <param name="id">The identifier.</param>
|
||||||
/// <param name="userId">The user identifier.</param>
|
/// <param name="userId">The user identifier.</param>
|
||||||
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
|
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
|
||||||
|
/// <param name="supportedLiveMediaTypes">The supported live media types.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>IEnumerable<MediaSourceInfo>.</returns>
|
/// <returns>IEnumerable<MediaSourceInfo>.</returns>
|
||||||
Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, CancellationToken cancellationToken);
|
Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, string[] supportedLiveMediaTypes, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the playack media sources.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id">The identifier.</param>
|
|
||||||
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
|
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
|
||||||
/// <returns>Task<IEnumerable<MediaSourceInfo>>.</returns>
|
|
||||||
Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, bool enablePathSubstitution, CancellationToken cancellationToken);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the static media sources.
|
/// Gets the static media sources.
|
||||||
|
@ -64,7 +56,7 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
/// <returns>IEnumerable<MediaSourceInfo>.</returns>
|
/// <returns>IEnumerable<MediaSourceInfo>.</returns>
|
||||||
IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null);
|
IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the static media source.
|
/// Gets the static media source.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -72,7 +64,7 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <param name="mediaSourceId">The media source identifier.</param>
|
/// <param name="mediaSourceId">The media source identifier.</param>
|
||||||
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
|
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
|
||||||
/// <returns>MediaSourceInfo.</returns>
|
/// <returns>MediaSourceInfo.</returns>
|
||||||
MediaSourceInfo GetStaticMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution);
|
Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens the media source.
|
/// Opens the media source.
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.Entities;
|
|
||||||
using MediaBrowser.Model.Drawing;
|
using MediaBrowser.Model.Drawing;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
|
@ -892,7 +892,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
||||||
|
|
||||||
request.MediaSource = hasMediaSources == null ?
|
request.MediaSource = hasMediaSources == null ?
|
||||||
null :
|
null :
|
||||||
mediaSourceManager.GetStaticMediaSource(hasMediaSources, request.MediaSourceId, false);
|
mediaSourceManager.GetMediaSource(hasMediaSources, request.MediaSourceId, false).Result;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
|
||||||
|
|
||||||
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
|
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(request.ItemId, false, cancellationToken).ConfigureAwait(false);
|
var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(request.ItemId, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
|
var mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
|
||||||
? mediaSources.First()
|
? mediaSources.First()
|
||||||
|
|
|
@ -132,7 +132,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
||||||
int subtitleStreamIndex,
|
int subtitleStreamIndex,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(itemId, false, cancellationToken).ConfigureAwait(false);
|
var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(itemId, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var mediaSource = mediaSources
|
var mediaSource = mediaSources
|
||||||
.First(i => string.Equals(i.Id, mediaSourceId));
|
.First(i => string.Equals(i.Id, mediaSourceId));
|
||||||
|
|
|
@ -208,6 +208,7 @@ namespace MediaBrowser.Model.Configuration
|
||||||
|
|
||||||
public bool EnableAudioArchiveFiles { get; set; }
|
public bool EnableAudioArchiveFiles { get; set; }
|
||||||
public bool EnableVideoArchiveFiles { get; set; }
|
public bool EnableVideoArchiveFiles { get; set; }
|
||||||
|
public int RemoteClientBitrateLimit { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
|
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
|
||||||
|
|
|
@ -19,12 +19,14 @@ namespace MediaBrowser.Model.Session
|
||||||
public bool SupportsOfflineAccess { get; set; }
|
public bool SupportsOfflineAccess { get; set; }
|
||||||
|
|
||||||
public DeviceProfile DeviceProfile { get; set; }
|
public DeviceProfile DeviceProfile { get; set; }
|
||||||
|
public List<string> SupportedLiveMediaTypes { get; set; }
|
||||||
|
|
||||||
public ClientCapabilities()
|
public ClientCapabilities()
|
||||||
{
|
{
|
||||||
PlayableMediaTypes = new List<string>();
|
PlayableMediaTypes = new List<string>();
|
||||||
SupportedCommands = new List<string>();
|
SupportedCommands = new List<string>();
|
||||||
SupportsPersistentIdentifier = true;
|
SupportsPersistentIdentifier = true;
|
||||||
|
SupportedLiveMediaTypes = new List<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -39,8 +39,9 @@ namespace MediaBrowser.Model.Users
|
||||||
public bool EnableLiveTvAccess { get; set; }
|
public bool EnableLiveTvAccess { get; set; }
|
||||||
|
|
||||||
public bool EnableMediaPlayback { get; set; }
|
public bool EnableMediaPlayback { get; set; }
|
||||||
public bool EnableMediaPlaybackTranscoding { get; set; }
|
public bool EnableAudioPlaybackTranscoding { get; set; }
|
||||||
|
public bool EnableVideoPlaybackTranscoding { get; set; }
|
||||||
|
|
||||||
public bool EnableContentDeletion { get; set; }
|
public bool EnableContentDeletion { get; set; }
|
||||||
public bool EnableContentDownloading { get; set; }
|
public bool EnableContentDownloading { get; set; }
|
||||||
|
|
||||||
|
@ -68,8 +69,9 @@ namespace MediaBrowser.Model.Users
|
||||||
EnableSyncTranscoding = true;
|
EnableSyncTranscoding = true;
|
||||||
|
|
||||||
EnableMediaPlayback = true;
|
EnableMediaPlayback = true;
|
||||||
EnableMediaPlaybackTranscoding = true;
|
EnableAudioPlaybackTranscoding = true;
|
||||||
|
EnableVideoPlaybackTranscoding = true;
|
||||||
|
|
||||||
EnableLiveTvManagement = true;
|
EnableLiveTvManagement = true;
|
||||||
EnableLiveTvAccess = true;
|
EnableLiveTvAccess = true;
|
||||||
|
|
||||||
|
|
|
@ -129,12 +129,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, bool enablePathSubstitution, CancellationToken cancellationToken)
|
public async Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, string[] supportedLiveMediaTypes, CancellationToken cancellationToken)
|
||||||
{
|
|
||||||
return GetPlayackMediaSources(id, null, enablePathSubstitution, cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, CancellationToken cancellationToken)
|
|
||||||
{
|
{
|
||||||
var item = _libraryManager.GetItemById(id);
|
var item = _libraryManager.GetItemById(id);
|
||||||
|
|
||||||
|
@ -184,9 +179,19 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
{
|
{
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
if (!user.Policy.EnableMediaPlaybackTranscoding)
|
if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
source.SupportsTranscoding = false;
|
if (!user.Policy.EnableAudioPlaybackTranscoding)
|
||||||
|
{
|
||||||
|
source.SupportsTranscoding = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
if (!user.Policy.EnableVideoPlaybackTranscoding)
|
||||||
|
{
|
||||||
|
source.SupportsTranscoding = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,9 +243,12 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MediaSourceInfo GetStaticMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution)
|
public async Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution)
|
||||||
{
|
{
|
||||||
return GetStaticMediaSources(item, enablePathSubstitution).FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
|
var sources = await GetPlayackMediaSources(item.Id.ToString("N"), null, enablePathSubstitution, new[] { MediaType.Audio, MediaType.Video },
|
||||||
|
CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return sources.FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null)
|
public IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null)
|
||||||
|
|
|
@ -122,7 +122,7 @@
|
||||||
"LabelFree": "Free",
|
"LabelFree": "Free",
|
||||||
"HeaderPlaybackError": "Playback Error",
|
"HeaderPlaybackError": "Playback Error",
|
||||||
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
|
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
|
||||||
"MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
|
"MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
|
||||||
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
|
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
|
||||||
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
|
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
|
||||||
"HeaderSelectAudio": "Select Audio",
|
"HeaderSelectAudio": "Select Audio",
|
||||||
|
|
|
@ -1410,6 +1410,10 @@
|
||||||
"LabelUploadSpeedLimit": "Upload speed limit (mbps):",
|
"LabelUploadSpeedLimit": "Upload speed limit (mbps):",
|
||||||
"OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
|
"OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
|
||||||
"HeaderPlayback": "Media Playback",
|
"HeaderPlayback": "Media Playback",
|
||||||
"OptionAllowMediaPlaybackTranscoding": "Allow media playback that requires transcoding",
|
"OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
|
||||||
"OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy."
|
"OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
|
||||||
|
"OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
|
||||||
|
"TabStreaming": "Streaming",
|
||||||
|
"LabelRemoteClientBitrateLimit": "Remote client bitrate limit (mbps):",
|
||||||
|
"LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle."
|
||||||
}
|
}
|
||||||
|
|
|
@ -305,12 +305,9 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId)
|
private Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId)
|
||||||
{
|
{
|
||||||
var sources = await _mediaSourceManager.GetPlayackMediaSources(item.Id.ToString("N"), false, CancellationToken.None)
|
return _mediaSourceManager.GetMediaSource(item, mediaSourceId, false);
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
return sources.FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -195,17 +195,39 @@ namespace MediaBrowser.Server.Implementations.Sync
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var maxAudioChannels = supportsAc3 || supportsDca ? "5" : "2";
|
|
||||||
codecProfiles.Add(new CodecProfile
|
codecProfiles.Add(new CodecProfile
|
||||||
{
|
{
|
||||||
Type = CodecType.VideoAudio,
|
Type = CodecType.VideoAudio,
|
||||||
|
Codec = "ac3",
|
||||||
Conditions = new[]
|
Conditions = new[]
|
||||||
{
|
{
|
||||||
new ProfileCondition
|
new ProfileCondition
|
||||||
{
|
{
|
||||||
Condition = ProfileConditionType.LessThanEqual,
|
Condition = ProfileConditionType.LessThanEqual,
|
||||||
Property = ProfileConditionValue.AudioChannels,
|
Property = ProfileConditionValue.AudioChannels,
|
||||||
Value = maxAudioChannels,
|
Value = "5",
|
||||||
|
IsRequired = true
|
||||||
|
},
|
||||||
|
new ProfileCondition
|
||||||
|
{
|
||||||
|
Condition = ProfileConditionType.Equals,
|
||||||
|
Property = ProfileConditionValue.IsSecondaryAudio,
|
||||||
|
Value = "false",
|
||||||
|
IsRequired = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
codecProfiles.Add(new CodecProfile
|
||||||
|
{
|
||||||
|
Type = CodecType.VideoAudio,
|
||||||
|
Codec = "ac3",
|
||||||
|
Conditions = new[]
|
||||||
|
{
|
||||||
|
new ProfileCondition
|
||||||
|
{
|
||||||
|
Condition = ProfileConditionType.LessThanEqual,
|
||||||
|
Property = ProfileConditionValue.AudioChannels,
|
||||||
|
Value = "2",
|
||||||
IsRequired = true
|
IsRequired = true
|
||||||
},
|
},
|
||||||
new ProfileCondition
|
new ProfileCondition
|
||||||
|
|
|
@ -482,6 +482,7 @@ namespace MediaBrowser.WebDashboard.Api
|
||||||
"selectserver.js",
|
"selectserver.js",
|
||||||
"serversecurity.js",
|
"serversecurity.js",
|
||||||
"songs.js",
|
"songs.js",
|
||||||
|
"streamingsettings.js",
|
||||||
"supporterkeypage.js",
|
"supporterkeypage.js",
|
||||||
"supporterpage.js",
|
"supporterpage.js",
|
||||||
"syncactivity.js",
|
"syncactivity.js",
|
||||||
|
|
|
@ -150,6 +150,9 @@
|
||||||
<Content Include="dashboard-ui\scripts\selectserver.js">
|
<Content Include="dashboard-ui\scripts\selectserver.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="dashboard-ui\scripts\streamingsettings.js">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="dashboard-ui\scripts\syncjob.js">
|
<Content Include="dashboard-ui\scripts\syncjob.js">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
@ -174,6 +177,9 @@
|
||||||
<Content Include="dashboard-ui\selectserver.html">
|
<Content Include="dashboard-ui\selectserver.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="dashboard-ui\streamingsettings.html">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="dashboard-ui\syncjob.html">
|
<Content Include="dashboard-ui\syncjob.html">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
Loading…
Reference in New Issue