add latest translations

pull/702/head
Luke Pulverenti 10 years ago
parent dcf2e70f03
commit 0200911afc

@ -328,7 +328,8 @@ namespace MediaBrowser.Api.Playback
{
var param = string.Empty;
var hasFixedResolution = state.VideoRequest.HasFixedResolution;
var isVc1 = state.VideoStream != null &&
string.Equals(state.VideoStream.Codec, "vc1", StringComparison.OrdinalIgnoreCase);
var qualitySetting = GetQualitySetting();
@ -364,24 +365,36 @@ namespace MediaBrowser.Api.Playback
// webm
else if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase))
{
// http://www.webmproject.org/docs/encoder-parameters/
param = "-speed 16 -quality good -profile:v 0 -slices 8";
// Values 0-3, 0 being highest quality but slower
var profileScore = 0;
string crf;
if (!hasFixedResolution)
switch (qualitySetting)
{
switch (qualitySetting)
{
case EncodingQuality.HighSpeed:
param += " -crf 18";
break;
case EncodingQuality.HighQuality:
param += " -crf 10";
break;
case EncodingQuality.MaxQuality:
param += " -crf 4";
break;
}
case EncodingQuality.HighSpeed:
crf = "18";
profileScore++;
break;
case EncodingQuality.HighQuality:
crf = "10";
break;
case EncodingQuality.MaxQuality:
crf = "4";
break;
default:
throw new ArgumentException("Unrecognized quality setting");
}
if (isVc1)
{
profileScore++;
}
// http://www.webmproject.org/docs/encoder-parameters/
param = string.Format("-speed 16 -quality good -profile:v {0} -slices 8 -crf {1}",
profileScore.ToString(UsCulture),
crf);
}
else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase))

@ -231,8 +231,8 @@ namespace MediaBrowser.Api
[ApiMember(Name = "PlayableMediaTypes", Description = "A list of playable media types, comma delimited. Audio, Video, Book, Game, Photo.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public string PlayableMediaTypes { get; set; }
[ApiMember(Name = "SupportsFullscreenToggle", Description = "Whether or not the session supports fullscreen toggle", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
public bool SupportsFullscreenToggle { get; set; }
[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; }
}
/// <summary>
@ -425,9 +425,9 @@ namespace MediaBrowser.Api
{
_sessionManager.ReportCapabilities(request.Id, new SessionCapabilities
{
PlayableMediaTypes = request.PlayableMediaTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries),
PlayableMediaTypes = request.PlayableMediaTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
SupportsFullscreenToggle = request.SupportsFullscreenToggle
SupportedCommands = request.SupportedCommands.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList()
});
}

@ -25,6 +25,7 @@ namespace MediaBrowser.Controller.Session
};
AdditionalUsers = new List<SessionUserInfo>();
SupportedCommands = new List<string>();
}
public List<SessionUserInfo> AdditionalUsers { get; set; }
@ -168,23 +169,11 @@ namespace MediaBrowser.Controller.Session
public ISessionController SessionController { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [supports fullscreen toggle].
/// Gets or sets the supported commands.
/// </summary>
/// <value><c>true</c> if [supports fullscreen toggle]; otherwise, <c>false</c>.</value>
public bool SupportsFullscreenToggle { get; set; }
/// <value>The supported commands.</value>
public List<string> SupportedCommands { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [supports osd toggle].
/// </summary>
/// <value><c>true</c> if [supports osd toggle]; otherwise, <c>false</c>.</value>
public bool SupportsOsdToggle { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [supports navigation commands].
/// </summary>
/// <value><c>true</c> if [supports navigation commands]; otherwise, <c>false</c>.</value>
public bool SupportsNavigationControl { get; set; }
/// <summary>
/// Gets a value indicating whether this instance is active.
/// </summary>

@ -146,7 +146,7 @@ namespace MediaBrowser.Dlna.PlayTo
}, _tokenSource.Token, TaskCreationOptions.LongRunning);
}
private void TryCreateController(IDictionary<string,string> headers)
private void TryCreateController(IDictionary<string, string> headers)
{
string location;
@ -244,9 +244,16 @@ namespace MediaBrowser.Dlna.PlayTo
_sessionManager.ReportCapabilities(sessionInfo.Id, new SessionCapabilities
{
PlayableMediaTypes = profile.GetSupportedMediaTypes().ToArray(),
PlayableMediaTypes = profile.GetSupportedMediaTypes(),
SupportsFullscreenToggle = false
SupportedCommands = new List<string>
{
GeneralCommandType.VolumeDown.ToString(),
GeneralCommandType.VolumeUp.ToString(),
GeneralCommandType.Mute.ToString(),
GeneralCommandType.Unmute.ToString(),
GeneralCommandType.ToggleMute.ToString()
}
});
_logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);

