Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser into upstream-master

pull/702/head
Tim Hobbs 10 years ago
commit 6e10825631

@ -7,7 +7,6 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using ServiceStack;
@ -32,16 +31,6 @@ namespace MediaBrowser.Api
public string Id { get; set; }
}
[Route("/Items/{Id}/RemoteSearch/Subtitles/{Language}", "GET")]
public class SearchRemoteSubtitles : IReturn<List<RemoteSubtitleInfo>>
{
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
[ApiMember(Name = "Language", Description = "Language", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Language { get; set; }
}
[Route("/Items/RemoteSearch/Movie", "POST")]
[Api(Description = "Gets external id infos for an item")]
public class GetMovieRemoteSearchResults : RemoteSearchQuery<MovieInfo>, IReturn<List<RemoteSearchResult>>
@ -121,24 +110,13 @@ namespace MediaBrowser.Api
private readonly IServerApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem;
private readonly ILibraryManager _libraryManager;
private readonly ISubtitleManager _subtitleManager;
public ItemLookupService(IProviderManager providerManager, IServerApplicationPaths appPaths, IFileSystem fileSystem, ILibraryManager libraryManager, ISubtitleManager subtitleManager)
public ItemLookupService(IProviderManager providerManager, IServerApplicationPaths appPaths, IFileSystem fileSystem, ILibraryManager libraryManager)
{
_providerManager = providerManager;
_appPaths = appPaths;
_fileSystem = fileSystem;
_libraryManager = libraryManager;
_subtitleManager = subtitleManager;
}
public object Get(SearchRemoteSubtitles request)
{
var video = (Video)_libraryManager.GetItemById(request.Id);
var response = _subtitleManager.SearchSubtitles(video, request.Language, CancellationToken.None).Result;
return ToOptimizedResult(response);
}
public object Get(GetExternalIdInfos request)

@ -1,5 +1,4 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@ -35,21 +34,6 @@ namespace MediaBrowser.Api.Library
public string Id { get; set; }
}
[Route("/Videos/{Id}/Subtitles/{Index}", "GET")]
[Api(Description = "Gets an external subtitle file")]
public class GetSubtitle
{
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
[ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
public int Index { get; set; }
}
/// <summary>
/// Class GetCriticReviews
/// </summary>
@ -305,25 +289,6 @@ namespace MediaBrowser.Api.Library
return ToStaticFileResult(item.Path);
}
public object Get(GetSubtitle request)
{
var subtitleStream = _itemRepo.GetMediaStreams(new MediaStreamQuery
{
Index = request.Index,
ItemId = new Guid(request.Id),
Type = MediaStreamType.Subtitle
}).FirstOrDefault();
if (subtitleStream == null)
{
throw new ResourceNotFoundException();
}
return ToStaticFileResult(subtitleStream.Path);
}
/// <summary>
/// Gets the specified request.
/// </summary>

@ -0,0 +1,162 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Api.Library
{
[Route("/Videos/{Id}/Subtitles/{Index}", "GET", Summary = "Gets an external subtitle file")]
public class GetSubtitle
{
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
[ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
public int Index { get; set; }
}
[Route("/Videos/{Id}/Subtitles/{Index}", "DELETE", Summary = "Deletes an external subtitle file")]
public class DeleteSubtitle
{
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
public string Id { get; set; }
[ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "DELETE")]
public int Index { get; set; }
}
[Route("/Items/{Id}/RemoteSearch/Subtitles/{Language}", "GET")]
public class SearchRemoteSubtitles : IReturn<List<RemoteSubtitleInfo>>
{
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
[ApiMember(Name = "Language", Description = "Language", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Language { get; set; }
}
[Route("/Items/{Id}/RemoteSearch/Subtitles/Providers", "GET")]
public class GetSubtitleProviders : IReturn<List<SubtitleProviderInfo>>
{
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
}
[Route("/Items/{Id}/RemoteSearch/Subtitles/{SubtitleId}", "POST")]
public class DownloadRemoteSubtitles : IReturnVoid
{
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public string Id { get; set; }
[ApiMember(Name = "SubtitleId", Description = "SubtitleId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public string SubtitleId { get; set; }
}
[Route("/Providers/Subtitles/Subtitles/{Id}", "GET")]
public class GetRemoteSubtitles : IReturnVoid
{
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
}
public class SubtitleService : BaseApiService
{
private readonly ILibraryManager _libraryManager;
private readonly ISubtitleManager _subtitleManager;
private readonly IItemRepository _itemRepo;
public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, IItemRepository itemRepo)
{
_libraryManager = libraryManager;
_subtitleManager = subtitleManager;
_itemRepo = itemRepo;
}
public object Get(SearchRemoteSubtitles request)
{
var video = (Video)_libraryManager.GetItemById(request.Id);
var response = _subtitleManager.SearchSubtitles(video, request.Language, CancellationToken.None).Result;
return ToOptimizedResult(response);
}
public object Get(GetSubtitle request)
{
var subtitleStream = _itemRepo.GetMediaStreams(new MediaStreamQuery
{
Index = request.Index,
ItemId = new Guid(request.Id),
Type = MediaStreamType.Subtitle
}).FirstOrDefault();
if (subtitleStream == null)
{
throw new ResourceNotFoundException();
}
return ToStaticFileResult(subtitleStream.Path);
}
public void Delete(DeleteSubtitle request)
{
var task = _subtitleManager.DeleteSubtitles(request.Id, request.Index);
Task.WaitAll(task);
}
public object Get(GetSubtitleProviders request)
{
var result = _subtitleManager.GetProviders(request.Id);
return ToOptimizedResult(result);
}
public object Get(GetRemoteSubtitles request)
{
var result = _subtitleManager.GetRemoteSubtitles(request.Id, CancellationToken.None).Result;
return ResultFactory.GetResult(result.Stream, MimeTypes.GetMimeType("file." + result.Format));
}
public void Post(DownloadRemoteSubtitles request)
{
var video = (Video)_libraryManager.GetItemById(request.Id);
Task.Run(async () =>
{
try
{
await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None)
.ConfigureAwait(false);
await video.RefreshMetadata(new MetadataRefreshOptions(), CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
Logger.ErrorException("Error downloading subtitles", ex);
}
});
}
}
}

@ -68,6 +68,7 @@
<Compile Include="ChannelService.cs" />
<Compile Include="Dlna\DlnaServerService.cs" />
<Compile Include="Dlna\DlnaService.cs" />
<Compile Include="Library\SubtitleService.cs" />
<Compile Include="Movies\CollectionService.cs" />
<Compile Include="Music\AlbumsService.cs" />
<Compile Include="AppThemeService.cs" />

@ -1,5 +1,6 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Dto;
@ -25,7 +26,6 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Api.Playback
{
@ -71,6 +71,7 @@ namespace MediaBrowser.Api.Playback
protected IItemRepository ItemRepository { get; private set; }
protected ILiveTvManager LiveTvManager { get; private set; }
protected IDlnaManager DlnaManager { get; private set; }
protected IChannelManager ChannelManager { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
@ -83,8 +84,9 @@ namespace MediaBrowser.Api.Playback
/// <param name="dtoService">The dto service.</param>
/// <param name="fileSystem">The file system.</param>
/// <param name="itemRepository">The item repository.</param>
protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager)
protected BaseStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager)
{
ChannelManager = channelManager;
DlnaManager = dlnaManager;
EncodingManager = encodingManager;
LiveTvManager = liveTvManager;
@ -169,13 +171,28 @@ namespace MediaBrowser.Api.Playback
/// <returns>System.String.</returns>
protected virtual string GetMapArgs(StreamState state)
{
var args = string.Empty;
// If we don't have known media info
// If input is video, use -sn to drop subtitles
// Otherwise just return empty
if (state.VideoStream == null && state.AudioStream == null)
{
return state.IsInputVideo ? "-sn" : string.Empty;
}
// We have media info, but we don't know the stream indexes
if (state.VideoStream != null && state.VideoStream.Index == -1)
{
return "-sn";
}
if (!state.HasMediaStreams)
// We have media info, but we don't know the stream indexes
if (state.AudioStream != null && state.AudioStream.Index == -1)
{
return state.IsInputVideo ? "-sn" : string.Empty;
}
var args = string.Empty;
if (state.VideoStream != null)
{
args += string.Format("-map 0:{0}", state.VideoStream.Index);
@ -350,11 +367,11 @@ namespace MediaBrowser.Api.Playback
switch (qualitySetting)
{
case EncodingQuality.HighSpeed:
crf = "16";
crf = "14";
profileScore = 2;
break;
case EncodingQuality.HighQuality:
crf = "10";
crf = "8";
profileScore = 1;
break;
case EncodingQuality.MaxQuality:
@ -1329,13 +1346,14 @@ namespace MediaBrowser.Api.Playback
throw new ArgumentException(string.Format("{0} is not allowed to play media.", user.Name));
}
List<MediaStream> mediaStreams = null;
if (item is ILiveTvRecording)
{
var recording = await LiveTvManager.GetInternalRecording(request.Id, cancellationToken).ConfigureAwait(false);
state.VideoType = VideoType.VideoFile;
state.IsInputVideo = string.Equals(recording.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
state.PlayableStreamFileNames = new List<string>();
var path = recording.RecordingInfo.Path;
var mediaUrl = recording.RecordingInfo.Url;
@ -1345,6 +1363,7 @@ namespace MediaBrowser.Api.Playback
var streamInfo = await LiveTvManager.GetRecordingStream(request.Id, cancellationToken).ConfigureAwait(false);
state.LiveTvStreamId = streamInfo.Id;
mediaStreams = streamInfo.MediaStreams;
path = streamInfo.Path;
mediaUrl = streamInfo.Url;
@ -1381,11 +1400,11 @@ namespace MediaBrowser.Api.Playback
state.VideoType = VideoType.VideoFile;
state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
state.PlayableStreamFileNames = new List<string>();
var streamInfo = await LiveTvManager.GetChannelStream(request.Id, cancellationToken).ConfigureAwait(false);
state.LiveTvStreamId = streamInfo.Id;
mediaStreams = streamInfo.MediaStreams;
if (!string.IsNullOrEmpty(streamInfo.Path))
{
@ -1406,6 +1425,16 @@ namespace MediaBrowser.Api.Playback
state.InputVideoSync = "-1";
state.InputAudioSync = "1";
}
else if (item is IChannelMediaItem)
{
var channelMediaSources = await ChannelManager.GetChannelItemMediaSources(request.Id, CancellationToken.None).ConfigureAwait(false);
var source = channelMediaSources.First();
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
state.IsRemote = source.IsRemote;
state.MediaPath = source.Path;
state.RunTimeTicks = item.RunTimeTicks;
}
else
{
state.MediaPath = item.Path;
@ -1424,7 +1453,11 @@ namespace MediaBrowser.Api.Playback
: video.PlayableStreamFileNames.ToList();
state.DeInterlace = string.Equals(video.Container, "wtv", StringComparison.OrdinalIgnoreCase);
state.InputTimestamp = video.Timestamp ?? TransportStreamTimestamp.None;
if (video.Timestamp.HasValue)
{
state.InputTimestamp = video.Timestamp.Value;
}
state.InputContainer = video.Container;
}
@ -1440,7 +1473,7 @@ namespace MediaBrowser.Api.Playback
var videoRequest = request as VideoStreamRequest;
var mediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery
mediaStreams = mediaStreams ?? ItemRepository.GetMediaStreams(new MediaStreamQuery
{
ItemId = item.Id
@ -1469,8 +1502,6 @@ namespace MediaBrowser.Api.Playback
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;
@ -1504,16 +1535,6 @@ namespace MediaBrowser.Api.Playback
}
}
var headers = new Dictionary<string, string>();
foreach (var key in Request.Headers.AllKeys)
{
headers[key] = Request.Headers[key];
}
state.DeviceProfile = string.IsNullOrWhiteSpace(state.Request.DeviceProfileId) ?
DlnaManager.GetProfile(headers) :
DlnaManager.GetProfile(state.Request.DeviceProfileId);
return state;
}
@ -1638,6 +1659,16 @@ namespace MediaBrowser.Api.Playback
private void ApplyDeviceProfileSettings(StreamState state)
{
var headers = new Dictionary<string, string>();
foreach (var key in Request.Headers.AllKeys)
{
headers[key] = Request.Headers[key];
}
state.DeviceProfile = string.IsNullOrWhiteSpace(state.Request.DeviceProfileId) ?
DlnaManager.GetProfile(headers) :
DlnaManager.GetProfile(state.Request.DeviceProfileId);
var profile = state.DeviceProfile;
if (profile == null)

@ -1,6 +1,7 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Dto;
@ -24,8 +25,7 @@ namespace MediaBrowser.Api.Playback.Hls
/// </summary>
public abstract class BaseHlsService : BaseStreamingService
{
protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager)
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, channelManager)
{
}

@ -1,4 +1,5 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Dto;
@ -59,7 +60,7 @@ namespace MediaBrowser.Api.Playback.Hls
public class DynamicHlsService : BaseHlsService
{
public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, channelManager)
{
}

@ -1,4 +1,5 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Dto;
@ -53,7 +54,7 @@ namespace MediaBrowser.Api.Playback.Hls
/// </summary>
public class VideoHlsService : BaseHlsService
{
public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
public VideoHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, channelManager)
{
}

@ -1,5 +1,6 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
@ -43,8 +44,7 @@ namespace MediaBrowser.Api.Playback.Progressive
/// </summary>
public class AudioService : BaseProgressiveStreamingService
{
public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IHttpClient httpClient, IImageProcessor imageProcessor)
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, httpClient, imageProcessor)
public AudioService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, channelManager, imageProcessor, httpClient)
{
}

@ -1,5 +1,6 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
@ -26,11 +27,10 @@ namespace MediaBrowser.Api.Playback.Progressive
protected readonly IImageProcessor ImageProcessor;
protected readonly IHttpClient HttpClient;
protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IHttpClient httpClient, IImageProcessor imageProcessor)
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, channelManager)
{
HttpClient = httpClient;
ImageProcessor = imageProcessor;
HttpClient = httpClient;
}
/// <summary>

@ -1,5 +1,6 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
@ -59,7 +60,7 @@ namespace MediaBrowser.Api.Playback.Progressive
/// </summary>
public class VideoService : BaseProgressiveStreamingService
{
public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IHttpClient httpClient, IImageProcessor imageProcessor) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, httpClient, imageProcessor)
public VideoService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager, IChannelManager channelManager, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager, channelManager, imageProcessor, httpClient)
{
}
@ -183,7 +184,7 @@ namespace MediaBrowser.Api.Playback.Progressive
private string GetAudioArguments(StreamState state)
{
// If the video doesn't have an audio stream, return a default.
if (state.AudioStream == null && state.HasMediaStreams)
if (state.AudioStream == null && state.VideoStream != null)
{
return string.Empty;
}

@ -28,6 +28,11 @@ namespace MediaBrowser.Api.Playback
get { return Request as VideoStreamRequest; }
}
public StreamState()
{
PlayableStreamFileNames = new List<string>();
}
/// <summary>
/// Gets or sets the log file stream.
/// </summary>
@ -57,8 +62,6 @@ namespace MediaBrowser.Api.Playback
public List<string> PlayableStreamFileNames { get; set; }
public bool HasMediaStreams { get; set; }
public string LiveTvStreamId { get; set; }
public int SegmentLength = 10;

@ -217,6 +217,12 @@ namespace MediaBrowser.Api
[ApiMember(Name = "SupportedCommands", Description = "A list of supported remote control commands, comma delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public string SupportedCommands { get; set; }
[ApiMember(Name = "MessageCallbackUrl", Description = "A url to post messages to, including remote control commands.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public string MessageCallbackUrl { get; set; }
[ApiMember(Name = "SupportsMediaControl", Description = "Determines whether media can be played remotely.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
public bool SupportsMediaControl { get; set; }
}
/// <summary>
@ -258,6 +264,8 @@ namespace MediaBrowser.Api
if (request.ControllableByUserId.HasValue)
{
result = result.Where(i => i.SupportsMediaControl);
var user = _userManager.GetUserById(request.ControllableByUserId.Value);
if (!user.Configuration.EnableRemoteControlOfOtherUsers)
@ -407,7 +415,11 @@ namespace MediaBrowser.Api
{
PlayableMediaTypes = request.PlayableMediaTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
SupportedCommands = request.SupportedCommands.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList()
SupportedCommands = request.SupportedCommands.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
SupportsMediaControl = request.SupportsMediaControl,
MessageCallbackUrl = request.MessageCallbackUrl
});
}

@ -390,7 +390,7 @@ namespace MediaBrowser.Common.Implementations
FileSystemManager = CreateFileSystemManager();
RegisterSingleInstance(FileSystemManager);
HttpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, Logger, FileSystemManager);
HttpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, Logger, FileSystemManager, ConfigurationManager);
RegisterSingleInstance(HttpClient);
NetworkManager = CreateNetworkManager();

@ -1,5 +1,4 @@
using System.Collections.Specialized;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.Logging;
@ -7,6 +6,7 @@ using MediaBrowser.Model.Net;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Linq;
@ -41,6 +41,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
private readonly IApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem;
private readonly IConfigurationManager _config;
/// <summary>
/// Initializes a new instance of the <see cref="HttpClientManager" /> class.
@ -51,7 +52,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
/// <exception cref="System.ArgumentNullException">appPaths
/// or
/// logger</exception>
public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
public HttpClientManager(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem, IConfigurationManager config)
{
if (appPaths == null)
{
@ -64,6 +65,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
_logger = logger;
_fileSystem = fileSystem;
_config = config;
_appPaths = appPaths;
// http://stackoverflow.com/questions/566437/http-post-returns-the-error-417-expectation-failed-c
@ -116,8 +118,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
request.ConnectionGroupName = GetHostFromUrl(options.Url);
request.KeepAlive = true;
request.KeepAlive = options.EnableKeepAlive;
request.Method = method;
request.Pipelined = true;
request.Timeout = 20000;
@ -128,14 +129,18 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
}
#if !__MonoCS__
// This is a hack to prevent KeepAlive from getting disabled internally by the HttpWebRequest
// May need to remove this for mono
var sp = request.ServicePoint;
if (_httpBehaviorPropertyInfo == null)
if (options.EnableKeepAlive)
{
_httpBehaviorPropertyInfo = sp.GetType().GetProperty("HttpBehaviour", BindingFlags.Instance | BindingFlags.NonPublic);
// This is a hack to prevent KeepAlive from getting disabled internally by the HttpWebRequest
// May need to remove this for mono
var sp = request.ServicePoint;
if (_httpBehaviorPropertyInfo == null)
{
_httpBehaviorPropertyInfo = sp.GetType().GetProperty("HttpBehaviour", BindingFlags.Instance | BindingFlags.NonPublic);
}
_httpBehaviorPropertyInfo.SetValue(sp, (byte)0, null);
}
_httpBehaviorPropertyInfo.SetValue(sp, (byte)0, null);
#endif
return request;

@ -351,18 +351,21 @@ namespace MediaBrowser.Common.Implementations.IO
throw new ArgumentNullException("to");
}
path = path.Replace(from, to, StringComparison.OrdinalIgnoreCase);
var newPath = path.Replace(from, to, StringComparison.OrdinalIgnoreCase);
if (to.IndexOf('/') != -1)
if (!string.Equals(newPath, path))
{
path = path.Replace('\\', '/');
}
else
{
path = path.Replace('/', '\\');
if (to.IndexOf('/') != -1)
{
newPath = path.Replace('\\', '/');
}
else
{
newPath = path.Replace('/', '\\');
}
}
return path;
return newPath;
}
}
}

@ -82,6 +82,7 @@ namespace MediaBrowser.Common.Net
public bool LogRequest { get; set; }
public bool LogErrorResponseBody { get; set; }
public bool EnableKeepAlive { get; set; }
private string GetHeaderValue(string name)
{
@ -99,6 +100,7 @@ namespace MediaBrowser.Common.Net
{
EnableHttpCompression = true;
BufferContent = true;
EnableKeepAlive = true;
RequestHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

@ -10,6 +10,11 @@ namespace MediaBrowser.Common.Net
/// </summary>
public interface IWebSocket : IDisposable
{
/// <summary>
/// Occurs when [closed].
/// </summary>
event EventHandler<EventArgs> Closed;
/// <summary>
/// Gets or sets the state.
/// </summary>

@ -7,6 +7,11 @@ namespace MediaBrowser.Common.Net
{
public interface IWebSocketConnection : IDisposable
{
/// <summary>
/// Occurs when [closed].
/// </summary>
event EventHandler<EventArgs> Closed;
/// <summary>
/// Gets the id.
/// </summary>

@ -10,7 +10,7 @@ namespace MediaBrowser.Controller.Channels
public override bool IsVisible(User user)
{
if (user.Configuration.BlockedChannels.Contains(Name, StringComparer.OrdinalIgnoreCase))
if (user.Configuration.BlockedChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
{
return false;
}

@ -1,6 +1,8 @@
using System.Linq;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Linq;
namespace MediaBrowser.Controller.Channels
{
@ -18,6 +20,8 @@ namespace MediaBrowser.Controller.Channels
public string OriginalImageUrl { get; set; }
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
protected override bool GetBlockUnratedValue(UserConfiguration config)
{
return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent);
@ -30,5 +34,23 @@ namespace MediaBrowser.Controller.Channels
return false;
}
}
public ChannelAudioItem()
{
ChannelMediaSources = new List<ChannelMediaInfo>();
}
public override LocationType LocationType
{
get
{
if (string.IsNullOrEmpty(Path))
{
return LocationType.Remote;
}
return base.LocationType;
}
}
}
}

@ -1,5 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Channels
{
@ -8,10 +9,11 @@ namespace MediaBrowser.Controller.Channels
public string ExternalId { get; set; }
public string ChannelId { get; set; }
public ChannelItemType ChannelItemType { get; set; }
public string OriginalImageUrl { get; set; }
public List<string> Tags { get; set; }
protected override bool GetBlockUnratedValue(UserConfiguration config)
{
@ -26,5 +28,10 @@ namespace MediaBrowser.Controller.Channels
return false;
}
}
public ChannelCategoryItem()
{
Tags = new List<string>();
}
}
}

@ -19,6 +19,7 @@ namespace MediaBrowser.Controller.Channels
public List<string> Genres { get; set; }
public List<string> Studios { get; set; }
public List<string> Tags { get; set; }
public List<PersonInfo> People { get; set; }
@ -49,6 +50,7 @@ namespace MediaBrowser.Controller.Channels
Genres = new List<string>();
Studios = new List<string>();
People = new List<PersonInfo>();
Tags = new List<string>();
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}

@ -18,9 +18,12 @@ namespace MediaBrowser.Controller.Channels
public int? Height { get; set; }
public int? AudioChannels { get; set; }
public bool IsRemote { get; set; }
public ChannelMediaInfo()
{
RequiredHttpHeaders = new Dictionary<string, string>();
IsRemote = true;
}
}
}

@ -1,6 +1,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@ -20,6 +21,8 @@ namespace MediaBrowser.Controller.Channels
public string OriginalImageUrl { get; set; }
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
public override string GetUserDataKey()
{
if (ContentType == ChannelMediaContentType.Trailer)
@ -55,5 +58,23 @@ namespace MediaBrowser.Controller.Channels
return false;
}
}
public ChannelVideoItem()
{
ChannelMediaSources = new List<ChannelMediaInfo>();
}
public override LocationType LocationType
{
get
{
if (string.IsNullOrEmpty(Path))
{
return LocationType.Remote;
}
return base.LocationType;
}
}
}
}

