Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser into upstream-master
This commit is contained in:
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>
|
||||
|
|
162
MediaBrowser.Api/Library/SubtitleService.cs
Normal file
162
MediaBrowser.Api/Library/SubtitleService.cs
Normal file
|
@ -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 (!state.HasMediaStreams)
|
||||
// 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";
|
||||
}
|
||||
|
||||
// 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,27 +99,6 @@ namespace MediaBrowser.Dlna.Server
|
|||
{
|
||||
var list = new List<StateVariable>();
|
||||
|
||||
list.Add(new StateVariable
|
||||
{
|
||||
Name = "A_ARG_TYPE_SortCriteria",
|
||||
DataType = "string",
|
||||
SendsEvents = false
|
||||
});
|
||||
|
||||
list.Add(new StateVariable
|
||||
{
|
||||
Name = "A_ARG_TYPE_UpdateID",
|
||||
DataType = "ui4",
|
||||
SendsEvents = false
|
||||
});
|
||||
|
||||
list.Add(new StateVariable
|
||||
{
|
||||
Name = "A_ARG_TYPE_SearchCriteria",
|
||||
DataType = "string",
|
||||
SendsEvents = false
|
||||
});
|
||||
|
||||
list.Add(new StateVariable
|
||||
{
|
||||
Name = "A_ARG_TYPE_Filter",
|
||||
|
@ -129,7 +108,7 @@ namespace MediaBrowser.Dlna.Server
|
|||
|
||||
list.Add(new StateVariable
|
||||
{
|
||||
Name = "A_ARG_TYPE_Result",
|
||||
Name = "A_ARG_TYPE_SortCriteria",
|
||||
DataType = "string",
|
||||
SendsEvents = false
|
||||
});
|
||||
|
@ -143,7 +122,21 @@ namespace MediaBrowser.Dlna.Server
|
|||
|
||||
list.Add(new StateVariable
|
||||
{
|
||||
Name = "A_ARG_TYPE_ObjectID",
|
||||
Name = "A_ARG_TYPE_Count",
|
||||
DataType = "ui4",
|
||||
SendsEvents = false
|
||||
});
|
||||
|
||||
list.Add(new StateVariable
|
||||
{
|
||||
Name = "A_ARG_TYPE_UpdateID",
|
||||
DataType = "ui4",
|
||||
SendsEvents = false
|
||||
});
|
||||
|
||||
list.Add(new StateVariable
|
||||
{
|
||||
Name = "SearchCapabilities",
|
||||
DataType = "string",
|
||||
SendsEvents = false
|
||||
});
|
||||
|
@ -157,15 +150,29 @@ namespace MediaBrowser.Dlna.Server
|
|||
|
||||
list.Add(new StateVariable
|
||||
{
|
||||
Name = "SearchCapabilities",
|
||||
Name = "SystemUpdateID",
|
||||
DataType = "ui4",
|
||||
SendsEvents = true
|
||||
});
|
||||
|
||||
list.Add(new StateVariable
|
||||
{
|
||||
Name = "A_ARG_TYPE_SearchCriteria",
|
||||
DataType = "string",
|
||||
SendsEvents = false
|
||||
});
|
||||
|
||||
list.Add(new StateVariable
|
||||
{
|
||||
Name = "A_ARG_TYPE_Count",
|
||||
DataType = "ui4",
|
||||
Name = "A_ARG_TYPE_Result",
|
||||
DataType = "string",
|
||||
SendsEvents = false
|
||||
});
|
||||
|
||||
list.Add(new StateVariable
|
||||
{
|
||||
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);
|
||||
|
||||
if ((_config.Configuration.SubtitleOptions.DownloadEpisodeSubtitles &&
|
||||
var externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, currentStreams.Count, directoryService, false).ToList();
|
||||
|
||||
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;
|
||||
|
|
135
MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
Normal file
135
MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
Normal file
|
@ -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…
Reference in New Issue
Block a user