@ -209,7 +209,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
if (isWebm)
{
return Math.Max(Environment.ProcessorCount - 1, 1);
return Math.Max(Environment.ProcessorCount - 1, 2);
}
return 0;
@ -224,9 +224,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
case EncodingQuality.HighSpeed:
return 2;
case EncodingQuality.HighQuality:
return isWebm ? Math.Max(Environment.ProcessorCount - 1, 1) : 0;
return isWebm ? Math.Max(Environment.ProcessorCount - 1, 2) : 0;
case EncodingQuality.MaxQuality:
return isWebm ? Math.Max(Environment.ProcessorCount - 1, 1) : 0;
return isWebm ? Math.Max(Environment.ProcessorCount - 1, 2) : 0;
default:
throw new Exception("Unrecognized MediaEncodingQuality value.");
}

@ -1,10 +1,9 @@
using System;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using MediaBrowser.Model.Dto;
using System.Collections.Generic;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Model.Dlna
{
@ -453,19 +452,19 @@ namespace MediaBrowser.Model.Dlna
if (actualValue.HasValue)
{
long expected;
if (long.TryParse(condition.Value, NumberStyles.Any, _usCulture, out expected))
double expected;
if (double.TryParse(condition.Value, NumberStyles.Any, _usCulture, out expected))
{
switch (condition.Condition)
{
case ProfileConditionType.Equals:
return actualValue.Value == expected;
return actualValue.Value.Equals(expected);
case ProfileConditionType.GreaterThanEqual:
return actualValue.Value >= expected;
case ProfileConditionType.LessThanEqual:
return actualValue.Value <= expected;
case ProfileConditionType.NotEquals:
return actualValue.Value != expected;
return !actualValue.Value.Equals(expected);
default:
throw new InvalidOperationException("Unexpected ProfileConditionType");
}
@ -486,7 +485,7 @@ namespace MediaBrowser.Model.Dlna
/// <param name="audioStream">The audio stream.</param>
/// <returns>System.Nullable{System.Int64}.</returns>
/// <exception cref="System.InvalidOperationException">Unexpected Property</exception>
private long? GetConditionValue(ProfileCondition condition, string mediaPath, MediaStream videoStream, MediaStream audioStream)
private double? GetConditionValue(ProfileCondition condition, string mediaPath, MediaStream videoStream, MediaStream audioStream)
{
switch (condition.Property)
{
@ -497,37 +496,17 @@ namespace MediaBrowser.Model.Dlna
case ProfileConditionValue.VideoBitrate:
return videoStream == null ? null : videoStream.BitRate;
case ProfileConditionValue.VideoFramerate:
return videoStream == null ? null : (ConvertToLong(videoStream.AverageFrameRate ?? videoStream.RealFrameRate));
return videoStream == null ? null : (videoStream.AverageFrameRate ?? videoStream.RealFrameRate);
case ProfileConditionValue.Height:
return videoStream == null ? null : videoStream.Height;
case ProfileConditionValue.Width:
return videoStream == null ? null : videoStream.Width;
case ProfileConditionValue.VideoLevel:
return videoStream == null ? null : ConvertToLong(videoStream.Level);
return videoStream == null ? null : videoStream.Level;
default:
throw new InvalidOperationException("Unexpected Property");
}
}
/// <summary>
/// Converts to long.
/// </summary>
/// <param name="val">The value.</param>
/// <returns>System.Nullable{System.Int64}.</returns>
private long? ConvertToLong(float? val)
{
return val.HasValue ? Convert.ToInt64(val.Value) : (long?)null;
}
/// <summary>
/// Converts to long.
/// </summary>
/// <param name="val">The value.</param>
/// <returns>System.Nullable{System.Int64}.</returns>
private long? ConvertToLong(double? val)
{
return val.HasValue ? Convert.ToInt64(val.Value) : (long?)null;
}
}
}

@ -1,19 +1,17 @@

using System.Collections.Generic;
namespace MediaBrowser.Model.Session
{
public class SessionCapabilities
{
public string[] PlayableMediaTypes { get; set; }
public bool SupportsFullscreenToggle { get; set; }
public List<string> PlayableMediaTypes { get; set; }
public bool SupportsOsdToggle { get; set; }
public List<string> SupportedCommands { get; set; }
public bool SupportsNavigationControl { get; set; }
public SessionCapabilities()
{
PlayableMediaTypes = new string[] {};
PlayableMediaTypes = new List<string>();
SupportedCommands = new List<string>();
}
}
}

@ -15,6 +15,12 @@ namespace MediaBrowser.Model.Session
/// <value><c>true</c> if this instance can seek; otherwise, <c>false</c>.</value>
public bool CanSeek { get; set; }
/// <summary>
/// Gets or sets the supported commands.
/// </summary>
/// <value>The supported commands.</value>
public List<string> SupportedCommands { get; set; }
/// <summary>
/// Gets or sets the remote end point.
/// </summary>
@ -167,6 +173,7 @@ namespace MediaBrowser.Model.Session
PlayableMediaTypes = new List<string>();
QueueableMediaTypes = new List<string>();
SupportedCommands = new List<string>();
}
}