@ -15,6 +15,12 @@ namespace MediaBrowser.Controller.Channels
/// <value>The name.</value>
string Name { get; }
/// <summary>
/// Gets the data version.
/// </summary>
/// <value>The data version.</value>
string DataVersion { get; }
/// <summary>
/// Gets the channel information.
/// </summary>
@ -59,4 +65,15 @@ namespace MediaBrowser.Controller.Channels
/// <returns>IEnumerable{ImageType}.</returns>
IEnumerable<ImageType> GetSupportedChannelImages();
}
public interface IRequiresMediaInfoCallback
{
/// <summary>
/// Gets the channel item media information.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{ChannelMediaInfo}}.</returns>
Task<IEnumerable<ChannelMediaInfo>> GetChannelItemMediaInfo(string id, CancellationToken cancellationToken);
}
}

@ -2,7 +2,7 @@
namespace MediaBrowser.Controller.Channels
{
public interface IChannelItem : IHasImages
public interface IChannelItem : IHasImages, IHasTags
{
string ChannelId { get; set; }

@ -31,5 +31,13 @@ namespace MediaBrowser.Controller.Channels
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{QueryResult{BaseItemDto}}.</returns>
Task<QueryResult<BaseItemDto>> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken);
/// <summary>
/// Gets the channel item media sources.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{ChannelMediaInfo}}.</returns>
Task<IEnumerable<ChannelMediaInfo>> GetChannelItemMediaSources(string id, CancellationToken cancellationToken);
}
}

@ -1,9 +1,13 @@
namespace MediaBrowser.Controller.Channels
using System.Collections.Generic;
namespace MediaBrowser.Controller.Channels
{
public interface IChannelMediaItem : IChannelItem
{
bool IsInfiniteStream { get; set; }
ChannelMediaContentType ContentType { get; set; }
List<ChannelMediaInfo> ChannelMediaSources { get; set; }
}
}

@ -3,7 +3,7 @@ using MediaBrowser.Controller.Providers;
namespace MediaBrowser.Controller.Entities
{
public class AdultVideo : Video, IHasPreferredMetadataLanguage, IHasTaglines
public class AdultVideo : Video, IHasProductionLocations, IHasPreferredMetadataLanguage, IHasTaglines
{
/// <summary>
/// Gets or sets the preferred metadata language.
@ -16,12 +16,14 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value>The preferred metadata country code.</value>
public string PreferredMetadataCountryCode { get; set; }
public List<string> ProductionLocations { get; set; }
public List<string> Taglines { get; set; }
public AdultVideo()
{
Taglines = new List<string>();
ProductionLocations = new List<string>();
}
public override bool BeforeMetadataRefresh()

@ -10,16 +10,18 @@ namespace MediaBrowser.Controller.Entities.Audio
/// <summary>
/// Class Audio
/// </summary>
public class Audio : BaseItem, IHasMediaStreams, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<SongInfo>
public class Audio : BaseItem, IHasMediaStreams, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<SongInfo>, IHasTags
{
public string FormatName { get; set; }
public long? Size { get; set; }
public string Container { get; set; }
public int? TotalBitrate { get; set; }
public List<string> Tags { get; set; }
public Audio()
{
Artists = new List<string>();
Tags = new List<string>();
}
/// <summary>

@ -1501,6 +1501,13 @@ namespace MediaBrowser.Controller.Entities
return userdata != null && userdata.Played;
}
public bool IsFavoriteOrLiked(User user)
{
var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey());
return userdata != null && (userdata.IsFavorite || (userdata.Likes ?? false));
}
public virtual bool IsUnplayed(User user)
{
var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey());

@ -281,7 +281,10 @@ namespace MediaBrowser.Controller.Entities
{
if (this is ICollectionFolder)
{
if (user.Configuration.BlockedMediaFolders.Contains(Name, StringComparer.OrdinalIgnoreCase))
if (user.Configuration.BlockedMediaFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase) ||
// Backwards compatibility
user.Configuration.BlockedMediaFolders.Contains(Name, StringComparer.OrdinalIgnoreCase))
{
return false;
}

@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Entities.Movies
/// <summary>
/// Class Movie
/// </summary>
public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasPreferredMetadataLanguage, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping
public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasPreferredMetadataLanguage, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping
{
public List<Guid> SpecialFeatureIds { get; set; }
@ -22,6 +22,7 @@ namespace MediaBrowser.Controller.Entities.Movies
public List<Guid> ThemeSongIds { get; set; }
public List<Guid> ThemeVideoIds { get; set; }
public List<string> ProductionLocations { get; set; }
/// <summary>
/// This is just a cache to enable quick access by Id
@ -48,6 +49,7 @@ namespace MediaBrowser.Controller.Entities.Movies
BoxSetIdList = new List<Guid>();
Taglines = new List<string>();
Keywords = new List<string>();
ProductionLocations = new List<string>();
}
public string AwardSummary { get; set; }

@ -9,7 +9,7 @@ using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities
{
public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasBudget, IHasLookupInfo<MusicVideoInfo>
public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasProductionLocations, IHasBudget, IHasLookupInfo<MusicVideoInfo>
{
/// <summary>
/// Gets or sets the artist.
@ -34,6 +34,12 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value>The revenue.</value>
public double? Revenue { get; set; }
public List<string> ProductionLocations { get; set; }
public MusicVideo()
{
ProductionLocations = new List<string>();
}
[IgnoreDataMember]
public List<string> AllArtists

@ -12,11 +12,12 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Class Trailer
/// </summary>
public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasBudget, IHasTrailers, IHasKeywords, IHasTaglines, IHasPreferredMetadataLanguage, IHasMetascore, IHasLookupInfo<TrailerInfo>
public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasProductionLocations, IHasBudget, IHasTrailers, IHasKeywords, IHasTaglines, IHasPreferredMetadataLanguage, IHasMetascore, IHasLookupInfo<TrailerInfo>
{
public List<Guid> SoundtrackIds { get; set; }
public string PreferredMetadataLanguage { get; set; }
public List<string> ProductionLocations { get; set; }
/// <summary>
/// Gets or sets the preferred metadata country code.
@ -31,6 +32,7 @@ namespace MediaBrowser.Controller.Entities
SoundtrackIds = new List<Guid>();
LocalTrailerIds = new List<Guid>();
Keywords = new List<string>();
ProductionLocations = new List<string>();
}
public float? Metascore { get; set; }

@ -62,34 +62,6 @@ namespace MediaBrowser.Controller.Providers
ValidationType = ValidationType.None
};
var hasTaglines = item as IHasTaglines;
if (hasTaglines != null)
{
hasTaglines.Taglines.Clear();
}
item.Studios.Clear();
item.Genres.Clear();
item.People.Clear();
var hasTags = item as IHasTags;
if (hasTags != null)
{
hasTags.Tags.Clear();
}
var hasKeywords = item as IHasKeywords;
if (hasKeywords != null)
{
hasKeywords.Keywords.Clear();
}
var hasTrailers = item as IHasTrailers;
if (hasTrailers != null)
{
hasTrailers.RemoteTrailers.Clear();
}
//Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken);
Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken);
}
@ -373,6 +345,15 @@ namespace MediaBrowser.Controller.Providers
break;
}
case "Countries":
{
using (var subtree = reader.ReadSubtree())
{
FetchFromCountriesNode(subtree, item);
}
break;
}
case "ContentRating":
case "MPAARating":
{
@ -857,6 +838,42 @@ namespace MediaBrowser.Controller.Providers
}
}
private void FetchFromCountriesNode(XmlReader reader, T item)
{
reader.MoveToContent();
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "Country":
{
var val = reader.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(val))
{
var hasProductionLocations = item as IHasProductionLocations;
if (hasProductionLocations != null)
{
if (!string.IsNullOrWhiteSpace(val))
{
hasProductionLocations.AddProductionLocation(val);
}
}
}
break;
}
default:
reader.Skip();
break;
}
}
}
}
/// <summary>
/// Fetches from taglines node.
/// </summary>
@ -1059,16 +1076,13 @@ namespace MediaBrowser.Controller.Providers
}
}
protected async Task FetchChaptersFromXmlNode(BaseItem item, XmlReader reader, IItemRepository repository, CancellationToken cancellationToken)
protected List<ChapterInfo> FetchChaptersFromXmlNode(BaseItem item, XmlReader reader)
{
var runtime = item.RunTimeTicks ?? 0;
using (reader)
{
var chapters = GetChaptersFromXmlNode(reader)
.Where(i => i.StartPositionTicks >= 0 && i.StartPositionTicks < runtime);
await repository.SaveChapters(item.Id, chapters, cancellationToken).ConfigureAwait(false);
return GetChaptersFromXmlNode(reader)
.Where(i => i.StartPositionTicks >= 0)
.ToList();
}
}

@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -35,10 +36,12 @@ namespace MediaBrowser.Controller.Providers
public T Item { get; set; }
public List<LocalImageInfo> Images { get; set; }
public List<ChapterInfo> Chapters { get; set; }
public LocalMetadataResult()
{
Images = new List<LocalImageInfo>();
Chapters = new List<ChapterInfo>();
}
}
}

@ -34,17 +34,22 @@ namespace MediaBrowser.Controller.Providers
/// <summary>
/// Providers will be executed based on default rules
/// </summary>
EnsureMetadata,
EnsureMetadata = 0,
/// <summary>
/// No providers will be executed
/// </summary>
None,
None = 1,
/// <summary>
/// All providers will be executed to search for new metadata
/// </summary>
FullRefresh
FullRefresh = 2,
/// <summary>
/// The validation only
/// </summary>
ValidationOnly = 3
}
public enum ImageRefreshMode
@ -52,16 +57,16 @@ namespace MediaBrowser.Controller.Providers
/// <summary>
/// The default
/// </summary>
Default,
Default = 0,
/// <summary>
/// Existing images will be validated
/// </summary>
ValidationOnly,
ValidationOnly = 1,
/// <summary>
/// All providers will be executed to search for new metadata
/// </summary>
FullRefresh
FullRefresh = 2
}
}

@ -1,5 +1,6 @@
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Session;
using MediaBrowser.Model.System;
using System.Threading;
using System.Threading.Tasks;
@ -13,6 +14,12 @@ namespace MediaBrowser.Controller.Session
/// <value><c>true</c> if this instance is session active; otherwise, <c>false</c>.</value>
bool IsSessionActive { get; }
/// <summary>
/// Gets a value indicating whether [supports media remote control].
/// </summary>
/// <value><c>true</c> if [supports media remote control]; otherwise, <c>false</c>.</value>
bool SupportsMediaControl { get; }
/// <summary>
/// Sends the play command.
/// </summary>
@ -48,9 +55,10 @@ namespace MediaBrowser.Controller.Session
/// <summary>
/// Sends the restart required message.
/// </summary>
/// <param name="info">The information.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SendRestartRequiredNotification(CancellationToken cancellationToken);
Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken);
/// <summary>
/// Sends the user data change info.

@ -139,6 +139,19 @@ namespace MediaBrowser.Controller.Session
}
}
public bool SupportsMediaControl
{
get
{
if (SessionController != null)
{
return SessionController.SupportsMediaControl;
}
return false;
}
}
public bool ContainsUser(Guid userId)
{
return (UserId ?? Guid.Empty) == UserId || AdditionalUsers.Any(i => userId == new Guid(i.UserId));

@ -39,12 +39,33 @@ namespace MediaBrowser.Controller.Subtitles
/// </summary>
/// <param name="video">The video.</param>
/// <param name="subtitleId">The subtitle identifier.</param>
/// <param name="providerName">Name of the provider.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task DownloadSubtitles(Video video,
string subtitleId,
string providerName,
CancellationToken cancellationToken);
/// <summary>
/// Gets the remote subtitles.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{SubtitleResponse}.</returns>
Task<SubtitleResponse> GetRemoteSubtitles(string id, CancellationToken cancellationToken);
/// <summary>
/// Deletes the subtitles.
/// </summary>
/// <param name="itemId">The item identifier.</param>
/// <param name="index">The index.</param>
/// <returns>Task.</returns>
Task DeleteSubtitles(string itemId, int index);
/// <summary>
/// Gets the providers.
/// </summary>
/// <param name="itemId">The item identifier.</param>
/// <returns>IEnumerable{SubtitleProviderInfo}.</returns>
IEnumerable<SubtitleProviderInfo> GetProviders(string itemId);
}
}

@ -6,6 +6,7 @@ namespace MediaBrowser.Controller.Subtitles
{
public string Language { get; set; }
public string Format { get; set; }
public bool IsForced { get; set; }
public Stream Stream { get; set; }
}
}

@ -21,8 +21,11 @@ namespace MediaBrowser.Controller.Subtitles
public long? RuntimeTicks { get; set; }
public Dictionary<string, string> ProviderIds { get; set; }
public bool SearchAllProviders { get; set; }
public SubtitleSearchRequest()
{
SearchAllProviders = true;
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}

@ -497,7 +497,7 @@ namespace MediaBrowser.Dlna
var profile = GetProfile(headers) ??
GetDefaultProfile();
return new DescriptionXmlBuilder(profile, serverUuId).GetXml();
return new DescriptionXmlBuilder(profile, serverUuId, "").GetXml();
}
public DlnaIconResponse GetIcon(string filename)

@ -19,6 +19,7 @@ using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.System;
namespace MediaBrowser.Dlna.PlayTo
{
@ -46,6 +47,11 @@ namespace MediaBrowser.Dlna.PlayTo
}
}
public bool SupportsMediaControl
{
get { return IsSessionActive; }
}
private Timer _updateTimer;
public PlayToController(SessionInfo session, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IDtoService dtoService, IImageProcessor imageProcessor, SsdpHandler ssdpHandler, string serverAddress)
@ -315,7 +321,7 @@ namespace MediaBrowser.Dlna.PlayTo
return Task.FromResult(true);
}
public Task SendRestartRequiredNotification(CancellationToken cancellationToken)
public Task SendRestartRequiredNotification(SystemInfo info, CancellationToken cancellationToken)
{
return Task.FromResult(true);
}

@ -306,7 +306,9 @@ namespace MediaBrowser.Dlna.PlayTo
GeneralCommandType.Unmute.ToString(),
GeneralCommandType.ToggleMute.ToString(),
GeneralCommandType.SetVolume.ToString()
}
},
SupportsMediaControl = true
});
_logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);

@ -99,6 +99,13 @@ namespace MediaBrowser.Dlna.Server
{
var list = new List<StateVariable>();
list.Add(new StateVariable
{
Name = "A_ARG_TYPE_Filter",
DataType = "string",
SendsEvents = false
});
list.Add(new StateVariable
{
Name = "A_ARG_TYPE_SortCriteria",
@ -108,64 +115,64 @@ namespace MediaBrowser.Dlna.Server
list.Add(new StateVariable
{
Name = "A_ARG_TYPE_UpdateID",
Name = "A_ARG_TYPE_Index",
DataType = "ui4",
SendsEvents = false
});
list.Add(new StateVariable
{
Name = "A_ARG_TYPE_SearchCriteria",
DataType = "string",
Name = "A_ARG_TYPE_Count",
DataType = "ui4",
SendsEvents = false
});
list.Add(new StateVariable
{
Name = "A_ARG_TYPE_Filter",
DataType = "string",
Name = "A_ARG_TYPE_UpdateID",
DataType = "ui4",
SendsEvents = false
});
list.Add(new StateVariable
{
Name = "A_ARG_TYPE_Result",
Name = "SearchCapabilities",
DataType = "string",
SendsEvents = false
});
list.Add(new StateVariable
{
Name = "A_ARG_TYPE_Index",
DataType = "ui4",
Name = "SortCapabilities",
DataType = "string",
SendsEvents = false
});
list.Add(new StateVariable
{
Name = "A_ARG_TYPE_ObjectID",
DataType = "string",
SendsEvents = false
Name = "SystemUpdateID",
DataType = "ui4",
SendsEvents = true
});
list.Add(new StateVariable
{
Name = "SortCapabilities",
Name = "A_ARG_TYPE_SearchCriteria",
DataType = "string",
SendsEvents = false
});
list.Add(new StateVariable
{
Name = "SearchCapabilities",
Name = "A_ARG_TYPE_Result",
DataType = "string",
SendsEvents = false
});
list.Add(new StateVariable
{
Name = "A_ARG_TYPE_Count",
DataType = "ui4",
Name = "A_ARG_TYPE_ObjectID",
DataType = "string",
SendsEvents = false
});
@ -182,13 +189,6 @@ namespace MediaBrowser.Dlna.Server
}
});
list.Add(new StateVariable
{
Name = "SystemUpdateID",
DataType = "ui4",
SendsEvents = true
});
list.Add(new StateVariable
{
Name = "A_ARG_TYPE_BrowseLetter",

@ -14,8 +14,9 @@ namespace MediaBrowser.Dlna.Server
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly string _serverUdn;
private readonly string _serverAddress;
public DescriptionXmlBuilder(DeviceProfile profile, string serverUdn)
public DescriptionXmlBuilder(DeviceProfile profile, string serverUdn, string serverAddress)
{
if (string.IsNullOrWhiteSpace(serverUdn))
{
@ -24,6 +25,7 @@ namespace MediaBrowser.Dlna.Server
_profile = profile;
_serverUdn = serverUdn;
_serverAddress = serverAddress;
}
public string GetXml()
@ -67,6 +69,7 @@ namespace MediaBrowser.Dlna.Server
builder.Append("<dlna:X_DLNACAP>" + SecurityElement.Escape(_profile.XDlnaCap ?? string.Empty) + "</dlna:X_DLNACAP>");
builder.Append("<dlna:X_DLNADOC xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\">" + SecurityElement.Escape(_profile.XDlnaDoc ?? string.Empty) + "</dlna:X_DLNADOC>");
builder.Append("<dlna:X_DLNADOC xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\">M-DMS-1.50</dlna:X_DLNADOC>");
builder.Append("<friendlyName>" + SecurityElement.Escape(_profile.FriendlyName ?? string.Empty) + "</friendlyName>");
builder.Append("<deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType>");
@ -78,6 +81,8 @@ namespace MediaBrowser.Dlna.Server
builder.Append("<modelURL>" + SecurityElement.Escape(_profile.ModelUrl ?? string.Empty) + "</modelURL>");
builder.Append("<serialNumber>" + SecurityElement.Escape(_profile.SerialNumber ?? string.Empty) + "</serialNumber>");
//builder.Append("<URLBase>" + SecurityElement.Escape(_serverAddress) + "</URLBase>");
if (!string.IsNullOrWhiteSpace(_profile.SonyAggregationFlags))
{
builder.Append("<av:aggregationFlags xmlns:av=\"urn:schemas-sony-com:av\">" + SecurityElement.Escape(_profile.SonyAggregationFlags) + "</av:aggregationFlags>");

@ -9,11 +9,11 @@ namespace MediaBrowser.Dlna.Server
{
var list = new List<ServiceAction>
{
GetGetSystemUpdateIDAction(),
GetSearchCapabilitiesAction(),
GetSortCapabilitiesAction(),
GetSearchAction(),
GetGetSystemUpdateIDAction(),
GetBrowseAction(),
GetSearchAction(),
GetX_GetFeatureListAction(),
GetXSetBookmarkAction(),
GetBrowseByLetterAction()

@ -1,91 +0,0 @@
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<string> { task.MediaPath }, task.IsInputRemote);
}
private string GetOutputModifier(InternalEncodingTask task)
{
var options = task.Request;
var audioTranscodeParams = new List<string>
{
"-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());
}
}
}

@ -64,77 +64,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
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;
@ -157,19 +86,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
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;
}
/// <summary>
/// Gets the number of audio channels to specify on the command line
/// </summary>
@ -201,35 +117,5 @@ namespace MediaBrowser.MediaEncoding.Encoder
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, 2);
}
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 ? Math.Max(Environment.ProcessorCount - 1, 2) : 0;
default:
throw new Exception("Unrecognized MediaEncodingQuality value.");
}
}
}
}

@ -1,168 +0,0 @@
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<InternalEncodingTask,string,string> 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;
}
}
}
}

@ -1,235 +0,0 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Logging;
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.MediaEncoding.Encoder
{
public class ImageEncoder
{
private readonly string _ffmpegPath;
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
private readonly IApplicationPaths _appPaths;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private static readonly SemaphoreSlim ResourcePool = new SemaphoreSlim(10, 10);
public ImageEncoder(string ffmpegPath, ILogger logger, IFileSystem fileSystem, IApplicationPaths appPaths)
{
_ffmpegPath = ffmpegPath;
_logger = logger;
_fileSystem = fileSystem;
_appPaths = appPaths;
}
public async Task<Stream> EncodeImage(ImageEncodingOptions options, CancellationToken cancellationToken)
{
ValidateInput(options);
await ResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
return await EncodeImageInternal(options, cancellationToken).ConfigureAwait(false);
}
finally
{
ResourcePool.Release();
}
}
private async Task<Stream> EncodeImageInternal(ImageEncodingOptions options, CancellationToken cancellationToken)
{
ValidateInput(options);
var inputPath = options.InputPath;
var filename = Path.GetFileName(inputPath);
if (HasDiacritics(filename))
{
inputPath = GetTempFile(inputPath);
filename = Path.GetFileName(inputPath);
}
var process = new Process
{
StartInfo = new ProcessStartInfo
{
CreateNoWindow = true,
UseShellExecute = false,
FileName = _ffmpegPath,
Arguments = GetArguments(options, filename),
WindowStyle = ProcessWindowStyle.Hidden,
ErrorDialog = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
WorkingDirectory = Path.GetDirectoryName(inputPath)
}
};
_logger.Debug("ffmpeg " + process.StartInfo.Arguments);
process.Start();
var memoryStream = new MemoryStream();
#pragma warning disable 4014
// Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
process.StandardOutput.BaseStream.CopyToAsync(memoryStream);
#pragma warning restore 4014
// MUST read both stdout and stderr asynchronously or a deadlock may occurr
process.BeginErrorReadLine();
var ranToCompletion = process.WaitForExit(5000);
if (!ranToCompletion)
{
try
{
_logger.Info("Killing ffmpeg process");
process.Kill();
process.WaitForExit(1000);
}
catch (Exception ex)
{
_logger.ErrorException("Error killing process", ex);
}
}
var exitCode = ranToCompletion ? process.ExitCode : -1;
process.Dispose();
if (exitCode == -1 || memoryStream.Length == 0)
{
memoryStream.Dispose();
var msg = string.Format("ffmpeg image encoding failed for {0}", options.InputPath);
_logger.Error(msg);
throw new ApplicationException(msg);
}
memoryStream.Position = 0;
return memoryStream;
}
private string GetTempFile(string path)
{
var extension = Path.GetExtension(path) ?? string.Empty;
var tempPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N") + extension);
File.Copy(path, tempPath);
return tempPath;
}
private string GetArguments(ImageEncodingOptions options, string inputFilename)
{
var vfScale = GetFilterGraph(options);
var outputFormat = GetOutputFormat(options.Format);
var quality = (options.Quality ?? 100) * .3;
quality = 31 - quality;
var qualityValue = Convert.ToInt32(Math.Max(quality, 1));
return string.Format("-f image2 -i file:\"{3}\" -q:v {0} {1} -f image2pipe -vcodec {2} -",
qualityValue.ToString(_usCulture),
vfScale,
outputFormat,
inputFilename);
}
private string GetFilterGraph(ImageEncodingOptions options)
{
if (!options.Width.HasValue &&
!options.Height.HasValue &&
!options.MaxHeight.HasValue &&
!options.MaxWidth.HasValue)
{
return string.Empty;
}
var widthScale = "-1";
var heightScale = "-1";
if (options.MaxWidth.HasValue)
{
widthScale = "min(iw\\," + options.MaxWidth.Value.ToString(_usCulture) + ")";
}
else if (options.Width.HasValue)
{
widthScale = options.Width.Value.ToString(_usCulture);
}
if (options.MaxHeight.HasValue)
{
heightScale = "min(ih\\," + options.MaxHeight.Value.ToString(_usCulture) + ")";
}
else if (options.Height.HasValue)
{
heightScale = options.Height.Value.ToString(_usCulture);
}
var scaleMethod = "lanczos";
return string.Format("-vf scale=\"{0}:{1}\"",
widthScale,
heightScale);
}
private string GetOutputFormat(string format)
{
if (string.Equals(format, "jpeg", StringComparison.OrdinalIgnoreCase) ||
string.Equals(format, "jpg", StringComparison.OrdinalIgnoreCase))
{
return "mjpeg";
}
return format;
}
private void ValidateInput(ImageEncodingOptions options)
{
}
/// <summary>
/// Determines whether the specified text has diacritics.
/// </summary>
/// <param name="text">The text.</param>
/// <returns><c>true</c> if the specified text has diacritics; otherwise, <c>false</c>.</returns>
private bool HasDiacritics(string text)
{
return !String.Equals(text, RemoveDiacritics(text), StringComparison.Ordinal);
}
/// <summary>
/// Removes the diacritics.
/// </summary>
/// <param name="text">The text.</param>
/// <returns>System.String.</returns>
private string RemoveDiacritics(string text)
{
return String.Concat(
text.Normalize(NormalizationForm.FormD)
.Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) !=
UnicodeCategory.NonSpacingMark)
).Normalize(NormalizationForm.FormC);
}
}
}

