From f756e39b9d5b461e6bcaa4e71006038983d28213 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 30 Mar 2014 12:49:40 -0400 Subject: restored live tv playback in the web client --- MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs | 91 ++++++ .../Encoder/EncodingUtils.cs | 233 +++++++++++++++ .../Encoder/FFMpegProcess.cs | 168 +++++++++++ .../Encoder/InternalEncodingTask.cs | 95 ++++++ .../Encoder/InternalEncodingTaskFactory.cs | 323 +++++++++++++++++++++ MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 64 +--- 6 files changed, 913 insertions(+), 61 deletions(-) create mode 100644 MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs create mode 100644 MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs create mode 100644 MediaBrowser.MediaEncoding/Encoder/FFMpegProcess.cs create mode 100644 MediaBrowser.MediaEncoding/Encoder/InternalEncodingTask.cs create mode 100644 MediaBrowser.MediaEncoding/Encoder/InternalEncodingTaskFactory.cs (limited to 'MediaBrowser.MediaEncoding/Encoder') diff --git a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs new file mode 100644 index 0000000000..08b7fbe492 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs @@ -0,0 +1,91 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; +using System.Collections.Generic; +using System.Globalization; +using System.Threading.Tasks; + +namespace MediaBrowser.MediaEncoding.Encoder +{ + public class AudioEncoder + { + private readonly string _ffmpegPath; + private readonly ILogger _logger; + private readonly IFileSystem _fileSystem; + private readonly IApplicationPaths _appPaths; + private readonly IIsoManager _isoManager; + private readonly ILiveTvManager _liveTvManager; + + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + + public AudioEncoder(string ffmpegPath, ILogger logger, IFileSystem fileSystem, IApplicationPaths appPaths, IIsoManager isoManager, ILiveTvManager liveTvManager) + { + _ffmpegPath = ffmpegPath; + _logger = logger; + _fileSystem = fileSystem; + _appPaths = appPaths; + _isoManager = isoManager; + _liveTvManager = liveTvManager; + } + + public Task BeginEncoding(InternalEncodingTask task) + { + return new FFMpegProcess(_ffmpegPath, _logger, _fileSystem, _appPaths, _isoManager, _liveTvManager).Start(task, GetArguments); + } + + private string GetArguments(InternalEncodingTask task, string mountedPath) + { + var options = task.Request; + + return string.Format("{0} -i {1} {2} -id3v2_version 3 -write_id3v1 1 \"{3}\"", + GetInputModifier(task), + GetInputArgument(task), + GetOutputModifier(task), + options.OutputPath).Trim(); + } + + private string GetInputModifier(InternalEncodingTask task) + { + return EncodingUtils.GetInputModifier(task); + } + + private string GetInputArgument(InternalEncodingTask task) + { + return EncodingUtils.GetInputArgument(new List { task.MediaPath }, task.IsInputRemote); + } + + private string GetOutputModifier(InternalEncodingTask task) + { + var options = task.Request; + + var audioTranscodeParams = new List + { + "-threads " + EncodingUtils.GetNumberOfThreads(task, false).ToString(_usCulture), + "-vn" + }; + + var bitrate = EncodingUtils.GetAudioBitrateParam(task); + + if (bitrate.HasValue) + { + audioTranscodeParams.Add("-ab " + bitrate.Value.ToString(_usCulture)); + } + + var channels = EncodingUtils.GetNumAudioChannelsParam(options, task.AudioStream); + + if (channels.HasValue) + { + audioTranscodeParams.Add("-ac " + channels.Value); + } + + if (options.AudioSampleRate.HasValue) + { + audioTranscodeParams.Add("-ar " + options.AudioSampleRate.Value); + } + + return string.Join(" ", audioTranscodeParams.ToArray()); + } + } +} diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs new file mode 100644 index 0000000000..79d512dc1d --- /dev/null +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -0,0 +1,233 @@ +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Entities; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +namespace MediaBrowser.MediaEncoding.Encoder +{ + public static class EncodingUtils + { + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + public static string GetInputArgument(List inputFiles, bool isRemote) + { + if (isRemote) + { + return GetHttpInputArgument(inputFiles); + } + + return GetConcatInputArgument(inputFiles); + } + + /// + /// Gets the concat input argument. + /// + /// The input files. + /// System.String. + private static string GetConcatInputArgument(List inputFiles) + { + // Get all streams + // If there's more than one we'll need to use the concat command + if (inputFiles.Count > 1) + { + var files = string.Join("|", inputFiles); + + return string.Format("concat:\"{0}\"", files); + } + + // Determine the input path for video files + return GetFileInputArgument(inputFiles[0]); + } + + /// + /// Gets the file input argument. + /// + /// The path. + /// System.String. + private static string GetFileInputArgument(string path) + { + return string.Format("file:\"{0}\"", path); + } + + /// + /// Gets the HTTP input argument. + /// + /// The input files. + /// System.String. + private static string GetHttpInputArgument(IEnumerable inputFiles) + { + var url = inputFiles.First(); + + return string.Format("\"{0}\"", url); + } + + public static string GetAudioInputModifier(InternalEncodingTask options) + { + return GetCommonInputModifier(options); + } + + public static string GetInputModifier(InternalEncodingTask options) + { + var inputModifier = GetCommonInputModifier(options); + + //if (state.VideoRequest != null) + //{ + // inputModifier += " -fflags genpts"; + //} + + //if (!string.IsNullOrEmpty(state.InputVideoCodec)) + //{ + // inputModifier += " -vcodec " + state.InputVideoCodec; + //} + + //if (!string.IsNullOrEmpty(state.InputVideoSync)) + //{ + // inputModifier += " -vsync " + state.InputVideoSync; + //} + + return inputModifier; + } + + private static string GetCommonInputModifier(InternalEncodingTask options) + { + var inputModifier = string.Empty; + + if (options.EnableDebugLogging) + { + inputModifier += "-loglevel debug"; + } + + var probeSize = GetProbeSizeArgument(options.InputVideoType.HasValue && options.InputVideoType.Value == VideoType.Dvd); + inputModifier += " " + probeSize; + inputModifier = inputModifier.Trim(); + + if (!string.IsNullOrWhiteSpace(options.UserAgent)) + { + inputModifier += " -user-agent \"" + options.UserAgent + "\""; + } + + inputModifier += " " + GetFastSeekValue(options.Request); + inputModifier = inputModifier.Trim(); + + if (!string.IsNullOrEmpty(options.InputFormat)) + { + inputModifier += " -f " + options.InputFormat; + } + + if (!string.IsNullOrEmpty(options.InputAudioCodec)) + { + inputModifier += " -acodec " + options.InputAudioCodec; + } + + if (!string.IsNullOrEmpty(options.InputAudioSync)) + { + inputModifier += " -async " + options.InputAudioSync; + } + + if (options.ReadInputAtNativeFramerate) + { + inputModifier += " -re"; + } + + return inputModifier; + } + + private static string GetFastSeekValue(EncodingOptions options) + { + var time = options.StartTimeTicks; + + if (time.HasValue) + { + var seconds = TimeSpan.FromTicks(time.Value).TotalSeconds; + + if (seconds > 0) + { + return string.Format("-ss {0}", seconds.ToString(UsCulture)); + } + } + + return string.Empty; + } + + public static string GetProbeSizeArgument(bool isDvd) + { + return isDvd ? "-probesize 1G -analyzeduration 200M" : string.Empty; + } + + public static int? GetAudioBitrateParam(InternalEncodingTask task) + { + if (task.Request.AudioBitRate.HasValue) + { + // Make sure we don't request a bitrate higher than the source + var currentBitrate = task.AudioStream == null ? task.Request.AudioBitRate.Value : task.AudioStream.BitRate ?? task.Request.AudioBitRate.Value; + + return Math.Min(currentBitrate, task.Request.AudioBitRate.Value); + } + + return null; + } + + /// + /// Gets the number of audio channels to specify on the command line + /// + /// The request. + /// The audio stream. + /// System.Nullable{System.Int32}. + public static int? GetNumAudioChannelsParam(EncodingOptions request, MediaStream audioStream) + { + if (audioStream != null) + { + if (audioStream.Channels > 2 && string.Equals(request.AudioCodec, "wma", StringComparison.OrdinalIgnoreCase)) + { + // wmav2 currently only supports two channel output + return 2; + } + } + + if (request.MaxAudioChannels.HasValue) + { + if (audioStream != null && audioStream.Channels.HasValue) + { + return Math.Min(request.MaxAudioChannels.Value, audioStream.Channels.Value); + } + + return request.MaxAudioChannels.Value; + } + + return request.AudioChannels; + } + + public static int GetNumberOfThreads(InternalEncodingTask state, bool isWebm) + { + // Use more when this is true. -re will keep cpu usage under control + if (state.ReadInputAtNativeFramerate) + { + if (isWebm) + { + return Math.Max(Environment.ProcessorCount - 1, 1); + } + + return 0; + } + + // Webm: http://www.webmproject.org/docs/encoder-parameters/ + // The decoder will usually automatically use an appropriate number of threads according to how many cores are available but it can only use multiple threads + // for the coefficient data if the encoder selected --token-parts > 0 at encode time. + + switch (state.QualitySetting) + { + case EncodingQuality.HighSpeed: + return 2; + case EncodingQuality.HighQuality: + return 2; + case EncodingQuality.MaxQuality: + return isWebm ? 2 : 0; + default: + throw new Exception("Unrecognized MediaEncodingQuality value."); + } + } + } +} diff --git a/MediaBrowser.MediaEncoding/Encoder/FFMpegProcess.cs b/MediaBrowser.MediaEncoding/Encoder/FFMpegProcess.cs new file mode 100644 index 0000000000..05733aef03 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Encoder/FFMpegProcess.cs @@ -0,0 +1,168 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; +using System; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.MediaEncoding.Encoder +{ + public class FFMpegProcess : IDisposable + { + private readonly string _ffmpegPath; + private readonly ILogger _logger; + private readonly IFileSystem _fileSystem; + private readonly IApplicationPaths _appPaths; + private readonly IIsoManager _isoManager; + private readonly ILiveTvManager _liveTvManager; + + private Stream _logFileStream; + private InternalEncodingTask _task; + private IIsoMount _isoMount; + + public FFMpegProcess(string ffmpegPath, ILogger logger, IFileSystem fileSystem, IApplicationPaths appPaths, IIsoManager isoManager, ILiveTvManager liveTvManager) + { + _ffmpegPath = ffmpegPath; + _logger = logger; + _fileSystem = fileSystem; + _appPaths = appPaths; + _isoManager = isoManager; + _liveTvManager = liveTvManager; + } + + public async Task Start(InternalEncodingTask task, Func argumentsFactory) + { + _task = task; + if (!File.Exists(_ffmpegPath)) + { + throw new InvalidOperationException("ffmpeg was not found at " + _ffmpegPath); + } + + Directory.CreateDirectory(Path.GetDirectoryName(task.Request.OutputPath)); + + string mountedPath = null; + if (task.InputVideoType.HasValue && task.InputVideoType == VideoType.Iso && task.IsoType.HasValue) + { + if (_isoManager.CanMount(task.MediaPath)) + { + _isoMount = await _isoManager.Mount(task.MediaPath, CancellationToken.None).ConfigureAwait(false); + mountedPath = _isoMount.MountedPath; + } + } + + var process = new Process + { + StartInfo = new ProcessStartInfo + { + CreateNoWindow = true, + UseShellExecute = false, + + // Must consume both stdout and stderr or deadlocks may occur + RedirectStandardOutput = true, + RedirectStandardError = true, + + FileName = _ffmpegPath, + WorkingDirectory = Path.GetDirectoryName(_ffmpegPath), + Arguments = argumentsFactory(task, mountedPath), + + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, + + EnableRaisingEvents = true + }; + + _logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments); + + var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-" + task.Id + ".txt"); + Directory.CreateDirectory(Path.GetDirectoryName(logFilePath)); + + // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. + _logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true); + + process.Exited += process_Exited; + + try + { + process.Start(); + } + catch (Exception ex) + { + _logger.ErrorException("Error starting ffmpeg", ex); + + task.OnError(); + + DisposeLogFileStream(); + + process.Dispose(); + + throw; + } + + task.OnBegin(); + + // MUST read both stdout and stderr asynchronously or a deadlock may occurr + process.BeginOutputReadLine(); + +#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.StandardError.BaseStream.CopyToAsync(_logFileStream); +#pragma warning restore 4014 + } + + async void process_Exited(object sender, EventArgs e) + { + var process = (Process)sender; + + if (_isoMount != null) + { + _isoMount.Dispose(); + _isoMount = null; + } + + DisposeLogFileStream(); + + try + { + _logger.Info("FFMpeg exited with code {0} for {1}", process.ExitCode, _task.Request.OutputPath); + } + catch + { + _logger.Info("FFMpeg exited with an error for {0}", _task.Request.OutputPath); + } + + _task.OnCompleted(); + + if (!string.IsNullOrEmpty(_task.LiveTvStreamId)) + { + try + { + await _liveTvManager.CloseLiveStream(_task.LiveTvStreamId, CancellationToken.None).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error closing live tv stream", ex); + } + } + } + + public void Dispose() + { + DisposeLogFileStream(); + } + + private void DisposeLogFileStream() + { + if (_logFileStream != null) + { + _logFileStream.Dispose(); + _logFileStream = null; + } + } + } +} diff --git a/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTask.cs b/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTask.cs new file mode 100644 index 0000000000..826525aef2 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTask.cs @@ -0,0 +1,95 @@ +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Entities; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace MediaBrowser.MediaEncoding.Encoder +{ + public class InternalEncodingTask + { + public string Id { get; set; } + + public CancellationTokenSource CancellationTokenSource { get; set; } + + public double ProgressPercentage { get; set; } + + public EncodingOptions Request { get; set; } + + public VideoEncodingOptions VideoRequest + { + get { return Request as VideoEncodingOptions; } + } + + public string MediaPath { get; set; } + public List StreamFileNames { get; set; } + public bool IsInputRemote { get; set; } + + public VideoType? InputVideoType { get; set; } + public IsoType? IsoType { get; set; } + public long? InputRunTimeTicks; + + public string AudioSync = "1"; + public string VideoSync = "vfr"; + + public string InputAudioSync { get; set; } + public string InputVideoSync { get; set; } + + public bool DeInterlace { get; set; } + + public bool ReadInputAtNativeFramerate { get; set; } + + public string InputFormat { get; set; } + + public string InputVideoCodec { get; set; } + + public string InputAudioCodec { get; set; } + + public string LiveTvStreamId { get; set; } + + public MediaStream AudioStream { get; set; } + public MediaStream VideoStream { get; set; } + public MediaStream SubtitleStream { get; set; } + public bool HasMediaStreams { get; set; } + + public int SegmentLength = 10; + public int HlsListSize; + + public string MimeType { get; set; } + public string OrgPn { get; set; } + public bool EnableMpegtsM2TsMode { get; set; } + + /// + /// Gets or sets the user agent. + /// + /// The user agent. + public string UserAgent { get; set; } + + public EncodingQuality QualitySetting { get; set; } + + public InternalEncodingTask() + { + Id = Guid.NewGuid().ToString("N"); + CancellationTokenSource = new CancellationTokenSource(); + StreamFileNames = new List(); + } + + public bool EnableDebugLogging { get; set; } + + internal void OnBegin() + { + + } + + internal void OnCompleted() + { + + } + + internal void OnError() + { + + } + } +} diff --git a/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTaskFactory.cs b/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTaskFactory.cs new file mode 100644 index 0000000000..fa9b879061 --- /dev/null +++ b/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTaskFactory.cs @@ -0,0 +1,323 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Dlna; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.LiveTv; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.MediaEncoding.Encoder +{ + public class InternalEncodingTaskFactory + { + private readonly ILibraryManager _libraryManager; + private readonly ILiveTvManager _liveTvManager; + private readonly IItemRepository _itemRepo; + private readonly IServerConfigurationManager _config; + + public InternalEncodingTaskFactory(ILibraryManager libraryManager, ILiveTvManager liveTvManager, IItemRepository itemRepo, IServerConfigurationManager config) + { + _libraryManager = libraryManager; + _liveTvManager = liveTvManager; + _itemRepo = itemRepo; + _config = config; + } + + public async Task Create(EncodingOptions request, CancellationToken cancellationToken) + { + ValidateInput(request); + + var state = new InternalEncodingTask + { + Request = request + }; + + var item = string.IsNullOrEmpty(request.MediaSourceId) ? + _libraryManager.GetItemById(new Guid(request.ItemId)) : + _libraryManager.GetItemById(new Guid(request.MediaSourceId)); + + if (item is ILiveTvRecording) + { + var recording = await _liveTvManager.GetInternalRecording(request.ItemId, cancellationToken).ConfigureAwait(false); + + if (string.Equals(recording.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) + { + state.InputVideoType = VideoType.VideoFile; + } + + var path = recording.RecordingInfo.Path; + var mediaUrl = recording.RecordingInfo.Url; + + if (string.IsNullOrWhiteSpace(path) && string.IsNullOrWhiteSpace(mediaUrl)) + { + var streamInfo = await _liveTvManager.GetRecordingStream(request.ItemId, cancellationToken).ConfigureAwait(false); + + state.LiveTvStreamId = streamInfo.Id; + + path = streamInfo.Path; + mediaUrl = streamInfo.Url; + } + + if (!string.IsNullOrEmpty(path) && File.Exists(path)) + { + state.MediaPath = path; + state.IsInputRemote = false; + } + else if (!string.IsNullOrEmpty(mediaUrl)) + { + state.MediaPath = mediaUrl; + state.IsInputRemote = true; + } + + state.InputRunTimeTicks = recording.RunTimeTicks; + if (recording.RecordingInfo.Status == RecordingStatus.InProgress && !state.IsInputRemote) + { + await Task.Delay(1000, cancellationToken).ConfigureAwait(false); + } + + state.ReadInputAtNativeFramerate = recording.RecordingInfo.Status == RecordingStatus.InProgress; + state.AudioSync = "1000"; + state.DeInterlace = true; + state.InputVideoSync = "-1"; + state.InputAudioSync = "1"; + } + else if (item is LiveTvChannel) + { + var channel = _liveTvManager.GetInternalChannel(request.ItemId); + + if (string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) + { + state.InputVideoType = VideoType.VideoFile; + } + + var streamInfo = await _liveTvManager.GetChannelStream(request.ItemId, cancellationToken).ConfigureAwait(false); + + state.LiveTvStreamId = streamInfo.Id; + + if (!string.IsNullOrEmpty(streamInfo.Path) && File.Exists(streamInfo.Path)) + { + state.MediaPath = streamInfo.Path; + state.IsInputRemote = false; + + await Task.Delay(1000, cancellationToken).ConfigureAwait(false); + } + else if (!string.IsNullOrEmpty(streamInfo.Url)) + { + state.MediaPath = streamInfo.Url; + state.IsInputRemote = true; + } + + state.ReadInputAtNativeFramerate = true; + state.AudioSync = "1000"; + state.DeInterlace = true; + state.InputVideoSync = "-1"; + state.InputAudioSync = "1"; + } + else + { + state.MediaPath = item.Path; + state.IsInputRemote = item.LocationType == LocationType.Remote; + + var video = item as Video; + + if (video != null) + { + state.InputVideoType = video.VideoType; + state.IsoType = video.IsoType; + + state.StreamFileNames = video.PlayableStreamFileNames.ToList(); + } + + state.InputRunTimeTicks = item.RunTimeTicks; + } + + var videoRequest = request as VideoEncodingOptions; + + var mediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery + { + ItemId = item.Id + + }).ToList(); + + if (videoRequest != null) + { + state.VideoStream = GetMediaStream(mediaStreams, videoRequest.VideoStreamIndex, MediaStreamType.Video); + state.SubtitleStream = GetMediaStream(mediaStreams, videoRequest.SubtitleStreamIndex, MediaStreamType.Subtitle, false); + state.AudioStream = GetMediaStream(mediaStreams, videoRequest.AudioStreamIndex, MediaStreamType.Audio); + + if (state.VideoStream != null && state.VideoStream.IsInterlaced) + { + state.DeInterlace = true; + } + } + else + { + state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true); + } + + state.HasMediaStreams = mediaStreams.Count > 0; + + state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 10; + state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440; + + state.QualitySetting = GetQualitySetting(); + + ApplyDeviceProfileSettings(state); + + return state; + } + + private void ValidateInput(EncodingOptions request) + { + if (string.IsNullOrWhiteSpace(request.ItemId)) + { + throw new ArgumentException("ItemId is required."); + } + if (string.IsNullOrWhiteSpace(request.OutputPath)) + { + throw new ArgumentException("OutputPath is required."); + } + if (string.IsNullOrWhiteSpace(request.Container)) + { + throw new ArgumentException("Container is required."); + } + if (string.IsNullOrWhiteSpace(request.AudioCodec)) + { + throw new ArgumentException("AudioCodec is required."); + } + + var videoRequest = request as VideoEncodingOptions; + + if (videoRequest == null) + { + return; + } + } + + /// + /// Determines which stream will be used for playback + /// + /// All stream. + /// Index of the desired. + /// The type. + /// if set to true [return first if no index]. + /// MediaStream. + private MediaStream GetMediaStream(IEnumerable allStream, int? desiredIndex, MediaStreamType type, bool returnFirstIfNoIndex = true) + { + var streams = allStream.Where(s => s.Type == type).OrderBy(i => i.Index).ToList(); + + if (desiredIndex.HasValue) + { + var stream = streams.FirstOrDefault(s => s.Index == desiredIndex.Value); + + if (stream != null) + { + return stream; + } + } + + if (returnFirstIfNoIndex && type == MediaStreamType.Audio) + { + return streams.FirstOrDefault(i => i.Channels.HasValue && i.Channels.Value > 0) ?? + streams.FirstOrDefault(); + } + + // Just return the first one + return returnFirstIfNoIndex ? streams.FirstOrDefault() : null; + } + + private void ApplyDeviceProfileSettings(InternalEncodingTask state) + { + var profile = state.Request.DeviceProfile; + + if (profile == null) + { + // Don't use settings from the default profile. + // Only use a specific profile if it was requested. + return; + } + + var container = state.Request.Container; + + var audioCodec = state.Request.AudioCodec; + + if (string.Equals(audioCodec, "copy", StringComparison.OrdinalIgnoreCase) && state.AudioStream != null) + { + audioCodec = state.AudioStream.Codec; + } + + var videoCodec = state.VideoRequest == null ? null : state.VideoRequest.VideoCodec; + + if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase) && state.VideoStream != null) + { + videoCodec = state.VideoStream.Codec; + } + + var mediaProfile = state.VideoRequest == null ? + profile.GetAudioMediaProfile(container, audioCodec, state.AudioStream) : + profile.GetVideoMediaProfile(container, audioCodec, videoCodec, state.AudioStream, state.VideoStream); + + if (mediaProfile != null) + { + state.MimeType = mediaProfile.MimeType; + state.OrgPn = mediaProfile.OrgPn; + } + + var transcodingProfile = state.VideoRequest == null ? + profile.GetAudioTranscodingProfile(container, audioCodec) : + profile.GetVideoTranscodingProfile(container, audioCodec, videoCodec); + + if (transcodingProfile != null) + { + //state.EstimateContentLength = transcodingProfile.EstimateContentLength; + state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode; + //state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; + + foreach (var setting in transcodingProfile.Settings) + { + switch (setting.Name) + { + case TranscodingSettingType.VideoProfile: + { + if (state.VideoRequest != null && string.IsNullOrWhiteSpace(state.VideoRequest.VideoProfile)) + { + state.VideoRequest.VideoProfile = setting.Value; + } + break; + } + default: + throw new ArgumentException("Unrecognized TranscodingSettingType"); + } + } + } + } + + private EncodingQuality GetQualitySetting() + { + var quality = _config.Configuration.MediaEncodingQuality; + + if (quality == EncodingQuality.Auto) + { + var cpuCount = Environment.ProcessorCount; + + if (cpuCount >= 4) + { + //return EncodingQuality.HighQuality; + } + + return EncodingQuality.HighSpeed; + } + + return quality; + } + } +} diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index fac54ecfff..93df0c8b91 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -6,10 +6,10 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using System; using System.Collections.Concurrent; -using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; +using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -122,35 +122,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// Unrecognized InputType public string GetInputArgument(string[] inputFiles, InputType type) { - string inputPath; - - switch (type) - { - case InputType.Bluray: - case InputType.Dvd: - case InputType.File: - inputPath = GetConcatInputArgument(inputFiles); - break; - case InputType.Url: - inputPath = GetHttpInputArgument(inputFiles); - break; - default: - throw new ArgumentException("Unrecognized InputType"); - } - - return inputPath; - } - - /// - /// Gets the HTTP input argument. - /// - /// The input files. - /// System.String. - private string GetHttpInputArgument(string[] inputFiles) - { - var url = inputFiles[0]; - - return string.Format("\"{0}\"", url); + return EncodingUtils.GetInputArgument(inputFiles.ToList(), type == InputType.Url); } /// @@ -160,7 +132,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// System.String. public string GetProbeSizeArgument(InputType type) { - return type == InputType.Dvd ? "-probesize 1G -analyzeduration 200M" : string.Empty; + return EncodingUtils.GetProbeSizeArgument(type == InputType.Dvd); } /// @@ -879,36 +851,6 @@ namespace MediaBrowser.MediaEncoding.Encoder return memoryStream; } - /// - /// Gets the file input argument. - /// - /// The path. - /// System.String. - private string GetFileInputArgument(string path) - { - return string.Format("file:\"{0}\"", path); - } - - /// - /// Gets the concat input argument. - /// - /// The playable stream files. - /// System.String. - private string GetConcatInputArgument(string[] playableStreamFiles) - { - // Get all streams - // If there's more than one we'll need to use the concat command - if (playableStreamFiles.Length > 1) - { - var files = string.Join("|", playableStreamFiles); - - return string.Format("concat:\"{0}\"", files); - } - - // Determine the input path for video files - return GetFileInputArgument(playableStreamFiles[0]); - } - public Task EncodeImage(ImageEncodingOptions options, CancellationToken cancellationToken) { return new ImageEncoder(FFMpegPath, _logger, _fileSystem, _appPaths).EncodeImage(options, cancellationToken); -- cgit v1.2.3 From bb5386bb3a8b71406728f8bd2249cf6e02a34ed2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 31 Mar 2014 17:04:22 -0400 Subject: added more remote control commands --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 4 +- MediaBrowser.Api/SessionsService.cs | 74 +++++++++++++++++++++- .../Session/ISessionController.cs | 10 +-- MediaBrowser.Controller/Session/ISessionManager.cs | 8 +-- MediaBrowser.Dlna/PlayTo/DlnaController.cs | 44 +++++++------ .../Encoder/EncodingUtils.cs | 4 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 2 +- .../MediaBrowser.Model.Portable.csproj | 7 +- .../MediaBrowser.Model.net35.csproj | 7 +- MediaBrowser.Model/ApiClient/IApiClient.cs | 10 +-- MediaBrowser.Model/ApiClient/IServerEvents.cs | 5 +- MediaBrowser.Model/ApiClient/ServerEventArgs.cs | 4 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 3 +- MediaBrowser.Model/Session/GeneralCommand.cs | 48 ++++++++++++++ MediaBrowser.Model/Session/GenericCommand.cs | 48 -------------- MediaBrowser.Model/Session/SystemCommand.cs | 14 ---- MediaBrowser.Model/System/SystemInfo.cs | 6 ++ .../Library/Resolvers/Movies/MovieResolver.cs | 9 +-- .../Localization/JavaScript/de.json | 31 +++++++++ .../Localization/JavaScript/en_US.json | 12 +++- .../Localization/JavaScript/es.json | 31 +++++++++ .../Localization/JavaScript/fr.json | 31 +++++++++ .../Localization/JavaScript/javascript.json | 12 +++- .../Localization/JavaScript/nl.json | 31 +++++++++ .../Localization/JavaScript/pt_PT.json | 20 ++++-- .../Localization/JavaScript/ru.json | 31 +++++++++ .../Localization/JavaScript/zh_TW.json | 31 +++++++++ .../Localization/LocalizationManager.cs | 11 +++- .../Localization/Server/de.json | 37 ++++++++++- .../Localization/Server/en_US.json | 35 +++++++++- .../Localization/Server/es.json | 50 +++++++++++++++ .../Localization/Server/fr.json | 50 +++++++++++++++ .../Localization/Server/nl.json | 50 +++++++++++++++ .../Localization/Server/pt_BR.json | 50 +++++++++++++++ .../Localization/Server/pt_PT.json | 35 +++++++++- .../Localization/Server/ru.json | 49 +++++++++++--- .../Localization/Server/server.json | 35 +++++++++- .../Localization/Server/zh_TW.json | 50 +++++++++++++++ .../MediaBrowser.Server.Implementations.csproj | 11 ++++ .../Roku/RokuSessionController.cs | 14 +--- .../Session/SessionManager.cs | 8 +-- .../Session/WebSocketController.cs | 18 +----- MediaBrowser.ServerApplication/ApplicationHost.cs | 1 + MediaBrowser.WebDashboard/Api/DashboardService.cs | 2 +- 44 files changed, 855 insertions(+), 188 deletions(-) create mode 100644 MediaBrowser.Model/Session/GeneralCommand.cs delete mode 100644 MediaBrowser.Model/Session/GenericCommand.cs delete mode 100644 MediaBrowser.Model/Session/SystemCommand.cs create mode 100644 MediaBrowser.Server.Implementations/Localization/JavaScript/de.json create mode 100644 MediaBrowser.Server.Implementations/Localization/JavaScript/es.json create mode 100644 MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json create mode 100644 MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json create mode 100644 MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json create mode 100644 MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json create mode 100644 MediaBrowser.Server.Implementations/Localization/Server/es.json create mode 100644 MediaBrowser.Server.Implementations/Localization/Server/fr.json create mode 100644 MediaBrowser.Server.Implementations/Localization/Server/nl.json create mode 100644 MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json create mode 100644 MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json (limited to 'MediaBrowser.MediaEncoding/Encoder') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 5ed77356b8..e6ec38846b 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -734,7 +734,9 @@ namespace MediaBrowser.Api.Playback { if (audioStream != null) { - if (audioStream.Channels > 2 && string.Equals(request.AudioCodec, "wma", StringComparison.OrdinalIgnoreCase)) + var codec = request.AudioCodec ?? string.Empty; + + if (audioStream.Channels > 2 && codec.IndexOf("wma", StringComparison.OrdinalIgnoreCase) != -1) { // wmav2 currently only supports two channel output return 2; diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs index a509c876ce..1f3bcf75be 100644 --- a/MediaBrowser.Api/SessionsService.cs +++ b/MediaBrowser.Api/SessionsService.cs @@ -146,7 +146,36 @@ namespace MediaBrowser.Api /// /// The play command. [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public SystemCommand Command { get; set; } + public string Command { get; set; } + } + + [Route("/Sessions/{Id}/Command/{Command}", "POST", Summary = "Issues a system command to a client")] + public class SendGeneralCommand : IReturnVoid + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public Guid Id { get; set; } + + /// + /// Gets or sets the command. + /// + /// The play command. + [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public string Command { get; set; } + } + + [Route("/Sessions/{Id}/Command", "POST", Summary = "Issues a system command to a client")] + public class SendFullGeneralCommand : GeneralCommand, IReturnVoid + { + /// + /// Gets or sets the id. + /// + /// The id. + [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] + public Guid Id { get; set; } } [Route("/Sessions/{Id}/Message", "POST", Summary = "Issues a command to a client to display a message to the user")] @@ -301,9 +330,22 @@ namespace MediaBrowser.Api /// The request. public void Post(SendSystemCommand request) { - var task = _sessionManager.SendSystemCommand(GetSession().Id, request.Id, request.Command, CancellationToken.None); + GeneralCommandType commandType; - Task.WaitAll(task); + if (Enum.TryParse(request.Command, true, out commandType)) + { + var currentSession = GetSession(); + + var command = new GeneralCommand + { + Name = commandType.ToString(), + ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null + }; + + var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); + } } /// @@ -343,6 +385,32 @@ namespace MediaBrowser.Api Task.WaitAll(task); } + public void Post(SendGeneralCommand request) + { + var currentSession = GetSession(); + + var command = new GeneralCommand + { + Name = request.Command, + ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null + }; + + var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None); + + Task.WaitAll(task); + } + + public void Post(SendFullGeneralCommand request) + { + var currentSession = GetSession(); + + request.ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null; + + var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, request, CancellationToken.None); + + Task.WaitAll(task); + } + public void Post(AddUserToSession request) { _sessionManager.AddAdditionalUser(request.Id, request.UserId); diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs index 02cc875bd0..cf57f6621e 100644 --- a/MediaBrowser.Controller/Session/ISessionController.cs +++ b/MediaBrowser.Controller/Session/ISessionController.cs @@ -19,14 +19,6 @@ namespace MediaBrowser.Controller.Session /// true if this instance is session active; otherwise, false. bool IsSessionActive { get; } - /// - /// Sends the system command. - /// - /// The command. - /// The cancellation token. - /// Task. - Task SendSystemCommand(SystemCommand command, CancellationToken cancellationToken); - /// /// Sends the message command. /// @@ -65,7 +57,7 @@ namespace MediaBrowser.Controller.Session /// The command. /// The cancellation token. /// Task. - Task SendGenericCommand(GenericCommand command, CancellationToken cancellationToken); + Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken); /// /// Sends the library update info. diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 459e43d081..434c513360 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -84,15 +84,15 @@ namespace MediaBrowser.Controller.Session Task ReportSessionEnded(Guid sessionId); /// - /// Sends the system command. + /// Sends the general command. /// /// The controlling session identifier. - /// The session id. + /// The session identifier. /// The command. /// The cancellation token. /// Task. - Task SendSystemCommand(Guid controllingSessionId, Guid sessionId, SystemCommand command, CancellationToken cancellationToken); - + Task SendGeneralCommand(Guid controllingSessionId, Guid sessionId, GeneralCommand command, CancellationToken cancellationToken); + /// /// Sends the message command. /// diff --git a/MediaBrowser.Dlna/PlayTo/DlnaController.cs b/MediaBrowser.Dlna/PlayTo/DlnaController.cs index 0c9f292ad8..96df8c8622 100644 --- a/MediaBrowser.Dlna/PlayTo/DlnaController.cs +++ b/MediaBrowser.Dlna/PlayTo/DlnaController.cs @@ -308,25 +308,6 @@ namespace MediaBrowser.Dlna.PlayTo return Task.FromResult(true); } - public Task SendSystemCommand(SystemCommand command, CancellationToken cancellationToken) - { - switch (command) - { - case SystemCommand.VolumeDown: - return _device.VolumeDown(); - case SystemCommand.VolumeUp: - return _device.VolumeUp(); - case SystemCommand.Mute: - return _device.VolumeDown(true); - case SystemCommand.Unmute: - return _device.VolumeUp(true); - case SystemCommand.ToggleMute: - return _device.ToggleMute(); - default: - return Task.FromResult(true); - } - } - public Task SendUserDataChangeInfo(UserDataChangeInfo info, CancellationToken cancellationToken) { return Task.FromResult(true); @@ -620,9 +601,30 @@ namespace MediaBrowser.Dlna.PlayTo } } - public Task SendGenericCommand(GenericCommand command, CancellationToken cancellationToken) + public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken) { - throw new NotImplementedException(); + GeneralCommandType commandType; + + if (!Enum.TryParse(command.Name, true, out commandType)) + { + switch (commandType) + { + case GeneralCommandType.VolumeDown: + return _device.VolumeDown(); + case GeneralCommandType.VolumeUp: + return _device.VolumeUp(); + case GeneralCommandType.Mute: + return _device.VolumeDown(true); + case GeneralCommandType.Unmute: + return _device.VolumeUp(true); + case GeneralCommandType.ToggleMute: + return _device.ToggleMute(); + default: + return Task.FromResult(true); + } + } + + return Task.FromResult(true); } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs index 79d512dc1d..4a9023c7f3 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs @@ -180,7 +180,9 @@ namespace MediaBrowser.MediaEncoding.Encoder { if (audioStream != null) { - if (audioStream.Channels > 2 && string.Equals(request.AudioCodec, "wma", StringComparison.OrdinalIgnoreCase)) + var codec = request.AudioCodec ?? string.Empty; + + if (audioStream.Channels > 2 && codec.IndexOf("wma", StringComparison.OrdinalIgnoreCase) != -1) { // wmav2 currently only supports two channel output return 2; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 93df0c8b91..675d43be74 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -768,7 +768,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case. - var args = useIFrame ? string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2},thumbnail=80\" -f image2 \"{1}\"", inputPath, "-", vf) : + var args = useIFrame ? string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2},thumbnail=50\" -f image2 \"{1}\"", inputPath, "-", vf) : string.Format("-i {0} -threads 0 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf); var probeSize = GetProbeSizeArgument(type); diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 6c4d9d9e29..00fb2131c6 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -428,8 +428,8 @@ Session\BrowseRequest.cs - - Session\GenericCommand.cs + + Session\GeneralCommand.cs Session\MessageCommand.cs @@ -449,9 +449,6 @@ Session\SessionInfoDto.cs - - Session\SystemCommand.cs - Session\UserDataChangeInfo.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index b39cecc61d..f8bc2a600f 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -415,8 +415,8 @@ Session\BrowseRequest.cs - - Session\GenericCommand.cs + + Session\GeneralCommand.cs Session\MessageCommand.cs @@ -436,9 +436,6 @@ Session\SessionInfoDto.cs - - Session\SystemCommand.cs - Session\UserDataChangeInfo.cs diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 28c5822e9a..dc5e26be3d 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -593,17 +593,9 @@ namespace MediaBrowser.Model.ApiClient /// Sends the command asynchronous. /// /// The session identifier. - /// The request. - /// Task. - Task SendCommandAsync(string sessionId, GenericCommand request); - - /// - /// Sends a system command to the client - /// - /// The session id. /// The command. /// Task. - Task SendSystemCommandAsync(string sessionId, SystemCommand command); + Task SendCommandAsync(string sessionId, GeneralCommand command); /// /// Instructs the client to display a message to the user diff --git a/MediaBrowser.Model/ApiClient/IServerEvents.cs b/MediaBrowser.Model/ApiClient/IServerEvents.cs index 0a38c63adc..63135baa2c 100644 --- a/MediaBrowser.Model/ApiClient/IServerEvents.cs +++ b/MediaBrowser.Model/ApiClient/IServerEvents.cs @@ -1,4 +1,5 @@ -using System; +using MediaBrowser.Model.Session; +using System; namespace MediaBrowser.Model.ApiClient { @@ -66,7 +67,7 @@ namespace MediaBrowser.Model.ApiClient /// /// Occurs when [system command]. /// - event EventHandler SystemCommand; + event EventHandler GeneralCommand; /// /// Occurs when [notification added]. /// diff --git a/MediaBrowser.Model/ApiClient/ServerEventArgs.cs b/MediaBrowser.Model/ApiClient/ServerEventArgs.cs index d3212caf45..b7f709e957 100644 --- a/MediaBrowser.Model/ApiClient/ServerEventArgs.cs +++ b/MediaBrowser.Model/ApiClient/ServerEventArgs.cs @@ -152,13 +152,13 @@ namespace MediaBrowser.Model.ApiClient /// /// Class SystemCommandEventArgs /// - public class SystemCommandEventArgs : EventArgs + public class GeneralCommandEventArgs : EventArgs { /// /// Gets or sets the command. /// /// The command. - public SystemCommand Command { get; set; } + public GeneralCommand Command { get; set; } } /// diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 207543fe88..0859f69998 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -132,7 +132,7 @@ - + @@ -171,7 +171,6 @@ - diff --git a/MediaBrowser.Model/Session/GeneralCommand.cs b/MediaBrowser.Model/Session/GeneralCommand.cs new file mode 100644 index 0000000000..0de7d6dd8e --- /dev/null +++ b/MediaBrowser.Model/Session/GeneralCommand.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; + +namespace MediaBrowser.Model.Session +{ + public class GeneralCommand + { + public string Name { get; set; } + + public string ControllingUserId { get; set; } + + public Dictionary Arguments { get; set; } + + public GeneralCommand() + { + Arguments = new Dictionary(StringComparer.OrdinalIgnoreCase); + } + } + + /// + /// This exists simply to identify a set of known commands. + /// + public enum GeneralCommandType + { + MoveUp = 0, + MoveDown = 1, + MoveLeft = 2, + MoveRight = 3, + PageUp = 4, + PageDown = 5, + PreviousLetter = 6, + NextLetter = 7, + ToggleOsd = 8, + ToggleContextMenu = 9, + Select = 10, + Back = 11, + TakeScreenshot = 12, + SendKey = 13, + SendString = 14, + GoHome = 15, + GoToSettings = 16, + VolumeUp = 17, + VolumeDown = 18, + Mute = 19, + Unmute = 20, + ToggleMute = 21 + } +} diff --git a/MediaBrowser.Model/Session/GenericCommand.cs b/MediaBrowser.Model/Session/GenericCommand.cs deleted file mode 100644 index f7ea0a84a5..0000000000 --- a/MediaBrowser.Model/Session/GenericCommand.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Model.Session -{ - public class GenericCommand - { - public string Name { get; set; } - - public string ControllingUserId { get; set; } - - public Dictionary Arguments { get; set; } - - public GenericCommand() - { - Arguments = new Dictionary(StringComparer.OrdinalIgnoreCase); - } - } - - /// - /// This exists simply to identify a set of known commands. - /// - public enum CoreGenericCommand - { - MoveUp = 0, - MoveDown = 1, - MoveLeft = 2, - MoveRight = 3, - PageUp = 4, - PageDown = 5, - PreviousLetter = 6, - NextLetter = 7, - ToggleOsd = 8, - ToggleContextMenu = 9, - Select = 10, - Back = 11, - TakeScreenshot = 12, - SendKey = 13, - SendString = 14, - GoHome = 15, - GoToSettings = 16, - VolumeUp = 17, - VolumeDown = 18, - Mute = 19, - Unmute = 20, - ToggleMute = 21 - } -} diff --git a/MediaBrowser.Model/Session/SystemCommand.cs b/MediaBrowser.Model/Session/SystemCommand.cs deleted file mode 100644 index 2fcaef6e39..0000000000 --- a/MediaBrowser.Model/Session/SystemCommand.cs +++ /dev/null @@ -1,14 +0,0 @@ - -namespace MediaBrowser.Model.Session -{ - public enum SystemCommand - { - GoHome, - GoToSettings, - VolumeUp, - VolumeDown, - Mute, - Unmute, - ToggleMute - } -} diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index ec31c55295..5b1e7d6bb9 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -116,6 +116,12 @@ namespace MediaBrowser.Model.System /// The log path. public string LogPath { get; set; } + /// + /// Gets or sets the internal metadata path. + /// + /// The internal metadata path. + public string InternalMetadataPath { get; set; } + /// /// Gets or sets the transcoding temporary path. /// diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 13a1e8f165..558087a252 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -115,22 +115,19 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies } // Find movies that are mixed in the same folder - if (args.Path.IndexOf("[trailers]", StringComparison.OrdinalIgnoreCase) != -1 || - string.Equals(collectionType, CollectionType.Trailers, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(collectionType, CollectionType.Trailers, StringComparison.OrdinalIgnoreCase)) { return ResolveVideo(args); } Video item = null; - if (args.Path.IndexOf("[musicvideos]", StringComparison.OrdinalIgnoreCase) != -1 || - string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { item = ResolveVideo(args); } - if (args.Path.IndexOf("[adultvideos]", StringComparison.OrdinalIgnoreCase) != -1 || - string.Equals(collectionType, CollectionType.AdultVideos, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(collectionType, CollectionType.AdultVideos, StringComparison.OrdinalIgnoreCase)) { item = ResolveVideo(args); } diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json new file mode 100644 index 0000000000..12cdb7035e --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json @@ -0,0 +1,31 @@ +{ + "SettingsSaved": "Einstellungen gespeichert", + "AddUser": "Benutzer hinzuf\u00fcgen", + "Users": "Benutzer", + "Delete": "L\u00f6schen", + "Administrator": "Administrator", + "Password": "Passwort", + "CreatePassword": "Passwort erstellen", + "DeleteImage": "Bild l\u00f6schen", + "DeleteImageConfirmation": "M\u00f6chten Sie das Bild wirklich l\u00f6schen?", + "FileReadCancelled": "Das Einlesen der Datei wurde abgebrochen.", + "FileNotFound": "Datei nicht gefunden", + "FileReadError": "Beim Lesen der Datei ist ein Fehler aufgetreten.", + "DeleteUser": "Benutzer l\u00f6schen", + "DeleteUserConfirmation": "M\u00f6chten Sie {0} wirklich l\u00f6schen?", + "PasswordResetHeader": "Passwort zur\u00fccksetzen", + "PasswordResetComplete": "Das Passwort wurde zur\u00fcckgesetzt.", + "PasswordResetConfirmation": "M\u00f6chten Sie das Passwort wirklich zur\u00fccksetzen?", + "PasswordSaved": "Passwort gespeichert", + "PasswordMatchError": "Passwort und Passwortbest\u00e4tigung stimmen nicht \u00fcberein.", + "OptionOff": "Aus", + "OptionOn": "Ein", + "OptionRelease": "Release", + "OptionBeta": "Beta", + "OptionDev": "Dev", + "UninstallPluginHeader": "Deinstalliere Plugin", + "UninstallPluginConfirmation": "M\u00f6chten Sie {0} wirklich deinstallieren?", + "NoPluginConfigurationMessage": "Bei diesem Plugin kann nichts eingestellt werden.", + "NoPluginsInstalledMessage": "Sie haben keine Plugins installiert.", + "BrowsePluginCatalogMessage": "Durchsuchen Sie unsere Bibliothek um alle verf\u00fcgbaren Plugins anzuzeigen." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json index 45f0d7e133..7184d47247 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json @@ -17,5 +17,15 @@ "PasswordResetComplete": "The password has been reset.", "PasswordResetConfirmation": "Are you sure you wish to reset the password?", "PasswordSaved": "Password saved.", - "PasswordMatchError": "Password and password confirmation must match." + "PasswordMatchError": "Password and password confirmation must match.", + "OptionOff": "Off", + "OptionOn": "On", + "OptionRelease": "Release", + "OptionBeta": "Beta", + "OptionDev": "Dev", + "UninstallPluginHeader": "Uninstall Plugin", + "UninstallPluginConfirmation": "Are you sure you wish to uninstall {0}?", + "NoPluginConfigurationMessage": "This plugin has nothing to configure.", + "NoPluginsInstalledMessage": "You have no plugins installed.", + "BrowsePluginCatalogMessage": "Browse our plugin catalog to view available plugins." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json new file mode 100644 index 0000000000..b0b9fd1a91 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json @@ -0,0 +1,31 @@ +{ + "SettingsSaved": "Configuracion guardada", + "AddUser": "Agregar usuario", + "Users": "Usuarios", + "Delete": "Borrar", + "Administrator": "Administrador", + "Password": "Contrase\u00f1a", + "CreatePassword": "Crear Contrase\u00f1a", + "DeleteImage": "Borrar Imagen", + "DeleteImageConfirmation": "Esta seguro que desea borrar esta imagen?", + "FileReadCancelled": "La lectura del archivo se ha cancelado.", + "FileNotFound": "Archivo no encontrado.", + "FileReadError": "Se encontr\u00f3 un error al leer el archivo.", + "DeleteUser": "Borrar Usuario", + "DeleteUserConfirmation": "Esta seguro que desea eliminar a {0}?", + "PasswordResetHeader": "Restablecer contrase\u00f1a", + "PasswordResetComplete": "La contrase\u00f1a se ha restablecido.", + "PasswordResetConfirmation": "Esta seguro que desea restablecer la contrase\u00f1a?", + "PasswordSaved": "Contrase\u00f1a guardada.", + "PasswordMatchError": "La contrase\u00f1a y la confirmaci\u00f3n de la contrase\u00f1a deben de ser iguales.", + "OptionOff": "Apagado", + "OptionOn": "Prendido", + "OptionRelease": "Liberar", + "OptionBeta": "Beta", + "OptionDev": "Desarrollo", + "UninstallPluginHeader": "Desinstalar Plugin", + "UninstallPluginConfirmation": "Esta seguro que desea desinstalar {0}?", + "NoPluginConfigurationMessage": "El plugin no requiere configuraci\u00f3n", + "NoPluginsInstalledMessage": "No tiene plugins instalados.", + "BrowsePluginCatalogMessage": "Navegar el catalogo de plugins para ver los plugins disponibles." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json new file mode 100644 index 0000000000..9e1ebbfee6 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json @@ -0,0 +1,31 @@ +{ + "SettingsSaved": "Param\u00e8tres sauvegard\u00e9s.", + "AddUser": "Ajout\u00e9 Usager", + "Users": "Usagers", + "Delete": "Supprimer", + "Administrator": "Administrateur", + "Password": "Mot de passe", + "CreatePassword": "Cr\u00e9er mot de passe", + "DeleteImage": "Supprimer Image", + "DeleteImageConfirmation": "\u00cates-vous s\u00fbr de vouloir supprimer l'image?", + "FileReadCancelled": "La lecture du fichier a \u00e9t\u00e9 annul\u00e9e.", + "FileNotFound": "Fichier non trouv\u00e9", + "FileReadError": "Un erreur est survenue pendant la lecture du fichier.", + "DeleteUser": "Supprimer Usager", + "DeleteUserConfirmation": "\u00cates-vous s\u00fbr de vouloir supprimer {0}?", + "PasswordResetHeader": "Red\u00e9marrage du mot de passe", + "PasswordResetComplete": "Le mot de passe a \u00e9t\u00e9 red\u00e9marr\u00e9.", + "PasswordResetConfirmation": "\u00cates-vous s\u00fbr de vouloir red\u00e9marrer le mot de passe?", + "PasswordSaved": "Mot de passe sauvegard\u00e9.", + "PasswordMatchError": "Mot de passe et confirmation de mot de passe doivent correspondre.", + "OptionOff": "Off", + "OptionOn": "On", + "OptionRelease": "Lancement", + "OptionBeta": "Beta", + "OptionDev": "Dev", + "UninstallPluginHeader": "D\u00e9sinstaller module d'extention", + "UninstallPluginConfirmation": "\u00cates-vous s\u00fbr de vouloir d\u00e9sinstaller {0}?", + "NoPluginConfigurationMessage": "Ce module d'extension n'a rien \u00e0 configurer.", + "NoPluginsInstalledMessage": "Vous n'avez aucun module d'extension install\u00e9.", + "BrowsePluginCatalogMessage": "Explorer notre catalogue de modules d'extension pour voir ce qui est disponible." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json index 41f8508a5f..6b014bf34f 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json @@ -17,5 +17,15 @@ "PasswordResetComplete": "The password has been reset.", "PasswordResetConfirmation": "Are you sure you wish to reset the password?", "PasswordSaved": "Password saved.", - "PasswordMatchError": "Password and password confirmation must match." + "PasswordMatchError": "Password and password confirmation must match.", + "OptionOff": "Off", + "OptionOn": "On", + "OptionRelease": "Release", + "OptionBeta": "Beta", + "OptionDev": "Dev", + "UninstallPluginHeader": "Uninstall Plugin", + "UninstallPluginConfirmation": "Are you sure you wish to uninstall {0}?", + "NoPluginConfigurationMessage": "This plugin has nothing to configure.", + "NoPluginsInstalledMessage": "You have no plugins installed.", + "BrowsePluginCatalogMessage": "Browse our plugin catalog to view available plugins." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json new file mode 100644 index 0000000000..17a343283c --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json @@ -0,0 +1,31 @@ +{ + "SettingsSaved": "Instellingen opgeslagen.", + "AddUser": "Gebruiker toevoegen", + "Users": "Gebruikers", + "Delete": "Verwijderen", + "Administrator": "Beheerder", + "Password": "Wachtwoord", + "CreatePassword": "Maak wachtwoord", + "DeleteImage": "Verwijder afbeelding", + "DeleteImageConfirmation": "Weet je zeker dat je deze afbeelding wilt verwijderen?", + "FileReadCancelled": "Het lezen van het bestand is geannuleerd", + "FileNotFound": "Bestand niet gevonden.", + "FileReadError": "Er is een fout opgetreden bij het lezen van het bestand.", + "DeleteUser": "Verwijder gebruiker", + "DeleteUserConfirmation": "Weet je zeker dat je {0} wilt verwijderen?", + "PasswordResetHeader": "Wachtwoord opnieuw instellen", + "PasswordResetComplete": "Het wachtwoord is opnieuw ingesteld.", + "PasswordResetConfirmation": "Weet je zeker dat je het wachtwoord opnieuw in wilt stellen?", + "PasswordSaved": "Wachtwoord opgeslagen.", + "PasswordMatchError": "Wachtwoord en wachtwoord bevestiging moeten hetzelfde zijn.", + "OptionOff": "Uit", + "OptionOn": "Aan", + "OptionRelease": "Release", + "OptionBeta": "Beta", + "OptionDev": "Dev", + "UninstallPluginHeader": "Deinstalleer Plugin", + "UninstallPluginConfirmation": "Weet u zeker dat u {0} wilt deinstalleren?", + "NoPluginConfigurationMessage": "Deze plugin heeft niets in te stellen", + "NoPluginsInstalledMessage": "U heeft geen plugins geinstalleerd", + "BrowsePluginCatalogMessage": "Blader door de Plugincatalogus voor beschikbare plugins." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json index 25d3ff9442..e81a18e798 100644 --- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json @@ -8,14 +8,24 @@ "CreatePassword": "Criar Senha", "DeleteImage": "Apagar Imagem", "DeleteImageConfirmation": "Tem a certeza que pretende apagar a imagem?", - "FileReadCancelled": "The file read has been cancelled.", + "FileReadCancelled": "A leitura do ficheiro foi cancelada.", "FileNotFound": "Ficheiro n\u00e3o encontrado", "FileReadError": "Ocorreu um erro ao ler o ficheiro.", "DeleteUser": "Apagar Utilizador", "DeleteUserConfirmation": "Tem a certeza que pretende apagar {0}?", - "PasswordResetHeader": "Password Reset", - "PasswordResetComplete": "The password has been reset.", - "PasswordResetConfirmation": "Are you sure you wish to reset the password?", + "PasswordResetHeader": "Redefinir Senha", + "PasswordResetComplete": "A senha foi redefinida.", + "PasswordResetConfirmation": "Tem a certeza que pretende redefinir a senha?", "PasswordSaved": "Senha guardada.", - "PasswordMatchError": "Password and password confirmation must match." + "PasswordMatchError": "A senha e a confirma\u00e7\u00e3o da senha devem coincidir.", + "OptionOff": "Desligado", + "OptionOn": "Ligado", + "OptionRelease": "Final", + "OptionBeta": "Beta", + "OptionDev": "Dev", + "UninstallPluginHeader": "Desinstalar extens\u00e3o", + "UninstallPluginConfirmation": "Tem a certeza que pretende desinstalar {0}?", + "NoPluginConfigurationMessage": "Esta extens\u00e3o n\u00e3o \u00e9 configur\u00e1vel.", + "NoPluginsInstalledMessage": "N\u00e3o tem extens\u00f5es instaladas.", + "BrowsePluginCatalogMessage": "Navegue o nosso cat\u00e1logo de extens\u00f5es para ser as extens\u00f5es dispon\u00edveis." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json new file mode 100644 index 0000000000..b54e3f1296 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json @@ -0,0 +1,31 @@ +{ + "SettingsSaved": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b", + "AddUser": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f", + "Users": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438", + "Delete": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c", + "Administrator": "\u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440", + "Password": "\u041f\u0430\u0440\u043e\u043b\u044c", + "CreatePassword": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c", + "DeleteImage": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435", + "DeleteImageConfirmation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u0442\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435?", + "FileReadCancelled": "\u0427\u0442\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0431\u044b\u043b\u043e \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u043e", + "FileNotFound": "\u0424\u0430\u0439\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d", + "FileReadError": "\u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430", + "DeleteUser": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f", + "DeleteUserConfirmation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c {0}?", + "PasswordResetHeader": "\u0421\u0431\u0440\u043e\u0441 \u043f\u0430\u0440\u043e\u043b\u044f", + "PasswordResetComplete": "\u041f\u0430\u0440\u043e\u043b\u044c \u0431\u044b\u043b \u0441\u0431\u0440\u043e\u0448\u0435\u043d", + "PasswordResetConfirmation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0441\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c?", + "PasswordSaved": "\u041f\u0430\u0440\u043e\u043b\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d", + "PasswordMatchError": "\u041f\u043e\u043b\u044f \u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u043e\u043b\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c", + "OptionOff": "\u0412\u044b\u043a\u043b.", + "OptionOn": "\u0412\u043a\u043b.", + "OptionRelease": "\u0412\u044b\u043f\u0443\u0441\u043a", + "OptionBeta": "\u0411\u0435\u0442\u0430", + "OptionDev": "\u0420\u0430\u0437\u0440\u0430\u0431.", + "UninstallPluginHeader": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d", + "UninstallPluginConfirmation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c {0}?", + "NoPluginConfigurationMessage": "\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043d\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a", + "NoPluginsInstalledMessage": "\u0423 \u0412\u0430\u0441 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430.", + "BrowsePluginCatalogMessage": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043d\u0430\u0448 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u0434\u043b\u044f \u043e\u0431\u0437\u043e\u0440\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json new file mode 100644 index 0000000000..ca7b3a7c75 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json @@ -0,0 +1,31 @@ +{ + "SettingsSaved": "\u8a2d\u7f6e\u5df2\u4fdd\u5b58", + "AddUser": "Add User", + "Users": "\u7528\u6236", + "Delete": "\u522a\u9664", + "Administrator": "\u7ba1\u7406\u54e1", + "Password": "\u5bc6\u78bc", + "CreatePassword": "\u5275\u5efa\u5bc6\u78bc", + "DeleteImage": "\u522a\u9664\u5716\u50cf", + "DeleteImageConfirmation": "\u4f60\u78ba\u5b9a\u8981\u522a\u9664\u9019\u5f35\u5716\u7247\uff1f", + "FileReadCancelled": "The file read has been cancelled.", + "FileNotFound": "File not found.", + "FileReadError": "An error occurred while reading the file.", + "DeleteUser": "\u522a\u9664\u7528\u6236", + "DeleteUserConfirmation": "Are you sure you wish to delete {0}?", + "PasswordResetHeader": "\u91cd\u8a2d\u5bc6\u78bc", + "PasswordResetComplete": "\u5bc6\u78bc\u5df2\u91cd\u8a2d", + "PasswordResetConfirmation": "\u4f60\u78ba\u5b9a\u8981\u91cd\u8a2d\u5bc6\u78bc\uff1f", + "PasswordSaved": "\u5bc6\u78bc\u5df2\u4fdd\u5b58\u3002", + "PasswordMatchError": "\u5bc6\u78bc\u548c\u78ba\u8a8d\u5bc6\u78bc\u5fc5\u9808\u4e00\u81f4\u3002", + "OptionOff": "Off", + "OptionOn": "On", + "OptionRelease": "Release", + "OptionBeta": "Beta", + "OptionDev": "Dev", + "UninstallPluginHeader": "Uninstall Plugin", + "UninstallPluginConfirmation": "Are you sure you wish to uninstall {0}?", + "NoPluginConfigurationMessage": "This plugin has nothing to configure.", + "NoPluginsInstalledMessage": "You have no plugins installed.", + "BrowsePluginCatalogMessage": "Browse our plugin catalog to view available plugins." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs index 6f39c67597..9b907ef747 100644 --- a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs +++ b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.IO; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Localization; using MediaBrowser.Model.Entities; @@ -12,7 +13,6 @@ using System.Globalization; using System.IO; using System.Linq; using System.Reflection; -using MediaBrowser.Common.Extensions; namespace MediaBrowser.Server.Implementations.Localization { @@ -334,9 +334,14 @@ namespace MediaBrowser.Server.Implementations.Localization return new List { new LocalizatonOption{ Name="English (United States)", Value="en-us"}, + new LocalizatonOption{ Name="Chinese Traditional", Value="zh-TW"}, + new LocalizatonOption{ Name="Dutch", Value="nl"}, + new LocalizatonOption{ Name="French", Value="fr"}, new LocalizatonOption{ Name="German", Value="de"}, + new LocalizatonOption{ Name="Portuguese (Brazil)", Value="pt-BR"}, new LocalizatonOption{ Name="Portuguese (Portugal)", Value="pt-PT"}, - new LocalizatonOption{ Name="Russian", Value="ru"} + new LocalizatonOption{ Name="Russian", Value="ru"}, + new LocalizatonOption{ Name="Spanish", Value="es"} }.OrderBy(i => i.Name); } diff --git a/MediaBrowser.Server.Implementations/Localization/Server/de.json b/MediaBrowser.Server.Implementations/Localization/Server/de.json index ab3271b50f..0aeaf3c502 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/de.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/de.json @@ -4,7 +4,7 @@ "LabelGithubWiki": "Github Wiki", "LabelSwagger": "Swagger", "LabelStandard": "Standard", - "LabelViewApiDocumentation": "Zeige Api Dokumentation", + "LabelViewApiDocumentation": "Zeige API Dokumentation", "LabelBrowseLibrary": "Durchsuche Bibliothek", "LabelConfigureMediaBrowser": "Konfiguriere Media Browser", "LabelOpenLibraryViewer": "\u00d6ffne Bibliothekenansicht", @@ -13,5 +13,38 @@ "LabelPrevious": "Vorheriges", "LabelFinish": "Ende", "LabelNext": "N\u00e4chstes", - "LabelYoureDone": "Du bist fertig!" + "LabelYoureDone": "Du bist fertig!", + "WelcomeToMediaBrowser": "Welcome to Media Browser!", + "LabelMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process.", + "TellUsAboutYourself": "Tell us about yourself", + "LabelYourFirstName": "Your first name:", + "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click Finish<\/b> to view the Dashboard<\/b>.", + "LabelConfigureSettings": "Configure settings", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "ButtonOk": "Ok", + "ButtonCancel": "Cancel", + "HeaderSetupLibrary": "Setup your media library", + "ButtonAddMediaFolder": "Add media folder", + "LabelFolderType": "Folder type:", + "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.", + "ReferToMediaLibraryWiki": "Refer to the media library wiki.", + "LabelCountry": "Country:", + "LabelLanguage": "Language:", + "HeaderPreferredMetadataLanguage": "Preferred metadata language:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json index f74cca1eb1..40269bde39 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json @@ -13,5 +13,38 @@ "LabelPrevious": "Previous", "LabelFinish": "Finish", "LabelNext": "Next", - "LabelYoureDone": "You're Done!" + "LabelYoureDone": "You're Done!", + "WelcomeToMediaBrowser": "Welcome to Media Browser!", + "LabelMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process.", + "TellUsAboutYourself": "Tell us about yourself", + "LabelYourFirstName": "Your first name:", + "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click Finish<\/b> to view the Dashboard<\/b>.", + "LabelConfigureSettings": "Configure settings", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "ButtonOk": "Ok", + "ButtonCancel": "Cancel", + "HeaderSetupLibrary": "Setup your media library", + "ButtonAddMediaFolder": "Add media folder", + "LabelFolderType": "Folder type:", + "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.", + "ReferToMediaLibraryWiki": "Refer to the media library wiki.", + "LabelCountry": "Country:", + "LabelLanguage": "Language:", + "HeaderPreferredMetadataLanguage": "Preferred metadata language:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es.json b/MediaBrowser.Server.Implementations/Localization/Server/es.json new file mode 100644 index 0000000000..f475e1db4d --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/Server/es.json @@ -0,0 +1,50 @@ +{ + "LabelExit": "Salir", + "LabelVisitCommunity": "Visitar la comunidad", + "LabelGithubWiki": "Wiki de Github", + "LabelSwagger": "Swagger", + "LabelStandard": "Estandar", + "LabelViewApiDocumentation": "Ver documentacion de Api", + "LabelBrowseLibrary": "Navegar biblioteca", + "LabelConfigureMediaBrowser": "Configurar Media Browser", + "LabelOpenLibraryViewer": "Abrir el visor de la biblioteca", + "LabelRestartServer": "reiniciar el servidor", + "LabelShowLogWindow": "Mostrar la ventana del log", + "LabelPrevious": "Anterior", + "LabelFinish": "Terminar", + "LabelNext": "Siguiente", + "LabelYoureDone": "Ha Terminado!", + "WelcomeToMediaBrowser": "Welcome to Media Browser!", + "LabelMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process.", + "TellUsAboutYourself": "Tell us about yourself", + "LabelYourFirstName": "Your first name:", + "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click Finish<\/b> to view the Dashboard<\/b>.", + "LabelConfigureSettings": "Configure settings", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "ButtonOk": "Ok", + "ButtonCancel": "Cancel", + "HeaderSetupLibrary": "Setup your media library", + "ButtonAddMediaFolder": "Add media folder", + "LabelFolderType": "Folder type:", + "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.", + "ReferToMediaLibraryWiki": "Refer to the media library wiki.", + "LabelCountry": "Country:", + "LabelLanguage": "Language:", + "HeaderPreferredMetadataLanguage": "Preferred metadata language:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/fr.json b/MediaBrowser.Server.Implementations/Localization/Server/fr.json new file mode 100644 index 0000000000..038fb56077 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/Server/fr.json @@ -0,0 +1,50 @@ +{ + "LabelExit": "Quitter", + "LabelVisitCommunity": "Visiter Communaut\u00e9", + "LabelGithubWiki": "GitHub Wiki", + "LabelSwagger": "Swagger", + "LabelStandard": "Standard", + "LabelViewApiDocumentation": "Consulter la documentation API", + "LabelBrowseLibrary": "Naviguer la biblioth\u00e8que", + "LabelConfigureMediaBrowser": "Configurer Media Browser", + "LabelOpenLibraryViewer": "Ouvrir le navigateur de biblioth\u00e8que", + "LabelRestartServer": "Red\u00e9marrer Serveur", + "LabelShowLogWindow": "Afficher la fen\u00eatre du journal d'\u00e9v\u00e8nements", + "LabelPrevious": "Pr\u00e9c\u00e9dant", + "LabelFinish": "Termin\u00e9", + "LabelNext": "Suivant", + "LabelYoureDone": "Vous avez Termin\u00e9!", + "WelcomeToMediaBrowser": "Welcome to Media Browser!", + "LabelMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process.", + "TellUsAboutYourself": "Tell us about yourself", + "LabelYourFirstName": "Your first name:", + "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click Finish<\/b> to view the Dashboard<\/b>.", + "LabelConfigureSettings": "Configure settings", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "ButtonOk": "Ok", + "ButtonCancel": "Cancel", + "HeaderSetupLibrary": "Setup your media library", + "ButtonAddMediaFolder": "Add media folder", + "LabelFolderType": "Folder type:", + "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.", + "ReferToMediaLibraryWiki": "Refer to the media library wiki.", + "LabelCountry": "Country:", + "LabelLanguage": "Language:", + "HeaderPreferredMetadataLanguage": "Preferred metadata language:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/nl.json b/MediaBrowser.Server.Implementations/Localization/Server/nl.json new file mode 100644 index 0000000000..0fcf20a537 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/Server/nl.json @@ -0,0 +1,50 @@ +{ + "LabelExit": "Afsluiten", + "LabelVisitCommunity": "Bezoek de community", + "LabelGithubWiki": "Github Wiki", + "LabelSwagger": "Swagger", + "LabelStandard": "Standaard", + "LabelViewApiDocumentation": "Bekijk Api documentatie", + "LabelBrowseLibrary": "Bekijk bibliotheek", + "LabelConfigureMediaBrowser": "Configureer Media Browser", + "LabelOpenLibraryViewer": "Open bibliotheek verkenner", + "LabelRestartServer": "Herstart server", + "LabelShowLogWindow": "Toon log venster", + "LabelPrevious": "Vorige", + "LabelFinish": "Finish", + "LabelNext": "Volgende", + "LabelYoureDone": "Gereed!", + "WelcomeToMediaBrowser": "Welcome to Media Browser!", + "LabelMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process.", + "TellUsAboutYourself": "Tell us about yourself", + "LabelYourFirstName": "Your first name:", + "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click Finish<\/b> to view the Dashboard<\/b>.", + "LabelConfigureSettings": "Configure settings", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "ButtonOk": "Ok", + "ButtonCancel": "Cancel", + "HeaderSetupLibrary": "Setup your media library", + "ButtonAddMediaFolder": "Add media folder", + "LabelFolderType": "Folder type:", + "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.", + "ReferToMediaLibraryWiki": "Refer to the media library wiki.", + "LabelCountry": "Country:", + "LabelLanguage": "Language:", + "HeaderPreferredMetadataLanguage": "Preferred metadata language:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json new file mode 100644 index 0000000000..a7997e5a2b --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json @@ -0,0 +1,50 @@ +{ + "LabelExit": "Sair", + "LabelVisitCommunity": "Visite o Community", + "LabelGithubWiki": "Wiki do Github", + "LabelSwagger": "Swagger", + "LabelStandard": "Standard", + "LabelViewApiDocumentation": "View Api Documentation", + "LabelBrowseLibrary": "Browse Library", + "LabelConfigureMediaBrowser": "Configure Media Browser", + "LabelOpenLibraryViewer": "Open Library Viewer", + "LabelRestartServer": "Restart Server", + "LabelShowLogWindow": "Show Log Window", + "LabelPrevious": "Previous", + "LabelFinish": "Finish", + "LabelNext": "Next", + "LabelYoureDone": "You're Done!", + "WelcomeToMediaBrowser": "Welcome to Media Browser!", + "LabelMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process.", + "TellUsAboutYourself": "Tell us about yourself", + "LabelYourFirstName": "Your first name:", + "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click Finish<\/b> to view the Dashboard<\/b>.", + "LabelConfigureSettings": "Configure settings", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "ButtonOk": "Ok", + "ButtonCancel": "Cancel", + "HeaderSetupLibrary": "Setup your media library", + "ButtonAddMediaFolder": "Add media folder", + "LabelFolderType": "Folder type:", + "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.", + "ReferToMediaLibraryWiki": "Refer to the media library wiki.", + "LabelCountry": "Country:", + "LabelLanguage": "Language:", + "HeaderPreferredMetadataLanguage": "Preferred metadata language:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json index 7003147086..9fddc4f98c 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json @@ -13,5 +13,38 @@ "LabelPrevious": "Anterior", "LabelFinish": "Terminar", "LabelNext": "Seguinte", - "LabelYoureDone": "Concluiu!" + "LabelYoureDone": "Concluiu!", + "WelcomeToMediaBrowser": "Welcome to Media Browser!", + "LabelMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process.", + "TellUsAboutYourself": "Tell us about yourself", + "LabelYourFirstName": "Your first name:", + "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click Finish<\/b> to view the Dashboard<\/b>.", + "LabelConfigureSettings": "Configure settings", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "ButtonOk": "Ok", + "ButtonCancel": "Cancel", + "HeaderSetupLibrary": "Setup your media library", + "ButtonAddMediaFolder": "Add media folder", + "LabelFolderType": "Folder type:", + "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.", + "ReferToMediaLibraryWiki": "Refer to the media library wiki.", + "LabelCountry": "Country:", + "LabelLanguage": "Language:", + "HeaderPreferredMetadataLanguage": "Preferred metadata language:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ru.json b/MediaBrowser.Server.Implementations/Localization/Server/ru.json index 4cc6b90f7f..5b673132ee 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/ru.json @@ -2,16 +2,49 @@ "LabelExit": "\u0412\u044b\u0445\u043e\u0434", "LabelVisitCommunity": "\u041f\u043e\u0441\u0435\u0442\u0438\u0442\u044c \u0421\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e", "LabelGithubWiki": "\u0412\u0438\u043a\u0438 \u043d\u0430 Github", - "LabelSwagger": "\u041e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435", - "LabelStandard": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439", + "LabelSwagger": "\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Swagger", + "LabelStandard": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f", "LabelViewApiDocumentation": "\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e API", "LabelBrowseLibrary": "\u041e\u0431\u043e\u0437\u0440\u0435\u0432\u0430\u0442\u0435\u043b\u044c \u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438", - "LabelConfigureMediaBrowser": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Media Browser", - "LabelOpenLibraryViewer": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438", - "LabelRestartServer": "\u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440", - "LabelShowLogWindow": "\u041e\u043a\u043d\u043e \u0416\u0443\u0440\u043d\u0430\u043b\u0430", + "LabelConfigureMediaBrowser": "\u041d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c Media Browser", + "LabelOpenLibraryViewer": "\u0418\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0443", + "LabelRestartServer": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440", + "LabelShowLogWindow": "\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0416\u0443\u0440\u043d\u0430\u043b \u0432 \u043e\u043a\u043d\u0435", "LabelPrevious": "\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435", - "LabelFinish": "\u0417\u0430\u043a\u043e\u043d\u0447\u0438\u0442\u044c", + "LabelFinish": "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c", "LabelNext": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435", - "LabelYoureDone": "\u0412\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0438!" + "LabelYoureDone": "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e!", + "WelcomeToMediaBrowser": "Welcome to Media Browser!", + "LabelMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process.", + "TellUsAboutYourself": "Tell us about yourself", + "LabelYourFirstName": "Your first name:", + "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click Finish<\/b> to view the Dashboard<\/b>.", + "LabelConfigureSettings": "Configure settings", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "ButtonOk": "Ok", + "ButtonCancel": "Cancel", + "HeaderSetupLibrary": "Setup your media library", + "ButtonAddMediaFolder": "Add media folder", + "LabelFolderType": "Folder type:", + "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.", + "ReferToMediaLibraryWiki": "Refer to the media library wiki.", + "LabelCountry": "Country:", + "LabelLanguage": "Language:", + "HeaderPreferredMetadataLanguage": "Preferred metadata language:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 62a4183911..9630509d3b 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -13,5 +13,38 @@ "LabelPrevious": "Previous", "LabelFinish": "Finish", "LabelNext": "Next", - "LabelYoureDone": "You're Done!" + "LabelYoureDone": "You're Done!", + "WelcomeToMediaBrowser": "Welcome to Media Browser!", + "LabelMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process.", + "TellUsAboutYourself": "Tell us about yourself", + "LabelYourFirstName": "Your first name:", + "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click Finish to view the Dashboard.", + "LabelConfigureSettings": "Configure settings", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "ButtonOk": "Ok", + "ButtonCancel": "Cancel", + "HeaderSetupLibrary": "Setup your media library", + "ButtonAddMediaFolder": "Add media folder", + "LabelFolderType": "Folder type:", + "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.", + "ReferToMediaLibraryWiki": "Refer to the media library wiki.", + "LabelCountry": "Country:", + "LabelLanguage": "Language:", + "HeaderPreferredMetadataLanguage": "Preferred metadata language:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json new file mode 100644 index 0000000000..6084c1511f --- /dev/null +++ b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json @@ -0,0 +1,50 @@ +{ + "LabelExit": "\u96e2\u958b", + "LabelVisitCommunity": "\u8a2a\u554f\u793e\u5340", + "LabelGithubWiki": "Github Wiki", + "LabelSwagger": "Swagger", + "LabelStandard": "\u6a19\u6dee", + "LabelViewApiDocumentation": "View Api Documentation", + "LabelBrowseLibrary": "Browse Library", + "LabelConfigureMediaBrowser": "Configure Media Browser", + "LabelOpenLibraryViewer": "Open Library Viewer", + "LabelRestartServer": "\u91cd\u65b0\u555f\u52d5\u670d\u52d9\u5668", + "LabelShowLogWindow": "\u986f\u793a\u65e5\u8a8c\u8996\u7a97", + "LabelPrevious": "\u4e0a\u4e00\u500b", + "LabelFinish": "\u5b8c\u7d50", + "LabelNext": "\u4e0b\u4e00\u500b", + "LabelYoureDone": "You're Done!", + "WelcomeToMediaBrowser": "Welcome to Media Browser!", + "LabelMediaBrowser": "Media Browser", + "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process.", + "TellUsAboutYourself": "Tell us about yourself", + "LabelYourFirstName": "Your first name:", + "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.", + "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.", + "LabelWindowsService": "Windows Service", + "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.", + "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.", + "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.", + "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click Finish<\/b> to view the Dashboard<\/b>.", + "LabelConfigureSettings": "Configure settings", + "LabelEnableVideoImageExtraction": "Enable video image extraction", + "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.", + "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies", + "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelEnableAutomaticPortMapping": "Enable automatic port mapping", + "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.", + "ButtonOk": "Ok", + "ButtonCancel": "Cancel", + "HeaderSetupLibrary": "Setup your media library", + "ButtonAddMediaFolder": "Add media folder", + "LabelFolderType": "Folder type:", + "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.", + "ReferToMediaLibraryWiki": "Refer to the media library wiki.", + "LabelCountry": "Country:", + "LabelLanguage": "Language:", + "HeaderPreferredMetadataLanguage": "Preferred metadata language:", + "LabelSaveLocalMetadata": "Save artwork and metadata into media folders", + "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.", + "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet", + "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations." +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 539b968c72..d06cf01812 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -290,6 +290,17 @@ + + + + + + + + + + + diff --git a/MediaBrowser.Server.Implementations/Roku/RokuSessionController.cs b/MediaBrowser.Server.Implementations/Roku/RokuSessionController.cs index 7c8d71b4f0..608e92b24c 100644 --- a/MediaBrowser.Server.Implementations/Roku/RokuSessionController.cs +++ b/MediaBrowser.Server.Implementations/Roku/RokuSessionController.cs @@ -41,16 +41,6 @@ namespace MediaBrowser.Server.Implementations.Roku } } - public Task SendSystemCommand(SystemCommand command, CancellationToken cancellationToken) - { - return SendCommand(new WebSocketMessage - { - MessageType = "SystemCommand", - Data = command.ToString() - - }, cancellationToken); - } - public Task SendMessageCommand(MessageCommand command, CancellationToken cancellationToken) { return SendCommand(new WebSocketMessage @@ -148,9 +138,9 @@ namespace MediaBrowser.Server.Implementations.Roku } - public Task SendGenericCommand(GenericCommand command, CancellationToken cancellationToken) + public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken) { - return SendCommand(new WebSocketMessage + return SendCommand(new WebSocketMessage { MessageType = "Command", Data = command diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 00d2aa992d..3b6e9fefbc 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -661,24 +661,24 @@ namespace MediaBrowser.Server.Implementations.Session return session; } - public Task SendSystemCommand(Guid controllingSessionId, Guid sessionId, SystemCommand command, CancellationToken cancellationToken) + public Task SendMessageCommand(Guid controllingSessionId, Guid sessionId, MessageCommand command, CancellationToken cancellationToken) { var session = GetSessionForRemoteControl(sessionId); var controllingSession = GetSession(controllingSessionId); AssertCanControl(session, controllingSession); - return session.SessionController.SendSystemCommand(command, cancellationToken); + return session.SessionController.SendMessageCommand(command, cancellationToken); } - public Task SendMessageCommand(Guid controllingSessionId, Guid sessionId, MessageCommand command, CancellationToken cancellationToken) + public Task SendGeneralCommand(Guid controllingSessionId, Guid sessionId, GeneralCommand command, CancellationToken cancellationToken) { var session = GetSessionForRemoteControl(sessionId); var controllingSession = GetSession(controllingSessionId); AssertCanControl(session, controllingSession); - return session.SessionController.SendMessageCommand(command, cancellationToken); + return session.SessionController.SendGeneralCommand(command, cancellationToken); } public Task SendPlayCommand(Guid controllingSessionId, Guid sessionId, PlayRequest command, CancellationToken cancellationToken) diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs index ddf4ec2ca7..3bb84fa0ee 100644 --- a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs +++ b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs @@ -57,18 +57,6 @@ namespace MediaBrowser.Server.Implementations.Session return socket; } - public Task SendSystemCommand(SystemCommand command, CancellationToken cancellationToken) - { - var socket = GetActiveSocket(); - - return socket.SendAsync(new WebSocketMessage - { - MessageType = "SystemCommand", - Data = command.ToString() - - }, cancellationToken); - } - public Task SendMessageCommand(MessageCommand command, CancellationToken cancellationToken) { var socket = GetActiveSocket(); @@ -199,13 +187,13 @@ namespace MediaBrowser.Server.Implementations.Session }, cancellationToken); } - public Task SendGenericCommand(GenericCommand command, CancellationToken cancellationToken) + public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken) { var socket = GetActiveSocket(); - return socket.SendAsync(new WebSocketMessage + return socket.SendAsync(new WebSocketMessage { - MessageType = "Command", + MessageType = "GeneralCommand", Data = command }, cancellationToken); diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 2575434f41..b545156ec0 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -879,6 +879,7 @@ namespace MediaBrowser.ServerApplication ProgramDataPath = ApplicationPaths.ProgramDataPath, LogPath = ApplicationPaths.LogDirectoryPath, ItemsByNamePath = ApplicationPaths.ItemsByNamePath, + InternalMetadataPath = ApplicationPaths.InternalMetadataPath, CachePath = ApplicationPaths.CachePath, MacAddress = GetMacAddress(), HttpServerPortNumber = HttpServerPort, diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 7313c089f2..1b83fb2e9e 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -219,7 +219,7 @@ namespace MediaBrowser.WebDashboard.Api var contentType = MimeTypes.GetMimeType(path); var isHtml = IsHtml(path); - var localizationCulture = isHtml ? GetLocalizationCulture() : null; + var localizationCulture = GetLocalizationCulture(); // Don't cache if not configured to do so // But always cache images to simulate production -- cgit v1.2.3 From 4afe2c3f731562efbe42147d1bcbdc0a7542cfeb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 1 Apr 2014 00:16:25 -0400 Subject: updated dlna profile format --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 30 ++++--------- MediaBrowser.Controller/Dlna/DeviceProfile.cs | 16 +++---- MediaBrowser.Controller/Dlna/MediaProfile.cs | 49 ---------------------- MediaBrowser.Controller/Dlna/ResponseProfile.cs | 49 ++++++++++++++++++++++ MediaBrowser.Controller/Dlna/TranscodingProfile.cs | 23 +--------- .../MediaBrowser.Controller.csproj | 2 +- MediaBrowser.Dlna/PlayTo/PlaylistItem.cs | 8 ---- MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs | 3 -- MediaBrowser.Dlna/Profiles/DefaultProfile.cs | 6 +-- .../Profiles/SamsungSmartTvProfile.cs | 6 +-- .../Profiles/SonyBlurayPlayerProfile.cs | 16 +++---- .../Profiles/SonyBravia2010Profile.cs | 12 +++--- .../Profiles/SonyBravia2011Profile.cs | 12 +++--- .../Profiles/SonyBravia2012Profile.cs | 12 +++--- .../Profiles/SonyBravia2013Profile.cs | 12 +++--- MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs | 8 ++-- MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs | 10 ++--- MediaBrowser.Dlna/Profiles/Xbox360Profile.cs | 12 ++---- MediaBrowser.Dlna/Profiles/XboxOneProfile.cs | 4 +- MediaBrowser.Dlna/Profiles/Xml/Default.xml | 12 ++---- MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml | 12 ++---- MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml | 14 ++----- MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml | 12 ++---- MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml | 14 ++----- .../Profiles/Xml/Samsung Smart TV.xml | 24 ++++------- .../Profiles/Xml/Sony Blu-ray Player 2013.xml | 14 ++----- .../Profiles/Xml/Sony Blu-ray Player.xml | 44 +++++++++---------- .../Profiles/Xml/Sony Bravia (2010).xml | 36 +++++++--------- .../Profiles/Xml/Sony Bravia (2011).xml | 36 +++++++--------- .../Profiles/Xml/Sony Bravia (2012).xml | 36 +++++++--------- .../Profiles/Xml/Sony Bravia (2013).xml | 36 +++++++--------- .../Profiles/Xml/Sony PlayStation 3.xml | 28 +++++-------- MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml | 22 ++++------ MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml | 22 ++++------ MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml | 16 +++---- MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml | 12 ++---- .../Encoder/InternalEncodingTaskFactory.cs | 16 +------ .../Localization/Server/fr.json | 2 +- 38 files changed, 264 insertions(+), 434 deletions(-) delete mode 100644 MediaBrowser.Controller/Dlna/MediaProfile.cs create mode 100644 MediaBrowser.Controller/Dlna/ResponseProfile.cs (limited to 'MediaBrowser.MediaEncoding/Encoder') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index e6ec38846b..6c406a11cf 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1492,21 +1492,9 @@ namespace MediaBrowser.Api.Playback state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode; state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; - foreach (var setting in transcodingProfile.Settings) + if (state.VideoRequest != null && string.IsNullOrWhiteSpace(state.VideoRequest.Profile)) { - switch (setting.Name) - { - case TranscodingSettingType.VideoProfile: - { - if (state.VideoRequest != null && string.IsNullOrWhiteSpace(state.VideoRequest.Profile)) - { - state.VideoRequest.Profile = setting.Value; - } - break; - } - default: - throw new ArgumentException("Unrecognized TranscodingSettingType"); - } + state.VideoRequest.Profile = transcodingProfile.VideoProfile; } } } @@ -1523,12 +1511,6 @@ namespace MediaBrowser.Api.Playback { var timeSeek = GetHeader("TimeSeekRange.dlna.org"); - if (!string.IsNullOrEmpty(timeSeek)) - { - ResultFactory.ThrowError(406, "Time seek not supported during encoding.", responseHeaders); - return; - } - var transferMode = GetHeader("transferMode.dlna.org"); responseHeaders["transferMode.dlna.org"] = string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode; responseHeaders["realTimeInfo.dlna.org"] = "DLNA.ORG_TLAG=*"; @@ -1537,7 +1519,13 @@ namespace MediaBrowser.Api.Playback var extension = GetOutputFileExtension(state); // first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none - var orgOp = isStaticallyStreamed || state.TranscodeSeekInfo == TranscodeSeekInfo.Bytes ? ";DLNA.ORG_OP=01" : ";DLNA.ORG_OP=00"; + var orgOp = ";DLNA.ORG_OP="; + + // Time-based seeking currently only possible when transcoding + orgOp += isStaticallyStreamed ? "0" : "1"; + + // Byte-based seeking only possible when not transcoding + orgOp += isStaticallyStreamed || state.TranscodeSeekInfo == TranscodeSeekInfo.Bytes ? "1" : "0"; // 0 = native, 1 = transcoded var orgCi = isStaticallyStreamed ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1"; diff --git a/MediaBrowser.Controller/Dlna/DeviceProfile.cs b/MediaBrowser.Controller/Dlna/DeviceProfile.cs index c1fc713e4a..bb9629c28b 100644 --- a/MediaBrowser.Controller/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Controller/Dlna/DeviceProfile.cs @@ -74,13 +74,13 @@ namespace MediaBrowser.Controller.Dlna public ContainerProfile[] ContainerProfiles { get; set; } public CodecProfile[] CodecProfiles { get; set; } - public MediaProfile[] MediaProfiles { get; set; } + public ResponseProfile[] ResponseProfiles { get; set; } public DeviceProfile() { DirectPlayProfiles = new DirectPlayProfile[] { }; TranscodingProfiles = new TranscodingProfile[] { }; - MediaProfiles = new MediaProfile[] { }; + ResponseProfiles = new ResponseProfile[] { }; CodecProfiles = new CodecProfile[] { }; ContainerProfiles = new ContainerProfile[] { }; @@ -147,11 +147,11 @@ namespace MediaBrowser.Controller.Dlna }); } - public MediaProfile GetAudioMediaProfile(string container, string audioCodec, MediaStream audioStream) + public ResponseProfile GetAudioMediaProfile(string container, string audioCodec, MediaStream audioStream) { container = (container ?? string.Empty).TrimStart('.'); - return MediaProfiles.FirstOrDefault(i => + return ResponseProfiles.FirstOrDefault(i => { if (i.Type != DlnaProfileType.Audio) { @@ -174,11 +174,11 @@ namespace MediaBrowser.Controller.Dlna }); } - public MediaProfile GetVideoMediaProfile(string container, string audioCodec, string videoCodec, MediaStream audioStream, MediaStream videoStream) + public ResponseProfile GetVideoMediaProfile(string container, string audioCodec, string videoCodec, MediaStream audioStream, MediaStream videoStream) { container = (container ?? string.Empty).TrimStart('.'); - return MediaProfiles.FirstOrDefault(i => + return ResponseProfiles.FirstOrDefault(i => { if (i.Type != DlnaProfileType.Video) { @@ -207,11 +207,11 @@ namespace MediaBrowser.Controller.Dlna }); } - public MediaProfile GetPhotoMediaProfile(string container) + public ResponseProfile GetPhotoMediaProfile(string container) { container = (container ?? string.Empty).TrimStart('.'); - return MediaProfiles.FirstOrDefault(i => + return ResponseProfiles.FirstOrDefault(i => { if (i.Type != DlnaProfileType.Photo) { diff --git a/MediaBrowser.Controller/Dlna/MediaProfile.cs b/MediaBrowser.Controller/Dlna/MediaProfile.cs deleted file mode 100644 index bf3057294c..0000000000 --- a/MediaBrowser.Controller/Dlna/MediaProfile.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using System.Xml.Serialization; - -namespace MediaBrowser.Controller.Dlna -{ - public class MediaProfile - { - [XmlAttribute("container")] - public string Container { get; set; } - - [XmlAttribute("audioCodec")] - public string AudioCodec { get; set; } - - [XmlAttribute("videoCodec")] - public string VideoCodec { get; set; } - - [XmlAttribute("type")] - public DlnaProfileType Type { get; set; } - - [XmlAttribute("orgPn")] - public string OrgPn { get; set; } - - [XmlAttribute("mimeType")] - public string MimeType { get; set; } - - public ProfileCondition[] Conditions { get; set; } - - public MediaProfile() - { - Conditions = new ProfileCondition[] {}; - } - - public List GetContainers() - { - return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); - } - - public List GetAudioCodecs() - { - return (AudioCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); - } - - public List GetVideoCodecs() - { - return (VideoCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); - } - } -} diff --git a/MediaBrowser.Controller/Dlna/ResponseProfile.cs b/MediaBrowser.Controller/Dlna/ResponseProfile.cs new file mode 100644 index 0000000000..163a95d5ac --- /dev/null +++ b/MediaBrowser.Controller/Dlna/ResponseProfile.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; +using System.Linq; +using System.Xml.Serialization; + +namespace MediaBrowser.Controller.Dlna +{ + public class ResponseProfile + { + [XmlAttribute("container")] + public string Container { get; set; } + + [XmlAttribute("audioCodec")] + public string AudioCodec { get; set; } + + [XmlAttribute("videoCodec")] + public string VideoCodec { get; set; } + + [XmlAttribute("type")] + public DlnaProfileType Type { get; set; } + + [XmlAttribute("orgPn")] + public string OrgPn { get; set; } + + [XmlAttribute("mimeType")] + public string MimeType { get; set; } + + public ProfileCondition[] Conditions { get; set; } + + public ResponseProfile() + { + Conditions = new ProfileCondition[] {}; + } + + public List GetContainers() + { + return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); + } + + public List GetAudioCodecs() + { + return (AudioCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); + } + + public List GetVideoCodecs() + { + return (VideoCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(); + } + } +} diff --git a/MediaBrowser.Controller/Dlna/TranscodingProfile.cs b/MediaBrowser.Controller/Dlna/TranscodingProfile.cs index 707f0c5731..704ba54d26 100644 --- a/MediaBrowser.Controller/Dlna/TranscodingProfile.cs +++ b/MediaBrowser.Controller/Dlna/TranscodingProfile.cs @@ -30,13 +30,8 @@ namespace MediaBrowser.Controller.Dlna [XmlAttribute("transcodeSeekInfo")] public TranscodeSeekInfo TranscodeSeekInfo { get; set; } - public TranscodingSetting[] Settings { get; set; } - - public TranscodingProfile() - { - Settings = new TranscodingSetting[] { }; - } - + [XmlAttribute("videoProfile")] + public string VideoProfile { get; set; } public List GetAudioCodecs() { @@ -44,20 +39,6 @@ namespace MediaBrowser.Controller.Dlna } } - public class TranscodingSetting - { - [XmlAttribute("name")] - public TranscodingSettingType Name { get; set; } - - [XmlAttribute("value")] - public string Value { get; set; } - } - - public enum TranscodingSettingType - { - VideoProfile = 0 - } - public enum TranscodeSeekInfo { Auto = 0, diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 16834a945f..a233c1f12f 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -84,7 +84,7 @@ - + diff --git a/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs b/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs index 50605c61fe..9f990bcb7b 100644 --- a/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs +++ b/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs @@ -1,5 +1,4 @@ using MediaBrowser.Controller.Dlna; -using System.Collections.Generic; namespace MediaBrowser.Dlna.PlayTo { @@ -27,8 +26,6 @@ namespace MediaBrowser.Dlna.PlayTo public string AudioCodec { get; set; } - public List TranscodingSettings { get; set; } - public int? AudioStreamIndex { get; set; } public int? SubtitleStreamIndex { get; set; } @@ -47,10 +44,5 @@ namespace MediaBrowser.Dlna.PlayTo public int? MaxFramerate { get; set; } public string DeviceProfileId { get; set; } - - public PlaylistItem() - { - TranscodingSettings = new List(); - } } } \ No newline at end of file diff --git a/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs b/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs index c14a851cab..6a42e6a756 100644 --- a/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs +++ b/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs @@ -48,7 +48,6 @@ namespace MediaBrowser.Dlna.PlayTo if (transcodingProfile != null) { playlistItem.Transcode = true; - playlistItem.TranscodingSettings = transcodingProfile.Settings.ToList(); playlistItem.Container = "." + transcodingProfile.Container.TrimStart('.'); playlistItem.AudioCodec = transcodingProfile.AudioCodec; @@ -88,7 +87,6 @@ namespace MediaBrowser.Dlna.PlayTo if (transcodingProfile != null) { playlistItem.Transcode = true; - playlistItem.TranscodingSettings = transcodingProfile.Settings.ToList(); playlistItem.Container = "." + transcodingProfile.Container.TrimStart('.'); } @@ -137,7 +135,6 @@ namespace MediaBrowser.Dlna.PlayTo if (transcodingProfile != null) { playlistItem.Transcode = true; - playlistItem.TranscodingSettings = transcodingProfile.Settings.ToList(); playlistItem.Container = "." + transcodingProfile.Container.TrimStart('.'); playlistItem.AudioCodec = transcodingProfile.AudioCodec.Split(',').FirstOrDefault(); playlistItem.VideoCodec = transcodingProfile.VideoCodec; diff --git a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs index 6b5513e289..e6b5668faf 100644 --- a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs +++ b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs @@ -35,11 +35,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video, AudioCodec = "aac", VideoCodec = "h264", - - Settings = new [] - { - new TranscodingSetting {Name = TranscodingSettingType.VideoProfile, Value = "baseline"} - } + VideoProfile= "baseline" } }; diff --git a/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs b/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs index 122bde875f..b008947d3f 100644 --- a/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs +++ b/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs @@ -302,16 +302,16 @@ namespace MediaBrowser.Dlna.Profiles } }; - MediaProfiles = new[] + ResponseProfiles = new[] { - new MediaProfile + new ResponseProfile { Container = "avi", MimeType = "video/x-msvideo", Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "mkv", MimeType = "video/x-mkv", diff --git a/MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs b/MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs index c5025edbb6..972fc48ed7 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBlurayPlayerProfile.cs @@ -206,9 +206,9 @@ namespace MediaBrowser.Dlna.Profiles } }; - MediaProfiles = new[] + ResponseProfiles = new[] { - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec = "h264,mpeg4,vc1", @@ -218,42 +218,42 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "avi", MimeType = "video/mpeg", Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "mkv", MimeType = "video/vnd.dlna.mpeg-tts", Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", MimeType = "video/vnd.dlna.mpeg-tts", Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "mp4", MimeType = "video/mpeg", Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "mpeg", MimeType = "video/mpeg", Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "mp3", MimeType = "audio/mpeg", diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs index 8f29ad76e3..870b97fe72 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs @@ -89,9 +89,9 @@ namespace MediaBrowser.Dlna.Profiles } }; - MediaProfiles = new[] + ResponseProfiles = new[] { - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="h264", @@ -101,7 +101,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="h264", @@ -111,7 +111,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="h264", @@ -121,7 +121,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="mpeg2video", @@ -130,7 +130,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "mpeg", VideoCodec="mpeg1video,mpeg2video", diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs index eaf6979a6b..2bba58696e 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs @@ -131,9 +131,9 @@ namespace MediaBrowser.Dlna.Profiles } }; - MediaProfiles = new[] + ResponseProfiles = new[] { - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="h264", @@ -143,7 +143,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="h264", @@ -153,7 +153,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="h264", @@ -163,7 +163,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="mpeg2video", @@ -172,7 +172,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "mpeg", VideoCodec="mpeg1video,mpeg2video", diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs index 41d057ef8a..f8a6dcfbd7 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2012Profile.cs @@ -119,9 +119,9 @@ namespace MediaBrowser.Dlna.Profiles } }; - MediaProfiles = new[] + ResponseProfiles = new[] { - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="h264", @@ -131,7 +131,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="h264", @@ -141,7 +141,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="h264", @@ -151,7 +151,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="mpeg2video", @@ -160,7 +160,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "mpeg", VideoCodec="mpeg1video,mpeg2video", diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs index 386a36ae0c..56eaf47f4f 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2013Profile.cs @@ -175,9 +175,9 @@ namespace MediaBrowser.Dlna.Profiles } }; - MediaProfiles = new[] + ResponseProfiles = new[] { - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="h264", @@ -187,7 +187,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="h264", @@ -197,7 +197,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="h264", @@ -207,7 +207,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "ts", VideoCodec="mpeg2video", @@ -216,7 +216,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "mpeg", VideoCodec="mpeg1video,mpeg2video", diff --git a/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs b/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs index 351a13f001..06d721f52e 100644 --- a/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyPs3Profile.cs @@ -207,9 +207,9 @@ namespace MediaBrowser.Dlna.Profiles } }; - MediaProfiles = new[] + ResponseProfiles = new[] { - new MediaProfile + new ResponseProfile { Container = "mp4,mov", AudioCodec="aac", @@ -217,7 +217,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "avi", MimeType = "video/divx", @@ -225,7 +225,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video }, - new MediaProfile + new ResponseProfile { Container = "wav", MimeType = "audio/wav", diff --git a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs index f0b95d4e88..c3b88f7bfc 100644 --- a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs +++ b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs @@ -43,11 +43,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video, VideoCodec = "h264", AudioCodec = "aac", - - Settings = new [] - { - new TranscodingSetting {Name = TranscodingSettingType.VideoProfile, Value = "baseline"} - } + VideoProfile= "baseline" }, new TranscodingProfile { @@ -157,9 +153,9 @@ namespace MediaBrowser.Dlna.Profiles } }; - MediaProfiles = new[] + ResponseProfiles = new[] { - new MediaProfile + new ResponseProfile { Container = "ts", OrgPn = "MPEG_TS_SD_NA", diff --git a/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs b/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs index 38d08adef7..3fae85f594 100644 --- a/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs +++ b/MediaBrowser.Dlna/Profiles/Xbox360Profile.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Dlna.Profiles { ModelName = "Xbox 360", - Headers = new [] + Headers = new[] { new HttpHeaderInfo {Name = "User-Agent", Value = "Xbox", Match = HeaderMatchType.Substring}, new HttpHeaderInfo {Name = "User-Agent", Value = "Xenon", Match = HeaderMatchType.Substring} @@ -48,11 +48,7 @@ namespace MediaBrowser.Dlna.Profiles Type = DlnaProfileType.Video, TranscodeSeekInfo = TranscodeSeekInfo.Bytes, EstimateContentLength = true, - - Settings = new [] - { - new TranscodingSetting {Name = TranscodingSettingType.VideoProfile, Value = "baseline"} - } + VideoProfile= "baseline" }, new TranscodingProfile { @@ -110,9 +106,9 @@ namespace MediaBrowser.Dlna.Profiles } }; - MediaProfiles = new[] + ResponseProfiles = new[] { - new MediaProfile + new ResponseProfile { Container = "avi", MimeType = "video/avi", diff --git a/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs b/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs index 058c69e1ff..59372655c0 100644 --- a/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs +++ b/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs @@ -42,9 +42,9 @@ namespace MediaBrowser.Dlna.Profiles } }; - MediaProfiles = new[] + ResponseProfiles = new[] { - new MediaProfile + new ResponseProfile { Container = "avi", MimeType = "video/x-msvideo", diff --git a/MediaBrowser.Dlna/Profiles/Xml/Default.xml b/MediaBrowser.Dlna/Profiles/Xml/Default.xml index 895cb99d32..9d72d68d23 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Default.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Default.xml @@ -20,16 +20,10 @@ - - - - - - - - + + - + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml index 58c5cefbc5..31ab8b85c7 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml @@ -24,16 +24,10 @@ - - - - - - - - + + - + \ 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 53781ad324..0e9ce618e7 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml @@ -29,15 +29,9 @@ - - - - - - - - - + + + @@ -69,5 +63,5 @@ - + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml index fc833b9186..39822e0a38 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml @@ -24,16 +24,10 @@ - - - - - - - - + + - + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml index 49fd05b1e0..ab815a645f 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml @@ -35,15 +35,9 @@ - - - - - - - - - + + + @@ -62,5 +56,5 @@ - + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml index 75c50aae36..bd17802a24 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml @@ -33,15 +33,9 @@ - - - - - - - - - + + + @@ -91,12 +85,12 @@ - - + + - - + + - - + + \ No newline at end of file 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 5bd27c7716..53b515e106 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml @@ -33,15 +33,9 @@ - - - - - - - - - + + + @@ -65,5 +59,5 @@ - + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml index f5502ca14a..76b52c7438 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml @@ -32,15 +32,9 @@ - - - - - - - - - + + + @@ -71,27 +65,27 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml index 1337b59361..8c41cc3b7e 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml @@ -30,15 +30,9 @@ - - - - - - - - - + + + @@ -80,21 +74,21 @@ - - + + - - + + - - + + - - + + - - + + - - + + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml index b022c10a51..1ccd5f1dec 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml @@ -33,15 +33,9 @@ - - - - - - - - - + + + @@ -83,21 +77,21 @@ - - + + - - + + - - + + - - + + - - + + - - + + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml index cbef70b378..b578a98b61 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml @@ -35,15 +35,9 @@ - - - - - - - - - + + + @@ -66,21 +60,21 @@ - - + + - - + + - - + + - - + + - - + + - - + + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml index 47db46ce11..fe5c63f90d 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml @@ -40,15 +40,9 @@ - - - - - - - - - + + + @@ -66,21 +60,21 @@ - - + + - - + + - - + + - - + + - - + + - - + + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml index d9aa441bb4..f0db13e2af 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml @@ -29,15 +29,9 @@ - - - - - - - - - + + + @@ -80,15 +74,15 @@ - - + + - - + + - - + + - - + + \ 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 0f4ad54a77..bebdb2b45e 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml @@ -38,17 +38,9 @@ - - - - - - - - - - - + + + @@ -72,9 +64,9 @@ - - + + - - + + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml index 1e8d8164c3..a2ac02ff91 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml @@ -33,17 +33,9 @@ - - - - - - - - - - - + + + @@ -95,9 +87,9 @@ - - + + - - + + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml index f6c338b2f5..aa2081dc0d 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml @@ -24,18 +24,14 @@ - - - - - - + + - - + + - - + + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml index f682e4c421..02a1529f3d 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml @@ -26,16 +26,10 @@ - - - - - - - - + + - + \ No newline at end of file diff --git a/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTaskFactory.cs b/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTaskFactory.cs index fa9b879061..e6b67b0df6 100644 --- a/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTaskFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/InternalEncodingTaskFactory.cs @@ -282,21 +282,9 @@ namespace MediaBrowser.MediaEncoding.Encoder state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode; //state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; - foreach (var setting in transcodingProfile.Settings) + if (state.VideoRequest != null && string.IsNullOrWhiteSpace(state.VideoRequest.VideoProfile)) { - switch (setting.Name) - { - case TranscodingSettingType.VideoProfile: - { - if (state.VideoRequest != null && string.IsNullOrWhiteSpace(state.VideoRequest.VideoProfile)) - { - state.VideoRequest.VideoProfile = setting.Value; - } - break; - } - default: - throw new ArgumentException("Unrecognized TranscodingSettingType"); - } + state.VideoRequest.VideoProfile = transcodingProfile.VideoProfile; } } } diff --git a/MediaBrowser.Server.Implementations/Localization/Server/fr.json b/MediaBrowser.Server.Implementations/Localization/Server/fr.json index 2c7e1b52b6..c2934807c9 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/fr.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/fr.json @@ -30,7 +30,7 @@ "LabelEnableVideoImageExtraction": "Activer l'extraction d'image des videos", "VideoImageExtractionHelp": "Pour les vid\u00e9os sans images et que nous n'avons pas trouv\u00e9 par Internet. Ce processus prolongera la mise \u00e0 jour initiale de biblioth\u00e8que mais offrira une meilleure pr\u00e9sentation visuelle.", "LabelEnableChapterImageExtractionForMovies": "Extraire les images de chapitre pour les films", - "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.", + "LabelChapterImageExtractionForMoviesHelp": "L'extraction d'images de chapitre permettra aux clients d'afficher des menus graphiques des sc\u00e8nes. Le processus peut \u00eatre long et exigeant en ressource processeur et de stockage (plusieurs Gigabytes). Il s'ex\u00e9cute par d\u00e9faut dans les t\u00e2ches programm\u00e9es \u00e0 4:00 AM mais peut \u00eatre modifi\u00e9 dans les options de t\u00e2ches programm\u00e9es. Il n'est pas recommand\u00e9 d'ex\u00e9cuter cette t\u00e2che dans les heures d'utilisation standard.", "LabelEnableAutomaticPortMapping": "Activer la configuration automatique de port", "LabelEnableAutomaticPortMappingHelp": "UPnP permet la configuration automatique de routeur pour un acc\u00e8s distance facile. Ceci peut ne pas fonctionner sur certains mod\u00e8les de routeur.", "ButtonOk": "Ok", -- cgit v1.2.3