@ -196,6 +196,7 @@
<Compile Include="TV\MissingEpisodeProvider.cs" />
<Compile Include="TV\MovieDbSeriesImageProvider.cs" />
<Compile Include="TV\MovieDbSeriesProvider.cs" />
<Compile Include="TV\SeasonXmlParser.cs" />
<Compile Include="TV\SeriesMetadataService.cs" />
<Compile Include="TV\TvdbEpisodeImageProvider.cs" />
<Compile Include="People\TvdbPersonImageProvider.cs" />

@ -2,7 +2,6 @@
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Globalization;
using System.IO;

@ -1,9 +1,10 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security;
using System.Text;
using System.Threading;
@ -32,9 +33,16 @@ namespace MediaBrowser.Providers.Savers
return false;
}
return item is Season && updateType >= ItemUpdateType.MetadataDownload;
if (!(item is Season))
{
return false;
}
return updateType >= ItemUpdateType.MetadataDownload || (updateType >= ItemUpdateType.MetadataImport && File.Exists(GetSavePath(item)));
}
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
/// <summary>
/// Saves the specified item.
/// </summary>
@ -47,13 +55,23 @@ namespace MediaBrowser.Providers.Savers
builder.Append("<Item>");
var season = (Season)item;
if (season.IndexNumber.HasValue)
{
builder.Append("<SeasonNumber>" + SecurityElement.Escape(season.IndexNumber.Value.ToString(_usCulture)) + "</SeasonNumber>");
}
XmlSaverHelpers.AddCommonNodes((Season)item, builder);
builder.Append("</Item>");
var xmlFilePath = GetSavePath(item);
XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> { });
XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
{
"SeasonNumber"
});
}
/// <summary>

@ -0,0 +1,46 @@
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using System.Xml;
namespace MediaBrowser.Providers.TV
{
public class SeasonXmlParser : BaseItemXmlParser<Season>
{
public SeasonXmlParser(ILogger logger)
: base(logger)
{
}
/// <summary>
/// Fetches the data from XML node.
/// </summary>
/// <param name="reader">The reader.</param>
/// <param name="item">The item.</param>
protected override void FetchDataFromXmlNode(XmlReader reader, Season item)
{
switch (reader.Name)
{
case "SeasonNumber":
{
var number = reader.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(number))
{
int num;
if (int.TryParse(number, out num))
{
item.IndexNumber = num;
}
}
break;
}
default:
base.FetchDataFromXmlNode(reader, item);
break;
}
}
}
}