@ -1,95 +0,0 @@
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<string> 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; }
/// <summary>
/// Gets or sets the user agent.
/// </summary>
/// <value>The user agent.</value>
public string UserAgent { get; set; }
public EncodingQuality QualitySetting { get; set; }
public InternalEncodingTask()
{
Id = Guid.NewGuid().ToString("N");
CancellationTokenSource = new CancellationTokenSource();
StreamFileNames = new List<string>();
}
public bool EnableDebugLogging { get; set; }
internal void OnBegin()
{
}
internal void OnCompleted()
{
}
internal void OnError()
{
}
}
}

@ -1,311 +0,0 @@
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<InternalEncodingTask> 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;
}
}
/// <summary>
/// Determines which stream will be used for playback
/// </summary>
/// <param name="allStream">All stream.</param>
/// <param name="desiredIndex">Index of the desired.</param>
/// <param name="type">The type.</param>
/// <param name="returnFirstIfNoIndex">if set to <c>true</c> [return first if no index].</param>
/// <returns>MediaStream.</returns>
private MediaStream GetMediaStream(IEnumerable<MediaStream> 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) :
// 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;
// if (state.VideoRequest != null && string.IsNullOrWhiteSpace(state.VideoRequest.VideoProfile))
// {
// state.VideoRequest.VideoProfile = transcodingProfile.VideoProfile;
// }
//}
}
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;
}
}
}

@ -853,7 +853,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
public Task<Stream> EncodeImage(ImageEncodingOptions options, CancellationToken cancellationToken)
{
return new ImageEncoder(FFMpegPath, _logger, _fileSystem, _appPaths).EncodeImage(options, cancellationToken);
throw new NotImplementedException();
}
/// <summary>

@ -53,12 +53,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="BdInfo\BdInfoExaminer.cs" />
<Compile Include="Encoder\AudioEncoder.cs" />
<Compile Include="Encoder\EncodingUtils.cs" />
<Compile Include="Encoder\FFMpegProcess.cs" />
<Compile Include="Encoder\ImageEncoder.cs" />
<Compile Include="Encoder\InternalEncodingTask.cs" />
<Compile Include="Encoder\InternalEncodingTaskFactory.cs" />
<Compile Include="Encoder\MediaEncoder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Subtitles\ISubtitleParser.cs" />

@ -3,5 +3,6 @@
public class LiveTvOptions
{
public int? GuideDays { get; set; }
public string ActiveService { get; set; }
}
}

@ -6,6 +6,10 @@ namespace MediaBrowser.Model.Configuration
ApplicationUpdateInstalled,
AudioPlayback,
GamePlayback,
VideoPlayback,
AudioPlaybackStopped,
GamePlaybackStopped,
VideoPlaybackStopped,
InstallationFailed,
PluginError,
PluginInstalled,
@ -14,7 +18,6 @@ namespace MediaBrowser.Model.Configuration
NewLibraryContent,
NewLibraryContentMultiple,
ServerRestartRequired,
TaskFailed,
VideoPlayback
TaskFailed
}
}

@ -318,44 +318,5 @@ namespace MediaBrowser.Model.Dlna
}
return null;
}
public ResponseProfile GetPhotoMediaProfile(string container, int? width, int? height)
{
container = (container ?? string.Empty).TrimStart('.');
foreach (var i in ResponseProfiles)
{
if (i.Type != DlnaProfileType.Photo)
{
continue;
}
List<string> containers = i.GetContainers().ToList();
if (containers.Count > 0 && !containers.Contains(container, StringComparer.OrdinalIgnoreCase))
{
continue;
}
ConditionProcessor conditionProcessor = new ConditionProcessor();
var anyOff = false;
foreach (ProfileCondition c in i.Conditions)
{
if (!conditionProcessor.IsImageConditionSatisfied(c, width, height))
{
anyOff = true;
break;
}
}
if (anyOff)
{
continue;
}
return i;
}
return null;
}
}
}

@ -133,6 +133,12 @@ namespace MediaBrowser.Model.Dto
/// <value>The custom rating.</value>
public string CustomRating { get; set; }
/// <summary>
/// Gets or sets the channel identifier.
/// </summary>
/// <value>The channel identifier.</value>
public string ChannelId { get; set; }
/// <summary>
/// Gets or sets the overview.
/// </summary>

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
namespace MediaBrowser.Model.Entities
{

@ -16,4 +16,10 @@ namespace MediaBrowser.Model.Providers
public int? DownloadCount { get; set; }
public bool? IsHashMatch { get; set; }
}
public class SubtitleProviderInfo
{
public string Name { get; set; }
public string Id { get; set; }
}
}

@ -82,5 +82,6 @@ namespace MediaBrowser.Model.Querying
public const string Studio = "Studio";
public const string Players = "Players";
public const string GameSystem = "GameSystem";
public const string IsFavoriteOrLiked = "IsFavoriteOrLiked";
}
}

@ -8,6 +8,10 @@ namespace MediaBrowser.Model.Session
public List<string> SupportedCommands { get; set; }
public bool SupportsMediaControl { get; set; }
public string MessageCallbackUrl { get; set; }
public SessionCapabilities()
{
PlayableMediaTypes = new List<string>();

@ -1,8 +1,10 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Movies;
using System.Collections.Generic;
using System.IO;
using System.Threading;
@ -20,7 +22,11 @@ namespace MediaBrowser.Providers.AdultVideos
protected override void Fetch(LocalMetadataResult<AdultVideo> result, string path, CancellationToken cancellationToken)
{
new MovieXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
var chapters = new List<ChapterInfo>();
new MovieXmlParser(_logger).Fetch(result.Item, chapters, path, cancellationToken);
result.Chapters = chapters;
}
protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)

@ -109,6 +109,7 @@
<Compile Include="MediaInfo\FFProbeProvider.cs" />
<Compile Include="MediaInfo\FFProbeVideoInfo.cs" />
<Compile Include="MediaInfo\SubtitleDownloader.cs" />
<Compile Include="MediaInfo\SubtitleResolver.cs" />
<Compile Include="Movies\MovieDbTrailerProvider.cs" />
<Compile Include="Movies\MovieExternalIds.cs" />
<Compile Include="Movies\TrailerMetadataService.cs" />

@ -142,7 +142,7 @@ namespace MediaBrowser.Providers.MediaInfo
var prober = new FFProbeVideoInfo(_logger, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager, _fileSystem, _config, _subtitleManager);
return prober.ProbeVideo(item, directoryService, cancellationToken);
return prober.ProbeVideo(item, directoryService, true, cancellationToken);
}
public Task<ItemUpdateType> FetchAudioInfo<T>(T item, CancellationToken cancellationToken)
@ -173,7 +173,7 @@ namespace MediaBrowser.Providers.MediaInfo
{
var prober = new FFProbeVideoInfo(_logger, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager, _fileSystem, _config, _subtitleManager);
return !video.SubtitleFiles.SequenceEqual(prober.GetSubtitleFiles(video, directoryService, false).Select(i => i.FullName).OrderBy(i => i), StringComparer.OrdinalIgnoreCase);
return !video.SubtitleFiles.SequenceEqual(SubtitleResolver.GetSubtitleFiles(video, directoryService, false).Select(i => i.FullName).OrderBy(i => i), StringComparer.OrdinalIgnoreCase);
}
}

@ -60,7 +60,7 @@ namespace MediaBrowser.Providers.MediaInfo
_subtitleManager = subtitleManager;
}
public async Task<ItemUpdateType> ProbeVideo<T>(T item, IDirectoryService directoryService, CancellationToken cancellationToken)
public async Task<ItemUpdateType> ProbeVideo<T>(T item, IDirectoryService directoryService, bool enableSubtitleDownloading, CancellationToken cancellationToken)
where T : Video
{
var isoMount = await MountIsoIfNeeded(item, cancellationToken).ConfigureAwait(false);
@ -105,7 +105,7 @@ namespace MediaBrowser.Providers.MediaInfo
cancellationToken.ThrowIfCancellationRequested();
await Fetch(item, cancellationToken, result, isoMount, blurayDiscInfo, directoryService).ConfigureAwait(false);
await Fetch(item, cancellationToken, result, isoMount, blurayDiscInfo, directoryService, enableSubtitleDownloading).ConfigureAwait(false);
}
finally
@ -160,7 +160,7 @@ namespace MediaBrowser.Providers.MediaInfo
return result;
}
protected async Task Fetch(Video video, CancellationToken cancellationToken, InternalMediaInfoResult data, IIsoMount isoMount, BlurayDiscInfo blurayInfo, IDirectoryService directoryService)
protected async Task Fetch(Video video, CancellationToken cancellationToken, InternalMediaInfoResult data, IIsoMount isoMount, BlurayDiscInfo blurayInfo, IDirectoryService directoryService, bool enableSubtitleDownloading)
{
var mediaInfo = MediaEncoderHelpers.GetMediaInfo(data);
var mediaStreams = mediaInfo.MediaStreams;
@ -208,7 +208,7 @@ namespace MediaBrowser.Providers.MediaInfo
FetchBdInfo(video, chapters, mediaStreams, blurayInfo);
}
await AddExternalSubtitles(video, mediaStreams, directoryService, cancellationToken).ConfigureAwait(false);
await AddExternalSubtitles(video, mediaStreams, directoryService, enableSubtitleDownloading, cancellationToken).ConfigureAwait(false);
FetchWtvInfo(video, data);
@ -255,7 +255,9 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
info.StartPositionTicks = chapter.start / 100;
// Limit accuracy to milliseconds to match xml saving
var ms = Math.Round(TimeSpan.FromTicks(chapter.start / 100).TotalMilliseconds);
info.StartPositionTicks = TimeSpan.FromMilliseconds(ms).Ticks;
return info;
}
@ -409,60 +411,22 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
private IEnumerable<string> SubtitleExtensions
{
get
{
return new[] { ".srt", ".ssa", ".ass", ".sub" };
}
}
public IEnumerable<FileSystemInfo> GetSubtitleFiles(Video video, IDirectoryService directoryService, bool clearCache)
{
var containingPath = video.ContainingFolderPath;
if (string.IsNullOrEmpty(containingPath))
{
throw new ArgumentException(string.Format("Cannot search for items that don't have a path: {0} {1}", video.Name, video.Id));
}
var files = directoryService.GetFiles(containingPath, clearCache);
var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
return files.Where(i =>
{
if (!i.Attributes.HasFlag(FileAttributes.Directory) &&
SubtitleExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
{
var fullName = i.FullName;
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName);
if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
});
}
/// <summary>
/// Adds the external subtitles.
/// </summary>
/// <param name="video">The video.</param>
/// <param name="currentStreams">The current streams.</param>
private async Task AddExternalSubtitles(Video video, List<MediaStream> currentStreams, IDirectoryService directoryService, CancellationToken cancellationToken)
/// <param name="directoryService">The directory service.</param>
/// <param name="enableSubtitleDownloading">if set to <c>true</c> [enable subtitle downloading].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
private async Task AddExternalSubtitles(Video video, List<MediaStream> currentStreams, IDirectoryService directoryService, bool enableSubtitleDownloading, CancellationToken cancellationToken)
{
var externalSubtitleStreams = GetExternalSubtitleStreams(video, currentStreams.Count, directoryService, false).ToList();
var subtitleResolver = new SubtitleResolver(_localization);
var externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, currentStreams.Count, directoryService, false).ToList();
if ((_config.Configuration.SubtitleOptions.DownloadEpisodeSubtitles &&
if (enableSubtitleDownloading && (_config.Configuration.SubtitleOptions.DownloadEpisodeSubtitles &&
video is Episode) ||
(_config.Configuration.SubtitleOptions.DownloadMovieSubtitles &&
video is Movie))
@ -480,7 +444,7 @@ namespace MediaBrowser.Providers.MediaInfo
// Rescan
if (downloadedLanguages.Count > 0)
{
externalSubtitleStreams = GetExternalSubtitleStreams(video, currentStreams.Count, directoryService, true).ToList();
externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, currentStreams.Count, directoryService, true).ToList();
}
}
@ -489,65 +453,6 @@ namespace MediaBrowser.Providers.MediaInfo
currentStreams.AddRange(externalSubtitleStreams);
}
private IEnumerable<MediaStream> GetExternalSubtitleStreams(Video video,
int startIndex,
IDirectoryService directoryService,
bool clearCache)
{
var files = GetSubtitleFiles(video, directoryService, clearCache);
var streams = new List<MediaStream>();
var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
foreach (var file in files)
{
var fullName = file.FullName;
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName);
// If the subtitle file matches the video file name
if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
{
streams.Add(new MediaStream
{
Index = startIndex++,
Type = MediaStreamType.Subtitle,
IsExternal = true,
Path = fullName,
Codec = Path.GetExtension(fullName).ToLower().TrimStart('.')
});
}
else if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
{
// Support xbmc naming conventions - 300.spanish.srt
var language = fileNameWithoutExtension.Split('.').LastOrDefault();
// Try to translate to three character code
// Be flexible and check against both the full and three character versions
var culture = _localization.GetCultures()
.FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.ThreeLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.TwoLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase));
if (culture != null)
{
language = culture.ThreeLetterISOLanguageName;
}
streams.Add(new MediaStream
{
Index = startIndex++,
Type = MediaStreamType.Subtitle,
IsExternal = true,
Path = fullName,
Codec = Path.GetExtension(fullName).ToLower().TrimStart('.'),
Language = language
});
}
}
return streams;
}
/// <summary>
/// The dummy chapter duration
/// </summary>

@ -124,7 +124,10 @@ namespace MediaBrowser.Providers.MediaInfo
Name = video.Name,
ParentIndexNumber = video.ParentIndexNumber,
ProductionYear = video.ProductionYear,
ProviderIds = video.ProviderIds
ProviderIds = video.ProviderIds,
// Stop as soon as we find something
SearchAllProviders = false
};
var episode = video as Episode;
@ -143,7 +146,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (result != null)
{
await _subtitleManager.DownloadSubtitles(video, result.Id, result.ProviderName, cancellationToken)
await _subtitleManager.DownloadSubtitles(video, result.Id, cancellationToken)
.ConfigureAwait(false);
return true;

@ -0,0 +1,135 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace MediaBrowser.Providers.MediaInfo
{
public class SubtitleResolver
{
private readonly ILocalizationManager _localization;
public SubtitleResolver(ILocalizationManager localization)
{
_localization = localization;
}
public IEnumerable<MediaStream> GetExternalSubtitleStreams(Video video,
int startIndex,
IDirectoryService directoryService,
bool clearCache)
{
var files = GetSubtitleFiles(video, directoryService, clearCache);
var streams = new List<MediaStream>();
var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
foreach (var file in files)
{
var fullName = file.FullName;
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName);
var codec = Path.GetExtension(fullName).ToLower().TrimStart('.');
// If the subtitle file matches the video file name
if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
{
streams.Add(new MediaStream
{
Index = startIndex++,
Type = MediaStreamType.Subtitle,
IsExternal = true,
Path = fullName,
Codec = codec
});
}
else if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
{
var isForced = fullName.IndexOf(".forced.", StringComparison.OrdinalIgnoreCase) != -1 ||
fullName.IndexOf(".foreign.", StringComparison.OrdinalIgnoreCase) != -1;
// Support xbmc naming conventions - 300.spanish.srt
var language = fileNameWithoutExtension
.Replace(".forced", string.Empty, StringComparison.OrdinalIgnoreCase)
.Replace(".foreign", string.Empty, StringComparison.OrdinalIgnoreCase)
.Split('.')
.LastOrDefault();
// Try to translate to three character code
// Be flexible and check against both the full and three character versions
var culture = _localization.GetCultures()
.FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.ThreeLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase) || string.Equals(i.TwoLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase));
if (culture != null)
{
language = culture.ThreeLetterISOLanguageName;
}
streams.Add(new MediaStream
{
Index = startIndex++,
Type = MediaStreamType.Subtitle,
IsExternal = true,
Path = fullName,
Codec = codec,
Language = language,
IsForced = isForced
});
}
}
return streams;
}
private static IEnumerable<string> SubtitleExtensions
{
get
{
return new[] { ".srt", ".ssa", ".ass", ".sub" };
}
}
public static IEnumerable<FileSystemInfo> GetSubtitleFiles(Video video, IDirectoryService directoryService, bool clearCache)
{
var containingPath = video.ContainingFolderPath;
if (string.IsNullOrEmpty(containingPath))
{
throw new ArgumentException(string.Format("Cannot search for items that don't have a path: {0} {1}", video.Name, video.Id));
}
var files = directoryService.GetFiles(containingPath, clearCache);
var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
return files.Where(i =>
{
if (!i.Attributes.HasFlag(FileAttributes.Directory) &&
SubtitleExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
{
var fullName = i.FullName;
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName);
if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
});
}
}
}

@ -133,6 +133,18 @@ namespace MediaBrowser.Providers.Movies
}
}
if (movieData.production_countries != null)
{
var hasProductionLocations = movie as IHasProductionLocations;
if (hasProductionLocations != null)
{
hasProductionLocations.ProductionLocations = movieData
.production_countries
.Select(i => i.name)
.ToList();
}
}
movie.SetProviderId(MetadataProviders.Tmdb, movieData.id.ToString(_usCulture));
movie.SetProviderId(MetadataProviders.Imdb, movieData.imdb_id);

@ -1,7 +1,9 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System.Collections.Generic;
using System.Threading;
using System.Xml;
@ -12,13 +14,20 @@ namespace MediaBrowser.Providers.Movies
/// </summary>
public class MovieXmlParser : BaseItemXmlParser<Video>
{
private List<ChapterInfo> _chaptersFound;
public MovieXmlParser(ILogger logger)
: base(logger)
{
}
public void FetchAsync(Video item, string metadataFile, CancellationToken cancellationToken)
public void Fetch(Video item,
List<ChapterInfo> chapters,
string metadataFile,
CancellationToken cancellationToken)
{
_chaptersFound = chapters;
Fetch(item, metadataFile, cancellationToken);
}
@ -32,7 +41,6 @@ namespace MediaBrowser.Providers.Movies
switch (reader.Name)
{
case "TmdbCollectionName":
{
var val = reader.ReadElementContentAsString();
var movie = item as Movie;
@ -41,13 +49,13 @@ namespace MediaBrowser.Providers.Movies
{
movie.TmdbCollectionName = val;
}
break;
}
case "Chapters":
//_chaptersTask = FetchChaptersFromXmlNode(item, reader.ReadSubtree(), _itemRepo, CancellationToken.None);
_chaptersFound.AddRange(FetchChaptersFromXmlNode(item, reader.ReadSubtree()));
break;
default:

@ -1,7 +1,9 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System.Collections.Generic;
using System.IO;
using System.Threading;
@ -19,7 +21,11 @@ namespace MediaBrowser.Providers.Movies
protected override void Fetch(LocalMetadataResult<Movie> result, string path, CancellationToken cancellationToken)
{
new MovieXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
var chapters = new List<ChapterInfo>();
new MovieXmlParser(_logger).Fetch(result.Item, chapters, path, cancellationToken);
result.Chapters = chapters;
}
protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)

@ -1,7 +1,9 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System.Collections.Generic;
using System.IO;
using System.Threading;
@ -19,7 +21,11 @@ namespace MediaBrowser.Providers.Movies
protected override void Fetch(LocalMetadataResult<Trailer> result, string path, CancellationToken cancellationToken)
{
new MovieXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
var chapters = new List<ChapterInfo>();
new MovieXmlParser(_logger).Fetch(result.Item, chapters, path, cancellationToken);
result.Chapters = chapters;
}
protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)