@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.TV
protected override void Fetch(LocalMetadataResult<Season> result, string path, CancellationToken cancellationToken)
{
new BaseItemXmlParser<Season>(_logger).Fetch(result.Item, path, cancellationToken);
new SeasonXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
}
protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)

@ -268,9 +268,7 @@ namespace MediaBrowser.Server.Implementations.Dto
PlayableMediaTypes = session.PlayableMediaTypes,
RemoteEndPoint = session.RemoteEndPoint,
AdditionalUsers = session.AdditionalUsers,
SupportsFullscreenToggle = session.SupportsFullscreenToggle,
SupportsNavigationControl = session.SupportsNavigationControl,
SupportsOsdToggle = session.SupportsOsdToggle
SupportedCommands = session.SupportedCommands
};
if (session.NowPlayingItem != null)
@ -1347,7 +1345,7 @@ namespace MediaBrowser.Server.Implementations.Dto
{
var mediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList();
return new MediaSourceInfo
var info = new MediaSourceInfo
{
Id = i.Id.ToString("N"),
IsoType = i.IsoType,
@ -1359,11 +1357,22 @@ namespace MediaBrowser.Server.Implementations.Dto
Video3DFormat = i.Video3DFormat,
VideoType = i.VideoType
};
if (i.VideoType == VideoType.VideoFile || i.VideoType == VideoType.Iso)
{
var locationType = i.LocationType;
if (!string.IsNullOrWhiteSpace(i.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual)
{
info.Container = Path.GetExtension(i.Path).TrimStart('.');
}
}
return info;
}
private MediaSourceInfo GetVersionInfo(Audio i)
{
return new MediaSourceInfo
var info = new MediaSourceInfo
{
Id = i.Id.ToString("N"),
LocationType = i.LocationType,
@ -1372,6 +1381,14 @@ namespace MediaBrowser.Server.Implementations.Dto
Path = GetMappedPath(i),
RunTimeTicks = i.RunTimeTicks
};
var locationType = i.LocationType;
if (!string.IsNullOrWhiteSpace(i.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual)
{
info.Container = Path.GetExtension(i.Path).TrimStart('.');
}
return info;
}
private string GetMappedPath(IHasMetadata item)

@ -417,6 +417,11 @@ namespace MediaBrowser.Server.Implementations.IO
_affectedPaths.AddOrUpdate(path, path, (key, oldValue) => affectedPath);
}
RestartTimer();
}
private void RestartTimer()
{
lock (_timerLock)
{
if (_updateTimer == null)
@ -436,6 +441,14 @@ namespace MediaBrowser.Server.Implementations.IO
/// <param name="stateInfo">The state info.</param>
private async void TimerStopped(object stateInfo)
{
// Extend the timer as long as any of the paths are still being written to.
if (_affectedPaths.Any(p => IsFileLocked(p.Key)))
{
Logger.Info("Timer extended.");
RestartTimer();
return;
}
Logger.Debug("Timer stopped.");
DisposeTimer();
@ -453,6 +466,70 @@ namespace MediaBrowser.Server.Implementations.IO
}
}
private bool IsFileLocked(string path)
{
try
{
var data = _fileSystem.GetFileSystemInfo(path);
if (!data.Exists
|| data.Attributes.HasFlag(FileAttributes.Directory)
// Opening a writable stream will fail with readonly files
|| data.Attributes.HasFlag(FileAttributes.ReadOnly))
{
return false;
}
}
catch (IOException)
{
return false;
}
catch (Exception ex)
{
Logger.ErrorException("Error getting file system info for: {0}", ex, path);
return false;
}
try
{
using (_fileSystem.GetFileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
if (_updateTimer != null)
{
//file is not locked
return false;
}
}
}
catch (DirectoryNotFoundException)
{
// File may have been deleted
return false;
}
catch (FileNotFoundException)
{
// File may have been deleted
return false;
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
Logger.Debug("{0} is locked.", path);
return true;
}
catch (Exception ex)
{
Logger.ErrorException("Error determining if file is locked: {0}", ex, path);
return false;
}
return false;
}
private void DisposeTimer()
{
lock (_timerLock)

@ -0,0 +1 @@
{"SettingsSaved":"Configuraci\u00f3n guardada.","AddUser":"Agregar usuario","Users":"Usuarios","Delete":"Eliminar","Administrator":"Administrador","Password":"Contrase\u00f1a","DeleteImage":"Eliminar imagen","DeleteImageConfirmation":"\u00bfEst\u00e1 seguro que desea eliminar esta imagen?","FileReadCancelled":"La lectura del archivo ha sido cancelada.","FileNotFound":"Archivo no encontrado.","FileReadError":"Ha ocurrido un error al leer el archivo.","DeleteUser":"Eliminar Usuario","DeleteUserConfirmation":"\u00bfEsta seguro que desea eliminar a {0}?","PasswordResetHeader":"Restablecer Contrase\u00f1a","PasswordResetComplete":"La contrase\u00f1a ha sido restablecida.","PasswordResetConfirmation":"\u00bfEst\u00e1 seguro que desea restablecer la contrase\u00f1a?","PasswordSaved":"Contrase\u00f1a guardada.","PasswordMatchError":"La Contrase\u00f1a y la confirmaci\u00f3n de la contrase\u00f1a deben coincidir.","OptionOff":"Apagado","OptionOn":"Encendido","OptionRelease":"Liberar","OptionBeta":"Beta","OptionDev":"Desarrollo","UninstallPluginHeader":"Desinstalar Complemento","UninstallPluginConfirmation":"\u00bfEst\u00e1 seguro que desea desinstalar {0}?","NoPluginConfigurationMessage":"El complemento no requiere configuraci\u00f3n","NoPluginsInstalledMessage":"No tiene complementos instalados.","BrowsePluginCatalogMessage":"Navege en el catalogo de complementos para ver los complementos disponibles."}

@ -1 +1 @@
{"SettingsSaved":"Configura\u00e7\u00f5es guardadas.","AddUser":"Adicionar Utilizador","Users":"Utilizadores","Delete":"Apagar","Administrator":"Administrador","Password":"Senha","DeleteImage":"Apagar Imagem","DeleteImageConfirmation":"Tem a certeza que pretende apagar a imagem?","FileReadCancelled":"A leitura do ficheiro foi cancelada.","FileNotFound":"Ficheiro n\u00e3o encontrado","FileReadError":"Ocorreu um erro ao ler o ficheiro.","DeleteUser":"Apagar Utilizador","DeleteUserConfirmation":"Tem a certeza que pretende apagar {0}?","PasswordResetHeader":"Redefinir Senha","PasswordResetComplete":"A senha foi redefinida.","PasswordResetConfirmation":"Tem a certeza que pretende redefinir a senha?","PasswordSaved":"Senha guardada.","PasswordMatchError":"A senha e a confirma\u00e7\u00e3o da senha devem coincidir.","OptionOff":"Desligado","OptionOn":"Ligado","OptionRelease":"Final","OptionBeta":"Beta","OptionDev":"Dev","UninstallPluginHeader":"Desinstalar extens\u00e3o","UninstallPluginConfirmation":"Tem a certeza que pretende desinstalar {0}?","NoPluginConfigurationMessage":"Esta extens\u00e3o n\u00e3o \u00e9 configur\u00e1vel.","NoPluginsInstalledMessage":"N\u00e3o tem extens\u00f5es instaladas.","BrowsePluginCatalogMessage":"Navegue o nosso cat\u00e1logo de extens\u00f5es para ver as extens\u00f5es dispon\u00edveis."}
{"SettingsSaved":"Configura\u00e7\u00f5es guardadas.","AddUser":"Adicionar Utilizador","Users":"Utilizadores","Delete":"Apagar","Administrator":"Administrador","Password":"Senha","DeleteImage":"Apagar Imagem","DeleteImageConfirmation":"Tem a certeza que pretende apagar a imagem?","FileReadCancelled":"A leitura do ficheiro foi cancelada.","FileNotFound":"Ficheiro n\u00e3o encontrado","FileReadError":"Ocorreu um erro ao ler o ficheiro.","DeleteUser":"Apagar Utilizador","DeleteUserConfirmation":"Tem a certeza que pretende apagar {0}?","PasswordResetHeader":"Redefinir Senha","PasswordResetComplete":"A senha foi redefinida.","PasswordResetConfirmation":"Tem a certeza que deseja redefinir a senha?","PasswordSaved":"Senha guardada.","PasswordMatchError":"A senha e a confirma\u00e7\u00e3o da senha devem coincidir.","OptionOff":"Desligado","OptionOn":"Ligado","OptionRelease":"Final","OptionBeta":"Beta","OptionDev":"Dev","UninstallPluginHeader":"Desinstalar extens\u00e3o","UninstallPluginConfirmation":"Tem a certeza que pretende desinstalar {0}?","NoPluginConfigurationMessage":"Esta extens\u00e3o n\u00e3o \u00e9 configur\u00e1vel.","NoPluginsInstalledMessage":"N\u00e3o tem extens\u00f5es instaladas.","BrowsePluginCatalogMessage":"Navegue o nosso cat\u00e1logo de extens\u00f5es, para ver as extens\u00f5es dispon\u00edveis."}

@ -1 +1 @@
{"SettingsSaved":"\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b","AddUser":"\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f","Users":"\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438","Delete":"\u0423\u0434\u0430\u043b\u0438\u0442\u044c","Administrator":"\u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440","Password":"\u041f\u0430\u0440\u043e\u043b\u044c","DeleteImage":"\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435","DeleteImageConfirmation":"\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u0442\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435?","FileReadCancelled":"\u0427\u0442\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0431\u044b\u043b\u043e \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u043e","FileNotFound":"\u0424\u0430\u0439\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d","FileReadError":"\u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430","DeleteUser":"\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f","DeleteUserConfirmation":"\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c {0}?","PasswordResetHeader":"\u0421\u0431\u0440\u043e\u0441 \u043f\u0430\u0440\u043e\u043b\u044f","PasswordResetComplete":"\u041f\u0430\u0440\u043e\u043b\u044c \u0431\u044b\u043b \u0441\u0431\u0440\u043e\u0448\u0435\u043d","PasswordResetConfirmation":"\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0441\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c?","PasswordSaved":"\u041f\u0430\u0440\u043e\u043b\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d","PasswordMatchError":"\u041f\u043e\u043b\u044f \u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u043e\u043b\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c","OptionOff":"\u0412\u044b\u043a\u043b.","OptionOn":"\u0412\u043a\u043b.","OptionRelease":"\u0412\u044b\u043f\u0443\u0441\u043a","OptionBeta":"\u0411\u0435\u0442\u0430","OptionDev":"\u0420\u0430\u0437\u0440\u0430\u0431.","UninstallPluginHeader":"\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d","UninstallPluginConfirmation":"\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c {0}?","NoPluginConfigurationMessage":"\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043d\u0435\u0447\u0435\u0433\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c.","NoPluginsInstalledMessage":"\u0423 \u0412\u0430\u0441 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430.","BrowsePluginCatalogMessage":"\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u043d\u0430\u0448\u0438\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u043c \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432."}
{"SettingsSaved":"\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b","AddUser":"\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f","Users":"\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438","Delete":"\u0423\u0434\u0430\u043b\u0438\u0442\u044c","Administrator":"\u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440","Password":"\u041f\u0430\u0440\u043e\u043b\u044c","DeleteImage":"\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435","DeleteImageConfirmation":"\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u044d\u0442\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435?","FileReadCancelled":"\u0427\u0442\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0431\u044b\u043b\u043e \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u043e","FileNotFound":"\u0424\u0430\u0439\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d","FileReadError":"\u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430","DeleteUser":"\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f","DeleteUserConfirmation":"\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c {0}?","PasswordResetHeader":"\u0421\u0431\u0440\u043e\u0441 \u043f\u0430\u0440\u043e\u043b\u044f","PasswordResetComplete":"\u041f\u0430\u0440\u043e\u043b\u044c \u0431\u044b\u043b \u0441\u0431\u0440\u043e\u0448\u0435\u043d","PasswordResetConfirmation":"\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0441\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c?","PasswordSaved":"\u041f\u0430\u0440\u043e\u043b\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d","PasswordMatchError":"\u041f\u043e\u043b\u044f \u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u043e\u043b\u044f \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c","OptionOff":"\u0412\u044b\u043a\u043b","OptionOn":"\u0412\u043a\u043b","OptionRelease":"\u0412\u044b\u043f\u0443\u0441\u043a","OptionBeta":"\u0411\u0435\u0442\u0430","OptionDev":"\u0420\u0430\u0437\u0440\u0430\u0431","UninstallPluginHeader":"\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d","UninstallPluginConfirmation":"\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c {0}?","NoPluginConfigurationMessage":"\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043d\u0435\u0447\u0435\u0433\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c.","NoPluginsInstalledMessage":"\u0423 \u0412\u0430\u0441 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430.","BrowsePluginCatalogMessage":"\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u043d\u0430\u0448\u0438\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u043c \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432."}

@ -343,7 +343,8 @@ namespace MediaBrowser.Server.Implementations.Localization
new LocalizatonOption{ Name="Portuguese (Brazil)", Value="pt-BR"},
new LocalizatonOption{ Name="Portuguese (Portugal)", Value="pt-PT"},
new LocalizatonOption{ Name="Russian", Value="ru"},
new LocalizatonOption{ Name="Spanish", Value="es"}
new LocalizatonOption{ Name="Spanish", Value="es"},
new LocalizatonOption{ Name="Spanish (Mexico)", Value="es-MX"}
}.OrderBy(i => i.Name);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -85,5 +85,64 @@
"TabGenres": "Genres",
"TabPeople": "People",
"TabNetworks": "Networks",
"HeaderUsers": "Users"
"HeaderUsers": "Users",
"HeaderFilters": "Filters:",
"ButtonFilter": "Filter",
"OptionFavorite": "Favorites",
"OptionLikes": "Likes",
"OptionDislikes": "Dislikes",
"OptionActors": "Actors",
"OptionGuestStars": "Guest Stars",
"OptionDirectors": "Directors",
"OptionWriters": "Writers",
"OptionProducers": "Producers",
"HeaderResume": "Resume",
"HeaderNextUp": "Next Up",
"NoNextUpItemsMessage": "None found. Start watching your shows!",
"HeaderLatestEpisodes": "Latest Episodes",
"HeaderPersonTypes": "Person Types:",
"TabSongs": "Songs",
"TabAlbums": "Albums",
"TabArtists": "Artists",
"TabAlbumArtists": "Album Artists",
"TabMusicVideos": "Music Videos",
"ButtonSort": "Sort",
"HeaderSortBy": "Sort By:",
"HeaderSortOrder": "Sort Order:",
"OptionPlayed": "Played",
"OptionUnplayed": "Unplayed",
"OptionAscending": "Ascending",
"OptionDescending": "Descending",
"OptionRuntime": "Runtime",
"OptionReleaseDate": "Release Date",
"OptionPlayCount": "Play Count",
"OptionDatePlayed": "Date Played",
"OptionDateAdded": "Date Added",
"OptionAlbumArtist": "Album Artist",
"OptionArtist": "Artist",
"OptionAlbum": "Album",
"OptionTrackName": "Track Name",
"OptionCommunityRating": "Community Rating",
"OptionNameSort": "Name",
"OptionBudget": "Budget",
"OptionRevenue": "Revenue",
"OptionPoster": "Poster",
"OptionTimeline": "Timeline",
"OptionCriticRating": "Critic Rating",
"OptionVideoBitrate": "Video Bitrate",
"OptionResumable": "Resumable",
"ScheduledTasksHelp": "Click a task to adjust it's schedule.",
"ScheduledTasksTitle": "ScheduledTasks",
"TabMyPlugins": "My Plugins",
"TabCatalog": "Catalog",
"TabUpdates": "Updates",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Automatic Updates",
"HeaderUpdateLevel": "Update Level",
"HeaderNowPlaying": "Now Playing",
"HeaderLatestAlbums": "Latest Albums",
"HeaderLatestSongs": "Latest Songs",
"HeaderRecentlyPlayed": "Recently Played",
"HeaderFrequentlyPlayed": "Frequently Played",
"DevBuildWarning": "Dev builds are the bleeding edge. Released often, these build have not been tested. The application may crash and entire features may not work at all."
}

File diff suppressed because one or more lines are too long

@ -305,6 +305,8 @@
<EmbeddedResource Include="Localization\JavaScript\pt_BR.json" />
<EmbeddedResource Include="Localization\Server\he.json" />
<EmbeddedResource Include="Localization\Server\it.json" />
<EmbeddedResource Include="Localization\Server\es_MX.json" />
<EmbeddedResource Include="Localization\JavaScript\es_MX.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>

@ -26,7 +26,6 @@ namespace MediaBrowser.Server.Implementations.Roku
if (string.Equals(session.Client, "roku", StringComparison.OrdinalIgnoreCase))
{
session.PlayableMediaTypes = new List<string> { MediaType.Video, MediaType.Audio };
session.SupportsFullscreenToggle = false;
return new RokuSessionController(_httpClient, _json, _appHost, session);
}

@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// <param name="logger">The logger.</param>
/// <param name="userRepository">The user repository.</param>
/// <param name="libraryManager">The library manager.</param>
public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager)
public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager)
{
_userDataRepository = userDataRepository;
_configurationManager = configurationManager;
@ -88,6 +88,7 @@ namespace MediaBrowser.Server.Implementations.Session
_userRepository = userRepository;
_libraryManager = libraryManager;
_userManager = userManager;
_musicManager = musicManager;
}
/// <summary>
@ -1013,10 +1014,8 @@ namespace MediaBrowser.Server.Implementations.Session
{
var session = GetSession(sessionId);
session.PlayableMediaTypes = capabilities.PlayableMediaTypes.ToList();
session.SupportsFullscreenToggle = capabilities.SupportsFullscreenToggle;
session.SupportsOsdToggle = capabilities.SupportsOsdToggle;
session.SupportsNavigationControl = capabilities.SupportsNavigationControl;
session.PlayableMediaTypes = capabilities.PlayableMediaTypes;
session.SupportedCommands = capabilities.SupportedCommands;
}
}
}