@ -34,6 +34,7 @@ namespace MediaBrowser.Providers.Savers
"Chapters",
"ContentRating",
"Countries",
"CustomRating",
"CriticRating",
"CriticRatingSummary",
@ -318,6 +319,22 @@ namespace MediaBrowser.Providers.Savers
}
}
var hasProductionLocations = item as IHasProductionLocations;
if (hasProductionLocations != null)
{
if (hasProductionLocations.ProductionLocations.Count > 0)
{
builder.Append("<Countries>");
foreach (var name in hasProductionLocations.ProductionLocations)
{
builder.Append("<Country>" + SecurityElement.Escape(name) + "</Country>");
}
builder.Append("</Countries>");
}
}
var hasDisplayOrder = item as IHasDisplayOrder;
if (hasDisplayOrder != null && !string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder))
{
@ -636,22 +653,27 @@ namespace MediaBrowser.Providers.Savers
{
var video = item as Video;
if (video != null && video.Video3DFormat.HasValue)
if (video != null)
{
switch (video.Video3DFormat.Value)
AddChapters(video, builder, itemRepository);
if (video.Video3DFormat.HasValue)
{
case Video3DFormat.FullSideBySide:
builder.Append("<Format3D>FSBS</Format3D>");
break;
case Video3DFormat.FullTopAndBottom:
builder.Append("<Format3D>FTAB</Format3D>");
break;
case Video3DFormat.HalfSideBySide:
builder.Append("<Format3D>HSBS</Format3D>");
break;
case Video3DFormat.HalfTopAndBottom:
builder.Append("<Format3D>HTAB</Format3D>");
break;
switch (video.Video3DFormat.Value)
{
case Video3DFormat.FullSideBySide:
builder.Append("<Format3D>FSBS</Format3D>");
break;
case Video3DFormat.FullTopAndBottom:
builder.Append("<Format3D>FTAB</Format3D>");
break;
case Video3DFormat.HalfSideBySide:
builder.Append("<Format3D>HSBS</Format3D>");
break;
case Video3DFormat.HalfTopAndBottom:
builder.Append("<Format3D>HTAB</Format3D>");
break;
}
}
}
}

@ -1,8 +1,10 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities;
@ -23,12 +25,16 @@ namespace MediaBrowser.Providers.Subtitles
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _monitor;
private readonly ILibraryManager _libraryManager;
private readonly IItemRepository _itemRepo;
public SubtitleManager(ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor)
public SubtitleManager(ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor, ILibraryManager libraryManager, IItemRepository itemRepo)
{
_logger = logger;
_fileSystem = fileSystem;
_monitor = monitor;
_libraryManager = libraryManager;
_itemRepo = itemRepo;
}
public void AddParts(IEnumerable<ISubtitleProvider> subtitleProviders)
@ -38,15 +44,45 @@ namespace MediaBrowser.Providers.Subtitles
public async Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(SubtitleSearchRequest request, CancellationToken cancellationToken)
{
var contentType = request.ContentType;
var providers = _subtitleProviders
.Where(i => i.SupportedMediaTypes.Contains(request.ContentType))
.Where(i => i.SupportedMediaTypes.Contains(contentType))
.ToList();
// If not searching all, search one at a time until something is found
if (!request.SearchAllProviders)
{
foreach (var provider in providers)
{
try
{
var searchResults = await provider.Search(request, cancellationToken).ConfigureAwait(false);
var list = searchResults.ToList();
if (list.Count > 0)
{
Normalize(list);
return list;
}
}
catch (Exception ex)
{
_logger.ErrorException("Error downloading subtitles from {0}", ex, provider.Name);
}
}
return new List<RemoteSubtitleInfo>();
}
var tasks = providers.Select(async i =>
{
try
{
return await i.Search(request, cancellationToken).ConfigureAwait(false);
var searchResults = await i.Search(request, cancellationToken).ConfigureAwait(false);
var list = searchResults.ToList();
Normalize(list);
return list;
}
catch (Exception ex)
{
@ -62,17 +98,21 @@ namespace MediaBrowser.Providers.Subtitles
public async Task DownloadSubtitles(Video video,
string subtitleId,
string providerName,
CancellationToken cancellationToken)
{
var provider = _subtitleProviders.First(i => string.Equals(i.Name, providerName, StringComparison.OrdinalIgnoreCase));
var response = await provider.GetSubtitles(subtitleId, cancellationToken).ConfigureAwait(false);
var response = await GetRemoteSubtitles(subtitleId, cancellationToken).ConfigureAwait(false);
using (var stream = response.Stream)
{
var savePath = Path.Combine(Path.GetDirectoryName(video.Path),
Path.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower() + "." + response.Format.ToLower());
var savePath = Path.Combine(Path.GetDirectoryName(video.Path),
Path.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower());
if (response.IsForced)
{
savePath += ".forced";
}
savePath += "." + response.Format.ToLower();
_logger.Info("Saving subtitles to {0}", savePath);
@ -139,5 +179,93 @@ namespace MediaBrowser.Providers.Subtitles
return SearchSubtitles(request, cancellationToken);
}
private void Normalize(IEnumerable<RemoteSubtitleInfo> subtitles)
{
foreach (var sub in subtitles)
{
sub.Id = GetProviderId(sub.ProviderName) + "_" + sub.Id;
}
}
private string GetProviderId(string name)
{
return name.ToLower().GetMD5().ToString("N");
}
private ISubtitleProvider GetProvider(string id)
{
return _subtitleProviders.First(i => string.Equals(id, GetProviderId(i.Name)));
}
public Task DeleteSubtitles(string itemId, int index)
{
var stream = _itemRepo.GetMediaStreams(new MediaStreamQuery
{
Index = index,
ItemId = new Guid(itemId),
Type = MediaStreamType.Subtitle
}).First();
var path = stream.Path;
_monitor.ReportFileSystemChangeBeginning(path);
try
{
File.Delete(path);
}
finally
{
_monitor.ReportFileSystemChangeComplete(path, false);
}
return _libraryManager.GetItemById(itemId).RefreshMetadata(new MetadataRefreshOptions
{
ImageRefreshMode = ImageRefreshMode.ValidationOnly,
MetadataRefreshMode = MetadataRefreshMode.ValidationOnly
}, CancellationToken.None);
}
public Task<SubtitleResponse> GetRemoteSubtitles(string id, CancellationToken cancellationToken)
{
var parts = id.Split(new[] { '_' }, 2);
var provider = GetProvider(parts.First());
id = parts.Last();
return provider.GetSubtitles(id, cancellationToken);
}
public IEnumerable<SubtitleProviderInfo> GetProviders(string itemId)
{
var video = _libraryManager.GetItemById(itemId) as Video;
VideoContentType mediaType;
if (video is Episode)
{
mediaType = VideoContentType.Episode;
}
else if (video is Movie)
{
mediaType = VideoContentType.Movie;
}
else
{
// These are the only supported types
return new List<SubtitleProviderInfo>();
}
var providers = _subtitleProviders
.Where(i => i.SupportedMediaTypes.Contains(mediaType))
.ToList();
return providers.Select(i => new SubtitleProviderInfo
{
Name = i.Name,
Id = GetProviderId(i.Name)
});
}
}
}

@ -17,6 +17,7 @@ namespace MediaBrowser.Providers.TV
public class EpisodeXmlParser : BaseItemXmlParser<Episode>
{
private List<LocalImageInfo> _imagesFound;
private List<ChapterInfo> _chaptersFound;
public EpisodeXmlParser(ILogger logger)
: base(logger)
@ -25,9 +26,14 @@ namespace MediaBrowser.Providers.TV
private string _xmlPath;
public void Fetch(Episode item, List<LocalImageInfo> images, string metadataFile, CancellationToken cancellationToken)
public void Fetch(Episode item,
List<LocalImageInfo> images,
List<ChapterInfo> chapters,
string metadataFile,
CancellationToken cancellationToken)
{
_imagesFound = images;
_chaptersFound = chapters;
_xmlPath = metadataFile;
Fetch(item, metadataFile, cancellationToken);
@ -46,7 +52,7 @@ namespace MediaBrowser.Providers.TV
{
case "Chapters":
//_chaptersTask = FetchChaptersFromXmlNode(item, reader.ReadSubtree(), _itemRepo, CancellationToken.None);
_chaptersFound.AddRange(FetchChaptersFromXmlNode(item, reader.ReadSubtree()));
break;
case "Episode":

@ -1,6 +1,7 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System.Collections.Generic;
using System.IO;
@ -21,10 +22,12 @@ namespace MediaBrowser.Providers.TV
protected override void Fetch(LocalMetadataResult<Episode> result, string path, CancellationToken cancellationToken)
{
var images = new List<LocalImageInfo>();
var chapters = new List<ChapterInfo>();
new EpisodeXmlParser(_logger).Fetch(result.Item, images, path, cancellationToken);
new EpisodeXmlParser(_logger).Fetch(result.Item, images, chapters, path, cancellationToken);
result.Images = images;
result.Chapters = chapters;
}
protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)

@ -98,7 +98,7 @@ namespace MediaBrowser.Server.Implementations.Channels
{
all = all.Take(query.Limit.Value).ToList();
}
// Get everything
var fields = Enum.GetNames(typeof(ItemFields))
.Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
@ -156,6 +156,24 @@ namespace MediaBrowser.Server.Implementations.Channels
progress.Report(100);
}
public Task<IEnumerable<ChannelMediaInfo>> GetChannelItemMediaSources(string id, CancellationToken cancellationToken)
{
var item = (IChannelMediaItem)_libraryManager.GetItemById(id);
var channelGuid = new Guid(item.ChannelId);
var channel = _channelEntities.First(i => i.Id == channelGuid);
var channelPlugin = GetChannelProvider(channel);
var requiresCallback = channelPlugin as IRequiresMediaInfoCallback;
if (requiresCallback != null)
{
return requiresCallback.GetChannelItemMediaInfo(item.ExternalId, cancellationToken);
}
return Task.FromResult<IEnumerable<ChannelMediaInfo>>(item.ChannelMediaSources);
}
private async Task<Channel> GetChannel(IChannel channelInfo, CancellationToken cancellationToken)
{
var path = Path.Combine(_config.ApplicationPaths.ItemsByNamePath, "channels", _fileSystem.GetValidFilename(channelInfo.Name));
@ -246,7 +264,9 @@ namespace MediaBrowser.Server.Implementations.Channels
var channelId = channel.Id.ToString("N");
var tasks = items.Select(i => GetChannelItemEntity(i, channelId, cancellationToken));
var channelPlugin = GetChannelProvider(channel);
var tasks = items.Select(i => GetChannelItemEntity(i, channelPlugin, channelId, cancellationToken));
return await Task.WhenAll(tasks).ConfigureAwait(false);
});
@ -303,10 +323,16 @@ namespace MediaBrowser.Server.Implementations.Channels
var query = new InternalChannelItemQuery
{
User = user,
CategoryId = categoryId
User = user
};
if (!string.IsNullOrWhiteSpace(categoryId))
{
var categoryItem = (IChannelItem)_libraryManager.GetItemById(new Guid(categoryId));
query.CategoryId = categoryItem.ExternalId;
}
var result = await channel.GetChannelItems(query, cancellationToken).ConfigureAwait(false);
CacheResponse(result, cachePath);
@ -339,7 +365,9 @@ namespace MediaBrowser.Server.Implementations.Channels
var categoryKey = string.IsNullOrWhiteSpace(categoryId) ? "root" : categoryId.GetMD5().ToString("N");
return Path.Combine(_config.ApplicationPaths.CachePath, "channels", channelId, categoryKey, user.Id.ToString("N") + ".json");
var version = string.IsNullOrWhiteSpace(channel.DataVersion) ? "0" : channel.DataVersion;
return Path.Combine(_config.ApplicationPaths.CachePath, "channels", channelId, version, categoryKey, user.Id.ToString("N") + ".json");
}
private async Task<QueryResult<BaseItemDto>> GetReturnItems(IEnumerable<BaseItem> items, User user, ChannelItemQuery query, CancellationToken cancellationToken)
@ -377,21 +405,29 @@ namespace MediaBrowser.Server.Implementations.Channels
};
}
private string GetIdToHash(string externalId)
private string GetIdToHash(string externalId, IChannel channelProvider)
{
// Increment this as needed to force new downloads
return externalId + "4";
// Incorporate Name because it's being used to convert channel entity to provider
return externalId + (channelProvider.DataVersion ?? string.Empty) + (channelProvider.Name ?? string.Empty) + "11";
}
private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info, string internalChannnelId, CancellationToken cancellationToken)
private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info, IChannel channelProvider, string internalChannnelId, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(internalChannnelId))
{
throw new ArgumentNullException("internalChannnelId");
}
BaseItem item;
Guid id;
var isNew = false;
var idToHash = GetIdToHash(info.Id, channelProvider);
if (info.Type == ChannelItemType.Category)
{
id = GetIdToHash(info.Id).GetMBId(typeof(ChannelCategoryItem));
id = idToHash.GetMBId(typeof(ChannelCategoryItem));
item = _libraryManager.GetItemById(id) as ChannelCategoryItem;
@ -403,7 +439,7 @@ namespace MediaBrowser.Server.Implementations.Channels
}
else if (info.MediaType == ChannelMediaType.Audio)
{
id = GetIdToHash(info.Id).GetMBId(typeof(ChannelCategoryItem));
id = idToHash.GetMBId(typeof(ChannelCategoryItem));
item = _libraryManager.GetItemById(id) as ChannelAudioItem;
@ -415,7 +451,7 @@ namespace MediaBrowser.Server.Implementations.Channels
}
else
{
id = GetIdToHash(info.Id).GetMBId(typeof(ChannelVideoItem));
id = idToHash.GetMBId(typeof(ChannelVideoItem));
item = _libraryManager.GetItemById(id) as ChannelVideoItem;
@ -429,10 +465,6 @@ namespace MediaBrowser.Server.Implementations.Channels
item.Id = id;
item.RunTimeTicks = info.RunTimeTicks;
var mediaSource = info.MediaSources.FirstOrDefault();
item.Path = mediaSource == null ? null : mediaSource.Path;
if (isNew)
{
item.Name = info.Name;
@ -459,12 +491,22 @@ namespace MediaBrowser.Server.Implementations.Channels
channelItem.ChannelId = internalChannnelId;
channelItem.ChannelItemType = info.Type;
if (isNew)
{
channelItem.Tags = info.Tags;
}
var channelMediaItem = item as IChannelMediaItem;
if (channelMediaItem != null)
{
channelMediaItem.IsInfiniteStream = info.IsInfiniteStream;
channelMediaItem.ContentType = info.ContentType;
channelMediaItem.ChannelMediaSources = info.MediaSources;
var mediaSource = info.MediaSources.FirstOrDefault();
item.Path = mediaSource == null ? null : mediaSource.Path;
}
if (isNew)

@ -1,5 +1,6 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
@ -1140,6 +1141,13 @@ namespace MediaBrowser.Server.Implementations.Dto
{
dto.MediaSources = GetMediaSources(tvChannel);
}
var channelItem = item as IChannelItem;
if (channelItem != null)
{
dto.ChannelId = channelItem.ChannelId;
}
}
public List<MediaSourceInfo> GetMediaSources(BaseItem item)

@ -44,7 +44,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// <summary>
/// The library update duration
/// </summary>
private const int LibraryUpdateDuration = 20000;
private const int LibraryUpdateDuration = 5000;
public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IUserManager userManager, ILogger logger)
{

@ -1,6 +1,4 @@
using System.Globalization;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller;
@ -20,6 +18,7 @@ using MediaBrowser.Model.Tasks;
using MediaBrowser.Model.Updates;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -71,6 +70,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
_userManager.UserCreated += _userManager_UserCreated;
_libraryManager.ItemAdded += _libraryManager_ItemAdded;
_sessionManager.PlaybackStart += _sessionManager_PlaybackStart;
_sessionManager.PlaybackStopped += _sessionManager_PlaybackStopped;
_appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged;
_appHost.HasUpdateAvailableChanged += _appHost_HasUpdateAvailableChanged;
_appHost.ApplicationUpdated += _appHost_ApplicationUpdated;
@ -164,18 +164,42 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
await SendNotification(notification).ConfigureAwait(false);
}
async void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e)
{
var user = e.Users.FirstOrDefault();
void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e)
{
var item = e.MediaInfo;
if (item == null)
{
_logger.Warn("PlaybackStart reported with null media info.");
return;
}
var type = GetPlaybackNotificationType(item.MediaType);
SendPlaybackNotification(type, e);
}
void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e)
{
var item = e.MediaInfo;
if (item == null)
{
_logger.Warn("PlaybackStart reported with null media info.");
_logger.Warn("PlaybackStopped reported with null media info.");
return;
}
var type = GetPlaybackStoppedNotificationType(item.MediaType);
SendPlaybackNotification(type, e);
}
private async void SendPlaybackNotification(string type, PlaybackProgressEventArgs e)
{
var user = e.Users.FirstOrDefault();
var item = e.MediaInfo;
if (e.Item != null && e.Item.Parent == null)
{
// Don't report theme song or local trailer playback
@ -185,7 +209,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
var notification = new NotificationRequest
{
NotificationType = GetPlaybackNotificationType(item.MediaType),
NotificationType = type,
ExcludeUserIds = e.Users.Select(i => i.Id.ToString("N")).ToList()
};
@ -216,6 +240,24 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
return null;
}
private string GetPlaybackStoppedNotificationType(string mediaType)
{
if (string.Equals(mediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
{
return NotificationType.AudioPlaybackStopped.ToString();
}
if (string.Equals(mediaType, MediaType.Game, StringComparison.OrdinalIgnoreCase))
{
return NotificationType.GamePlaybackStopped.ToString();
}
if (string.Equals(mediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
{
return NotificationType.VideoPlaybackStopped.ToString();
}
return null;
}
private readonly List<BaseItem> _itemsAdded = new List<BaseItem>();
void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
{

@ -1,4 +1,5 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.Logging;
using System;
using System.Net.WebSockets;
@ -19,6 +20,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// </summary>
private readonly ILogger _logger;
public event EventHandler<EventArgs> Closed;
/// <summary>
/// Gets or sets the web socket.
/// </summary>
@ -97,6 +100,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
if (bytes == null)
{
// Connection closed
EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger);
break;
}

@ -84,7 +84,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
_services.AddRange(services);
SetActiveService(_services.FirstOrDefault());
SetActiveService(_config.Configuration.LiveTvOptions.ActiveService);
}
private void SetActiveService(string name)
{
var service = _services.FirstOrDefault(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)) ??
_services.FirstOrDefault();
SetActiveService(service);
}
private void SetActiveService(ILiveTvService service)

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "Playback Settings",
"LabelAudioLanguagePreference": "\u0627\u0644\u0644\u063a\u0629 \u0627\u0644\u0645\u0641\u0636\u0644\u0629 \u0644\u0644\u0635\u0648\u062a:",
"LabelSubtitleLanguagePreference": "\u0627\u0644\u0644\u063a\u0629 \u0627\u0644\u0645\u0641\u0636\u0644\u0629 \u0644\u0644\u062a\u0631\u062c\u0645\u0629:",
"LabelDisplayForcedSubtitlesOnly": "\u0639\u0631\u0636 \u0641\u0642\u0637 \u0627\u0644\u062a\u0631\u062c\u0645\u0627\u062a \u0627\u0644\u0642\u0633\u0631\u064a\u0629",
"OptionDefaultSubtitles": "Default",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
"OptionNoSubtitles": "No Subtitles",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
"TabProfiles": "\u0633\u062c\u0644 (\u0646\u0628\u0630\u0629)",
"TabSecurity": "\u062d\u0645\u0627\u064a\u0629",
"ButtonAddUser": "\u0627\u0636\u0627\u0641\u0629 \u0645\u0633\u062a\u062e\u062f\u0645",
@ -161,6 +168,10 @@
"OptionIso": "Iso",
"Option3D": "3D",
"LabelFeatures": "Features:",
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
"LabelLastResult": "Last result:",
"OptionHasSubtitles": "Subtitles",
"OptionHasTrailer": "Trailer",
"OptionHasThemeSong": "Theme Song",
@ -224,6 +235,8 @@
"ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "Please support other free products we utilize:",
"VersionNumber": "Version {0}",
"TabPaths": "Paths",
@ -270,8 +283,8 @@
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
"OptionImageSavingCompatible": "Compatible - MB3\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB3\/MB2",
"OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
"HeaderPleaseSignIn": "Please sign in",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
"TabGuide": "Guide",
"TabChannels": "Channels",
"TabCollections": "Collections",
"HeaderChannels": "Channels",
"TabRecordings": "Recordings",
"TabScheduled": "Scheduled",
"TabSeries": "Series",
"TabFavorites": "Favorites",
"TabMyLibrary": "My Library",
"ButtonCancelRecording": "Cancel Recording",
"HeaderPrePostPadding": "Pre\/Post Padding",
"LabelPrePaddingMinutes": "Pre-padding minutes:",
@ -319,7 +335,7 @@
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
"LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
"HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
"OptionDownloadThumbImage": "Thumb",
"OptionDownloadMenuImage": "Menu",
"OptionDownloadLogoImage": "Logo",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "Primary",
"HeaderFetchImages": "Fetch Images:",
"HeaderImageSettings": "Image Settings",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
"LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
"LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
@ -463,9 +480,9 @@
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
"LabelSeries": "Series:",
"LabelSeasonNumber": "Season number:",
"LabelEpisodeNumber": "Episode number:",
"LabelEndingEpisodeNumber": "Ending episode number:",
"LabelSeasonNumber": "Season number",
"LabelEpisodeNumber": "Episode number",
"LabelEndingEpisodeNumber": "Ending episode number",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@ -529,8 +546,8 @@
"ButtonRetrieveKey": "Retrieve Key",
"LabelSupporterKey": "Supporter Key (paste from email)",
"LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
"MessageInvalidKey": "MB3 Key Missing or Invalid",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be an MB3 Supporter. Please donate and support the continued development of the core product. Thank you.",
"MessageInvalidKey": "Supporter key is missing or invalid.",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
"HeaderDisplaySettings": "Display Settings",
"TabPlayTo": "Play To",
"LabelEnableDlnaServer": "Enable Dlna server",
@ -558,9 +575,12 @@
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
"NotificationOptionPluginInstalled": "Plugin installed",
"NotificationOptionPluginUninstalled": "Plugin uninstalled",
"NotificationOptionVideoPlayback": "Video playback",
"NotificationOptionAudioPlayback": "Audio playback",
"NotificationOptionGamePlayback": "Game playback",
"NotificationOptionVideoPlayback": "Video playback started",
"NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionGamePlayback": "Game playback started",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "Scheduled task failure",
"NotificationOptionInstallationFailed": "Installation failure",
"NotificationOptionNewLibraryContent": "New content added",
@ -588,6 +608,7 @@
"ButtonArrowRight": "Right",
"ButtonBack": "Back",
"ButtonInfo": "Info",
"ButtonOsd": "On screen display",
"ButtonPageUp": "Page Up",
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "Volume down",
"ButtonMute": "Mute",
"HeaderLatestMedia": "Latest Media",
"OptionNoSubtitles": "No Subtitles",
"OptionSpecialFeatures": "Special Features",
"HeaderCollections": "Collections",
"HeaderMyLibrary": "My Library",
@ -704,12 +724,26 @@
"TabSubtitles": "Subtitles",
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Download languages:",
"ButtonRegister": "Register",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
"HeaderSendMessage": "Send Message",
"ButtonSend": "Send",
"LabelMessageText": "Message text:"
"LabelMessageText": "Message text:",
"MessageNoAvailablePlugins": "No available plugins.",
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Others",
"LabelEpisodeName": "Episode name",
"LabelSeriesName": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "Playback Settings",
"LabelAudioLanguagePreference": "Audio language preference:",
"LabelSubtitleLanguagePreference": "Subtitle language preference:",
"LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
"OptionDefaultSubtitles": "Default",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
"OptionNoSubtitles": "No Subtitles",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
"TabProfiles": "Profiles",
"TabSecurity": "Security",
"ButtonAddUser": "Add User",
@ -161,6 +168,10 @@
"OptionIso": "Iso",
"Option3D": "3D",
"LabelFeatures": "Features:",
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
"LabelLastResult": "Last result:",
"OptionHasSubtitles": "Subtitles",
"OptionHasTrailer": "Trailer",
"OptionHasThemeSong": "Theme Song",
@ -224,6 +235,8 @@
"ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "Please support other free products we utilize:",
"VersionNumber": "Version {0}",
"TabPaths": "Paths",
@ -270,8 +283,8 @@
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
"OptionImageSavingCompatible": "Compatible - MB3\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB3\/MB2",
"OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
"HeaderPleaseSignIn": "Please sign in",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
"TabGuide": "Guide",
"TabChannels": "Channels",
"TabCollections": "Collections",
"HeaderChannels": "Channels",
"TabRecordings": "Recordings",
"TabScheduled": "Scheduled",
"TabSeries": "Series",
"TabFavorites": "Favorites",
"TabMyLibrary": "My Library",
"ButtonCancelRecording": "Cancel Recording",
"HeaderPrePostPadding": "Pre\/Post Padding",
"LabelPrePaddingMinutes": "Pre-padding minutes:",
@ -319,7 +335,7 @@
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
"LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
"HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
"OptionDownloadThumbImage": "Thumb",
"OptionDownloadMenuImage": "Menu",
"OptionDownloadLogoImage": "Logo",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "Primary",
"HeaderFetchImages": "Fetch Images:",
"HeaderImageSettings": "Image Settings",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
"LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
"LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
@ -463,9 +480,9 @@
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
"LabelSeries": "Series:",
"LabelSeasonNumber": "Season number:",
"LabelEpisodeNumber": "Episode number:",
"LabelEndingEpisodeNumber": "Ending episode number:",
"LabelSeasonNumber": "Season number",
"LabelEpisodeNumber": "Episode number",
"LabelEndingEpisodeNumber": "Ending episode number",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@ -529,8 +546,8 @@
"ButtonRetrieveKey": "Retrieve Key",
"LabelSupporterKey": "Supporter Key (paste from email)",
"LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
"MessageInvalidKey": "MB3 Key Missing or Invalid",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be an MB3 Supporter. Please donate and support the continued development of the core product. Thank you.",
"MessageInvalidKey": "Supporter key is missing or invalid.",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
"HeaderDisplaySettings": "Display Settings",
"TabPlayTo": "Play To",
"LabelEnableDlnaServer": "Enable Dlna server",
@ -558,9 +575,12 @@
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
"NotificationOptionPluginInstalled": "Plugin installed",
"NotificationOptionPluginUninstalled": "Plugin uninstalled",
"NotificationOptionVideoPlayback": "Video playback",
"NotificationOptionAudioPlayback": "Audio playback",
"NotificationOptionGamePlayback": "Game playback",
"NotificationOptionVideoPlayback": "Video playback started",
"NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionGamePlayback": "Game playback started",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "Scheduled task failure",
"NotificationOptionInstallationFailed": "Installation failure",
"NotificationOptionNewLibraryContent": "New content added",
@ -588,6 +608,7 @@
"ButtonArrowRight": "Right",
"ButtonBack": "Back",
"ButtonInfo": "Info",
"ButtonOsd": "On screen display",
"ButtonPageUp": "Page Up",
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "Volume down",
"ButtonMute": "Mute",
"HeaderLatestMedia": "Latest Media",
"OptionNoSubtitles": "No Subtitles",
"OptionSpecialFeatures": "Special Features",
"HeaderCollections": "Collections",
"HeaderMyLibrary": "My Library",
@ -704,12 +724,26 @@
"TabSubtitles": "Subtitles",
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Download languages:",
"ButtonRegister": "Register",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
"HeaderSendMessage": "Send Message",
"ButtonSend": "Send",
"LabelMessageText": "Message text:"
"LabelMessageText": "Message text:",
"MessageNoAvailablePlugins": "No available plugins.",
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Others",
"LabelEpisodeName": "Episode name",
"LabelSeriesName": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "Playback Settings",
"LabelAudioLanguagePreference": "Up\u0159ednost\u0148ovan\u00fd jazyk videa:",
"LabelSubtitleLanguagePreference": "Up\u0159ednost\u0148ovan\u00fd jazyk titulk\u016f:",
"LabelDisplayForcedSubtitlesOnly": "Zobrazit pouze vynucen\u00e9 titulky",
"OptionDefaultSubtitles": "Default",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
"OptionNoSubtitles": "No Subtitles",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
"TabProfiles": "Profily",
"TabSecurity": "Zabezpe\u010den\u00ed",
"ButtonAddUser": "P\u0159idat u\u017eivatele",
@ -161,6 +168,10 @@
"OptionIso": "Iso",
"Option3D": "3D",
"LabelFeatures": "Vlastnosti:",
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
"LabelLastResult": "Last result:",
"OptionHasSubtitles": "Titulky",
"OptionHasTrailer": "Uk\u00e1zka\/trailer",
"OptionHasThemeSong": "Tematick\u00e1 hudba",
@ -224,6 +235,8 @@
"ButtonSearch": "Hled\u00e1n\u00ed",
"ButtonGroupVersions": "Skupinov\u00e9 verze",
"PismoMessage": "Vyu\u017e\u00edv\u00e1me spr\u00e1vce soubor\u016f \"Pismo\" skrze dotovanou licenci.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "Pros\u00edm podpo\u0159te dal\u0161\u00ed bezplatn\u00e9 produkty, kter\u00e9 vyu\u017e\u00edv\u00e1me:",
"VersionNumber": "Verze {0}",
"TabPaths": "Cesty",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "Heslo nen\u00ed nutn\u00e9, pokud se p\u0159ihla\u0161ujete z m\u00edstn\u00edho PC-",
"TabGuide": "Pr\u016fvodce",
"TabChannels": "Kan\u00e1ly",
"TabCollections": "Collections",
"HeaderChannels": "Kan\u00e1ly",
"TabRecordings": "Nahran\u00e9",
"TabScheduled": "Napl\u00e1nov\u00e1no",
"TabSeries": "S\u00e9rie",
"TabFavorites": "Favorites",
"TabMyLibrary": "My Library",
"ButtonCancelRecording": "Zru\u0161it nahr\u00e1v\u00e1n\u00ed",
"HeaderPrePostPadding": "P\u0159ed\/po nahr\u00e1v\u00e1n\u00ed",
"LabelPrePaddingMinutes": "Minuty nahr\u00e1van\u00e9 p\u0159ed za\u010d\u00e1tkem nahr\u00e1v\u00e1n\u00ed",
@ -319,7 +335,7 @@
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "P\u0159ed pokra\u010dov\u00e1n\u00edm je vy\u017eadov\u00e1n plugin TV poskytovatele.",
"LiveTvPluginRequiredHelp": "Pros\u00edm nainstalujte jeden z dostupn\u00fdch plugin\u016f, jako Next PVR nebo ServerWmc",
"HeaderCustomizeOptionsPerMediaType": "Upravit nastaven\u00ed podle typu m\u00e9dia",
"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
"OptionDownloadThumbImage": "Miniatura",
"OptionDownloadMenuImage": "Nab\u00eddka",
"OptionDownloadLogoImage": "Logo",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "Prim\u00e1rn\u00ed",
"HeaderFetchImages": "Na\u010d\u00edst obr\u00e1zky:",
"HeaderImageSettings": "Nastaven\u00ed obr\u00e1zk\u016f",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "Maxim\u00e1ln\u00ed po\u010det obr\u00e1zk\u016f na pozad\u00ed pro polo\u017eku:",
"LabelMaxScreenshotsPerItem": "Maxim\u00e1ln\u00ed po\u010det screenshot\u016f:",
"LabelMinBackdropDownloadWidth": "Maxim\u00e1ln\u00ed \u0161\u00ed\u0159ka pozad\u00ed:",
@ -463,9 +480,9 @@
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
"LabelSeries": "Series:",
"LabelSeasonNumber": "Season number:",
"LabelEpisodeNumber": "Episode number:",
"LabelEndingEpisodeNumber": "Ending episode number:",
"LabelSeasonNumber": "Season number",
"LabelEpisodeNumber": "Episode number",
"LabelEndingEpisodeNumber": "Ending episode number",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@ -529,8 +546,8 @@
"ButtonRetrieveKey": "Retrieve Key",
"LabelSupporterKey": "Supporter Key (paste from email)",
"LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
"MessageInvalidKey": "MB3 Key Missing or Invalid",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be an MB3 Supporter. Please donate and support the continued development of the core product. Thank you.",
"MessageInvalidKey": "Supporter key is missing or invalid.",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
"HeaderDisplaySettings": "Display Settings",
"TabPlayTo": "Play To",
"LabelEnableDlnaServer": "Enable Dlna server",
@ -558,9 +575,12 @@
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
"NotificationOptionPluginInstalled": "Plugin installed",
"NotificationOptionPluginUninstalled": "Plugin uninstalled",
"NotificationOptionVideoPlayback": "Video playback",
"NotificationOptionAudioPlayback": "Audio playback",
"NotificationOptionGamePlayback": "Game playback",
"NotificationOptionVideoPlayback": "Video playback started",
"NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionGamePlayback": "Game playback started",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "Scheduled task failure",
"NotificationOptionInstallationFailed": "Installation failure",
"NotificationOptionNewLibraryContent": "New content added",
@ -588,6 +608,7 @@
"ButtonArrowRight": "Right",
"ButtonBack": "Back",
"ButtonInfo": "Info",
"ButtonOsd": "On screen display",
"ButtonPageUp": "Page Up",
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "Volume down",
"ButtonMute": "Mute",
"HeaderLatestMedia": "Latest Media",
"OptionNoSubtitles": "No Subtitles",
"OptionSpecialFeatures": "Special Features",
"HeaderCollections": "Collections",
"HeaderMyLibrary": "My Library",
@ -704,12 +724,26 @@
"TabSubtitles": "Subtitles",
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Download languages:",
"ButtonRegister": "Register",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
"HeaderSendMessage": "Send Message",
"ButtonSend": "Send",
"LabelMessageText": "Message text:"
"LabelMessageText": "Message text:",
"MessageNoAvailablePlugins": "No available plugins.",
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Others",
"LabelEpisodeName": "Episode name",
"LabelSeriesName": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "Playback Settings",
"LabelAudioLanguagePreference": "Audio language preference:",
"LabelSubtitleLanguagePreference": "Subtitle language preference:",
"LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
"OptionDefaultSubtitles": "Default",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
"OptionNoSubtitles": "Ingen undertekster",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
"TabProfiles": "Profiles",
"TabSecurity": "Security",
"ButtonAddUser": "Add User",
@ -161,6 +168,10 @@
"OptionIso": "Iso",
"Option3D": "3D",
"LabelFeatures": "Features:",
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
"LabelLastResult": "Last result:",
"OptionHasSubtitles": "Subtitles",
"OptionHasTrailer": "Trailer",
"OptionHasThemeSong": "Theme Song",
@ -224,6 +235,8 @@
"ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "Please support other free products we utilize:",
"VersionNumber": "Version {0}",
"TabPaths": "Paths",
@ -270,8 +283,8 @@
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
"OptionImageSavingCompatible": "Compatible - MB3\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB3\/MB2",
"OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
"HeaderPleaseSignIn": "Please sign in",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
"TabGuide": "Guide",
"TabChannels": "Channels",
"TabCollections": "Collections",
"HeaderChannels": "Channels",
"TabRecordings": "Recordings",
"TabScheduled": "Scheduled",
"TabSeries": "Series",
"TabFavorites": "Favorites",
"TabMyLibrary": "My Library",
"ButtonCancelRecording": "Cancel Recording",
"HeaderPrePostPadding": "Pre\/Post Padding",
"LabelPrePaddingMinutes": "Pre-padding minutes:",
@ -319,7 +335,7 @@
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
"LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
"HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
"OptionDownloadThumbImage": "Thumb",
"OptionDownloadMenuImage": "Menu",
"OptionDownloadLogoImage": "Logo",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "Primary",
"HeaderFetchImages": "Fetch Images:",
"HeaderImageSettings": "Image Settings",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
"LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
"LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
@ -463,9 +480,9 @@
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
"LabelSeries": "Series:",
"LabelSeasonNumber": "Season number:",
"LabelEpisodeNumber": "Episode number:",
"LabelEndingEpisodeNumber": "Ending episode number:",
"LabelSeasonNumber": "Season number",
"LabelEpisodeNumber": "Episode number",
"LabelEndingEpisodeNumber": "Ending episode number",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@ -529,8 +546,8 @@
"ButtonRetrieveKey": "Retrieve Key",
"LabelSupporterKey": "Supporter Key (paste from email)",
"LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
"MessageInvalidKey": "MB3 Key Missing or Invalid",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be an MB3 Supporter. Please donate and support the continued development of the core product. Thank you.",
"MessageInvalidKey": "Supporter key is missing or invalid.",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
"HeaderDisplaySettings": "Display Settings",
"TabPlayTo": "Play To",
"LabelEnableDlnaServer": "Enable Dlna server",
@ -558,9 +575,12 @@
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
"NotificationOptionPluginInstalled": "Plugin installed",
"NotificationOptionPluginUninstalled": "Plugin uninstalled",
"NotificationOptionVideoPlayback": "Video playback",
"NotificationOptionAudioPlayback": "Audio playback",
"NotificationOptionGamePlayback": "Game playback",
"NotificationOptionVideoPlayback": "Video playback started",
"NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionGamePlayback": "Game playback started",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "Scheduled task failure",
"NotificationOptionInstallationFailed": "Installation failure",
"NotificationOptionNewLibraryContent": "New content added",
@ -588,6 +608,7 @@
"ButtonArrowRight": "H\u00f8jre",
"ButtonBack": "Tilbage",
"ButtonInfo": "Info",
"ButtonOsd": "On screen display",
"ButtonPageUp": "Side op",
"ButtonPageDown": "Side ned",
"PageAbbreviation": "PG",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "Volume down",
"ButtonMute": "Mute",
"HeaderLatestMedia": "Latest Media",
"OptionNoSubtitles": "Ingen undertekster",
"OptionSpecialFeatures": "Special Features",
"HeaderCollections": "Collections",
"HeaderMyLibrary": "Mit bibliotek",
@ -704,12 +724,26 @@
"TabSubtitles": "Undertekster",
"LabelOpenSubtitlesUsername": "Open Subtitles brugernavn:",
"LabelOpenSubtitlesPassword": "Open Subtitles kode:",
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Download languages:",
"ButtonRegister": "Register",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck dette for at sikre at alle videoer har undertekster, uanset hvilket sprog lydsporet anvender.",
"HeaderSendMessage": "Send besked",
"ButtonSend": "Send",
"LabelMessageText": "Tekst besked"
"LabelMessageText": "Tekst besked",
"MessageNoAvailablePlugins": "No available plugins.",
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Others",
"LabelEpisodeName": "Episode name",
"LabelSeriesName": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "Wiedergabe Einstellungen",
"LabelAudioLanguagePreference": "Audiosprache Einstellungen:",
"LabelSubtitleLanguagePreference": "Untertitelsprache Einstellungen:",
"LabelDisplayForcedSubtitlesOnly": "Zeige nur erzwungene Untertitel",
"OptionDefaultSubtitles": "Default",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
"OptionNoSubtitles": "Keine Untertitel",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
"TabProfiles": "Profile",
"TabSecurity": "Sicherheit",
"ButtonAddUser": "User hinzuf\u00fcgen",
@ -76,7 +83,7 @@
"LabelMaxParentalRating": "H\u00f6chste erlaubte elterlich Bewertung:",
"MaxParentalRatingHelp": "Inhalt mit einer h\u00f6heren Bewertung wird dem User nicht angezeigt.",
"LibraryAccessHelp": "W\u00e4hlen Sie die Medienordner die Sie mit diesem Benutzer teilen m\u00f6chten. Administratoren k\u00f6nnen den Metadata-Manager verwenden um alle Ordner zu bearbeiten.",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
"ChannelAccessHelp": "W\u00e4hlen Sie die Kan\u00e4le, die mit diesem Benutzer geteilt werden sollen. Administratoren sind in der Lage alle K\u00e4nale \u00fcber den Metadata Manager zu bearbeiten.",
"ButtonDeleteImage": "L\u00f6sche Bild",
"LabelSelectUsers": "W\u00e4hle Benutzer:",
"ButtonUpload": "Hochladen",
@ -161,6 +168,10 @@
"OptionIso": "ISO",
"Option3D": "3D",
"LabelFeatures": "Merkmal:",
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
"LabelLastResult": "Last result:",
"OptionHasSubtitles": "Untertitel",
"OptionHasTrailer": "Trailer",
"OptionHasThemeSong": "Titellied",
@ -224,6 +235,8 @@
"ButtonSearch": "Suche",
"ButtonGroupVersions": "Gruppiere Versionen",
"PismoMessage": "Verwendet Pismo File Mount durch eine gespendete Lizenz.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "Bitte unterst\u00fctzen Sie andere freie Produkte die wir benutzen:",
"VersionNumber": "Version {0}",
"TabPaths": "Pfade",
@ -270,8 +283,8 @@
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Speicherconvention der Bilddatein:",
"LabelImageSavingConventionHelp": "Media Browser erkennt Bilddateien von den meisten gro\u00dfen Medienanwendungen. Die Auswahl ihrer Downloadconvention ist n\u00fctzlich, wenn Sie auch andere Produkte benutzen.",
"OptionImageSavingCompatible": "Kompatibel - MB3\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB3\/MB2",
"OptionImageSavingCompatible": "Kompatibel - Media Browser\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Einloggen",
"TitleSignIn": "Einloggen",
"HeaderPleaseSignIn": "Bitte einloggen",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "Passw\u00f6rter werden nich gebraucht, wenn Sie sich vom Localhost aus einloggen.",
"TabGuide": "Programm",
"TabChannels": "Kan\u00e4le",
"TabCollections": "Collections",
"HeaderChannels": "Kan\u00e4le",
"TabRecordings": "Aufnahmen",
"TabScheduled": "Geplant",
"TabSeries": "Serie",
"TabFavorites": "Favorites",
"TabMyLibrary": "My Library",
"ButtonCancelRecording": "Aufnahme abbrechen",
"HeaderPrePostPadding": "Pufferzeit vor\/nach der Aufnahme",
"LabelPrePaddingMinutes": "Minuten vor der Aufnahme",
@ -319,7 +335,7 @@
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "Ein Live TV Serviceproviderplugin ist notwendig um fortzufahren.",
"LiveTvPluginRequiredHelp": "Bitte installieren Sie eines der verf\u00fcgbaren Plugins, wie z.B. Next Pvr oder ServerWmc.",
"HeaderCustomizeOptionsPerMediaType": "Passe die Optionen per Medientyp an",
"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
"OptionDownloadThumbImage": "Thumb",
"OptionDownloadMenuImage": "Men\u00fc",
"OptionDownloadLogoImage": "Logo",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "Prim\u00e4r",
"HeaderFetchImages": "Bilder abrufen:",
"HeaderImageSettings": "Bild Einstellungen",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "Maximale Anzahl von Backdrops pro Element:",
"LabelMaxScreenshotsPerItem": "Maximale Anzahl von Screenshots pro Element:",
"LabelMinBackdropDownloadWidth": "Minimale Breite f\u00fcr zu herunterladende Backdrops:",
@ -463,9 +480,9 @@
"LabelSkipped": "\u00dcbersprungen",
"HeaderEpisodeOrganization": "Episode Organization",
"LabelSeries": "Serien:",
"LabelSeasonNumber": "Staffelnummer:",
"LabelEpisodeNumber": "Episodennummer:",
"LabelEndingEpisodeNumber": "Ending episode number:",
"LabelSeasonNumber": "Staffelnummer",
"LabelEpisodeNumber": "Episodennummer",
"LabelEndingEpisodeNumber": "Ending episode number",
"LabelEndingEpisodeNumberHelp": "Nur erforderlich f\u00fcr Mehrfachepisoden",
"HeaderSupportTheTeam": "Unterst\u00fcze das Media Browser Team",
"LabelSupportAmount": "Betrag (USD)",
@ -529,8 +546,8 @@
"ButtonRetrieveKey": "Schl\u00fcssel wiederherstellen",
"LabelSupporterKey": "Unterst\u00fctzerschl\u00fcssel (einf\u00fcgen aus E-Mail)",
"LabelSupporterKeyHelp": "Geben Sie ihren Unterst\u00fctzerschl\u00fcssel ein, um zus\u00e4tzliche Vorteile zugenie\u00dfen, die die Community f\u00fcr Media Browser entwickelt hat.",
"MessageInvalidKey": "MB3 Schl\u00fcssel nicht vorhanden oder ung\u00fcltig",
"ErrorMessageInvalidKey": "Um einen Premiuminhalt zu registrieren, m\u00fcssen sie ein MB3 Unters\u00fctzer sein. Bitte spenden sie und unterst\u00fctzen so die Weiterentwicklung des Kernprodukts. Danke.",
"MessageInvalidKey": "MB3 Schl\u00fcssel nicht vorhanden oder ung\u00fcltig.",
"ErrorMessageInvalidKey": "Um einen Premiuminhalt zu registrieren, m\u00fcssen sie auch ein MB3 Unters\u00fctzer sein. Bitte spenden sie und unterst\u00fctzen so die Weiterentwicklung des Kernprodukts. Danke.",
"HeaderDisplaySettings": "Anzeige Einstellungen",
"TabPlayTo": "Spiele an",
"LabelEnableDlnaServer": "Aktiviere DLNA Server",
@ -560,9 +577,12 @@
"NotificationOptionPluginUninstalled": "Plugin deinstalliert",
"NotificationOptionVideoPlayback": "Videowiedergabe",
"NotificationOptionAudioPlayback": "Audiowiedergabe",
"NotificationOptionGamePlayback": "Game playback",
"NotificationOptionGamePlayback": "Game playback started",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "Scheduled task failure",
"NotificationOptionInstallationFailed": "Installation failure",
"NotificationOptionInstallationFailed": "Installationsfehler",
"NotificationOptionNewLibraryContent": "Neuer Inhalt hinzugef\u00fcgt",
"NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
"SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.",
@ -576,26 +596,27 @@
"CategorySystem": "System",
"CategoryApplication": "Anwendung",
"CategoryPlugin": "Plugin",
"LabelMessageTitle": "Message title:",
"LabelAvailableTokens": "Available tokens:",
"AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.",
"LabelMessageTitle": "Benachrichtigungstitel:",
"LabelAvailableTokens": "Verf\u00fcgbare Tokens:",
"AdditionalNotificationServices": "Durchsuchen Sie den Plugin Katalog, um weitere Benachrichtigungsservices zu installieren.",
"OptionAllUsers": "Alle Benutzer",
"OptionAdminUsers": "Administratoren",
"OptionCustomUsers": "Custom",
"OptionCustomUsers": "Benutzer",
"ButtonArrowUp": "Auf",
"ButtonArrowDown": "Ab",
"ButtonArrowLeft": "Links",
"ButtonArrowRight": "Rechts",
"ButtonBack": "Zur\u00fcck",
"ButtonInfo": "Info",
"ButtonOsd": "On screen display",
"ButtonPageUp": "Bild auf",
"ButtonPageDown": "Bild ab",
"PageAbbreviation": "PG",
"ButtonHome": "Home",
"ButtonSettings": "Einstellungen",
"ButtonTakeScreenshot": "Bildschirmfoto aufnehmen",
"ButtonLetterUp": "Letter Up",
"ButtonLetterDown": "Letter Down",
"ButtonLetterUp": "Buchstabe hoch",
"ButtonLetterDown": "Buchstabe runter",
"PageButtonAbbreviation": "PG",
"LetterButtonAbbreviation": "A",
"TabNowPlaying": "Aktuelle Wiedergabe",
@ -610,30 +631,29 @@
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Gruppiere Filme in Collections",
"LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.",
"LabelGroupMoviesIntoCollectionsHelp": "Wenn Filmlisten angezeigt werden, dann werden Filme, die zu einer Collection geh\u00f6ren, als ein gruppiertes Element angezeigt.",
"NotificationOptionPluginError": "Plugin Fehler",
"ButtonVolumeUp": "Lauter",
"ButtonVolumeDown": "Leiser",
"ButtonMute": "Stumm",
"HeaderLatestMedia": "Latest Media",
"OptionNoSubtitles": "No Subtitles",
"HeaderLatestMedia": "Letzte Medien",
"OptionSpecialFeatures": "Special Features",
"HeaderCollections": "Collections",
"HeaderMyLibrary": "My Library",
"LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
"LabelType": "Type:",
"HeaderMyLibrary": "Meine Bibliothek",
"LabelProfileCodecsHelp": "Getrennt durch Komma. Leerlassen, um auf alle Codecs anzuwenden.",
"LabelProfileContainersHelp": "Getrennt durch Komma. Leerlassen, um auf alle Container anzuwenden.",
"HeaderResponseProfile": "Antwort Profil",
"LabelType": "Typ:",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
"LabelProfileVideoCodecs": "Video Codecs:",
"LabelProfileAudioCodecs": "Audio Codecs:",
"LabelProfileCodecs": "Codecs:",
"HeaderDirectPlayProfile": "Direct Play Profile",
"HeaderTranscodingProfile": "Transcoding Profile",
"HeaderCodecProfile": "Codec Profile",
"HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.",
"HeaderContainerProfile": "Container Profile",
"HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.",
"HeaderDirectPlayProfile": "Direktwiedergabe Profil",
"HeaderTranscodingProfile": "Transcoding Profil",
"HeaderCodecProfile": "Codec Profil",
"HeaderCodecProfileHelp": "Codec Profile weisen auf Beschr\u00e4nkungen eines Ger\u00e4tes beim Abspielen bestimmter Codecs hin. Wenn eine Beschr\u00e4nkung zutrifft, dann werden Medien transcodiert, auch wenn der Codec f\u00fcr die Direktwiedergabe konfiguriert ist.",
"HeaderContainerProfile": "Container Profil",
"HeaderContainerProfileHelp": "Container Profile weisen auf Beschr\u00e4nkungen einen Ger\u00e4tes beim Abspielen bestimmter Formate hin. Wenn eine Beschr\u00e4nkung zutrifft, dann werden Medien transcodiert, auch wenn das Format f\u00fcr die Direktwiedergabe konfiguriert ist.",
"OptionProfileVideo": "Video",
"OptionProfileAudio": "Audio",
"OptionProfileVideoAudio": "Video Audio",
@ -646,11 +666,11 @@
"OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".",
"LabelSupportedMediaTypes": "Supported Media Types:",
"TabIdentification": "Identification",
"TabDirectPlay": "Direct Play",
"TabContainers": "Containers",
"TabDirectPlay": "Direktwiedergabe",
"TabContainers": "Container",
"TabCodecs": "Codecs",
"TabResponses": "Responses",
"HeaderProfileInformation": "Profile Information",
"HeaderProfileInformation": "Profil Infomationen",
"LabelEmbedAlbumArtDidl": "Embed album art in Didl",
"LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.",
"LabelAlbumArtPN": "Album art PN:",
@ -672,8 +692,8 @@
"LabelFriendlyName": "Friendly name",
"LabelManufacturer": "Manufacturer",
"LabelManufacturerUrl": "Manufacturer url",
"LabelModelName": "Model name",
"LabelModelNumber": "Model number",
"LabelModelName": "Modellname",
"LabelModelNumber": "Modellnummer",
"LabelModelDescription": "Model description",
"LabelModelUrl": "Model url",
"LabelSerialNumber": "Serial number",
@ -704,12 +724,26 @@
"TabSubtitles": "Subtitles",
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Download languages:",
"ButtonRegister": "Register",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
"HeaderSendMessage": "Send Message",
"ButtonSend": "Send",
"LabelMessageText": "Message text:"
"LabelMessageText": "Message text:",
"MessageNoAvailablePlugins": "No available plugins.",
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Others",
"LabelEpisodeName": "Episode name",
"LabelSeriesName": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "Playback Settings",
"LabelAudioLanguagePreference": "Audio language preference:",
"LabelSubtitleLanguagePreference": "Subtitle language preference:",
"LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
"OptionDefaultSubtitles": "Default",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
"OptionNoSubtitles": "No Subtitles",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
"TabProfiles": "\u03c4\u03b1 \u03c0\u03c1\u03bf\u03c6\u03af\u03bb",
"TabSecurity": "A\u03c3\u03c6\u03ac\u03bb\u03b5\u03b9\u03b1 ",
"ButtonAddUser": "\u03a0\u03c1\u03bf\u03c3\u03b8\u03ae\u03ba\u03b7 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7",
@ -161,6 +168,10 @@
"OptionIso": "Iso",
"Option3D": "3D",
"LabelFeatures": "Features:",
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
"LabelLastResult": "Last result:",
"OptionHasSubtitles": "Subtitles",
"OptionHasTrailer": "Trailer",
"OptionHasThemeSong": "Theme Song",
@ -224,6 +235,8 @@
"ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "Please support other free products we utilize:",
"VersionNumber": "Version {0}",
"TabPaths": "Paths",
@ -270,8 +283,8 @@
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
"OptionImageSavingCompatible": "Compatible - MB3\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB3\/MB2",
"OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
"HeaderPleaseSignIn": "Please sign in",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
"TabGuide": "Guide",
"TabChannels": "Channels",
"TabCollections": "Collections",
"HeaderChannels": "Channels",
"TabRecordings": "Recordings",
"TabScheduled": "Scheduled",
"TabSeries": "Series",
"TabFavorites": "Favorites",
"TabMyLibrary": "My Library",
"ButtonCancelRecording": "Cancel Recording",
"HeaderPrePostPadding": "Pre\/Post Padding",
"LabelPrePaddingMinutes": "Pre-padding minutes:",
@ -319,7 +335,7 @@
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
"LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
"HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
"OptionDownloadThumbImage": "Thumb",
"OptionDownloadMenuImage": "Menu",
"OptionDownloadLogoImage": "Logo",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "Primary",
"HeaderFetchImages": "Fetch Images:",
"HeaderImageSettings": "Image Settings",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
"LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
"LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
@ -463,9 +480,9 @@
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
"LabelSeries": "Series:",
"LabelSeasonNumber": "Season number:",
"LabelEpisodeNumber": "Episode number:",
"LabelEndingEpisodeNumber": "Ending episode number:",
"LabelSeasonNumber": "Season number",
"LabelEpisodeNumber": "Episode number",
"LabelEndingEpisodeNumber": "Ending episode number",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@ -529,8 +546,8 @@
"ButtonRetrieveKey": "Retrieve Key",
"LabelSupporterKey": "Supporter Key (paste from email)",
"LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
"MessageInvalidKey": "MB3 Key Missing or Invalid",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be an MB3 Supporter. Please donate and support the continued development of the core product. Thank you.",
"MessageInvalidKey": "Supporter key is missing or invalid.",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
"HeaderDisplaySettings": "Display Settings",
"TabPlayTo": "Play To",
"LabelEnableDlnaServer": "Enable Dlna server",
@ -558,9 +575,12 @@
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
"NotificationOptionPluginInstalled": "Plugin installed",
"NotificationOptionPluginUninstalled": "Plugin uninstalled",
"NotificationOptionVideoPlayback": "Video playback",
"NotificationOptionAudioPlayback": "Audio playback",
"NotificationOptionGamePlayback": "Game playback",
"NotificationOptionVideoPlayback": "Video playback started",
"NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionGamePlayback": "Game playback started",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "Scheduled task failure",
"NotificationOptionInstallationFailed": "Installation failure",
"NotificationOptionNewLibraryContent": "New content added",
@ -588,6 +608,7 @@
"ButtonArrowRight": "Right",
"ButtonBack": "Back",
"ButtonInfo": "Info",
"ButtonOsd": "On screen display",
"ButtonPageUp": "Page Up",
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "Volume down",
"ButtonMute": "Mute",
"HeaderLatestMedia": "Latest Media",
"OptionNoSubtitles": "No Subtitles",
"OptionSpecialFeatures": "Special Features",
"HeaderCollections": "Collections",
"HeaderMyLibrary": "My Library",
@ -704,12 +724,26 @@
"TabSubtitles": "Subtitles",
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Download languages:",
"ButtonRegister": "Register",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
"HeaderSendMessage": "Send Message",
"ButtonSend": "Send",
"LabelMessageText": "Message text:"
"LabelMessageText": "Message text:",
"MessageNoAvailablePlugins": "No available plugins.",
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Others",
"LabelEpisodeName": "Episode name",
"LabelSeriesName": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "Playback Settings",
"LabelAudioLanguagePreference": "Audio language preference:",
"LabelSubtitleLanguagePreference": "Subtitle language preference:",
"LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
"OptionDefaultSubtitles": "Default",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
"OptionNoSubtitles": "No Subtitles",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
"TabProfiles": "Profiles",
"TabSecurity": "Security",
"ButtonAddUser": "Add User",
@ -161,6 +168,10 @@
"OptionIso": "Iso",
"Option3D": "3D",
"LabelFeatures": "Features:",
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
"LabelLastResult": "Last result:",
"OptionHasSubtitles": "Subtitles",
"OptionHasTrailer": "Trailer",
"OptionHasThemeSong": "Theme Song",
@ -224,6 +235,8 @@
"ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "Please support other free products we utilise:",
"VersionNumber": "Version {0}",
"TabPaths": "Paths",
@ -270,8 +283,8 @@
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognises images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
"OptionImageSavingCompatible": "Compatible - MB3\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB3\/MB2",
"OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
"HeaderPleaseSignIn": "Please sign in",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
"TabGuide": "Guide",
"TabChannels": "Channels",
"TabCollections": "Collections",
"HeaderChannels": "Channels",
"TabRecordings": "Recordings",
"TabScheduled": "Scheduled",
"TabSeries": "Series",
"TabFavorites": "Favorites",
"TabMyLibrary": "My Library",
"ButtonCancelRecording": "Cancel Recording",
"HeaderPrePostPadding": "Pre\/Post Padding",
"LabelPrePaddingMinutes": "Pre-padding minutes:",
@ -319,7 +335,7 @@
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
"LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
"HeaderCustomizeOptionsPerMediaType": "Customise options per media type",
"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
"OptionDownloadThumbImage": "Thumb",
"OptionDownloadMenuImage": "Menu",
"OptionDownloadLogoImage": "Logo",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "Primary",
"HeaderFetchImages": "Fetch Images:",
"HeaderImageSettings": "Image Settings",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
"LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
"LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
@ -463,9 +480,9 @@
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
"LabelSeries": "Series:",
"LabelSeasonNumber": "Season number:",
"LabelEpisodeNumber": "Episode number:",
"LabelEndingEpisodeNumber": "Ending episode number:",
"LabelSeasonNumber": "Season number",
"LabelEpisodeNumber": "Episode number",
"LabelEndingEpisodeNumber": "Ending episode number",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@ -529,8 +546,8 @@
"ButtonRetrieveKey": "Retrieve Key",
"LabelSupporterKey": "Supporter Key (paste from email)",
"LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
"MessageInvalidKey": "MB3 Key Missing or Invalid",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be an MB3 Supporter. Please donate and support the continued development of the core product. Thank you.",
"MessageInvalidKey": "Supporter key is missing or invalid.",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
"HeaderDisplaySettings": "Display Settings",
"TabPlayTo": "Play To",
"LabelEnableDlnaServer": "Enable Dlna server",
@ -558,9 +575,12 @@
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
"NotificationOptionPluginInstalled": "Plugin installed",
"NotificationOptionPluginUninstalled": "Plugin uninstalled",
"NotificationOptionVideoPlayback": "Video playback",
"NotificationOptionAudioPlayback": "Audio playback",
"NotificationOptionGamePlayback": "Game playback",
"NotificationOptionVideoPlayback": "Video playback started",
"NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionGamePlayback": "Game playback started",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "Scheduled task failure",
"NotificationOptionInstallationFailed": "Installation failure",
"NotificationOptionNewLibraryContent": "New content added",
@ -588,6 +608,7 @@
"ButtonArrowRight": "Right",
"ButtonBack": "Back",
"ButtonInfo": "Info",
"ButtonOsd": "On screen display",
"ButtonPageUp": "Page Up",
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "Volume down",
"ButtonMute": "Mute",
"HeaderLatestMedia": "Latest Media",
"OptionNoSubtitles": "No Subtitles",
"OptionSpecialFeatures": "Special Features",
"HeaderCollections": "Collections",
"HeaderMyLibrary": "My Library",
@ -704,12 +724,26 @@
"TabSubtitles": "Subtitles",
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Download languages:",
"ButtonRegister": "Register",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
"HeaderSendMessage": "Send Message",
"ButtonSend": "Send",
"LabelMessageText": "Message text:"
"LabelMessageText": "Message text:",
"MessageNoAvailablePlugins": "No available plugins.",
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Others",
"LabelEpisodeName": "Episode name",
"LabelSeriesName": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "Playback Settings",
"LabelAudioLanguagePreference": "Audio language preference:",
"LabelSubtitleLanguagePreference": "Subtitle language preference:",
"LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
"OptionDefaultSubtitles": "Default",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
"OptionNoSubtitles": "No Subtitles",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
"TabProfiles": "Profiles",
"TabSecurity": "Security",
"ButtonAddUser": "Add User",
@ -161,6 +168,10 @@
"OptionIso": "Iso",
"Option3D": "3D",
"LabelFeatures": "Features:",
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
"LabelLastResult": "Last result:",
"OptionHasSubtitles": "Subtitles",
"OptionHasTrailer": "Trailer",
"OptionHasThemeSong": "Theme Song",
@ -224,6 +235,8 @@
"ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "Please support other free products we utilize:",
"VersionNumber": "Version {0}",
"TabPaths": "Paths",
@ -270,8 +283,8 @@
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
"OptionImageSavingCompatible": "Compatible - MB3\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB3\/MB2",
"OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
"HeaderPleaseSignIn": "Please sign in",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
"TabGuide": "Guide",
"TabChannels": "Channels",
"TabCollections": "Collections",
"HeaderChannels": "Channels",
"TabRecordings": "Recordings",
"TabScheduled": "Scheduled",
"TabSeries": "Series",
"TabFavorites": "Favorites",
"TabMyLibrary": "My Library",
"ButtonCancelRecording": "Cancel Recording",
"HeaderPrePostPadding": "Pre\/Post Padding",
"LabelPrePaddingMinutes": "Pre-padding minutes:",
@ -319,7 +335,7 @@
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
"LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
"HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
"OptionDownloadThumbImage": "Thumb",
"OptionDownloadMenuImage": "Menu",
"OptionDownloadLogoImage": "Logo",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "Primary",
"HeaderFetchImages": "Fetch Images:",
"HeaderImageSettings": "Image Settings",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
"LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
"LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
@ -463,9 +480,9 @@
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
"LabelSeries": "Series:",
"LabelSeasonNumber": "Season number:",
"LabelEpisodeNumber": "Episode number:",
"LabelEndingEpisodeNumber": "Ending episode number:",
"LabelSeasonNumber": "Season number",
"LabelEpisodeNumber": "Episode number",
"LabelEndingEpisodeNumber": "Ending episode number",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@ -529,8 +546,8 @@
"ButtonRetrieveKey": "Retrieve Key",
"LabelSupporterKey": "Supporter Key (paste from email)",
"LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
"MessageInvalidKey": "MB3 Key Missing or Invalid",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be an MB3 Supporter. Please donate and support the continued development of the core product. Thank you.",
"MessageInvalidKey": "Supporter key is missing or invalid.",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
"HeaderDisplaySettings": "Display Settings",
"TabPlayTo": "Play To",
"LabelEnableDlnaServer": "Enable Dlna server",
@ -558,9 +575,12 @@
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
"NotificationOptionPluginInstalled": "Plugin installed",
"NotificationOptionPluginUninstalled": "Plugin uninstalled",
"NotificationOptionVideoPlayback": "Video playback",
"NotificationOptionAudioPlayback": "Audio playback",
"NotificationOptionGamePlayback": "Game playback",
"NotificationOptionVideoPlayback": "Video playback started",
"NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionGamePlayback": "Game playback started",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "Scheduled task failure",
"NotificationOptionInstallationFailed": "Installation failure",
"NotificationOptionNewLibraryContent": "New content added",
@ -588,6 +608,7 @@
"ButtonArrowRight": "Right",
"ButtonBack": "Back",
"ButtonInfo": "Info",
"ButtonOsd": "On screen display",
"ButtonPageUp": "Page Up",
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "Volume down",
"ButtonMute": "Mute",
"HeaderLatestMedia": "Latest Media",
"OptionNoSubtitles": "No Subtitles",
"OptionSpecialFeatures": "Special Features",
"HeaderCollections": "Collections",
"HeaderMyLibrary": "My Library",
@ -704,12 +724,26 @@
"TabSubtitles": "Subtitles",
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Download languages:",
"ButtonRegister": "Register",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
"HeaderSendMessage": "Send Message",
"ButtonSend": "Send",
"LabelMessageText": "Message text:"
"LabelMessageText": "Message text:",
"MessageNoAvailablePlugins": "No available plugins.",
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Others",
"LabelEpisodeName": "Episode name",
"LabelSeriesName": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "Ajustes de reproducci\u00f3n",
"LabelAudioLanguagePreference": "Preferencia de idioma de audio",
"LabelSubtitleLanguagePreference": "Preferencia de idioma de subtitulos",
"LabelDisplayForcedSubtitlesOnly": "Mostrar \u00fanicamente subtitulos forzados",
"OptionDefaultSubtitles": "Default",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
"OptionNoSubtitles": "Sin subt\u00edtulos",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
"TabProfiles": "Perfiles",
"TabSecurity": "Seguridad",
"ButtonAddUser": "Agregar Usuario",
@ -161,6 +168,10 @@
"OptionIso": "Iso",
"Option3D": "3D",
"LabelFeatures": "Caracter\u00edsticas",
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
"LabelLastResult": "Last result:",
"OptionHasSubtitles": "Subt\u00edtulos",
"OptionHasTrailer": "Trailer",
"OptionHasThemeSong": "Banda sonora",
@ -224,6 +235,8 @@
"ButtonSearch": "Buscar",
"ButtonGroupVersions": "Versiones de Grupo",
"PismoMessage": "Usando Pismo File Mount a trav\u00e9s de una licencia donada.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "Por favor apoye otros productos gratuitos que utilizamos:",
"VersionNumber": "Versi\u00f3n {0}",
"TabPaths": "Ruta",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "No se necesitan contrase\u00f1as al iniciar sesi\u00f3n desde localhost.",
"TabGuide": "Gu\u00eda",
"TabChannels": "Canales",
"TabCollections": "Collections",
"HeaderChannels": "Canales",
"TabRecordings": "Grabaciones",
"TabScheduled": "Programado",
"TabSeries": "Series",
"TabFavorites": "Favorites",
"TabMyLibrary": "My Library",
"ButtonCancelRecording": "Cancelar grabaci\u00f3n",
"HeaderPrePostPadding": "Pre\/post grabaci\u00f3n extra",
"LabelPrePaddingMinutes": "Minutos previos extras:",
@ -319,7 +335,7 @@
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "El servicio de TV en vivo es necesario para poder continuar.",
"LiveTvPluginRequiredHelp": "Instale uno de los plugins disponibles, como Next Pvr o ServerVmc.",
"HeaderCustomizeOptionsPerMediaType": "Personalizar las opciones por tipo de medio",
"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
"OptionDownloadThumbImage": "Miniatura",
"OptionDownloadMenuImage": "Men\u00fa",
"OptionDownloadLogoImage": "Logo",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "Principal",
"HeaderFetchImages": "Buscar im\u00e1genes",
"HeaderImageSettings": "Opciones de im\u00e1gen",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "M\u00e1ximo n\u00famero de im\u00e1genes de fondo por \u00edtem:",
"LabelMaxScreenshotsPerItem": "M\u00e1ximo n\u00famero de capturas de pantalla por \u00edtem:",
"LabelMinBackdropDownloadWidth": "Anchura m\u00ednima de descarga de im\u00e1genes de fondo:",
@ -561,6 +578,9 @@
"NotificationOptionVideoPlayback": "Reproducci\u00f3n de video",
"NotificationOptionAudioPlayback": "Reproducci\u00f3n de audio",
"NotificationOptionGamePlayback": "Iniciar juegos",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "La tarea programada ha fallado",
"NotificationOptionInstallationFailed": "Fallo en la instalaci\u00f3n",
"NotificationOptionNewLibraryContent": "Nuevo contenido a\u00f1adido",
@ -588,6 +608,7 @@
"ButtonArrowRight": "Derecha",
"ButtonBack": "Atr\u00e1s",
"ButtonInfo": "Info",
"ButtonOsd": "On screen display",
"ButtonPageUp": "P\u00e1gina arriba",
"ButtonPageDown": "P\u00e1gina abajo",
"PageAbbreviation": "PG",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "Bajar volumen",
"ButtonMute": "Silencio",
"HeaderLatestMedia": "\u00daltimos medios",
"OptionNoSubtitles": "Sin subt\u00edtulos",
"OptionSpecialFeatures": "Caracter\u00edsticas especiales",
"HeaderCollections": "Colecciones",
"HeaderMyLibrary": "Mi librer\u00eda",
@ -704,12 +724,26 @@
"TabSubtitles": "Subt\u00edtulos",
"LabelOpenSubtitlesUsername": "Usuario de Open Subtitles:",
"LabelOpenSubtitlesPassword": "Contrase\u00f1a de Open Subtitles:",
"LabelAudioLanguagePreferenceHelp": "Si est\u00e1 vac\u00edo, se seleccionar\u00e1 la pista de audio por defecto, sin importar el idioma.",
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Idiomas de descarga:",
"ButtonRegister": "Registrar",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
"HeaderSendMessage": "Send Message",
"ButtonSend": "Send",
"LabelMessageText": "Message text:"
"LabelMessageText": "Message text:",
"MessageNoAvailablePlugins": "No available plugins.",
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Others",
"LabelEpisodeName": "Episode name",
"LabelSeriesName": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "Configuraci\u00f3n de Reproducci\u00f3n",
"LabelAudioLanguagePreference": "Preferencia de idioma de audio:",
"LabelSubtitleLanguagePreference": "Preferencia de idioma de subt\u00edtulos:",
"LabelDisplayForcedSubtitlesOnly": "Mostrar \u00fanicamente subtitulos forzados",
"OptionDefaultSubtitles": "Por Defecto",
"OptionOnlyForcedSubtitles": "\u00danicamente subt\u00edtulos forzados",
"OptionAlwaysPlaySubtitles": "Siempre mostrar subt\u00edtulos",
"OptionNoSubtitles": "Sin Subtitulos",
"OptionDefaultSubtitlesHelp": "Los subt\u00edtulos que coincidan con el lenguaje preferido ser\u00e1n cargados cuando el audio se encuentre en un lenguaje extrangero.",
"OptionOnlyForcedSubtitlesHelp": "Se cargar\u00e1n \u00fanicamente subt\u00edtulos marcados como forzados.",
"OptionAlwaysPlaySubtitlesHelp": "Los subt\u00edtulos que coincidan con el lenguaje preferido ser\u00e1n cargados independientemente del lenguaje del audio.",
"OptionNoSubtitlesHelp": "Los subt\u00edtulos no ser\u00e1n cargados por defecto.",
"TabProfiles": "Perfiles",
"TabSecurity": "Seguridad",
"ButtonAddUser": "Agregar Usuario",
@ -161,6 +168,10 @@
"OptionIso": "ISO",
"Option3D": "3D",
"LabelFeatures": "Caracter\u00edsticas:",
"LabelService": "Servicio:",
"LabelStatus": "Estado:",
"LabelVersion": "Versi\u00f3n:",
"LabelLastResult": "\u00daltimo resultado:",
"OptionHasSubtitles": "Subt\u00edtulos",
"OptionHasTrailer": "Avance",
"OptionHasThemeSong": "Canci\u00f3n del Tema",
@ -224,6 +235,8 @@
"ButtonSearch": "B\u00fasqueda",
"ButtonGroupVersions": "Agrupar Versiones",
"PismoMessage": "Utilizando Pismo File Mount a trav\u00e9s de una licencia donada.",
"TangibleSoftwareMessage": "Utilizando convertidores Java\/C# de Tangible Solutions por medio de una licencia donada.",
"HeaderCredits": "Cr\u00e9ditos",
"PleaseSupportOtherProduces": "Por favor apoye otros productos libres que utilizamos:",
"VersionNumber": "Versi\u00f3n {0}",
"TabPaths": "Rutas",
@ -270,8 +283,8 @@
"ButtonAutoScroll": "Auto-desplazamiento",
"LabelImageSavingConvention": "Convenci\u00f3n de almacenamiento de im\u00e1genes:",
"LabelImageSavingConventionHelp": "MediaBrowser reconoce im\u00e1genes de las aplicaciones de medios m\u00e1s importantes. Seleccionar la convenci\u00f3n de descarga es \u00fatil si utiliza otros productos.",
"OptionImageSavingCompatible": "Compatible - MB3\/Plex\/Xbmc",
"OptionImageSavingStandard": "Est\u00e1ndar - MB3\/MB2",
"OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
"OptionImageSavingStandard": "Est\u00e1ndar - MB2",
"ButtonSignIn": "Iniciar Sesi\u00f3n",
"TitleSignIn": "Iniciar Sesi\u00f3n",
"HeaderPleaseSignIn": "Por favor inicie sesi\u00f3n",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "Las contrase\u00f1as no se requieren cuando se inicia sesi\u00f3n desde localhost.",
"TabGuide": "Gu\u00eda",
"TabChannels": "Canales",
"TabCollections": "Colecciones",
"HeaderChannels": "Canales",
"TabRecordings": "Grabaciones",
"TabScheduled": "Programados",
"TabSeries": "Series",
"TabFavorites": "Favoritos",
"TabMyLibrary": "Mi Biblioteca",
"ButtonCancelRecording": "Cancelar Grabaci\u00f3n",
"HeaderPrePostPadding": "Pre\/Post protecci\u00f3n",
"LabelPrePaddingMinutes": "Minutos de protecci\u00f3n previos:",
@ -319,7 +335,7 @@
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "Se requiere de un complemento proveedor de servicios de TV en vivo para continuar.",
"LiveTvPluginRequiredHelp": "Por favor instale alguno de los complementos disponibles, como Next PVR o ServerWMC.",
"HeaderCustomizeOptionsPerMediaType": "Personalice opciones por tipo de medio",
"LabelCustomizeOptionsPerMediaType": "Personalizar por tipo de medio:",
"OptionDownloadThumbImage": "Miniatura",
"OptionDownloadMenuImage": "Men\u00fa",
"OptionDownloadLogoImage": "Logo",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "Principal",
"HeaderFetchImages": "Buscar im\u00e1genes:",
"HeaderImageSettings": "Opciones de Im\u00e1genes",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "N\u00famero m\u00e1ximo de im\u00e1genes de fondo por \u00edtem:",
"LabelMaxScreenshotsPerItem": "N\u00famero m\u00e1ximo de capturas de pantalla por \u00edtem:",
"LabelMinBackdropDownloadWidth": "Anchura m\u00ednima de descarga de im\u00e1genes de fondo:",
@ -463,9 +480,9 @@
"LabelSkipped": "Omitido",
"HeaderEpisodeOrganization": "Organizaci\u00f3n de Episodios",
"LabelSeries": "Series:",
"LabelSeasonNumber": "N\u00famero de temporada:",
"LabelEpisodeNumber": "N\u00famero de episodio:",
"LabelEndingEpisodeNumber": "N\u00famero episodio final:",
"LabelSeasonNumber": "N\u00famero de temporada",
"LabelEpisodeNumber": "N\u00famero de episodio",
"LabelEndingEpisodeNumber": "N\u00famero episodio final",
"LabelEndingEpisodeNumberHelp": "S\u00f3lo requerido para archivos multi-episodio",
"HeaderSupportTheTeam": "Apoye al Equipo de Media Browser",
"LabelSupportAmount": "Importe (USD)",
@ -529,8 +546,8 @@
"ButtonRetrieveKey": "Recuperar Clave",
"LabelSupporterKey": "Clave de Aficionado (pegue desde el correo electr\u00f3nico)",
"LabelSupporterKeyHelp": "Introduzca su clave de aficionado para comenzar a disfrutar beneficios adicionales que la comunidad ha desarrollado para Media Browser.",
"MessageInvalidKey": "Falta Clave de MB3 o es Inv\u00e1lida",
"ErrorMessageInvalidKey": "Para que cualquier contenido Premium sea registrado, tambi\u00e9n debe ser un Aficionado MB3. Por favor done y ayude a continuar con el desarrollo del producto base. Gracias.",
"MessageInvalidKey": "Falta Clave de aficionado o es Inv\u00e1lida",
"ErrorMessageInvalidKey": "Para que cualquier contenido Premium sea registrado, tambi\u00e9n debe ser un Aficionado de Media Browser. Por favor done y ayude a continuar con el desarrollo del producto base. Gracias.",
"HeaderDisplaySettings": "Configuraci\u00f3n de Pantalla",
"TabPlayTo": "Reproducir En",
"LabelEnableDlnaServer": "Habilitar servidor DLNA",
@ -561,10 +578,13 @@
"NotificationOptionVideoPlayback": "Reproducci\u00f3n de video",
"NotificationOptionAudioPlayback": "Reproducci\u00f3n de audio",
"NotificationOptionGamePlayback": "Ejecuci\u00f3n de juegos",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "Falla de tarea programada",
"NotificationOptionInstallationFailed": "Falla de instalaci\u00f3n",
"NotificationOptionNewLibraryContent": "Adici\u00f3n de nuevos contenidos",
"NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
"NotificationOptionNewLibraryContentMultiple": "Nuevo contenido agregado (varios).",
"SendNotificationHelp": "Por defecto, las notificaciones son enviadas a la bandeja de entrada del panel de control. Navegue el cat\u00e1logo de complementos para instalar opciones de notificaci\u00f3n adicionales.",
"NotificationOptionServerRestartRequired": "Reinicio del servidor requerido",
"LabelNotificationEnabled": "Habilitar esta notificaci\u00f3n",
@ -588,6 +608,7 @@
"ButtonArrowRight": "Derecha",
"ButtonBack": "Atr\u00e1s",
"ButtonInfo": "Info",
"ButtonOsd": "Visualizaci\u00f3n en pantalla",
"ButtonPageUp": "P\u00e1gina arriba",
"ButtonPageDown": "P\u00e1gina abajo",
"PageAbbreviation": "Pag.",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "Bajar Volumen",
"ButtonMute": "Mudo",
"HeaderLatestMedia": "\u00daltimos Medios",
"OptionNoSubtitles": "Sin Subtitulos",
"OptionSpecialFeatures": "Caracter\u00edsticas Especiales",
"HeaderCollections": "Colecciones",
"HeaderMyLibrary": "Mi Biblioteca",
@ -683,11 +703,11 @@
"HeaderTranscodingProfileHelp": "A\u00f1ada perfiles de transcodificaci\u00f3n para indicar que formatos deben ser usados cuando se requiera transcodificar.",
"HeaderResponseProfileHelp": "Los perfiles de respuesta proporcionan un medio para personalizar la informaci\u00f3n enviada a un dispositivo cuando se reproducen ciertos tipos de medios.",
"LabelXDlnaCap": "X-DLNA cap:",
"LabelXDlnaCapHelp": "Determina el contenido del elemento X_DLNACAP em el namespace urn:schemas-dlna-org:device-1-0.",
"LabelXDlnaCapHelp": "Determina el contenido del elemento X_DLNACAP en el namespace urn:schemas-dlna-org:device-1-0.",
"LabelXDlnaDoc": "X-DLNA Doc:",
"LabelXDlnaDocHelp": "Determina el contenido del elemento X_DLNADOC en el namespace urn:schemas-dlna-org:device-1-0.",
"LabelSonyAggregationFlags": "Banderas de agregaci\u00f3n Sony:",
"LabelSonyAggregationFlagsHelp": "Determina el contenido del elemento aggregationFlags in el namespace urn:schemas-sonycom:av",
"LabelSonyAggregationFlagsHelp": "Determina el contenido del elemento aggregationFlags en el namespace urn:schemas-sonycom:av",
"LabelTranscodingContainer": "Contenedor:",
"LabelTranscodingVideoCodec": "Codec de video:",
"LabelTranscodingVideoProfile": "Perfil de video:",
@ -704,12 +724,26 @@
"TabSubtitles": "Subt\u00edtulos",
"LabelOpenSubtitlesUsername": "Nombre de usuario de Open Subtitles:",
"LabelOpenSubtitlesPassword": "Contrase\u00f1a de Open Subtitles:",
"LabelAudioLanguagePreferenceHelp": "Si se deja vac\u00edo, la pista de audio por defecto ser\u00e1 seleccionada, independientemente del lenguaje.",
"LabelPlayDefaultAudioTrack": "Reproducir la pista de audio por defecto independientemente del lenguaje",
"LabelSubtitlePlaybackMode": "Modo de subt\u00edtulo:",
"LabelDownloadLanguages": "Descargar lenguajes:",
"ButtonRegister": "Registrar",
"LabelSkipIfAudioTrackPresent": "Omitir si la pista de audio por defecto coincide con el lenguaje de descarga",
"LabelSkipIfAudioTrackPresentHelp": "Desactive esto para asegurar que todos los videos tengan subt\u00edtulos, independientemente del lenguaje del audio.",
"HeaderSendMessage": "Send Message",
"ButtonSend": "Send",
"LabelMessageText": "Message text:"
"HeaderSendMessage": "Enviar Mensaje",
"ButtonSend": "Enviar",
"LabelMessageText": "Texto del Mensaje:",
"MessageNoAvailablePlugins": "No hay complementos disponibles.",
"LabelDisplayPluginsFor": "Desplegar complementos para:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Otros",
"LabelEpisodeName": "Nombre del episodio",
"LabelSeriesName": "Nombre de la serie",
"ValueSeriesNamePeriod": "Nombre.serie",
"ValueSeriesNameUnderscore": "Nombre_serie",
"ValueEpisodeNamePeriod": "Nombre del episodio",
"ValueEpisodeNameUnderscore": "Nombre_episodio",
"HeaderTypeText": "Capturar Texto",
"LabelTypeText": "Texto"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "Param\u00e8tres de lecture",
"LabelAudioLanguagePreference": "Param\u00e8tres de langue audio:",
"LabelSubtitleLanguagePreference": "Param\u00e8tres de langue de sous-titre",
"LabelDisplayForcedSubtitlesOnly": "Afficher seulement les sous-titres forc\u00e9s",
"OptionDefaultSubtitles": "Par d\u00e9faut",
"OptionOnlyForcedSubtitles": "Seulement les sous-titres forc\u00e9s",
"OptionAlwaysPlaySubtitles": "Toujours afficher les sous-titres",
"OptionNoSubtitles": "Aucun sous-titre",
"OptionDefaultSubtitlesHelp": "Les sous-titres correspondants \u00e0 la langue pr\u00e9f\u00e9r\u00e9e seront charg\u00e9s lorsque la langue audio est \u00e9trang\u00e8re.",
"OptionOnlyForcedSubtitlesHelp": "Seulement les sous-titres forc\u00e9s seront charg\u00e9s.",
"OptionAlwaysPlaySubtitlesHelp": "Les sous-titres correspondants \u00e0 la langue pr\u00e9f\u00e9r\u00e9e seront charg\u00e9s peu importe la langue audio.",
"OptionNoSubtitlesHelp": "Les sous-titres ne seront pas charg\u00e9s par d\u00e9faut.",
"TabProfiles": "Profils",
"TabSecurity": "S\u00e9curit\u00e9",
"ButtonAddUser": "Ajouter utilisateur",
@ -161,6 +168,10 @@
"OptionIso": "ISO",
"Option3D": "3D",
"LabelFeatures": "Caract\u00e9ristiques:",
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
"LabelLastResult": "Dernier r\u00e9sultat:",
"OptionHasSubtitles": "Sous-titres",
"OptionHasTrailer": "Bande-annnonce",
"OptionHasThemeSong": "Chanson th\u00e8me",
@ -224,6 +235,8 @@
"ButtonSearch": "Recherche",
"ButtonGroupVersions": "Versions des groupes",
"PismoMessage": "En utilisation de \"Pismo File Mount\" par une license fournie.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "SVP, soutenez les autres produits gratuits que nous utilisons:",
"VersionNumber": "Version {0}",
"TabPaths": "Chemins d'acc\u00e8s",
@ -270,8 +283,8 @@
"ButtonAutoScroll": "D\u00e9fillement automatique",
"LabelImageSavingConvention": "Convention de sauvegarde des images:",
"LabelImageSavingConventionHelp": "Media Browser reconnait les images des autres applications de m\u00e9dia importants. Choisir la convention de t\u00e9l\u00e9chargement peut \u00eatre pratique si vous utilisez aussi d'autres produits.",
"OptionImageSavingCompatible": "Compatible - MB3\/Plex\/XBMC",
"OptionImageSavingStandard": "Standard - MB3\/MB2",
"OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/XBMC",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Se connecter",
"TitleSignIn": "Se connecter",
"HeaderPleaseSignIn": "SVP se connecter",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "Aucun mot de passe requis pour les connexions par \"localhost\".",
"TabGuide": "Guide horaire",
"TabChannels": "Cha\u00eenes",
"TabCollections": "Collections",
"HeaderChannels": "Cha\u00eenes",
"TabRecordings": "Enregistrements",
"TabScheduled": "Programm\u00e9s",
"TabSeries": "S\u00e9ries",
"TabFavorites": "Favoris",
"TabMyLibrary": "Ma Biblioth\u00e8que",
"ButtonCancelRecording": "Annuler l'enregistrement",
"HeaderPrePostPadding": "Pr\u00e9-remplissage",
"LabelPrePaddingMinutes": "Minutes de Pr\u00e9-remplissage:",
@ -319,7 +335,7 @@
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "Un fournisseur de service de TV en direct est requis pour continuer.",
"LiveTvPluginRequiredHelp": "SVP installer un de nos Plugins disponibles, comme Next Pvr ou ServerWmc.",
"HeaderCustomizeOptionsPerMediaType": "Personnaliser les param\u00e8tres par type de m\u00e9dias",
"LabelCustomizeOptionsPerMediaType": "Personnaliser pour le type de m\u00e9dia:",
"OptionDownloadThumbImage": "Vignette",
"OptionDownloadMenuImage": "Menu",
"OptionDownloadLogoImage": "Logo",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "Principal",
"HeaderFetchImages": "T\u00e9l\u00e9charger Images:",
"HeaderImageSettings": "Param\u00e8tres d'image",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "Nombre maximum d'images d'arri\u00e8re-plan par item:",
"LabelMaxScreenshotsPerItem": "Nombre maximum de captures d'\u00e9cran par item:",
"LabelMinBackdropDownloadWidth": "Largeur minimum d'image d'arri\u00e8re-plan \u00e0 t\u00e9l\u00e9charger:",
@ -463,9 +480,9 @@
"LabelSkipped": "Saut\u00e9",
"HeaderEpisodeOrganization": "Organisation d'\u00e9pisodes",
"LabelSeries": "S\u00e9ries:",
"LabelSeasonNumber": "Num\u00e9ro de saison:",
"LabelSeasonNumber": "Num\u00e9ro de saison",
"LabelEpisodeNumber": "Num\u00e9ro d'\u00e9pisode",
"LabelEndingEpisodeNumber": "Num\u00e9ro d'\u00e9pisode se terminant:",
"LabelEndingEpisodeNumber": "Num\u00e9ro d'\u00e9pisode se terminant",
"LabelEndingEpisodeNumberHelp": "Seulement requis pour les fichiers multi-\u00e9pisodes",
"HeaderSupportTheTeam": "Soutenez l'\u00e9quippe Media Browser",
"LabelSupportAmount": "Montant (USD)",
@ -529,8 +546,8 @@
"ButtonRetrieveKey": "obtenir la cl\u00e9",
"LabelSupporterKey": "Cl\u00e9 de supporteur (coller du courriel)",
"LabelSupporterKeyHelp": "Entrez votre cl\u00e9 du supporteur pour commencer \u00e0 profiter des b\u00e9n\u00e9fices additionnels que la communaut\u00e9 a d\u00e9velopp\u00e9 pour Media Browser.",
"MessageInvalidKey": "Cl\u00e9 MB3 manquante ou invalide",
"ErrorMessageInvalidKey": "Pour que le contenu premium soit enregistr\u00e9, vous devez aussi \u00eatre supporteur MB3. S'il vous plait effectuez des dons et soutenez la continuation du d\u00e9veloppement de Media Browser.",
"MessageInvalidKey": "Cl\u00e9 de supporteur manquante ou invalide",
"ErrorMessageInvalidKey": "Pour que le contenu premium soit enregistr\u00e9, vous devez aussi \u00eatre supporteur Media Browser. S'il vous plait, effectuez des dons et soutenez la continuation du d\u00e9veloppement de Media Browser.",
"HeaderDisplaySettings": "Param\u00e8tres d'affichage",
"TabPlayTo": "Lire sur",
"LabelEnableDlnaServer": "Activer le serveur DLNA",
@ -561,6 +578,9 @@
"NotificationOptionVideoPlayback": "Lecture vid\u00e9o",
"NotificationOptionAudioPlayback": "Lecture audio",
"NotificationOptionGamePlayback": "Lecture des jeux",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "\u00c9chec de t\u00e2che programm\u00e9e",
"NotificationOptionInstallationFailed": "\u00c9chec d'installation",
"NotificationOptionNewLibraryContent": "Nouveau contenu ajout\u00e9",
@ -588,6 +608,7 @@
"ButtonArrowRight": "Droite",
"ButtonBack": "Retour arri\u00e8re",
"ButtonInfo": "Info",
"ButtonOsd": "Affichage \u00e0 l'\u00e9cran",
"ButtonPageUp": "Page suivante",
"ButtonPageDown": "Page pr\u00e9c\u00e9dante",
"PageAbbreviation": "PG",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "Volume bas",
"ButtonMute": "Sourdine",
"HeaderLatestMedia": "Derniers m\u00e9dias",
"OptionNoSubtitles": "Aucun sous-titre",
"OptionSpecialFeatures": "\u00c9v\u00eanements sp\u00e9ciaux",
"HeaderCollections": "Collections",
"HeaderMyLibrary": "Ma biblioth\u00e8que",
@ -699,17 +719,31 @@
"OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.",
"HeaderSubtitleDownloadingHelp": "Lorsque Media Browser balaye vos fichiers vid\u00e9os, le serveur peut rechercher des sous-titres manquants et les t\u00e9l\u00e9charger en utilisant un fournisseur de sous-titre comme OpenSubtitles.org.",
"HeaderDownloadSubtitlesFor": "T\u00e9l\u00e9charger les sous-titres pour:",
"LabelSkipIfGraphicalSubsPresent": "Sauter le vid\u00e9o contient d\u00e9j\u00e0 des sous-titres graphiques",
"LabelSkipIfGraphicalSubsPresent": "Sauter la vid\u00e9o si elle contient d\u00e9j\u00e0 des sous-titres graphiques",
"LabelSkipIfGraphicalSubsPresentHelp": "Garder des versions textes des sous-titres va \u00eatre plus efficace avec les appareils mobiles.",
"TabSubtitles": "Sous-titres:",
"LabelOpenSubtitlesUsername": "Nom d'utilisateur de Open Subtitles:",
"LabelOpenSubtitlesPassword": "Mot de passe de Open Subtitles:",
"LabelAudioLanguagePreferenceHelp": "Si laiss\u00e9 vide, la piste audio par d\u00e9faut sera s\u00e9lectionn\u00e9e, peu importe la langue.",
"LabelDownloadLanguages": "Langes de t\u00e9l\u00e9chargement:",
"LabelPlayDefaultAudioTrack": "Utiliser la flux audio par d\u00e9faut peu importe la langue",
"LabelSubtitlePlaybackMode": "Mode de sous-titres:",
"LabelDownloadLanguages": "T\u00e9l\u00e9chargement de langues:",
"ButtonRegister": "S'enregistrer",
"LabelSkipIfAudioTrackPresent": "Sauter si la piste audio correspond \u00e0 la langue de t\u00e9l\u00e9chargement",
"LabelSkipIfAudioTrackPresentHelp": "D\u00e9cocher cette option va assurer que tous les vid\u00e9os ont des sous-titres, peu importe la langue audio.",
"HeaderSendMessage": "Envoyer message",
"ButtonSend": "Envoyer",
"LabelMessageText": "Texte du message:"
"LabelMessageText": "Texte du message:",
"MessageNoAvailablePlugins": "Aucun plugin disponible.",
"LabelDisplayPluginsFor": "Afficher les plugins pour:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theatre",
"TabOtherPlugins": "Autres",
"LabelEpisodeName": "Nom d'\u00e9pisode",
"LabelSeriesName": "Nom de s\u00e9ries",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
"HeaderTypeText": "Entrer texte",
"LabelTypeText": "Texte"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "\u05d0\u05e4\u05e9\u05e8\u05d5\u05d9\u05d5\u05ea \u05e0\u05d9\u05d2\u05d5\u05df",
"LabelAudioLanguagePreference": "\u05e9\u05e4\u05ea \u05e7\u05d5\u05dc \u05de\u05d5\u05e2\u05d3\u05e4\u05ea:",
"LabelSubtitleLanguagePreference": "\u05e9\u05e4\u05ea \u05db\u05ea\u05d5\u05d1\u05d9\u05d5\u05ea \u05de\u05d5\u05e2\u05d3\u05e4\u05ea:",
"LabelDisplayForcedSubtitlesOnly": "\u05d4\u05e6\u05d2 \u05e8\u05e7 \u05db\u05ea\u05d5\u05d1\u05d9\u05d5\u05ea \u05de\u05d0\u05d5\u05dc\u05e6\u05d5\u05ea",
"OptionDefaultSubtitles": "Default",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
"OptionNoSubtitles": "No Subtitles",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
"TabProfiles": "\u05e4\u05e8\u05d5\u05e4\u05d9\u05dc\u05d9\u05dd",
"TabSecurity": "\u05d1\u05d8\u05d9\u05d7\u05d5\u05ea",
"ButtonAddUser": "\u05d4\u05d5\u05e1\u05e3 \u05de\u05e9\u05ea\u05de\u05e9",
@ -161,6 +168,10 @@
"OptionIso": "ISO",
"Option3D": "\u05ea\u05dc\u05ea \u05de\u05d9\u05de\u05d3",
"LabelFeatures": "\u05de\u05d0\u05e4\u05d9\u05d9\u05e0\u05d9\u05dd:",
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
"LabelLastResult": "Last result:",
"OptionHasSubtitles": "\u05db\u05ea\u05d5\u05d1\u05d9\u05d5\u05ea",
"OptionHasTrailer": "\u05d8\u05e8\u05d9\u05d9\u05dc\u05e8",
"OptionHasThemeSong": "\u05e9\u05d9\u05e8 \u05e0\u05d5\u05e9\u05d0",
@ -224,6 +235,8 @@
"ButtonSearch": "\u05d7\u05d9\u05e4\u05d5\u05e9",
"ButtonGroupVersions": "\u05e7\u05d1\u05d5\u05e6\u05ea \u05d2\u05e8\u05e1\u05d0\u05d5\u05ea",
"PismoMessage": "\u05d0\u05e4\u05e9\u05e8 \u05d8\u05e2\u05d9\u05e0\u05ea \u05e7\u05d1\u05e6\u05d9 Pismo \u05d3\u05e8\u05da \u05e8\u05d9\u05e9\u05d9\u05d5\u05df \u05ea\u05e8\u05d5\u05de\u05d4.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "\u05d0\u05e0\u05d0 \u05ea\u05de\u05db\u05d5 \u05d1\u05e9\u05d9\u05e8\u05d5\u05ea\u05d9\u05dd \u05d7\u05d9\u05e0\u05de\u05d9\u05d9\u05dd \u05d0\u05d7\u05e8\u05d9\u05dd \u05e9\u05d1\u05d4\u05dd \u05d0\u05e0\u05d5 \u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd:",
"VersionNumber": "\u05d2\u05d9\u05e8\u05e1\u05d0 {0}",
"TabPaths": "\u05e0\u05ea\u05d9\u05d1\u05d9\u05dd",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "\u05d0\u05d9\u05df \u05e6\u05d5\u05e8\u05da \u05d1\u05e1\u05d9\u05e1\u05de\u05d0 \u05db\u05d0\u05e9\u05e8 \u05de\u05ea\u05d7\u05d1\u05e8\u05d9\u05dd \u05de\u05d4\u05e9\u05e8\u05ea \u05d4\u05de\u05e7\u05d5\u05de\u05d9.",
"TabGuide": "\u05de\u05d3\u05e8\u05d9\u05da",
"TabChannels": "\u05e2\u05e8\u05d5\u05e6\u05d9\u05dd",
"TabCollections": "Collections",
"HeaderChannels": "\u05e2\u05e8\u05d5\u05e6\u05d9\u05dd",
"TabRecordings": "\u05d4\u05e7\u05dc\u05d8\u05d5\u05ea",
"TabScheduled": "\u05dc\u05d5\u05d7 \u05d6\u05de\u05e0\u05d9\u05dd",
"TabSeries": "\u05e1\u05d3\u05e8\u05d5\u05ea",
"TabFavorites": "Favorites",
"TabMyLibrary": "My Library",
"ButtonCancelRecording": "\u05d1\u05d8\u05dc \u05d4\u05e7\u05dc\u05d8\u05d4",
"HeaderPrePostPadding": "\u05de\u05e8\u05d5\u05d5\u05d7 \u05de\u05e7\u05d3\u05d9\u05dd\/\u05de\u05d0\u05d5\u05d7\u05e8",
"LabelPrePaddingMinutes": "\u05d3\u05e7\u05d5\u05ea \u05e9\u05dc \u05de\u05e8\u05d5\u05d5\u05d7 \u05de\u05e7\u05d3\u05d9\u05dd:",
@ -319,7 +335,7 @@
"OptionAutomatic": "\u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9",
"LiveTvPluginRequired": "\u05d9\u05e9 \u05e6\u05d5\u05e8\u05da \u05d1\u05ea\u05d5\u05e1\u05e3 \u05e1\u05e4\u05e7 \u05d8\u05dc\u05d5\u05d5\u05d9\u05d6\u05d9\u05d4 \u05d7\u05d9\u05d9\u05d4 \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05d4\u05de\u05e9\u05d9\u05da.",
"LiveTvPluginRequiredHelp": "\u05d0\u05e0\u05d0 \u05d4\u05ea\u05e7\u05df \u05d0\u05ea \u05d0\u05d7\u05d3 \u05de\u05d4\u05ea\u05d5\u05e1\u05e4\u05d9\u05dd \u05d4\u05d0\u05e4\u05e9\u05e8\u05d9\u05d9\u05dd \u05e9\u05dc\u05e0\u05d5\u05ea \u05db\u05de\u05d5 Next Pvr \u05d0\u05d5 ServerWmc.",
"HeaderCustomizeOptionsPerMediaType": "\u05d0\u05e4\u05e9\u05e8\u05d5\u05d9\u05d5\u05ea \u05d4\u05ea\u05d0\u05de\u05d4 \u05dc\u05e4\u05d9 \u05e1\u05d5\u05d2 \u05de\u05d3\u05d9\u05d4",
"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
"OptionDownloadThumbImage": "Thumb",
"OptionDownloadMenuImage": "\u05ea\u05e4\u05e8\u05d9\u05d8",
"OptionDownloadLogoImage": "\u05dc\u05d5\u05d2\u05d5",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "\u05e8\u05d0\u05e9\u05d9",
"HeaderFetchImages": "\u05d4\u05d1\u05d0 \u05ea\u05de\u05d5\u05e0\u05d5\u05ea:",
"HeaderImageSettings": "\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05ea\u05de\u05d5\u05e0\u05d4",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "\u05de\u05e1\u05e4\u05e8 \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05e8\u05e7\u05e2 \u05de\u05e7\u05e1\u05d9\u05de\u05d0\u05dc\u05d9 \u05dc\u05e4\u05e8\u05d9\u05d8:",
"LabelMaxScreenshotsPerItem": "\u05de\u05e1\u05e4\u05e8 \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05de\u05e1\u05da \u05de\u05e7\u05e1\u05d9\u05de\u05d0\u05dc\u05d9 \u05dc\u05e4\u05e8\u05d9\u05d8:",
"LabelMinBackdropDownloadWidth": "\u05e8\u05d5\u05d7\u05d1 \u05ea\u05de\u05d5\u05e0\u05ea \u05e8\u05e7\u05e2 \u05de\u05d9\u05e0\u05d9\u05de\u05d0\u05dc\u05d9 \u05dc\u05d4\u05d5\u05e8\u05d3\u05d4:",
@ -561,6 +578,9 @@
"NotificationOptionVideoPlayback": "\u05e0\u05d9\u05d2\u05d5\u05df \u05d5\u05d5\u05d9\u05d3\u05d0\u05d5",
"NotificationOptionAudioPlayback": "\u05e0\u05d9\u05d2\u05d5\u05df \u05d0\u05d5\u05d3\u05d9\u05d5",
"NotificationOptionGamePlayback": "\u05d4\u05e6\u05d2\u05ea \u05de\u05e9\u05d7\u05e7",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "\u05de\u05e9\u05d9\u05de\u05d4 \u05de\u05ea\u05d5\u05d6\u05de\u05e0\u05ea \u05e0\u05db\u05e9\u05dc\u05d4",
"NotificationOptionInstallationFailed": "\u05d4\u05ea\u05e7\u05e0\u05d4 \u05e0\u05db\u05e9\u05dc\u05d4",
"NotificationOptionNewLibraryContent": "\u05ea\u05d5\u05db\u05df \u05d7\u05d3\u05e9 \u05e0\u05d5\u05e1\u05e3",
@ -588,6 +608,7 @@
"ButtonArrowRight": "Right",
"ButtonBack": "Back",
"ButtonInfo": "Info",
"ButtonOsd": "On screen display",
"ButtonPageUp": "Page Up",
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "Volume down",
"ButtonMute": "Mute",
"HeaderLatestMedia": "Latest Media",
"OptionNoSubtitles": "No Subtitles",
"OptionSpecialFeatures": "Special Features",
"HeaderCollections": "Collections",
"HeaderMyLibrary": "My Library",
@ -704,12 +724,26 @@
"TabSubtitles": "Subtitles",
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Download languages:",
"ButtonRegister": "Register",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
"HeaderSendMessage": "Send Message",
"ButtonSend": "Send",
"LabelMessageText": "Message text:"
"LabelMessageText": "Message text:",
"MessageNoAvailablePlugins": "No available plugins.",
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Others",
"LabelEpisodeName": "Episode name",
"LabelSeriesName": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "Impostazioni di riproduzione",
"LabelAudioLanguagePreference": "Audio preferenze di lingua:",
"LabelSubtitleLanguagePreference": "Sottotitoli preferenze di lingua:",
"LabelDisplayForcedSubtitlesOnly": "Visualizzare solo i sottotitoli forzati",
"OptionDefaultSubtitles": "Predefinito",
"OptionOnlyForcedSubtitles": "Solo i sottotitoli forzati",
"OptionAlwaysPlaySubtitles": "Visualizza sempre i sottotitoli",
"OptionNoSubtitles": "Nessun Sottotitolo",
"OptionDefaultSubtitlesHelp": "Sottotitoli corrispondenti alla lingua di preferenza saranno caricati quando l'audio \u00e8 in una lingua straniera.",
"OptionOnlyForcedSubtitlesHelp": "Solo sottotitoli contrassegnati come forzati saranno caricati.",
"OptionAlwaysPlaySubtitlesHelp": "Sottotitoli corrispondenti alla lingua di preferenza saranno caricati a prescindere dalla lingua audio.",
"OptionNoSubtitlesHelp": "I sottotitoli non verranno caricati di default.",
"TabProfiles": "Profili",
"TabSecurity": "Sicurezza",
"ButtonAddUser": "Aggiungi Utente",
@ -161,6 +168,10 @@
"OptionIso": "Iso",
"Option3D": "3D",
"LabelFeatures": "Caratteristiche:",
"LabelService": "Servizio:",
"LabelStatus": "Stato:",
"LabelVersion": "Versione:",
"LabelLastResult": "Ultimo risultato:",
"OptionHasSubtitles": "Sottotitoli",
"OptionHasTrailer": "Trailer",
"OptionHasThemeSong": "Tema Canzone",
@ -224,6 +235,8 @@
"ButtonSearch": "Cerca",
"ButtonGroupVersions": "Versione Gruppo",
"PismoMessage": "Dona per avere una licenza di Pismo",
"TangibleSoftwareMessage": "Utilizzando materiali Solutions convertitori Java \/ C # attraverso una licenza dopo aver donato.",
"HeaderCredits": "Crediti",
"PleaseSupportOtherProduces": "Per favore supporta gli altri prodotti 'GRATIS' che MB utilizza",
"VersionNumber": "Versione {0}",
"TabPaths": "Percorso",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "Le password non sono richieste quando l'accesso e fatto da questo pc.",
"TabGuide": "Guida",
"TabChannels": "Canali",
"TabCollections": "Collezioni",
"HeaderChannels": "Canali",
"TabRecordings": "Registrazioni",
"TabScheduled": "Pianificato",
"TabSeries": "Serie TV",
"TabFavorites": "Preferiti",
"TabMyLibrary": "Mia Libreria",
"ButtonCancelRecording": "Annulla la registrazione",
"HeaderPrePostPadding": "Pre\/Post Registrazione",
"LabelPrePaddingMinutes": "Pre registrazione minuti",
@ -319,7 +335,7 @@
"OptionAutomatic": "Automatico",
"LiveTvPluginRequired": "\u00e8 richiesto il servizio LIVE TV per continuare.",
"LiveTvPluginRequiredHelp": "Installa un servizio disponibile, come Next Pvr or ServerWMC.",
"HeaderCustomizeOptionsPerMediaType": "Personalizza le opzioni per i media.",
"LabelCustomizeOptionsPerMediaType": "Personalizza per il tipo di supporto:",
"OptionDownloadThumbImage": "Foto",
"OptionDownloadMenuImage": "Menu",
"OptionDownloadLogoImage": "Logo",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "Locandina",
"HeaderFetchImages": "Identifica Immagini:",
"HeaderImageSettings": "Impostazioni Immagini",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "Massimo numero di sfondi per oggetto.",
"LabelMaxScreenshotsPerItem": "Massimo numero di foto per oggetto:",
"LabelMinBackdropDownloadWidth": "Massima larghezza sfondo:",
@ -561,10 +578,13 @@
"NotificationOptionVideoPlayback": "Riproduzione video",
"NotificationOptionAudioPlayback": "Riproduzione Audio",
"NotificationOptionGamePlayback": "Riproduzione gioco",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "Fallimento operazione pianificata",
"NotificationOptionInstallationFailed": "errore di installazione",
"NotificationOptionNewLibraryContent": "Nuovo contenuto aggiunto",
"NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
"NotificationOptionNewLibraryContentMultiple": "Nuovi contenuti aggiunti",
"SendNotificationHelp": "Per impostazione predefinita, le notifiche vengono consegnate al cruscotto della Posta in arrivo . Sfoglia il catalogo plugin da installare opzioni di notifica aggiuntive.",
"NotificationOptionServerRestartRequired": "Riavvio del server necessaria",
"LabelNotificationEnabled": "Abilita questa notifica",
@ -588,6 +608,7 @@
"ButtonArrowRight": "Destra",
"ButtonBack": "Indietro",
"ButtonInfo": "Info",
"ButtonOsd": "Su Schermo",
"ButtonPageUp": "Pagina Su",
"ButtonPageDown": "Pagina Gi\u00f9",
"PageAbbreviation": "PG",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "Diminuisci volume",
"ButtonMute": "Muto",
"HeaderLatestMedia": "Ultimi Media",
"OptionNoSubtitles": "Nessun Sottotitolo",
"OptionSpecialFeatures": "caratteristiche Speciali",
"HeaderCollections": "Collezioni",
"HeaderMyLibrary": "Mia Libereria",
@ -697,19 +717,33 @@
"OptionEstimateContentLength": "Stimare la lunghezza contenuto quando transcodifica",
"OptionReportByteRangeSeekingWhenTranscoding": "Segnala che il server supporta la ricerca di byte quando transcodifica",
"OptionReportByteRangeSeekingWhenTranscodingHelp": "Questo \u00e8 necessario per alcuni dispositivi che il tempo non cercano molto bene.",
"HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
"HeaderDownloadSubtitlesFor": "Download subtitles for:",
"LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
"LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
"TabSubtitles": "Subtitles",
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
"LabelDownloadLanguages": "Download languages:",
"ButtonRegister": "Register",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
"HeaderSendMessage": "Send Message",
"ButtonSend": "Send",
"LabelMessageText": "Message text:"
"HeaderSubtitleDownloadingHelp": "Quando Media Browser esegue la scansione dei file video \u00e8 possibile cercare i sottotitoli mancanti, e scaricarli utilizzando un provider sottotitolo come OpenSubtitles.org.",
"HeaderDownloadSubtitlesFor": "Scarica sottotitoli per:",
"LabelSkipIfGraphicalSubsPresent": "Salta se il video contiene gi\u00e0 i sottotitoli grafici",
"LabelSkipIfGraphicalSubsPresentHelp": "Mantenere le versioni del testo di sottotitoli si tradurr\u00e0 in consegna pi\u00f9 efficiente ai clienti di telefonia mobile.",
"TabSubtitles": "sottotitoli",
"LabelOpenSubtitlesUsername": "Sottotitoli utente:",
"LabelOpenSubtitlesPassword": "Sottotitoli password:",
"LabelPlayDefaultAudioTrack": "Riprodurre la traccia audio di default indipendentemente dalla lingua",
"LabelSubtitlePlaybackMode": "Modalit\u00e0 Sottotitolo:",
"LabelDownloadLanguages": "Scarica lingue:",
"ButtonRegister": "registro",
"LabelSkipIfAudioTrackPresent": "Ignora se la traccia audio di default corrisponde alla lingua di download",
"LabelSkipIfAudioTrackPresentHelp": "Deselezionare questa opzione per assicurare che tutti i video hanno i sottotitoli, a prescindere dalla lingua audio.",
"HeaderSendMessage": "Invia un messaggio",
"ButtonSend": "Invia",
"LabelMessageText": "Testo del messaggio:",
"MessageNoAvailablePlugins": "Nessun plugin disponibili.",
"LabelDisplayPluginsFor": "Mostra plugin per:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Altri",
"LabelEpisodeName": "Episode name",
"LabelSeriesName": "Nome serie",
"ValueSeriesNamePeriod": "Nome Serie",
"ValueSeriesNameUnderscore": "Nome Serie",
"ValueEpisodeNamePeriod": "Nome Episodio",
"ValueEpisodeNameUnderscore": "Nome Episodio",
"HeaderTypeText": "Inserisci il testo",
"LabelTypeText": "Testo"
}

@ -63,7 +63,14 @@
"HeaderPlaybackSettings": "\u041e\u0439\u043d\u0430\u0442\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456",
"LabelAudioLanguagePreference": "\u0414\u044b\u0431\u044b\u0441 \u0442\u0456\u043b\u0456\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:",
"LabelSubtitleLanguagePreference": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440 \u0442\u0456\u043b\u0456\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:",
"LabelDisplayForcedSubtitlesOnly": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u043c\u04d9\u0436\u0431\u04af\u0440\u043b\u0456 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
"OptionDefaultSubtitles": "Default",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
"OptionNoSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 \u0436\u043e\u049b",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
"TabProfiles": "\u041f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0435\u0440",
"TabSecurity": "\u049a\u0430\u0443\u0456\u043f\u0441\u0456\u0437\u0434\u0456\u043a",
"ButtonAddUser": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b \u04af\u0441\u0442\u0435\u0443",
@ -161,6 +168,10 @@
"OptionIso": "ISO",
"Option3D": "3D",
"LabelFeatures": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430\u043b\u0430\u0440:",
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
"LabelLastResult": "Last result:",
"OptionHasSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440",
"OptionHasTrailer": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440",
"OptionHasThemeSong": "\u0422\u0430\u049b\u044b\u0440\u044b\u043f \u04d9\u043d\u0456",
@ -224,6 +235,8 @@
"ButtonSearch": "\u0406\u0437\u0434\u0435\u0443",
"ButtonGroupVersions": "\u041d\u04b1\u0441\u049b\u0430\u043b\u0430\u0440\u0434\u044b \u0442\u043e\u043f\u0442\u0430\u0443",
"PismoMessage": "\u0421\u044b\u0439\u043b\u0430\u043d\u0493\u0430\u043d \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044f \u0430\u0440\u049b\u044b\u043b\u044b Pismo File Mount \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0434\u0430.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "\u0411\u0456\u0437 \u049b\u043e\u043b\u0434\u0430\u043d\u0430\u0442\u044b\u043d \u0431\u0430\u0441\u049b\u0430 \u0430\u0448\u044b\u049b \u04e9\u043d\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u049b\u043e\u043b\u0434\u0430\u04a3\u044b\u0437:",
"VersionNumber": "\u041d\u04b1\u0441\u049b\u0430\u0441\u044b: {0}",
"TabPaths": "\u0416\u043e\u043b\u0434\u0430\u0440",
@ -281,10 +294,13 @@
"PasswordLocalhostMessage": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 (localhost) \u043e\u0440\u044b\u043d\u0434\u0430\u043d \u043a\u0456\u0440\u0433\u0435\u043d\u0434\u0435 \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0435\u0440 \u049b\u0430\u0436\u0435\u0442 \u0435\u043c\u0435\u0441.",
"TabGuide": "\u0422\u0414 \u043a\u0435\u0441\u0442\u0435\u0441\u0456",
"TabChannels": "\u0422\u0435\u043b\u0435\u0430\u0440\u043d\u0430\u043b\u0430\u0440",
"TabCollections": "Collections",
"HeaderChannels": "\u0422\u0435\u043b\u0435\u0430\u0440\u043d\u0430\u043b\u0430\u0440",
"TabRecordings": "\u0416\u0430\u0437\u0431\u0430\u043b\u0430\u0440",
"TabScheduled": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d",
"TabSeries": "\u0421\u0435\u0440\u0438\u0430\u043b",
"TabFavorites": "Favorites",
"TabMyLibrary": "My Library",
"ButtonCancelRecording": "\u0416\u0430\u0437\u0443\u0434\u044b \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443",
"HeaderPrePostPadding": "\u0410\u043b\u0493\u0430\/\u0410\u0440\u0442\u049b\u0430 \u0448\u0435\u0433\u0456\u043d\u0456\u0441",
"LabelPrePaddingMinutes": "\u0410\u043b\u0493\u0430 \u0448\u0435\u0433\u0456\u043d\u0456\u0441, \u043c\u0438\u043d:",
@ -319,7 +335,7 @@
"OptionAutomatic": "\u0410\u0432\u0442\u043e\u0442\u0430\u04a3\u0434\u0430\u0443",
"LiveTvPluginRequired": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u044d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414 \u049b\u044b\u0437\u043c\u0435\u0442\u0456\u043d \u0436\u0435\u0442\u043a\u0456\u0437\u0443\u0448\u0456\u0441\u0456 \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0456 \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437.",
"LiveTvPluginRequiredHelp": "\u0411\u0456\u0437\u0434\u0456\u04a3 \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 (Next Pvr \u043d\u0435 ServerWmc \u0441\u0438\u044f\u049b\u0442\u044b) \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440\u0434\u0456\u04a3 \u0431\u0456\u0440\u0435\u0443\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437.",
"HeaderCustomizeOptionsPerMediaType": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u0442\u0430\u0441\u0443\u0448\u044b \u0442\u04af\u0440\u0456 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0442\u0435\u04a3\u0448\u0435\u0443",
"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
"OptionDownloadThumbImage": "\u041d\u043e\u0431\u0430\u0439",
"OptionDownloadMenuImage": "\u041c\u04d9\u0437\u0456\u0440",
"OptionDownloadLogoImage": "\u041b\u043e\u0433\u043e\u0442\u0438\u043f",
@ -331,6 +347,7 @@
"OptionDownloadPrimaryImage": "\u0411\u0430\u0441\u0442\u0430\u043f\u049b\u044b",
"HeaderFetchImages": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0448\u044b\u0493\u0430\u0440\u044b\u043f \u0430\u043b\u0443:",
"HeaderImageSettings": "\u0421\u0443\u0440\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456",
"TabOther": "Other",
"LabelMaxBackdropsPerItem": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0430\u0440\u0442\u049b\u044b \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456\u04a3 \u0435\u04a3 \u043a\u04e9\u043f \u0441\u0430\u043d\u044b:",
"LabelMaxScreenshotsPerItem": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0435\u04a3 \u043a\u04e9\u043f \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0441\u0430\u043d\u044b:",
"LabelMinBackdropDownloadWidth": "\u0410\u0440\u0442\u049b\u044b \u0441\u0443\u0440\u0435\u0442\u0442\u0456\u04a3 \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0430\u0442\u044b\u043d \u0435\u04a3 \u0430\u0437 \u0435\u043d\u0456:",
@ -561,6 +578,9 @@
"NotificationOptionVideoPlayback": "\u0411\u0435\u0439\u043d\u0435 \u043e\u0439\u043d\u0430\u0442\u0443",
"NotificationOptionAudioPlayback": "\u0414\u044b\u0431\u044b\u0441 \u043e\u0439\u043d\u0430\u0442\u0443",
"NotificationOptionGamePlayback": "\u041e\u0439\u044b\u043d \u043e\u0439\u043d\u0430\u0442\u0443",
"NotificationOptionVideoPlaybackStopped": "Video playback stopped",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionGamePlaybackStopped": "Game playback stopped",
"NotificationOptionTaskFailed": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0441\u04d9\u0442\u0441\u0456\u0437\u0434\u0456\u0433\u0456",
"NotificationOptionInstallationFailed": "\u041e\u0440\u043d\u0430\u0442\u0443 \u0441\u04d9\u0442\u0441\u0456\u0437\u0434\u0456\u0433\u0456",
"NotificationOptionNewLibraryContent": "\u0416\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d",
@ -588,6 +608,7 @@
"ButtonArrowRight": "\u041e\u04a3 \u0436\u0430\u049b\u049b\u0430",
"ButtonBack": "\u0410\u0440\u0442\u049b\u0430",
"ButtonInfo": "\u0410\u049b\u043f\u0430\u0440\u0430\u0442",
"ButtonOsd": "On screen display",
"ButtonPageUp": "\u0416\u043e\u0493\u0430\u0440\u0493\u044b \u0431\u0435\u0442\u043a\u0435",
"ButtonPageDown": "\u0422\u04e9\u043c\u0435\u043d\u0433\u0456 \u0431\u0435\u0442\u043a\u0435",
"PageAbbreviation": "PG",
@ -616,7 +637,6 @@
"ButtonVolumeDown": "\u04ae\u043d\u0434\u0456\u043b\u0456\u043a\u0442\u0456 \u0442\u04e9\u043c\u0435\u043d\u0434\u0435\u0442\u0443",
"ButtonMute": "\u0414\u044b\u0431\u044b\u0441\u0442\u044b \u04e9\u0448\u0456\u0440\u0443",
"HeaderLatestMedia": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0442\u0430\u0441\u0443\u0448\u044b\u043b\u0430\u0440",
"OptionNoSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 \u0436\u043e\u049b",
"OptionSpecialFeatures": "\u0410\u0440\u043d\u0430\u0439\u044b \u049b\u043e\u0441\u044b\u043c\u0448\u0430\u043b\u0430\u0440",
"HeaderCollections": "Collections",
"HeaderMyLibrary": "My Library",
@ -704,12 +724,26 @@
"TabSubtitles": "Subtitles",
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Download languages:",
"ButtonRegister": "Register",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
"HeaderSendMessage": "Send Message",
"ButtonSend": "Send",
"LabelMessageText": "Message text:"
"LabelMessageText": "Message text:",
"MessageNoAvailablePlugins": "No available plugins.",
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
"TabOtherPlugins": "Others",
"LabelEpisodeName": "Episode name",
"LabelSeriesName": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text"
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save