@ -452,6 +452,7 @@ namespace MediaBrowser.ServerApplication
LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager);
RegisterSingleInstance(LibraryManager);
var musicManager = new MusicManager(LibraryManager);
RegisterSingleInstance<IMusicManager>(new MusicManager(LibraryManager));
LibraryMonitor = new LibraryMonitor(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager);
@ -465,7 +466,7 @@ namespace MediaBrowser.ServerApplication
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager);
SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager);
RegisterSingleInstance(SessionManager);
HttpServer = ServerFactory.CreateServer(this, LogManager, "Media Browser", "mediabrowser", "dashboard/index.html");

@ -312,6 +312,7 @@ namespace MediaBrowser.WebDashboard.Api
/// Modifies the HTML by adding common meta tags, css and js.
/// </summary>
/// <param name="sourceStream">The source stream.</param>
/// <param name="localizationCulture">The localization culture.</param>
/// <returns>Task{Stream}.</returns>
private async Task<Stream> ModifyHtml(Stream sourceStream, string localizationCulture)
{
@ -327,7 +328,11 @@ namespace MediaBrowser.WebDashboard.Api
if (!string.IsNullOrWhiteSpace(localizationCulture))
{
var lang = localizationCulture.Split('-').FirstOrDefault();
html = _localization.LocalizeDocument(html, localizationCulture, GetLocalizationToken);
html = html.Replace("<html>", "<html lang=\"" + lang + "\">");
}
try

Loading…
Cancel
Save