aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke <luke.pulverenti@gmail.com>2015-04-14 00:43:41 -0400
committerLuke <luke.pulverenti@gmail.com>2015-04-14 00:43:41 -0400
commit935de313d58c7a7ba792345c16cfd1c1aad09a78 (patch)
tree2e9334986de5864b00d4901f031b5de6a970305e
parent71a4f2761e784513ae2f3dda03aa549903808ebb (diff)
parentbd253399c2f1913c544c93fd6927dee37f8add2f (diff)
Merge pull request #1079 from MediaBrowser/dev
3.0.5582.0
-rw-r--r--Emby.Drawing/Common/ImageHeader.cs (renamed from MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs)2
-rw-r--r--Emby.Drawing/Emby.Drawing.csproj98
-rw-r--r--Emby.Drawing/GDI/DynamicImageHelpers.cs138
-rw-r--r--Emby.Drawing/GDI/GDIImageEncoder.cs254
-rw-r--r--Emby.Drawing/GDI/ImageExtensions.cs217
-rw-r--r--Emby.Drawing/GDI/PercentPlayedDrawer.cs34
-rw-r--r--Emby.Drawing/GDI/PlayedIndicatorDrawer.cs32
-rw-r--r--Emby.Drawing/GDI/UnplayedCountIndicator.cs50
-rw-r--r--Emby.Drawing/IImageEncoder.cs53
-rw-r--r--Emby.Drawing/ImageMagick/ImageMagickEncoder.cs229
-rw-r--r--Emby.Drawing/ImageMagick/PercentPlayedDrawer.cs (renamed from MediaBrowser.Server.Implementations/Drawing/PercentPlayedDrawer.cs)2
-rw-r--r--Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs (renamed from MediaBrowser.Server.Implementations/Drawing/PlayedIndicatorDrawer.cs)2
-rw-r--r--Emby.Drawing/ImageMagick/StripCollageBuilder.cs518
-rw-r--r--Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs (renamed from MediaBrowser.Server.Implementations/Drawing/UnplayedCountIndicator.cs)2
-rw-r--r--Emby.Drawing/ImageProcessor.cs (renamed from MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs)153
-rw-r--r--Emby.Drawing/Properties/AssemblyInfo.cs31
-rw-r--r--Emby.Drawing/packages.config4
-rw-r--r--MediaBrowser.Api/ApiEntryPoint.cs187
-rw-r--r--MediaBrowser.Api/BaseApiService.cs10
-rw-r--r--MediaBrowser.Api/ConfigurationService.cs2
-rw-r--r--MediaBrowser.Api/FilterService.cs2
-rw-r--r--MediaBrowser.Api/LiveTv/LiveTvService.cs29
-rw-r--r--MediaBrowser.Api/Movies/MoviesService.cs4
-rw-r--r--MediaBrowser.Api/Music/AlbumsService.cs4
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs113
-rw-r--r--MediaBrowser.Api/Playback/Dash/MpegDashService.cs14
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs33
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs38
-rw-r--r--MediaBrowser.Api/Playback/Hls/VideoHlsService.cs2
-rw-r--r--MediaBrowser.Api/Playback/MediaInfoService.cs51
-rw-r--r--MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs7
-rw-r--r--MediaBrowser.Api/Playback/Progressive/VideoService.cs1
-rw-r--r--MediaBrowser.Api/Playback/TranscodingThrottler.cs2
-rw-r--r--MediaBrowser.Api/Session/SessionsService.cs4
-rw-r--r--MediaBrowser.Api/SimilarItemsHelper.cs2
-rw-r--r--MediaBrowser.Api/Subtitles/SubtitleService.cs4
-rw-r--r--MediaBrowser.Api/Sync/SyncService.cs11
-rw-r--r--MediaBrowser.Api/UserLibrary/ArtistsService.cs4
-rw-r--r--MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs3
-rw-r--r--MediaBrowser.Api/UserLibrary/GameGenresService.cs2
-rw-r--r--MediaBrowser.Api/UserLibrary/GenresService.cs2
-rw-r--r--MediaBrowser.Api/UserLibrary/MusicGenresService.cs2
-rw-r--r--MediaBrowser.Api/UserLibrary/PersonsService.cs2
-rw-r--r--MediaBrowser.Api/UserLibrary/PlaystateService.cs48
-rw-r--r--MediaBrowser.Api/UserLibrary/StudiosService.cs2
-rw-r--r--MediaBrowser.Common.Implementations/BaseApplicationHost.cs13
-rw-r--r--MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs12
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs17
-rw-r--r--MediaBrowser.Controller/Channels/Channel.cs15
-rw-r--r--MediaBrowser.Controller/Channels/ChannelAudioItem.cs8
-rw-r--r--MediaBrowser.Controller/Channels/ChannelFolderItem.cs5
-rw-r--r--MediaBrowser.Controller/Channels/ChannelVideoItem.cs12
-rw-r--r--MediaBrowser.Controller/Drawing/IImageProcessor.cs12
-rw-r--r--MediaBrowser.Controller/Drawing/ImageCollageOptions.cs32
-rw-r--r--MediaBrowser.Controller/Dto/IDtoService.cs8
-rw-r--r--MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs7
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs96
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs20
-rw-r--r--MediaBrowser.Controller/Entities/IHasImages.cs8
-rw-r--r--MediaBrowser.Controller/Entities/LinkedChild.cs3
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs18
-rw-r--r--MediaBrowser.Controller/Entities/PhotoAlbum.cs36
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs85
-rw-r--r--MediaBrowser.Controller/IO/ThrottledStream.cs (renamed from MediaBrowser.Server.Implementations/HttpServer/ThrottledStream.cs)14
-rw-r--r--MediaBrowser.Controller/Library/IMediaSourceManager.cs24
-rw-r--r--MediaBrowser.Controller/Library/NameExtensions.cs41
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs11
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvService.cs7
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj10
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs2
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs8
-rw-r--r--MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs290
-rw-r--r--MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs25
-rw-r--r--MediaBrowser.Controller/Providers/BaseItemXmlParser.cs14
-rw-r--r--MediaBrowser.Controller/Providers/IImageEnhancer.cs3
-rw-r--r--MediaBrowser.Controller/Providers/IProviderManager.cs13
-rw-r--r--MediaBrowser.Controller/Sync/IHasDynamicAccess.cs4
-rw-r--r--MediaBrowser.Controller/Sync/IRemoteSyncProvider.cs10
-rw-r--r--MediaBrowser.Controller/Sync/IServerSyncProvider.cs34
-rw-r--r--MediaBrowser.Controller/Sync/ISyncDataProvider.cs14
-rw-r--r--MediaBrowser.Controller/Sync/ISyncManager.cs14
-rw-r--r--MediaBrowser.Controller/Sync/SyncedFileInfo.cs5
-rw-r--r--MediaBrowser.Controller/packages.config1
-rw-r--r--MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs8
-rw-r--r--MediaBrowser.Dlna/Didl/DidlBuilder.cs9
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlayToController.cs8
-rw-r--r--MediaBrowser.Dlna/Ssdp/SsdpHandler.cs12
-rw-r--r--MediaBrowser.LocalMetadata/BaseXmlProvider.cs2
-rw-r--r--MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs7
-rw-r--r--MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs5
-rw-r--r--MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs2
-rw-r--r--MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs5
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs19
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs9
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs392
-rw-r--r--MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj11
-rw-r--r--MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs (renamed from MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs)2
-rw-r--r--MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs (renamed from MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs)6
-rw-r--r--MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs887
-rw-r--r--MediaBrowser.MediaEncoding/Probing/whitelist.txt (renamed from MediaBrowser.Providers/MediaInfo/whitelist.txt)0
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs2
-rw-r--r--MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj9
-rw-r--r--MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj9
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs6
-rw-r--r--MediaBrowser.Model/Configuration/UserConfiguration.cs7
-rw-r--r--MediaBrowser.Model/Dlna/StreamBuilder.cs43
-rw-r--r--MediaBrowser.Model/Dlna/StreamInfo.cs1
-rw-r--r--MediaBrowser.Model/Dto/BaseItemDto.cs15
-rw-r--r--MediaBrowser.Model/Dto/BaseItemPerson.cs4
-rw-r--r--MediaBrowser.Model/Dto/IHasSyncInfo.cs13
-rw-r--r--MediaBrowser.Model/Entities/CollectionType.cs1
-rw-r--r--MediaBrowser.Model/Entities/MediaInfo.cs26
-rw-r--r--MediaBrowser.Model/Entities/MediaStream.cs9
-rw-r--r--MediaBrowser.Model/LiveTv/ProgramQuery.cs6
-rw-r--r--MediaBrowser.Model/LiveTv/RecommendedProgramQuery.cs5
-rw-r--r--MediaBrowser.Model/LiveTv/RecordingInfoDto.cs24
-rw-r--r--MediaBrowser.Model/MediaBrowser.Model.csproj3
-rw-r--r--MediaBrowser.Model/MediaInfo/MediaInfo.cs66
-rw-r--r--MediaBrowser.Model/Notifications/NotificationOptions.cs5
-rw-r--r--MediaBrowser.Model/Querying/ItemFields.cs5
-rw-r--r--MediaBrowser.Model/Querying/ItemQuery.cs10
-rw-r--r--MediaBrowser.Model/Querying/ItemSortBy.cs1
-rw-r--r--MediaBrowser.Model/Session/ClientCapabilities.cs5
-rw-r--r--MediaBrowser.Model/Sync/LocalItem.cs5
-rw-r--r--MediaBrowser.Model/Sync/SyncOptions.cs8
-rw-r--r--MediaBrowser.Model/Sync/SyncQualityOption.cs5
-rw-r--r--MediaBrowser.Model/Users/UserPolicy.cs17
-rw-r--r--MediaBrowser.Mono.sln11
-rw-r--r--MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs6
-rw-r--r--MediaBrowser.Providers/Manager/ItemImageProvider.cs37
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs7
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj8
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs350
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs311
-rw-r--r--MediaBrowser.Providers/Music/ArtistMetadataService.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelManager.cs11
-rw-r--r--MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs3
-rw-r--r--MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Dto/DtoService.cs47
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs55
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs52
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs40
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/LibraryManager.cs13
-rw-r--r--MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs78
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs13
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs18
-rw-r--r--MediaBrowser.Server.Implementations/Library/SearchEngine.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserManager.cs26
-rw-r--r--MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs2
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs2
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs49
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs89
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/bg_BG.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/da.json45
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/de.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/el.json107
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/es.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json13
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json13
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/he.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/hu.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/it.json81
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json15
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json13
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json35
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/sl_SI.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/uk.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json11
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ar.json43
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/bg_BG.json39
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ca.json43
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/cs.json39
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/da.json79
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/de.json41
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/el.json489
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/en_GB.json39
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/en_US.json43
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/es.json39
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/es_MX.json45
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/fi.json43
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/fr.json41
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/he.json39
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/hr.json39
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/it.json337
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/kk.json71
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ko.json43
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ms.json43
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/nb.json47
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/nl.json39
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/pl.json43
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json43
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json79
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ru.json101
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/server.json43
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/sl_SI.json43
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/sv.json39
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/tr.json39
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/uk.json43
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/vi.json43
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json39
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json39
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj28
-rw-r--r--MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs3
-rw-r--r--MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs55
-rw-r--r--MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs133
-rw-r--r--MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs132
-rw-r--r--MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs5
-rw-r--r--MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs3
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionManager.cs7
-rw-r--r--MediaBrowser.Server.Implementations/Sorting/StartDateComparer.cs47
-rw-r--r--MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs26
-rw-r--r--MediaBrowser.Server.Implementations/Sync/MediaSync.cs84
-rw-r--r--MediaBrowser.Server.Implementations/Sync/MultiProviderSync.cs9
-rw-r--r--MediaBrowser.Server.Implementations/Sync/ServerSyncScheduledTask.cs9
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs20
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncManager.cs137
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs7
-rw-r--r--MediaBrowser.Server.Implementations/Sync/TargetDataProvider.cs35
-rw-r--r--MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs28
-rw-r--r--MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs180
-rw-r--r--MediaBrowser.Server.Implementations/packages.config6
-rw-r--r--MediaBrowser.Server.Startup.Common/ApplicationHost.cs25
-rw-r--r--MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs18
-rw-r--r--MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs9
-rw-r--r--MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj4
-rw-r--r--MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs7
-rw-r--r--MediaBrowser.ServerApplication/MainStartup.cs1
-rw-r--r--MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj2
-rw-r--r--MediaBrowser.ServerApplication/ServerNotifyIcon.cs7
-rw-r--r--MediaBrowser.ServerApplication/packages.config2
-rw-r--r--MediaBrowser.WebDashboard/Api/PackageCreator.cs2
-rw-r--r--MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj20
-rw-r--r--MediaBrowser.WebDashboard/packages.config2
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs10
-rw-r--r--MediaBrowser.sln23
-rw-r--r--Nuget/MediaBrowser.Common.Internal.nuspec4
-rw-r--r--Nuget/MediaBrowser.Common.nuspec2
-rw-r--r--Nuget/MediaBrowser.Model.Signed.nuspec2
-rw-r--r--Nuget/MediaBrowser.Server.Core.nuspec5
-rw-r--r--OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs6
-rw-r--r--SharedVersion.cs2
269 files changed, 7185 insertions, 3137 deletions
diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs b/Emby.Drawing/Common/ImageHeader.cs
index 7117482c8..b66bd71ea 100644
--- a/MediaBrowser.Server.Implementations/Drawing/ImageHeader.cs
+++ b/Emby.Drawing/Common/ImageHeader.cs
@@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
-namespace MediaBrowser.Server.Implementations.Drawing
+namespace Emby.Drawing.Common
{
/// <summary>
/// Taken from http://stackoverflow.com/questions/111345/getting-image-dimensions-without-reading-the-entire-file/111349
diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj
new file mode 100644
index 000000000..dbb976f03
--- /dev/null
+++ b/Emby.Drawing/Emby.Drawing.csproj
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{08FFF49B-F175-4807-A2B5-73B0EBD9F716}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Emby.Drawing</RootNamespace>
+ <AssemblyName>Emby.Drawing</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+ <RestorePackages>true</RestorePackages>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="ImageMagickSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\packages\ImageMagickSharp.1.0.0.14\lib\net45\ImageMagickSharp.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\SharedVersion.cs">
+ <Link>Properties\SharedVersion.cs</Link>
+ </Compile>
+ <Compile Include="GDI\DynamicImageHelpers.cs" />
+ <Compile Include="GDI\GDIImageEncoder.cs" />
+ <Compile Include="GDI\ImageExtensions.cs" />
+ <Compile Include="GDI\PercentPlayedDrawer.cs" />
+ <Compile Include="GDI\PlayedIndicatorDrawer.cs" />
+ <Compile Include="GDI\UnplayedCountIndicator.cs" />
+ <Compile Include="IImageEncoder.cs" />
+ <Compile Include="Common\ImageHeader.cs" />
+ <Compile Include="ImageMagick\ImageMagickEncoder.cs" />
+ <Compile Include="ImageMagick\StripCollageBuilder.cs" />
+ <Compile Include="ImageProcessor.cs" />
+ <Compile Include="ImageMagick\PercentPlayedDrawer.cs" />
+ <Compile Include="ImageMagick\PlayedIndicatorDrawer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ImageMagick\UnplayedCountIndicator.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="ImageMagick\fonts\MontserratLight.otf" />
+ <EmbeddedResource Include="ImageMagick\fonts\robotoregular.ttf" />
+ <EmbeddedResource Include="ImageMagick\fonts\webdings.ttf" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
+ <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project>
+ <Name>MediaBrowser.Common</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj">
+ <Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
+ <Name>MediaBrowser.Controller</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
+ <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
+ <Name>MediaBrowser.Model</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/Emby.Drawing/GDI/DynamicImageHelpers.cs b/Emby.Drawing/GDI/DynamicImageHelpers.cs
new file mode 100644
index 000000000..c49007c5f
--- /dev/null
+++ b/Emby.Drawing/GDI/DynamicImageHelpers.cs
@@ -0,0 +1,138 @@
+using Emby.Drawing.ImageMagick;
+using MediaBrowser.Common.IO;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+
+namespace Emby.Drawing.GDI
+{
+ public static class DynamicImageHelpers
+ {
+ public static void CreateThumbCollage(List<string> files,
+ IFileSystem fileSystem,
+ string file,
+ int width,
+ int height)
+ {
+ const int numStrips = 4;
+ files = StripCollageBuilder.ProjectPaths(files, numStrips).ToList();
+
+ const int rows = 1;
+ int cols = numStrips;
+
+ int cellWidth = 2 * (width / 3);
+ int cellHeight = height;
+ var index = 0;
+
+ using (var img = new Bitmap(width, height, PixelFormat.Format32bppPArgb))
+ {
+ using (var graphics = Graphics.FromImage(img))
+ {
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ graphics.CompositingMode = CompositingMode.SourceCopy;
+
+ for (var row = 0; row < rows; row++)
+ {
+ for (var col = 0; col < cols; col++)
+ {
+ var x = col * (cellWidth / 2);
+ var y = row * cellHeight;
+
+ if (files.Count > index)
+ {
+ using (var fileStream = fileSystem.GetFileStream(files[index], FileMode.Open, FileAccess.Read, FileShare.Read, true))
+ {
+ using (var memoryStream = new MemoryStream())
+ {
+ fileStream.CopyTo(memoryStream);
+
+ memoryStream.Position = 0;
+
+ using (var imgtemp = Image.FromStream(memoryStream, true, false))
+ {
+ graphics.DrawImage(imgtemp, x, y, cellWidth, cellHeight);
+ }
+ }
+ }
+ }
+
+ index++;
+ }
+ }
+ img.Save(file);
+ }
+ }
+ }
+
+ public static void CreateSquareCollage(List<string> files,
+ IFileSystem fileSystem,
+ string file,
+ int width,
+ int height)
+ {
+ files = StripCollageBuilder.ProjectPaths(files, 4).ToList();
+
+ const int rows = 2;
+ const int cols = 2;
+
+ int singleSize = width / 2;
+ var index = 0;
+
+ using (var img = new Bitmap(width, height, PixelFormat.Format32bppPArgb))
+ {
+ using (var graphics = Graphics.FromImage(img))
+ {
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ graphics.CompositingMode = CompositingMode.SourceCopy;
+
+ for (var row = 0; row < rows; row++)
+ {
+ for (var col = 0; col < cols; col++)
+ {
+ var x = col * singleSize;
+ var y = row * singleSize;
+
+ using (var fileStream = fileSystem.GetFileStream(files[index], FileMode.Open, FileAccess.Read, FileShare.Read, true))
+ {
+ using (var memoryStream = new MemoryStream())
+ {
+ fileStream.CopyTo(memoryStream);
+
+ memoryStream.Position = 0;
+
+ using (var imgtemp = Image.FromStream(memoryStream, true, false))
+ {
+ graphics.DrawImage(imgtemp, x, y, singleSize, singleSize);
+ }
+ }
+ }
+
+ index++;
+ }
+ }
+ img.Save(file);
+ }
+ }
+ }
+
+ private static Stream GetStream(Image image)
+ {
+ var ms = new MemoryStream();
+
+ image.Save(ms, ImageFormat.Png);
+
+ ms.Position = 0;
+
+ return ms;
+ }
+ }
+}
diff --git a/Emby.Drawing/GDI/GDIImageEncoder.cs b/Emby.Drawing/GDI/GDIImageEncoder.cs
new file mode 100644
index 000000000..d968b8b5f
--- /dev/null
+++ b/Emby.Drawing/GDI/GDIImageEncoder.cs
@@ -0,0 +1,254 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Model.Drawing;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using ImageFormat = MediaBrowser.Model.Drawing.ImageFormat;
+
+namespace Emby.Drawing.GDI
+{
+ public class GDIImageEncoder : IImageEncoder
+ {
+ private readonly IFileSystem _fileSystem;
+ private readonly ILogger _logger;
+
+ public GDIImageEncoder(IFileSystem fileSystem, ILogger logger)
+ {
+ _fileSystem = fileSystem;
+ _logger = logger;
+ }
+
+ public string[] SupportedInputFormats
+ {
+ get
+ {
+ return new[]
+ {
+ "png",
+ "jpeg",
+ "jpg",
+ "gif",
+ "bmp"
+ };
+ }
+ }
+
+ public ImageFormat[] SupportedOutputFormats
+ {
+ get
+ {
+ return new[] { ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png };
+ }
+ }
+
+ public ImageSize GetImageSize(string path)
+ {
+ using (var image = Image.FromFile(path))
+ {
+ return new ImageSize
+ {
+ Width = image.Width,
+ Height = image.Height
+ };
+ }
+ }
+
+ public void CropWhiteSpace(string inputPath, string outputPath)
+ {
+ using (var image = (Bitmap)Image.FromFile(inputPath))
+ {
+ using (var croppedImage = image.CropWhitespace())
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
+
+ using (var outputStream = _fileSystem.GetFileStream(outputPath, FileMode.Create, FileAccess.Write, FileShare.Read, false))
+ {
+ croppedImage.Save(System.Drawing.Imaging.ImageFormat.Png, outputStream, 100);
+ }
+ }
+ }
+ }
+
+ public void EncodeImage(string inputPath, string cacheFilePath, int width, int height, int quality, ImageProcessingOptions options)
+ {
+ var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed > 0;
+
+ using (var originalImage = Image.FromFile(inputPath))
+ {
+ var newWidth = Convert.ToInt32(width);
+ var newHeight = Convert.ToInt32(height);
+
+ var selectedOutputFormat = options.OutputFormat;
+
+ // Graphics.FromImage will throw an exception if the PixelFormat is Indexed, so we need to handle that here
+ // Also, Webp only supports Format32bppArgb and Format32bppRgb
+ var pixelFormat = selectedOutputFormat == ImageFormat.Webp
+ ? PixelFormat.Format32bppArgb
+ : PixelFormat.Format32bppPArgb;
+
+ using (var thumbnail = new Bitmap(newWidth, newHeight, pixelFormat))
+ {
+ // Mono throw an exeception if assign 0 to SetResolution
+ if (originalImage.HorizontalResolution > 0 && originalImage.VerticalResolution > 0)
+ {
+ // Preserve the original resolution
+ thumbnail.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution);
+ }
+
+ using (var thumbnailGraph = Graphics.FromImage(thumbnail))
+ {
+ thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality;
+ thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality;
+ thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ thumbnailGraph.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ thumbnailGraph.CompositingMode = !hasPostProcessing ?
+ CompositingMode.SourceCopy :
+ CompositingMode.SourceOver;
+
+ SetBackgroundColor(thumbnailGraph, options);
+
+ thumbnailGraph.DrawImage(originalImage, 0, 0, newWidth, newHeight);
+
+ DrawIndicator(thumbnailGraph, newWidth, newHeight, options);
+
+ var outputFormat = GetOutputFormat(originalImage, selectedOutputFormat);
+
+ Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
+
+ // Save to the cache location
+ using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, false))
+ {
+ // Save to the memory stream
+ thumbnail.Save(outputFormat, cacheFileStream, quality);
+ }
+ }
+ }
+
+ }
+ }
+
+ /// <summary>
+ /// Sets the color of the background.
+ /// </summary>
+ /// <param name="graphics">The graphics.</param>
+ /// <param name="options">The options.</param>
+ private void SetBackgroundColor(Graphics graphics, ImageProcessingOptions options)
+ {
+ var color = options.BackgroundColor;
+
+ if (!string.IsNullOrEmpty(color))
+ {
+ Color drawingColor;
+
+ try
+ {
+ drawingColor = ColorTranslator.FromHtml(color);
+ }
+ catch
+ {
+ drawingColor = ColorTranslator.FromHtml("#" + color);
+ }
+
+ graphics.Clear(drawingColor);
+ }
+ }
+
+ /// <summary>
+ /// Draws the indicator.
+ /// </summary>
+ /// <param name="graphics">The graphics.</param>
+ /// <param name="imageWidth">Width of the image.</param>
+ /// <param name="imageHeight">Height of the image.</param>
+ /// <param name="options">The options.</param>
+ private void DrawIndicator(Graphics graphics, int imageWidth, int imageHeight, ImageProcessingOptions options)
+ {
+ if (!options.AddPlayedIndicator && !options.UnplayedCount.HasValue && options.PercentPlayed.Equals(0))
+ {
+ return;
+ }
+
+ try
+ {
+ if (options.AddPlayedIndicator)
+ {
+ var currentImageSize = new Size(imageWidth, imageHeight);
+
+ new PlayedIndicatorDrawer().DrawPlayedIndicator(graphics, currentImageSize);
+ }
+ else if (options.UnplayedCount.HasValue)
+ {
+ var currentImageSize = new Size(imageWidth, imageHeight);
+
+ new UnplayedCountIndicator().DrawUnplayedCountIndicator(graphics, currentImageSize, options.UnplayedCount.Value);
+ }
+
+ if (options.PercentPlayed > 0)
+ {
+ var currentImageSize = new Size(imageWidth, imageHeight);
+
+ new PercentPlayedDrawer().Process(graphics, currentImageSize, options.PercentPlayed);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error drawing indicator overlay", ex);
+ }
+ }
+
+ /// <summary>
+ /// Gets the output format.
+ /// </summary>
+ /// <param name="image">The image.</param>
+ /// <param name="outputFormat">The output format.</param>
+ /// <returns>ImageFormat.</returns>
+ private System.Drawing.Imaging.ImageFormat GetOutputFormat(Image image, ImageFormat outputFormat)
+ {
+ switch (outputFormat)
+ {
+ case ImageFormat.Bmp:
+ return System.Drawing.Imaging.ImageFormat.Bmp;
+ case ImageFormat.Gif:
+ return System.Drawing.Imaging.ImageFormat.Gif;
+ case ImageFormat.Jpg:
+ return System.Drawing.Imaging.ImageFormat.Jpeg;
+ case ImageFormat.Png:
+ return System.Drawing.Imaging.ImageFormat.Png;
+ default:
+ return image.RawFormat;
+ }
+ }
+
+ public void CreateImageCollage(ImageCollageOptions options)
+ {
+ double ratio = options.Width;
+ ratio /= options.Height;
+
+ if (ratio >= 1.4)
+ {
+ DynamicImageHelpers.CreateThumbCollage(options.InputPaths.ToList(), _fileSystem, options.OutputPath, options.Width, options.Height);
+ }
+ else if (ratio >= .9)
+ {
+ DynamicImageHelpers.CreateSquareCollage(options.InputPaths.ToList(), _fileSystem, options.OutputPath, options.Width, options.Height);
+ }
+ else
+ {
+ DynamicImageHelpers.CreateSquareCollage(options.InputPaths.ToList(), _fileSystem, options.OutputPath, options.Width, options.Width);
+ }
+ }
+
+ public void Dispose()
+ {
+ }
+
+ public string Name
+ {
+ get { return "GDI"; }
+ }
+ }
+}
diff --git a/Emby.Drawing/GDI/ImageExtensions.cs b/Emby.Drawing/GDI/ImageExtensions.cs
new file mode 100644
index 000000000..6af5a8688
--- /dev/null
+++ b/Emby.Drawing/GDI/ImageExtensions.cs
@@ -0,0 +1,217 @@
+using System;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.IO;
+
+namespace Emby.Drawing.GDI
+{
+ public static class ImageExtensions
+ {
+ /// <summary>
+ /// Saves the image.
+ /// </summary>
+ /// <param name="outputFormat">The output format.</param>
+ /// <param name="image">The image.</param>
+ /// <param name="toStream">To stream.</param>
+ /// <param name="quality">The quality.</param>
+ public static void Save(this Image image, ImageFormat outputFormat, Stream toStream, int quality)
+ {
+ // Use special save methods for jpeg and png that will result in a much higher quality image
+ // All other formats use the generic Image.Save
+ if (ImageFormat.Jpeg.Equals(outputFormat))
+ {
+ SaveAsJpeg(image, toStream, quality);
+ }
+ else if (ImageFormat.Png.Equals(outputFormat))
+ {
+ image.Save(toStream, ImageFormat.Png);
+ }
+ else
+ {
+ image.Save(toStream, outputFormat);
+ }
+ }
+
+ /// <summary>
+ /// Saves the JPEG.
+ /// </summary>
+ /// <param name="image">The image.</param>
+ /// <param name="target">The target.</param>
+ /// <param name="quality">The quality.</param>
+ public static void SaveAsJpeg(this Image image, Stream target, int quality)
+ {
+ using (var encoderParameters = new EncoderParameters(1))
+ {
+ encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, quality);
+ image.Save(target, GetImageCodecInfo("image/jpeg"), encoderParameters);
+ }
+ }
+
+ private static readonly ImageCodecInfo[] Encoders = ImageCodecInfo.GetImageEncoders();
+
+ /// <summary>
+ /// Gets the image codec info.
+ /// </summary>
+ /// <param name="mimeType">Type of the MIME.</param>
+ /// <returns>ImageCodecInfo.</returns>
+ private static ImageCodecInfo GetImageCodecInfo(string mimeType)
+ {
+ foreach (var encoder in Encoders)
+ {
+ if (string.Equals(encoder.MimeType, mimeType, StringComparison.OrdinalIgnoreCase))
+ {
+ return encoder;
+ }
+ }
+
+ return Encoders.Length == 0 ? null : Encoders[0];
+ }
+
+ /// <summary>
+ /// Crops an image by removing whitespace and transparency from the edges
+ /// </summary>
+ /// <param name="bmp">The BMP.</param>
+ /// <returns>Bitmap.</returns>
+ /// <exception cref="System.Exception"></exception>
+ public static Bitmap CropWhitespace(this Bitmap bmp)
+ {
+ var width = bmp.Width;
+ var height = bmp.Height;
+
+ var topmost = 0;
+ for (int row = 0; row < height; ++row)
+ {
+ if (IsAllWhiteRow(bmp, row, width))
+ topmost = row;
+ else break;
+ }
+
+ int bottommost = 0;
+ for (int row = height - 1; row >= 0; --row)
+ {
+ if (IsAllWhiteRow(bmp, row, width))
+ bottommost = row;
+ else break;
+ }
+
+ int leftmost = 0, rightmost = 0;
+ for (int col = 0; col < width; ++col)
+ {
+ if (IsAllWhiteColumn(bmp, col, height))
+ leftmost = col;
+ else
+ break;
+ }
+
+ for (int col = width - 1; col >= 0; --col)
+ {
+ if (IsAllWhiteColumn(bmp, col, height))
+ rightmost = col;
+ else
+ break;
+ }
+
+ if (rightmost == 0) rightmost = width; // As reached left
+ if (bottommost == 0) bottommost = height; // As reached top.
+
+ var croppedWidth = rightmost - leftmost;
+ var croppedHeight = bottommost - topmost;
+
+ if (croppedWidth == 0) // No border on left or right
+ {
+ leftmost = 0;
+ croppedWidth = width;
+ }
+
+ if (croppedHeight == 0) // No border on top or bottom
+ {
+ topmost = 0;
+ croppedHeight = height;
+ }
+
+ // Graphics.FromImage will throw an exception if the PixelFormat is Indexed, so we need to handle that here
+ var thumbnail = new Bitmap(croppedWidth, croppedHeight, PixelFormat.Format32bppPArgb);
+
+ // Preserve the original resolution
+ TrySetResolution(thumbnail, bmp.HorizontalResolution, bmp.VerticalResolution);
+
+ using (var thumbnailGraph = Graphics.FromImage(thumbnail))
+ {
+ thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality;
+ thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality;
+ thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ thumbnailGraph.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ thumbnailGraph.CompositingMode = CompositingMode.SourceCopy;
+
+ thumbnailGraph.DrawImage(bmp,
+ new RectangleF(0, 0, croppedWidth, croppedHeight),
+ new RectangleF(leftmost, topmost, croppedWidth, croppedHeight),
+ GraphicsUnit.Pixel);
+ }
+ return thumbnail;
+ }
+
+ /// <summary>
+ /// Tries the set resolution.
+ /// </summary>
+ /// <param name="bmp">The BMP.</param>
+ /// <param name="x">The x.</param>
+ /// <param name="y">The y.</param>
+ private static void TrySetResolution(Bitmap bmp, float x, float y)
+ {
+ if (x > 0 && y > 0)
+ {
+ bmp.SetResolution(x, y);
+ }
+ }
+
+ /// <summary>
+ /// Determines whether or not a row of pixels is all whitespace
+ /// </summary>
+ /// <param name="bmp">The BMP.</param>
+ /// <param name="row">The row.</param>
+ /// <param name="width">The width.</param>
+ /// <returns><c>true</c> if [is all white row] [the specified BMP]; otherwise, <c>false</c>.</returns>
+ private static bool IsAllWhiteRow(Bitmap bmp, int row, int width)
+ {
+ for (var i = 0; i < width; ++i)
+ {
+ if (!IsWhiteSpace(bmp.GetPixel(i, row)))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Determines whether or not a column of pixels is all whitespace
+ /// </summary>
+ /// <param name="bmp">The BMP.</param>
+ /// <param name="col">The col.</param>
+ /// <param name="height">The height.</param>
+ /// <returns><c>true</c> if [is all white column] [the specified BMP]; otherwise, <c>false</c>.</returns>
+ private static bool IsAllWhiteColumn(Bitmap bmp, int col, int height)
+ {
+ for (var i = 0; i < height; ++i)
+ {
+ if (!IsWhiteSpace(bmp.GetPixel(col, i)))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Determines if a color is whitespace
+ /// </summary>
+ /// <param name="color">The color.</param>
+ /// <returns><c>true</c> if [is white space] [the specified color]; otherwise, <c>false</c>.</returns>
+ private static bool IsWhiteSpace(Color color)
+ {
+ return (color.R == 255 && color.G == 255 && color.B == 255) || color.A == 0;
+ }
+ }
+}
diff --git a/Emby.Drawing/GDI/PercentPlayedDrawer.cs b/Emby.Drawing/GDI/PercentPlayedDrawer.cs
new file mode 100644
index 000000000..c7afda60e
--- /dev/null
+++ b/Emby.Drawing/GDI/PercentPlayedDrawer.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Drawing;
+
+namespace Emby.Drawing.GDI
+{
+ public class PercentPlayedDrawer
+ {
+ private const int IndicatorHeight = 8;
+
+ public void Process(Graphics graphics, Size imageSize, double percent)
+ {
+ var y = imageSize.Height - IndicatorHeight;
+
+ using (var backdroundBrush = new SolidBrush(Color.FromArgb(225, 0, 0, 0)))
+ {
+ const int innerX = 0;
+ var innerY = y;
+ var innerWidth = imageSize.Width;
+ var innerHeight = imageSize.Height;
+
+ graphics.FillRectangle(backdroundBrush, innerX, innerY, innerWidth, innerHeight);
+
+ using (var foregroundBrush = new SolidBrush(Color.FromArgb(82, 181, 75)))
+ {
+ double foregroundWidth = innerWidth;
+ foregroundWidth *= percent;
+ foregroundWidth /= 100;
+
+ graphics.FillRectangle(foregroundBrush, innerX, innerY, Convert.ToInt32(Math.Round(foregroundWidth)), innerHeight);
+ }
+ }
+ }
+ }
+}
diff --git a/Emby.Drawing/GDI/PlayedIndicatorDrawer.cs b/Emby.Drawing/GDI/PlayedIndicatorDrawer.cs
new file mode 100644
index 000000000..4428e4cba
--- /dev/null
+++ b/Emby.Drawing/GDI/PlayedIndicatorDrawer.cs
@@ -0,0 +1,32 @@
+using System.Drawing;
+
+namespace Emby.Drawing.GDI
+{
+ public class PlayedIndicatorDrawer
+ {
+ private const int IndicatorHeight = 40;
+ public const int IndicatorWidth = 40;
+ private const int FontSize = 40;
+ private const int OffsetFromTopRightCorner = 10;
+
+ public void DrawPlayedIndicator(Graphics graphics, Size imageSize)
+ {
+ var x = imageSize.Width - IndicatorWidth - OffsetFromTopRightCorner;
+
+ using (var backdroundBrush = new SolidBrush(Color.FromArgb(225, 82, 181, 75)))
+ {
+ graphics.FillEllipse(backdroundBrush, x, OffsetFromTopRightCorner, IndicatorWidth, IndicatorHeight);
+
+ x = imageSize.Width - 45 - OffsetFromTopRightCorner;
+
+ using (var font = new Font("Webdings", FontSize, FontStyle.Regular, GraphicsUnit.Pixel))
+ {
+ using (var fontBrush = new SolidBrush(Color.White))
+ {
+ graphics.DrawString("a", font, fontBrush, x, OffsetFromTopRightCorner - 2);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Emby.Drawing/GDI/UnplayedCountIndicator.cs b/Emby.Drawing/GDI/UnplayedCountIndicator.cs
new file mode 100644
index 000000000..6420abb27
--- /dev/null
+++ b/Emby.Drawing/GDI/UnplayedCountIndicator.cs
@@ -0,0 +1,50 @@
+using System.Drawing;
+
+namespace Emby.Drawing.GDI
+{
+ public class UnplayedCountIndicator
+ {
+ private const int IndicatorHeight = 41;
+ public const int IndicatorWidth = 41;
+ private const int OffsetFromTopRightCorner = 10;
+
+ public void DrawUnplayedCountIndicator(Graphics graphics, Size imageSize, int count)
+ {
+ var x = imageSize.Width - IndicatorWidth - OffsetFromTopRightCorner;
+
+ using (var backdroundBrush = new SolidBrush(Color.FromArgb(225, 82, 181, 75)))
+ {
+ graphics.FillEllipse(backdroundBrush, x, OffsetFromTopRightCorner, IndicatorWidth, IndicatorHeight);
+
+ var text = count.ToString();
+
+ x = imageSize.Width - IndicatorWidth - OffsetFromTopRightCorner;
+ var y = OffsetFromTopRightCorner + 6;
+ var fontSize = 24;
+
+ if (text.Length == 1)
+ {
+ x += 10;
+ }
+ else if (text.Length == 2)
+ {
+ x += 3;
+ }
+ else if (text.Length == 3)
+ {
+ x += 1;
+ y += 1;
+ fontSize = 20;
+ }
+
+ using (var font = new Font("Sans-Serif", fontSize, FontStyle.Regular, GraphicsUnit.Pixel))
+ {
+ using (var fontBrush = new SolidBrush(Color.White))
+ {
+ graphics.DrawString(text, font, fontBrush, x, y);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Emby.Drawing/IImageEncoder.cs b/Emby.Drawing/IImageEncoder.cs
new file mode 100644
index 000000000..29261dbdb
--- /dev/null
+++ b/Emby.Drawing/IImageEncoder.cs
@@ -0,0 +1,53 @@
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Model.Drawing;
+using System;
+
+namespace Emby.Drawing
+{
+ public interface IImageEncoder : IDisposable
+ {
+ /// <summary>
+ /// Gets the supported input formats.
+ /// </summary>
+ /// <value>The supported input formats.</value>
+ string[] SupportedInputFormats { get; }
+ /// <summary>
+ /// Gets the supported output formats.
+ /// </summary>
+ /// <value>The supported output formats.</value>
+ ImageFormat[] SupportedOutputFormats { get; }
+ /// <summary>
+ /// Gets the size of the image.
+ /// </summary>
+ /// <param name="path">The path.</param>
+ /// <returns>ImageSize.</returns>
+ ImageSize GetImageSize(string path);
+ /// <summary>
+ /// Crops the white space.
+ /// </summary>
+ /// <param name="inputPath">The input path.</param>
+ /// <param name="outputPath">The output path.</param>
+ void CropWhiteSpace(string inputPath, string outputPath);
+ /// <summary>
+ /// Encodes the image.
+ /// </summary>
+ /// <param name="inputPath">The input path.</param>
+ /// <param name="outputPath">The output path.</param>
+ /// <param name="width">The width.</param>
+ /// <param name="height">The height.</param>
+ /// <param name="quality">The quality.</param>
+ /// <param name="options">The options.</param>
+ void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options);
+
+ /// <summary>
+ /// Creates the image collage.
+ /// </summary>
+ /// <param name="options">The options.</param>
+ void CreateImageCollage(ImageCollageOptions options);
+ /// <summary>
+ /// Gets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ string Name { get; }
+ }
+}
diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
new file mode 100644
index 000000000..3d6cdd03d
--- /dev/null
+++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs
@@ -0,0 +1,229 @@
+using ImageMagickSharp;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Model.Drawing;
+using MediaBrowser.Model.Logging;
+using System;
+using System.IO;
+
+namespace Emby.Drawing.ImageMagick
+{
+ public class ImageMagickEncoder : IImageEncoder
+ {
+ private readonly ILogger _logger;
+ private readonly IApplicationPaths _appPaths;
+
+ public ImageMagickEncoder(ILogger logger, IApplicationPaths appPaths)
+ {
+ _logger = logger;
+ _appPaths = appPaths;
+
+ LogImageMagickVersion();
+ }
+
+ public string[] SupportedInputFormats
+ {
+ get
+ {
+ // Some common file name extensions for RAW picture files include: .cr2, .crw, .dng, .nef, .orf, .rw2, .pef, .arw, .sr2, .srf, and .tif.
+ return new[]
+ {
+ "tiff",
+ "jpeg",
+ "jpg",
+ "png",
+ "aiff",
+ "cr2",
+ "crw",
+ "dng",
+ "nef",
+ "orf",
+ "pef",
+ "arw",
+ "webp",
+ "gif",
+ "bmp"
+ };
+ }
+ }
+
+ public ImageFormat[] SupportedOutputFormats
+ {
+ get
+ {
+ if (_webpAvailable)
+ {
+ return new[] { ImageFormat.Webp, ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png };
+ }
+ return new[] { ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png };
+ }
+ }
+
+ private void LogImageMagickVersion()
+ {
+ _logger.Info("ImageMagick version: " + Wand.VersionString);
+ TestWebp();
+ }
+
+ private bool _webpAvailable = true;
+ private void TestWebp()
+ {
+ try
+ {
+ var tmpPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".webp");
+ Directory.CreateDirectory(Path.GetDirectoryName(tmpPath));
+
+ using (var wand = new MagickWand(1, 1, new PixelWand("none", 1)))
+ {
+ wand.SaveImage(tmpPath);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error loading webp: ", ex);
+ _webpAvailable = false;
+ }
+ }
+
+ public void CropWhiteSpace(string inputPath, string outputPath)
+ {
+ CheckDisposed();
+
+ using (var wand = new MagickWand(inputPath))
+ {
+ wand.CurrentImage.TrimImage(10);
+ wand.SaveImage(outputPath);
+ }
+ }
+
+ public ImageSize GetImageSize(string path)
+ {
+ CheckDisposed();
+
+ using (var wand = new MagickWand())
+ {
+ wand.PingImage(path);
+ var img = wand.CurrentImage;
+
+ return new ImageSize
+ {
+ Width = img.Width,
+ Height = img.Height
+ };
+ }
+ }
+
+ public void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options)
+ {
+ if (string.IsNullOrWhiteSpace(options.BackgroundColor))
+ {
+ using (var originalImage = new MagickWand(inputPath))
+ {
+ originalImage.CurrentImage.ResizeImage(width, height);
+
+ DrawIndicator(originalImage, width, height, options);
+
+ originalImage.CurrentImage.CompressionQuality = quality;
+
+ originalImage.SaveImage(outputPath);
+ }
+ }
+ else
+ {
+ using (var wand = new MagickWand(width, height, options.BackgroundColor))
+ {
+ using (var originalImage = new MagickWand(inputPath))
+ {
+ originalImage.CurrentImage.ResizeImage(width, height);
+
+ wand.CurrentImage.CompositeImage(originalImage, CompositeOperator.OverCompositeOp, 0, 0);
+ DrawIndicator(wand, width, height, options);
+
+ wand.CurrentImage.CompressionQuality = quality;
+
+ wand.SaveImage(outputPath);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Draws the indicator.
+ /// </summary>
+ /// <param name="wand">The wand.</param>
+ /// <param name="imageWidth">Width of the image.</param>
+ /// <param name="imageHeight">Height of the image.</param>
+ /// <param name="options">The options.</param>
+ private void DrawIndicator(MagickWand wand, int imageWidth, int imageHeight, ImageProcessingOptions options)
+ {
+ if (!options.AddPlayedIndicator && !options.UnplayedCount.HasValue && options.PercentPlayed.Equals(0))
+ {
+ return;
+ }
+
+ try
+ {
+ if (options.AddPlayedIndicator)
+ {
+ var currentImageSize = new ImageSize(imageWidth, imageHeight);
+
+ new PlayedIndicatorDrawer(_appPaths).DrawPlayedIndicator(wand, currentImageSize);
+ }
+ else if (options.UnplayedCount.HasValue)
+ {
+ var currentImageSize = new ImageSize(imageWidth, imageHeight);
+
+ new UnplayedCountIndicator(_appPaths).DrawUnplayedCountIndicator(wand, currentImageSize, options.UnplayedCount.Value);
+ }
+
+ if (options.PercentPlayed > 0)
+ {
+ new PercentPlayedDrawer().Process(wand, options.PercentPlayed);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error drawing indicator overlay", ex);
+ }
+ }
+
+ public void CreateImageCollage(ImageCollageOptions options)
+ {
+ double ratio = options.Width;
+ ratio /= options.Height;
+
+ if (ratio >= 1.4)
+ {
+ new StripCollageBuilder(_appPaths).BuildThumbCollage(options.InputPaths, options.OutputPath, options.Width, options.Height, options.Text);
+ }
+ else if (ratio >= .9)
+ {
+ new StripCollageBuilder(_appPaths).BuildSquareCollage(options.InputPaths, options.OutputPath, options.Width, options.Height, options.Text);
+ }
+ else
+ {
+ new StripCollageBuilder(_appPaths).BuildPosterCollage(options.InputPaths, options.OutputPath, options.Width, options.Height, options.Text);
+ }
+ }
+
+ public string Name
+ {
+ get { return "ImageMagick"; }
+ }
+
+ private bool _disposed;
+ public void Dispose()
+ {
+ _disposed = true;
+ Wand.CloseEnvironment();
+ }
+
+ private void CheckDisposed()
+ {
+ if (_disposed)
+ {
+ throw new ObjectDisposedException(GetType().Name);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Drawing/PercentPlayedDrawer.cs b/Emby.Drawing/ImageMagick/PercentPlayedDrawer.cs
index 20c2ab93b..90f9d5609 100644
--- a/MediaBrowser.Server.Implementations/Drawing/PercentPlayedDrawer.cs
+++ b/Emby.Drawing/ImageMagick/PercentPlayedDrawer.cs
@@ -1,7 +1,7 @@
using ImageMagickSharp;
using System;
-namespace MediaBrowser.Server.Implementations.Drawing
+namespace Emby.Drawing.ImageMagick
{
public class PercentPlayedDrawer
{
diff --git a/MediaBrowser.Server.Implementations/Drawing/PlayedIndicatorDrawer.cs b/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs
index 359065cc2..5eeb15771 100644
--- a/MediaBrowser.Server.Implementations/Drawing/PlayedIndicatorDrawer.cs
+++ b/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs
@@ -4,7 +4,7 @@ using MediaBrowser.Model.Drawing;
using System;
using System.IO;
-namespace MediaBrowser.Server.Implementations.Drawing
+namespace Emby.Drawing.ImageMagick
{
public class PlayedIndicatorDrawer
{
diff --git a/Emby.Drawing/ImageMagick/StripCollageBuilder.cs b/Emby.Drawing/ImageMagick/StripCollageBuilder.cs
new file mode 100644
index 000000000..7cdd0077d
--- /dev/null
+++ b/Emby.Drawing/ImageMagick/StripCollageBuilder.cs
@@ -0,0 +1,518 @@
+using ImageMagickSharp;
+using MediaBrowser.Common.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Emby.Drawing.ImageMagick
+{
+ public class StripCollageBuilder
+ {
+ private readonly IApplicationPaths _appPaths;
+
+ public StripCollageBuilder(IApplicationPaths appPaths)
+ {
+ _appPaths = appPaths;
+ }
+
+ public void BuildPosterCollage(IEnumerable<string> paths, string outputPath, int width, int height, string text)
+ {
+ if (!string.IsNullOrWhiteSpace(text))
+ {
+ using (var wand = BuildPosterCollageWandWithText(paths, text, width, height))
+ {
+ wand.SaveImage(outputPath);
+ }
+ }
+ else
+ {
+ using (var wand = BuildPosterCollageWand(paths, width, height))
+ {
+ wand.SaveImage(outputPath);
+ }
+ }
+ }
+
+ public void BuildSquareCollage(IEnumerable<string> paths, string outputPath, int width, int height, string text)
+ {
+ if (!string.IsNullOrWhiteSpace(text))
+ {
+ using (var wand = BuildSquareCollageWandWithText(paths, text, width, height))
+ {
+ wand.SaveImage(outputPath);
+ }
+ }
+ else
+ {
+ using (var wand = BuildSquareCollageWand(paths, width, height))
+ {
+ wand.SaveImage(outputPath);
+ }
+ }
+ }
+
+ public void BuildThumbCollage(IEnumerable<string> paths, string outputPath, int width, int height, string text)
+ {
+ if (!string.IsNullOrWhiteSpace(text))
+ {
+ using (var wand = BuildThumbCollageWandWithText(paths, text, width, height))
+ {
+ wand.SaveImage(outputPath);
+ }
+ }
+ else
+ {
+ using (var wand = BuildThumbCollageWand(paths, width, height))
+ {
+ wand.SaveImage(outputPath);
+ }
+ }
+ }
+
+ internal static string[] ProjectPaths(IEnumerable<string> paths, int count)
+ {
+ var clone = paths.ToList();
+ var list = new List<string>();
+
+ while (list.Count < count)
+ {
+ foreach (var path in clone)
+ {
+ list.Add(path);
+
+ if (list.Count >= count)
+ {
+ break;
+ }
+ }
+ }
+
+ return list.Take(count).ToArray();
+ }
+
+ private MagickWand BuildThumbCollageWandWithText(IEnumerable<string> paths, string text, int width, int height)
+ {
+ var inputPaths = ProjectPaths(paths, 8);
+ using (var wandImages = new MagickWand(inputPaths))
+ {
+ var wand = new MagickWand(width, height);
+ wand.OpenImage("gradient:#111111-#111111");
+ using (var draw = new DrawingWand())
+ {
+ using (var fcolor = new PixelWand(ColorName.White))
+ {
+ draw.FillColor = fcolor;
+ draw.Font = MontserratLightFont;
+ draw.FontSize = 60;
+ draw.FontWeight = FontWeightType.LightStyle;
+ draw.TextAntialias = true;
+ }
+
+ var fontMetrics = wand.QueryFontMetrics(draw, text);
+ var textContainerY = Convert.ToInt32(height * .165);
+ wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, text);
+
+ var iSlice = Convert.ToInt32(width * .1166666667);
+ int iTrans = Convert.ToInt32(height * 0.2);
+ int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296);
+ var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
+
+ foreach (var element in wandImages.ImageList)
+ {
+ int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
+ element.Gravity = GravityType.CenterGravity;
+ element.BackgroundColor = new PixelWand("none", 1);
+ element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
+ int ix = (int)Math.Abs((iWidth - iSlice) / 2);
+ element.CropImage(iSlice, iHeight, ix, 0);
+
+ element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
+ }
+
+ wandImages.SetFirstIterator();
+ using (var wandList = wandImages.AppendImages())
+ {
+ wandList.CurrentImage.TrimImage(1);
+ using (var mwr = wandList.CloneMagickWand())
+ {
+ using (var blackPixelWand = new PixelWand(ColorName.Black))
+ {
+ using (var greyPixelWand = new PixelWand(ColorName.Grey70))
+ {
+ mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
+ mwr.CurrentImage.FlipImage();
+
+ mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
+ mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
+
+ using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
+ {
+ mwg.OpenImage("gradient:black-none");
+ var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
+ mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.DstInCompositeOp, 0, verticalSpacing);
+
+ wandList.AddImage(mwr);
+ int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
+ wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * 0.26851851851851851851851851851852));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return wand;
+ }
+ }
+
+ private MagickWand BuildPosterCollageWand(IEnumerable<string> paths, int width, int height)
+ {
+ var inputPaths = ProjectPaths(paths, 4);
+ using (var wandImages = new MagickWand(inputPaths))
+ {
+ var wand = new MagickWand(width, height);
+ wand.OpenImage("gradient:#111111-#111111");
+ using (var draw = new DrawingWand())
+ {
+ var iSlice = Convert.ToInt32(width * 0.225);
+ int iTrans = Convert.ToInt32(height * .25);
+ int iHeight = Convert.ToInt32(height * .65);
+ var horizontalImagePadding = Convert.ToInt32(width * 0.0275);
+
+ foreach (var element in wandImages.ImageList)
+ {
+ using (var blackPixelWand = new PixelWand(ColorName.Black))
+ {
+ int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
+ element.Gravity = GravityType.CenterGravity;
+ element.BackgroundColor = blackPixelWand;
+ element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
+ int ix = (int)Math.Abs((iWidth - iSlice) / 2);
+ element.CropImage(iSlice, iHeight, ix, 0);
+
+ element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
+ }
+ }
+
+ wandImages.SetFirstIterator();
+ using (var wandList = wandImages.AppendImages())
+ {
+ wandList.CurrentImage.TrimImage(1);
+ using (var mwr = wandList.CloneMagickWand())
+ {
+ using (var blackPixelWand = new PixelWand(ColorName.Black))
+ {
+ using (var greyPixelWand = new PixelWand(ColorName.Grey70))
+ {
+ mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
+ mwr.CurrentImage.FlipImage();
+
+ mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
+ mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
+
+ using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
+ {
+ mwg.OpenImage("gradient:black-none");
+ var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
+ mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing);
+
+ wandList.AddImage(mwr);
+ int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
+ wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .05));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return wand;
+ }
+ }
+
+ private MagickWand BuildPosterCollageWandWithText(IEnumerable<string> paths, string label, int width, int height)
+ {
+ var inputPaths = ProjectPaths(paths, 4);
+ using (var wandImages = new MagickWand(inputPaths))
+ {
+ var wand = new MagickWand(width, height);
+ wand.OpenImage("gradient:#111111-#111111");
+ using (var draw = new DrawingWand())
+ {
+ using (var fcolor = new PixelWand(ColorName.White))
+ {
+ draw.FillColor = fcolor;
+ draw.Font = MontserratLightFont;
+ draw.FontSize = 60;
+ draw.FontWeight = FontWeightType.LightStyle;
+ draw.TextAntialias = true;
+ }
+
+ var fontMetrics = wand.QueryFontMetrics(draw, label);
+ var textContainerY = Convert.ToInt32(height * .165);
+ wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, label);
+
+ var iSlice = Convert.ToInt32(width * 0.225);
+ int iTrans = Convert.ToInt32(height * 0.2);
+ int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296);
+ var horizontalImagePadding = Convert.ToInt32(width * 0.0275);
+
+ foreach (var element in wandImages.ImageList)
+ {
+ int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
+ element.Gravity = GravityType.CenterGravity;
+ element.BackgroundColor = new PixelWand("none", 1);
+ element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
+ int ix = (int)Math.Abs((iWidth - iSlice) / 2);
+ element.CropImage(iSlice, iHeight, ix, 0);
+
+ element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
+ }
+
+ wandImages.SetFirstIterator();
+ using (var wandList = wandImages.AppendImages())
+ {
+ wandList.CurrentImage.TrimImage(1);
+ using (var mwr = wandList.CloneMagickWand())
+ {
+ using (var blackPixelWand = new PixelWand(ColorName.Black))
+ {
+ using (var greyPixelWand = new PixelWand(ColorName.Grey70))
+ {
+ mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
+ mwr.CurrentImage.FlipImage();
+
+ mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
+ mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
+
+ using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
+ {
+ mwg.OpenImage("gradient:black-none");
+ var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
+ mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.DstInCompositeOp, 0, verticalSpacing);
+
+ wandList.AddImage(mwr);
+ int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
+ wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * 0.26851851851851851851851851851852));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return wand;
+ }
+ }
+
+ private MagickWand BuildThumbCollageWand(IEnumerable<string> paths, int width, int height)
+ {
+ var inputPaths = ProjectPaths(paths, 8);
+ using (var wandImages = new MagickWand(inputPaths))
+ {
+ var wand = new MagickWand(width, height);
+ wand.OpenImage("gradient:#111111-#111111");
+ using (var draw = new DrawingWand())
+ {
+ var iSlice = Convert.ToInt32(width * .1166666667);
+ int iTrans = Convert.ToInt32(height * .25);
+ int iHeight = Convert.ToInt32(height * .62);
+ var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
+
+ foreach (var element in wandImages.ImageList)
+ {
+ using (var blackPixelWand = new PixelWand(ColorName.Black))
+ {
+ int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
+ element.Gravity = GravityType.CenterGravity;
+ element.BackgroundColor = blackPixelWand;
+ element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
+ int ix = (int)Math.Abs((iWidth - iSlice) / 2);
+ element.CropImage(iSlice, iHeight, ix, 0);
+
+ element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
+ }
+ }
+
+ wandImages.SetFirstIterator();
+ using (var wandList = wandImages.AppendImages())
+ {
+ wandList.CurrentImage.TrimImage(1);
+ using (var mwr = wandList.CloneMagickWand())
+ {
+ using (var blackPixelWand = new PixelWand(ColorName.Black))
+ {
+ using (var greyPixelWand = new PixelWand(ColorName.Grey70))
+ {
+ mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
+ mwr.CurrentImage.FlipImage();
+
+ mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
+ mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
+
+ using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
+ {
+ mwg.OpenImage("gradient:black-none");
+ var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
+ mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing);
+
+ wandList.AddImage(mwr);
+ int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
+ wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .085));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return wand;
+ }
+ }
+
+ private MagickWand BuildSquareCollageWand(IEnumerable<string> paths, int width, int height)
+ {
+ var inputPaths = ProjectPaths(paths, 4);
+ using (var wandImages = new MagickWand(inputPaths))
+ {
+ var wand = new MagickWand(width, height);
+ wand.OpenImage("gradient:#111111-#111111");
+ using (var draw = new DrawingWand())
+ {
+ var iSlice = Convert.ToInt32(width * .225);
+ int iTrans = Convert.ToInt32(height * .25);
+ int iHeight = Convert.ToInt32(height * .63);
+ var horizontalImagePadding = Convert.ToInt32(width * 0.02);
+
+ foreach (var element in wandImages.ImageList)
+ {
+ using (var blackPixelWand = new PixelWand(ColorName.Black))
+ {
+ int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
+ element.Gravity = GravityType.CenterGravity;
+ element.BackgroundColor = blackPixelWand;
+ element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
+ int ix = (int)Math.Abs((iWidth - iSlice) / 2);
+ element.CropImage(iSlice, iHeight, ix, 0);
+
+ element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
+ }
+ }
+
+ wandImages.SetFirstIterator();
+ using (var wandList = wandImages.AppendImages())
+ {
+ wandList.CurrentImage.TrimImage(1);
+ using (var mwr = wandList.CloneMagickWand())
+ {
+ using (var blackPixelWand = new PixelWand(ColorName.Black))
+ {
+ using (var greyPixelWand = new PixelWand(ColorName.Grey70))
+ {
+ mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
+ mwr.CurrentImage.FlipImage();
+
+ mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
+ mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
+
+ using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
+ {
+ mwg.OpenImage("gradient:black-none");
+ var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
+ mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing);
+
+ wandList.AddImage(mwr);
+ int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
+ wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .07));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return wand;
+ }
+ }
+
+ private MagickWand BuildSquareCollageWandWithText(IEnumerable<string> paths, string label, int width, int height)
+ {
+ var inputPaths = ProjectPaths(paths, 4);
+ using (var wandImages = new MagickWand(inputPaths))
+ {
+ var wand = new MagickWand(width, height);
+ wand.OpenImage("gradient:#111111-#111111");
+ using (var draw = new DrawingWand())
+ {
+ using (var fcolor = new PixelWand(ColorName.White))
+ {
+ draw.FillColor = fcolor;
+ draw.Font = MontserratLightFont;
+ draw.FontSize = 60;
+ draw.FontWeight = FontWeightType.LightStyle;
+ draw.TextAntialias = true;
+ }
+
+ var fontMetrics = wand.QueryFontMetrics(draw, label);
+ var textContainerY = Convert.ToInt32(height * .165);
+ wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, label);
+
+ var iSlice = Convert.ToInt32(width * .225);
+ int iTrans = Convert.ToInt32(height * 0.2);
+ int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296);
+ var horizontalImagePadding = Convert.ToInt32(width * 0.02);
+
+ foreach (var element in wandImages.ImageList)
+ {
+ int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
+ element.Gravity = GravityType.CenterGravity;
+ element.BackgroundColor = new PixelWand("none", 1);
+ element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
+ int ix = (int)Math.Abs((iWidth - iSlice) / 2);
+ element.CropImage(iSlice, iHeight, ix, 0);
+
+ element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
+ }
+
+ wandImages.SetFirstIterator();
+ using (var wandList = wandImages.AppendImages())
+ {
+ wandList.CurrentImage.TrimImage(1);
+ using (var mwr = wandList.CloneMagickWand())
+ {
+ using (var blackPixelWand = new PixelWand(ColorName.Black))
+ {
+ using (var greyPixelWand = new PixelWand(ColorName.Grey70))
+ {
+ mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
+ mwr.CurrentImage.FlipImage();
+
+ mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
+ mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
+
+ using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
+ {
+ mwg.OpenImage("gradient:black-none");
+ var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
+ mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.DstInCompositeOp, 0, verticalSpacing);
+
+ wandList.AddImage(mwr);
+ int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
+ wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * 0.26851851851851851851851851851852));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return wand;
+ }
+ }
+
+ private string MontserratLightFont
+ {
+ get { return PlayedIndicatorDrawer.ExtractFont("MontserratLight.otf", _appPaths); }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Drawing/UnplayedCountIndicator.cs b/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs
index 71cced041..dd25004d6 100644
--- a/MediaBrowser.Server.Implementations/Drawing/UnplayedCountIndicator.cs
+++ b/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs
@@ -3,7 +3,7 @@ using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Drawing;
using System.Globalization;
-namespace MediaBrowser.Server.Implementations.Drawing
+namespace Emby.Drawing.ImageMagick
{
public class UnplayedCountIndicator
{
diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs
index d78d5e8ea..c7d06559a 100644
--- a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
+++ b/Emby.Drawing/ImageProcessor.cs
@@ -1,4 +1,4 @@
-using ImageMagickSharp;
+using Emby.Drawing.Common;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
@@ -18,7 +18,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-namespace MediaBrowser.Server.Implementations.Drawing
+namespace Emby.Drawing
{
/// <summary>
/// Class ImageProcessor
@@ -50,12 +50,14 @@ namespace MediaBrowser.Server.Implementations.Drawing
private readonly IFileSystem _fileSystem;
private readonly IJsonSerializer _jsonSerializer;
private readonly IServerApplicationPaths _appPaths;
+ private readonly IImageEncoder _imageEncoder;
- public ImageProcessor(ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem, IJsonSerializer jsonSerializer)
+ public ImageProcessor(ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem, IJsonSerializer jsonSerializer, IImageEncoder imageEncoder)
{
_logger = logger;
_fileSystem = fileSystem;
_jsonSerializer = jsonSerializer;
+ _imageEncoder = imageEncoder;
_appPaths = appPaths;
_saveImageSizeTimer = new Timer(SaveImageSizeCallback, null, Timeout.Infinite, Timeout.Infinite);
@@ -85,8 +87,14 @@ namespace MediaBrowser.Server.Implementations.Drawing
}
_cachedImagedSizes = new ConcurrentDictionary<Guid, ImageSize>(sizeDictionary);
+ }
- LogImageMagickVersionVersion();
+ public string[] SupportedInputFormats
+ {
+ get
+ {
+ return _imageEncoder.SupportedInputFormats;
+ }
}
private string ResizedImageCachePath
@@ -130,44 +138,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
public ImageFormat[] GetSupportedImageOutputFormats()
{
- if (_webpAvailable)
- {
- return new[] { ImageFormat.Webp, ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png };
- }
- return new[] { ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png };
- }
-
- private bool _webpAvailable = true;
- private void TestWebp()
- {
- try
- {
- var tmpPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".webp");
- Directory.CreateDirectory(Path.GetDirectoryName(tmpPath));
-
- using (var wand = new MagickWand(1, 1, new PixelWand("none", 1)))
- {
- wand.SaveImage(tmpPath);
- }
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error loading webp: ", ex);
- _webpAvailable = false;
- }
- }
-
- private void LogImageMagickVersionVersion()
- {
- try
- {
- _logger.Info("ImageMagick version: " + Wand.VersionString);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error loading ImageMagick: ", ex);
- }
- TestWebp();
+ return _imageEncoder.SupportedOutputFormats;
}
public async Task<string> ProcessImage(ImageProcessingOptions options)
@@ -244,36 +215,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
- if (string.IsNullOrWhiteSpace(options.BackgroundColor))
- {
- using (var originalImage = new MagickWand(originalImagePath))
- {
- originalImage.CurrentImage.ResizeImage(newWidth, newHeight);
-
- DrawIndicator(originalImage, newWidth, newHeight, options);
-
- originalImage.CurrentImage.CompressionQuality = quality;
-
- originalImage.SaveImage(cacheFilePath);
- }
- }
- else
- {
- using (var wand = new MagickWand(newWidth, newHeight, options.BackgroundColor))
- {
- using (var originalImage = new MagickWand(originalImagePath))
- {
- originalImage.CurrentImage.ResizeImage(newWidth, newHeight);
-
- wand.CurrentImage.CompositeImage(originalImage, CompositeOperator.OverCompositeOp, 0, 0);
- DrawIndicator(wand, newWidth, newHeight, options);
-
- wand.CurrentImage.CompressionQuality = quality;
-
- wand.SaveImage(cacheFilePath);
- }
- }
- }
+ _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, newWidth, newHeight, quality, options);
}
}
finally
@@ -286,7 +228,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
private ImageFormat GetOutputFormat(ImageFormat requestedFormat)
{
- if (requestedFormat == ImageFormat.Webp && !_webpAvailable)
+ if (requestedFormat == ImageFormat.Webp && !_imageEncoder.SupportedOutputFormats.Contains(ImageFormat.Webp))
{
return ImageFormat.Png;
}
@@ -295,46 +237,6 @@ namespace MediaBrowser.Server.Implementations.Drawing
}
/// <summary>
- /// Draws the indicator.
- /// </summary>
- /// <param name="wand">The wand.</param>
- /// <param name="imageWidth">Width of the image.</param>
- /// <param name="imageHeight">Height of the image.</param>
- /// <param name="options">The options.</param>
- private void DrawIndicator(MagickWand wand, int imageWidth, int imageHeight, ImageProcessingOptions options)
- {
- if (!options.AddPlayedIndicator && !options.UnplayedCount.HasValue && options.PercentPlayed.Equals(0))
- {
- return;
- }
-
- try
- {
- if (options.AddPlayedIndicator)
- {
- var currentImageSize = new ImageSize(imageWidth, imageHeight);
-
- new PlayedIndicatorDrawer(_appPaths).DrawPlayedIndicator(wand, currentImageSize);
- }
- else if (options.UnplayedCount.HasValue)
- {
- var currentImageSize = new ImageSize(imageWidth, imageHeight);
-
- new UnplayedCountIndicator(_appPaths).DrawUnplayedCountIndicator(wand, currentImageSize, options.UnplayedCount.Value);
- }
-
- if (options.PercentPlayed > 0)
- {
- new PercentPlayedDrawer().Process(wand, options.PercentPlayed);
- }
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error drawing indicator overlay", ex);
- }
- }
-
- /// <summary>
/// Crops whitespace from an image, caches the result, and returns the cached path
/// </summary>
private async Task<Tuple<string, DateTime, long>> GetWhitespaceCroppedImage(string originalImagePath, DateTime dateModified, long length)
@@ -360,11 +262,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
{
Directory.CreateDirectory(Path.GetDirectoryName(croppedImagePath));
- using (var wand = new MagickWand(originalImagePath))
- {
- wand.CurrentImage.TrimImage(10);
- wand.SaveImage(croppedImagePath);
- }
+ _imageEncoder.CropWhiteSpace(originalImagePath, croppedImagePath);
}
catch (Exception ex)
{
@@ -500,17 +398,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
CheckDisposed();
- using (var wand = new MagickWand())
- {
- wand.PingImage(path);
- var img = wand.CurrentImage;
-
- size = new ImageSize
- {
- Width = img.Width,
- Height = img.Height
- };
- }
+ size = _imageEncoder.GetImageSize(path);
}
StartSaveImageSizeTimer();
@@ -838,6 +726,11 @@ namespace MediaBrowser.Server.Implementations.Drawing
return Path.Combine(path, filename);
}
+ public void CreateImageCollage(ImageCollageOptions options)
+ {
+ _imageEncoder.CreateImageCollage(options);
+ }
+
public IEnumerable<IImageEnhancer> GetSupportedEnhancers(IHasImages item, ImageType imageType)
{
return ImageEnhancers.Where(i =>
@@ -860,7 +753,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
public void Dispose()
{
_disposed = true;
- Wand.CloseEnvironment();
+ _imageEncoder.Dispose();
_saveImageSizeTimer.Dispose();
}
diff --git a/Emby.Drawing/Properties/AssemblyInfo.cs b/Emby.Drawing/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..fba168d03
--- /dev/null
+++ b/Emby.Drawing/Properties/AssemblyInfo.cs
@@ -0,0 +1,31 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Emby.Drawing")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Emby.Drawing")]
+[assembly: AssemblyCopyright("Copyright © 2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("87b6f14e-16d8-4a58-a553-fd9945e47458")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+// \ No newline at end of file
diff --git a/Emby.Drawing/packages.config b/Emby.Drawing/packages.config
new file mode 100644
index 000000000..a331f20b3
--- /dev/null
+++ b/Emby.Drawing/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="ImageMagickSharp" version="1.0.0.14" targetFramework="net45" />
+</packages> \ No newline at end of file
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs
index 08ac5671d..e91dd1a9b 100644
--- a/MediaBrowser.Api/ApiEntryPoint.cs
+++ b/MediaBrowser.Api/ApiEntryPoint.cs
@@ -151,7 +151,7 @@ namespace MediaBrowser.Api
{
lock (_activeTranscodingJobs)
{
- var job = new TranscodingJob
+ var job = new TranscodingJob(Logger)
{
Type = type,
Path = path,
@@ -284,28 +284,72 @@ namespace MediaBrowser.Api
{
job.ActiveRequestCount++;
- job.DisposeKillTimer();
+ if (string.IsNullOrWhiteSpace(job.PlaySessionId) || job.Type == TranscodingJobType.Progressive)
+ {
+ job.StopKillTimer();
+ }
}
-
+
public void OnTranscodeEndRequest(TranscodingJob job)
{
job.ActiveRequestCount--;
+ Logger.Debug("OnTranscodeEndRequest job.ActiveRequestCount={0}", job.ActiveRequestCount);
+ if (job.ActiveRequestCount <= 0)
+ {
+ PingTimer(job, false);
+ }
+ }
+ internal void PingTranscodingJob(string playSessionId)
+ {
+ if (string.IsNullOrEmpty(playSessionId))
+ {
+ throw new ArgumentNullException("playSessionId");
+ }
+
+ Logger.Debug("PingTranscodingJob PlaySessionId={0}", playSessionId);
+
+ var jobs = new List<TranscodingJob>();
- if (job.ActiveRequestCount == 0)
+ lock (_activeTranscodingJobs)
{
- // TODO: Lower this hls timeout
- var timerDuration = job.Type == TranscodingJobType.Progressive ?
- 1000 :
- 7200000;
+ // This is really only needed for HLS.
+ // Progressive streams can stop on their own reliably
+ jobs = jobs.Where(j => string.Equals(playSessionId, j.PlaySessionId, StringComparison.OrdinalIgnoreCase)).ToList();
+ }
- if (job.KillTimer == null)
- {
- job.KillTimer = new Timer(OnTranscodeKillTimerStopped, job, timerDuration, Timeout.Infinite);
- }
- else
- {
- job.KillTimer.Change(timerDuration, Timeout.Infinite);
- }
+ foreach (var job in jobs)
+ {
+ PingTimer(job, true);
+ }
+ }
+
+ private void PingTimer(TranscodingJob job, bool isProgressCheckIn)
+ {
+ if (job.HasExited)
+ {
+ job.StopKillTimer();
+ return;
+ }
+
+ // TODO: Lower this hls timeout
+ var timerDuration = job.Type == TranscodingJobType.Progressive ?
+ 1000 :
+ 1800000;
+
+ // We can really reduce the timeout for apps that are using the newer api
+ if (!string.IsNullOrWhiteSpace(job.PlaySessionId) && job.Type != TranscodingJobType.Progressive)
+ {
+ timerDuration = 20000;
+ }
+
+ // Don't start the timer for playback checkins with progressive streaming
+ if (job.Type != TranscodingJobType.Progressive || !isProgressCheckIn)
+ {
+ job.StartKillTimer(timerDuration, OnTranscodeKillTimerStopped);
+ }
+ else
+ {
+ job.ChangeKillTimerIfStarted(timerDuration);
}
}
@@ -317,6 +361,8 @@ namespace MediaBrowser.Api
{
var job = (TranscodingJob)state;
+ Logger.Debug("Transcoding kill timer stopped for JobId {0} PlaySessionId {1}. Killing transcoding", job.Id, job.PlaySessionId);
+
KillTranscodingJob(job, path => true);
}
@@ -329,19 +375,14 @@ namespace MediaBrowser.Api
/// <returns>Task.</returns>
internal void KillTranscodingJobs(string deviceId, string playSessionId, Func<string, bool> deleteFiles)
{
- if (string.IsNullOrEmpty(deviceId))
- {
- throw new ArgumentNullException("deviceId");
- }
-
KillTranscodingJobs(j =>
{
- if (string.Equals(deviceId, j.DeviceId, StringComparison.OrdinalIgnoreCase))
+ if (!string.IsNullOrWhiteSpace(playSessionId))
{
- return string.IsNullOrWhiteSpace(playSessionId) || string.Equals(playSessionId, j.PlaySessionId, StringComparison.OrdinalIgnoreCase);
+ return string.Equals(playSessionId, j.PlaySessionId, StringComparison.OrdinalIgnoreCase);
}
- return false;
+ return string.Equals(deviceId, j.DeviceId, StringComparison.OrdinalIgnoreCase);
}, deleteFiles);
}
@@ -381,6 +422,10 @@ namespace MediaBrowser.Api
/// <param name="delete">The delete.</param>
private void KillTranscodingJob(TranscodingJob job, Func<string, bool> delete)
{
+ job.DisposeKillTimer();
+
+ Logger.Debug("KillTranscodingJob - JobId {0} PlaySessionId {1}. Killing transcoding", job.Id, job.PlaySessionId);
+
lock (_activeTranscodingJobs)
{
_activeTranscodingJobs.Remove(job);
@@ -389,34 +434,23 @@ namespace MediaBrowser.Api
{
job.CancellationTokenSource.Cancel();
}
-
- job.DisposeKillTimer();
}
lock (job.ProcessLock)
{
- var process = job.Process;
-
- var hasExited = true;
-
- try
+ if (job.TranscodingThrottler != null)
{
- hasExited = process.HasExited;
- }
- catch (Exception ex)
- {
- Logger.ErrorException("Error determining if ffmpeg process has exited for {0}", ex, job.Path);
+ job.TranscodingThrottler.Stop();
}
+ var process = job.Process;
+
+ var hasExited = job.HasExited;
+
if (!hasExited)
{
try
{
- if (job.TranscodingThrottler != null)
- {
- job.TranscodingThrottler.Stop();
- }
-
Logger.Info("Killing ffmpeg process for {0}", job.Path);
//process.Kill();
@@ -558,6 +592,7 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The process.</value>
public Process Process { get; set; }
+ public ILogger Logger { get; private set; }
/// <summary>
/// Gets or sets the active request count.
/// </summary>
@@ -567,7 +602,7 @@ namespace MediaBrowser.Api
/// Gets or sets the kill timer.
/// </summary>
/// <value>The kill timer.</value>
- public Timer KillTimer { get; set; }
+ private Timer KillTimer { get; set; }
public string DeviceId { get; set; }
@@ -590,12 +625,74 @@ namespace MediaBrowser.Api
public TranscodingThrottler TranscodingThrottler { get; set; }
+ private readonly object _timerLock = new object();
+
+ public TranscodingJob(ILogger logger)
+ {
+ Logger = logger;
+ }
+
+ public void StopKillTimer()
+ {
+ lock (_timerLock)
+ {
+ if (KillTimer != null)
+ {
+ KillTimer.Change(Timeout.Infinite, Timeout.Infinite);
+ }
+ }
+ }
+
public void DisposeKillTimer()
{
- if (KillTimer != null)
+ lock (_timerLock)
+ {
+ if (KillTimer != null)
+ {
+ KillTimer.Dispose();
+ KillTimer = null;
+ }
+ }
+ }
+
+ public void StartKillTimer(int intervalMs, TimerCallback callback)
+ {
+ CheckHasExited();
+
+ lock (_timerLock)
+ {
+ if (KillTimer == null)
+ {
+ Logger.Debug("Starting kill timer at {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
+ KillTimer = new Timer(callback, this, intervalMs, Timeout.Infinite);
+ }
+ else
+ {
+ Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
+ KillTimer.Change(intervalMs, Timeout.Infinite);
+ }
+ }
+ }
+
+ public void ChangeKillTimerIfStarted(int intervalMs)
+ {
+ CheckHasExited();
+
+ lock (_timerLock)
+ {
+ if (KillTimer != null)
+ {
+ Logger.Debug("Changing kill timer to {0}ms. JobId {1} PlaySessionId {2}", intervalMs, Id, PlaySessionId);
+ KillTimer.Change(intervalMs, Timeout.Infinite);
+ }
+ }
+ }
+
+ private void CheckHasExited()
+ {
+ if (HasExited)
{
- KillTimer.Dispose();
- KillTimer = null;
+ throw new ObjectDisposedException("Job");
}
}
}
diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index 4465be97a..66b2a314e 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -259,7 +259,7 @@ namespace MediaBrowser.Api
.GetRecursiveChildren(i => i is IHasArtist)
.Cast<IHasArtist>()
.SelectMany(i => i.AllArtists)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.FirstOrDefault(i =>
{
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
@@ -281,7 +281,7 @@ namespace MediaBrowser.Api
return libraryManager.RootFolder.GetRecursiveChildren()
.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.FirstOrDefault(i =>
{
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
@@ -301,7 +301,7 @@ namespace MediaBrowser.Api
return libraryManager.RootFolder
.GetRecursiveChildren(i => i is Game)
.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.FirstOrDefault(i =>
{
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
@@ -324,7 +324,7 @@ namespace MediaBrowser.Api
return libraryManager.RootFolder
.GetRecursiveChildren()
.SelectMany(i => i.Studios)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.FirstOrDefault(i =>
{
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
@@ -348,7 +348,7 @@ namespace MediaBrowser.Api
.GetRecursiveChildren()
.SelectMany(i => i.People)
.Select(i => i.Name)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.FirstOrDefault(i =>
{
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs
index d0abd18c2..9f6c07dd2 100644
--- a/MediaBrowser.Api/ConfigurationService.cs
+++ b/MediaBrowser.Api/ConfigurationService.cs
@@ -123,7 +123,7 @@ namespace MediaBrowser.Api
public void Post(AutoSetMetadataOptions request)
{
- _configurationManager.DisableMetadataService("Media Browser Xml");
+ _configurationManager.DisableMetadataService("Emby Xml");
_configurationManager.SaveConfiguration();
}
diff --git a/MediaBrowser.Api/FilterService.cs b/MediaBrowser.Api/FilterService.cs
index fb51b2bdd..6d1c5d868 100644
--- a/MediaBrowser.Api/FilterService.cs
+++ b/MediaBrowser.Api/FilterService.cs
@@ -76,7 +76,7 @@ namespace MediaBrowser.Api
.ToArray();
result.Genres = items.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.OrderBy(i => i)
.ToArray();
diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
index 24c91e172..b8b74369c 100644
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dto;
@@ -186,6 +187,9 @@ namespace MediaBrowser.Api.LiveTv
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
public bool? IsMovie { get; set; }
+ [ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
+ public bool? IsSports { get; set; }
+
[ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? StartIndex { get; set; }
@@ -218,6 +222,9 @@ namespace MediaBrowser.Api.LiveTv
[ApiMember(Name = "HasAired", Description = "Optional. Filter by programs that have completed airing, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? HasAired { get; set; }
+ [ApiMember(Name = "IsSports", Description = "Optional filter for sports.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET,POST")]
+ public bool? IsSports { get; set; }
+
[ApiMember(Name = "IsMovie", Description = "Optional filter for movies.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsMovie { get; set; }
}
@@ -422,11 +429,12 @@ namespace MediaBrowser.Api.LiveTv
query.SortBy = (request.SortBy ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
query.SortOrder = request.SortOrder;
query.IsMovie = request.IsMovie;
+ query.IsSports = request.IsSports;
query.Genres = (request.Genres ?? String.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var result = await _liveTvManager.GetPrograms(query, CancellationToken.None).ConfigureAwait(false);
- return ToOptimizedSerializedResultUsingCache(result);
+ return ToOptimizedResult(result);
}
public async Task<object> Get(GetRecommendedPrograms request)
@@ -437,12 +445,13 @@ namespace MediaBrowser.Api.LiveTv
IsAiring = request.IsAiring,
Limit = request.Limit,
HasAired = request.HasAired,
- IsMovie = request.IsMovie
+ IsMovie = request.IsMovie,
+ IsSports = request.IsSports
};
var result = await _liveTvManager.GetRecommendedPrograms(query, CancellationToken.None).ConfigureAwait(false);
- return ToOptimizedSerializedResultUsingCache(result);
+ return ToOptimizedResult(result);
}
public object Post(GetPrograms request)
@@ -452,6 +461,9 @@ namespace MediaBrowser.Api.LiveTv
public async Task<object> Get(GetRecordings request)
{
+ var options = new DtoOptions();
+ options.DeviceId = AuthorizationContext.GetAuthorizationInfo(Request).DeviceId;
+
var result = await _liveTvManager.GetRecordings(new RecordingQuery
{
ChannelId = request.ChannelId,
@@ -463,16 +475,19 @@ namespace MediaBrowser.Api.LiveTv
SeriesTimerId = request.SeriesTimerId,
IsInProgress = request.IsInProgress
- }, CancellationToken.None).ConfigureAwait(false);
+ }, options, CancellationToken.None).ConfigureAwait(false);
- return ToOptimizedSerializedResultUsingCache(result);
+ return ToOptimizedResult(result);
}
public async Task<object> Get(GetRecording request)
{
var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(request.UserId);
- var result = await _liveTvManager.GetRecording(request.Id, CancellationToken.None, user).ConfigureAwait(false);
+ var options = new DtoOptions();
+ options.DeviceId = AuthorizationContext.GetAuthorizationInfo(Request).DeviceId;
+
+ var result = await _liveTvManager.GetRecording(request.Id, options, CancellationToken.None, user).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
index 07f5942c6..1a7f6d8f4 100644
--- a/MediaBrowser.Api/Movies/MoviesService.cs
+++ b/MediaBrowser.Api/Movies/MoviesService.cs
@@ -410,7 +410,7 @@ namespace MediaBrowser.Api.Movies
return items
.SelectMany(i => i.People.Where(p => !string.Equals(PersonType.Director, p.Type, StringComparison.OrdinalIgnoreCase)).Take(2))
.Select(i => i.Name)
- .Distinct(StringComparer.OrdinalIgnoreCase);
+ .DistinctNames();
}
private IEnumerable<string> GetDirectors(IEnumerable<BaseItem> items)
@@ -419,7 +419,7 @@ namespace MediaBrowser.Api.Movies
.Select(i => i.People.FirstOrDefault(p => string.Equals(PersonType.Director, p.Type, StringComparison.OrdinalIgnoreCase)))
.Where(i => i != null)
.Select(i => i.Name)
- .Distinct(StringComparer.OrdinalIgnoreCase);
+ .DistinctNames();
}
}
}
diff --git a/MediaBrowser.Api/Music/AlbumsService.cs b/MediaBrowser.Api/Music/AlbumsService.cs
index a1c98addb..37f79bf20 100644
--- a/MediaBrowser.Api/Music/AlbumsService.cs
+++ b/MediaBrowser.Api/Music/AlbumsService.cs
@@ -79,12 +79,12 @@ namespace MediaBrowser.Api.Music
var artists1 = album1
.AllArtists
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.ToList();
var artists2 = album2
.AllArtists
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
return points + artists1.Where(artists2.ContainsKey).Sum(i => 5);
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 75321f872..827aed4f2 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -1026,7 +1026,7 @@ namespace MediaBrowser.Api.Playback
// FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
state.LogFileStream = FileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true);
- var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(commandLineLogMessage + Environment.NewLine + Environment.NewLine);
+ var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(Request.AbsoluteUri + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine);
await state.LogFileStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false);
process.Exited += (sender, args) => OnFfMpegProcessExited(process, transcodingJob, state);
@@ -1515,6 +1515,10 @@ namespace MediaBrowser.Api.Playback
}
else if (i == 22)
{
+ // api_key
+ }
+ else if (i == 23)
+ {
request.LiveStreamId = val;
}
}
@@ -1624,14 +1628,19 @@ namespace MediaBrowser.Api.Playback
var archivable = item as IArchivable;
state.IsInputArchive = archivable != null && archivable.IsArchive;
- MediaSourceInfo mediaSource = null;
+ MediaSourceInfo mediaSource;
if (string.IsNullOrWhiteSpace(request.LiveStreamId))
{
- var mediaSources = await MediaSourceManager.GetPlayackMediaSources(request.Id, false, cancellationToken).ConfigureAwait(false);
+ var mediaSources = (await MediaSourceManager.GetPlayackMediaSources(request.Id, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false)).ToList();
mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
? mediaSources.First()
- : mediaSources.First(i => string.Equals(i.Id, request.MediaSourceId));
+ : mediaSources.FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId));
+
+ if (mediaSource == null && string.Equals(request.Id, request.MediaSourceId, StringComparison.OrdinalIgnoreCase))
+ {
+ mediaSource = mediaSources.First();
+ }
}
else
{
@@ -1700,6 +1709,102 @@ namespace MediaBrowser.Api.Playback
{
state.OutputAudioCodec = "copy";
}
+
+ if (string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && TranscodingJobType == TranscodingJobType.Hls)
+ {
+ var segmentLength = GetSegmentLength(state);
+ if (segmentLength.HasValue)
+ {
+ state.SegmentLength = segmentLength.Value;
+ }
+ }
+ }
+
+ private int? GetSegmentLength(StreamState state)
+ {
+ var stream = state.VideoStream;
+
+ if (stream == null)
+ {
+ return null;
+ }
+
+ var frames = stream.KeyFrames;
+
+ if (frames == null || frames.Count < 2)
+ {
+ return null;
+ }
+
+ Logger.Debug("Found keyframes at {0}", string.Join(",", frames.ToArray()));
+
+ var intervals = new List<int>();
+ for (var i = 1; i < frames.Count; i++)
+ {
+ var start = frames[i - 1];
+ var end = frames[i];
+ intervals.Add(end - start);
+ }
+
+ Logger.Debug("Found keyframes intervals {0}", string.Join(",", intervals.ToArray()));
+
+ var results = new List<Tuple<int, int>>();
+
+ for (var i = 1; i <= 10; i++)
+ {
+ var idealMs = i*1000;
+
+ if (intervals.Max() < idealMs - 1000)
+ {
+ break;
+ }
+
+ var segments = PredictStreamCopySegments(intervals, idealMs);
+ var variance = segments.Select(s => Math.Abs(idealMs - s)).Sum();
+
+ results.Add(new Tuple<int, int>(i, variance));
+ }
+
+ if (results.Count == 0)
+ {
+ return null;
+ }
+
+ return results.OrderBy(i => i.Item2).ThenBy(i => i.Item1).Select(i => i.Item1).First();
+ }
+
+ private List<int> PredictStreamCopySegments(List<int> intervals, int idealMs)
+ {
+ var segments = new List<int>();
+ var currentLength = 0;
+
+ foreach (var interval in intervals)
+ {
+ if (currentLength == 0 || (currentLength + interval) <= idealMs)
+ {
+ currentLength += interval;
+ }
+
+ else
+ {
+ // The segment will either be above or below the ideal.
+ // Need to figure out which is preferable
+ var offset1 = Math.Abs(idealMs - currentLength);
+ var offset2 = Math.Abs(idealMs - (currentLength + interval));
+
+ if (offset1 <= offset2)
+ {
+ segments.Add(currentLength);
+ currentLength = interval;
+ }
+ else
+ {
+ currentLength += interval;
+ }
+ }
+ }
+ Logger.Debug("Predicted actual segment lengths for length {0}: {1}", idealMs, string.Join(",", segments.ToArray()));
+ return segments;
}
private void AttachMediaSourceInfo(StreamState state,
diff --git a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs
index ba3f17257..0692c4863 100644
--- a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs
+++ b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs
@@ -5,7 +5,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.IO;
@@ -518,25 +517,14 @@ namespace MediaBrowser.Api.Playback.Dash
private async Task WaitForSegment(string playlist, string segment, CancellationToken cancellationToken)
{
- var tmpPath = playlist + ".tmp";
-
var segmentFilename = Path.GetFileName(segment);
Logger.Debug("Waiting for {0} in {1}", segmentFilename, playlist);
while (true)
{
- FileStream fileStream;
- try
- {
- fileStream = FileSystem.GetFileStream(tmpPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true);
- }
- catch (IOException)
- {
- fileStream = FileSystem.GetFileStream(playlist, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true);
- }
// Need to use FileShare.ReadWrite because we're reading the file at the same time it's being written
- using (fileStream)
+ using (var fileStream = GetPlaylistFileStream(playlist))
{
using (var reader = new StreamReader(fileStream))
{
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 207bc2f67..919fe0773 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -3,7 +3,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.IO;
@@ -86,6 +85,7 @@ namespace MediaBrowser.Api.Playback.Hls
state.Request.StartTimeTicks = null;
}
+ TranscodingJob job = null;
var playlist = state.OutputFilePath;
if (!File.Exists(playlist))
@@ -98,7 +98,7 @@ namespace MediaBrowser.Api.Playback.Hls
// If the playlist doesn't already exist, startup ffmpeg
try
{
- await StartFfMpeg(state, playlist, cancellationTokenSource).ConfigureAwait(false);
+ job = await StartFfMpeg(state, playlist, cancellationTokenSource).ConfigureAwait(false);
}
catch
{
@@ -117,6 +117,12 @@ namespace MediaBrowser.Api.Playback.Hls
if (isLive)
{
+ job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType);
+
+ if (job != null)
+ {
+ ApiEntryPoint.Instance.OnTranscodeEndRequest(job);
+ }
return ResultFactory.GetResult(GetLivePlaylistText(playlist, state.SegmentLength), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
@@ -135,6 +141,13 @@ namespace MediaBrowser.Api.Playback.Hls
var playlistText = GetMasterPlaylistFileText(playlist, videoBitrate + audioBitrate, appendBaselineStream, baselineStreamBitrate);
+ job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType);
+
+ if (job != null)
+ {
+ ApiEntryPoint.Instance.OnTranscodeEndRequest(job);
+ }
+
return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
@@ -186,7 +199,7 @@ namespace MediaBrowser.Api.Playback.Hls
while (true)
{
// Need to use FileShare.ReadWrite because we're reading the file at the same time it's being written
- using (var fileStream = FileSystem.GetFileStream(playlist, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
+ using (var fileStream = GetPlaylistFileStream(playlist))
{
using (var reader = new StreamReader(fileStream))
{
@@ -212,6 +225,20 @@ namespace MediaBrowser.Api.Playback.Hls
}
}
+ protected Stream GetPlaylistFileStream(string path)
+ {
+ var tmpPath = path + ".tmp";
+
+ try
+ {
+ return FileSystem.GetFileStream(tmpPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true);
+ }
+ catch (IOException)
+ {
+ return FileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true);
+ }
+ }
+
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
{
var hlsVideoRequest = state.VideoRequest as GetHlsVideoStream;
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index cbfadb886..1b11f1f33 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dlna;
@@ -128,9 +127,27 @@ namespace MediaBrowser.Api.Playback.Hls
}
else
{
+ var startTranscoding = false;
+
var currentTranscodingIndex = GetCurrentTranscodingIndex(playlistPath, segmentExtension);
- var segmentGapRequiringTranscodingChange = 24/state.SegmentLength;
- if (currentTranscodingIndex == null || requestedIndex < currentTranscodingIndex.Value || (requestedIndex - currentTranscodingIndex.Value) > segmentGapRequiringTranscodingChange)
+ var segmentGapRequiringTranscodingChange = 24 / state.SegmentLength;
+
+ if (currentTranscodingIndex == null)
+ {
+ Logger.Debug("Starting transcoding because currentTranscodingIndex=null");
+ startTranscoding = true;
+ }
+ else if (requestedIndex < currentTranscodingIndex.Value)
+ {
+ Logger.Debug("Starting transcoding because requestedIndex={0} and currentTranscodingIndex={1}", requestedIndex, currentTranscodingIndex);
+ startTranscoding = true;
+ }
+ else if ((requestedIndex - currentTranscodingIndex.Value) > segmentGapRequiringTranscodingChange)
+ {
+ Logger.Debug("Starting transcoding because segmentGap is {0} and max allowed gap is {1}. requestedIndex={2}", (requestedIndex - currentTranscodingIndex.Value), segmentGapRequiringTranscodingChange, requestedIndex);
+ startTranscoding = true;
+ }
+ if (startTranscoding)
{
// If the playlist doesn't already exist, startup ffmpeg
try
@@ -145,7 +162,6 @@ namespace MediaBrowser.Api.Playback.Hls
request.StartTimeTicks = GetSeekPositionTicks(state, requestedIndex);
job = await StartFfMpeg(state, playlistPath, cancellationTokenSource).ConfigureAwait(false);
- ApiEntryPoint.Instance.OnTranscodeBeginRequest(job);
}
catch
{
@@ -153,7 +169,15 @@ namespace MediaBrowser.Api.Playback.Hls
throw;
}
- await WaitForMinimumSegmentCount(playlistPath, 1, cancellationTokenSource.Token).ConfigureAwait(false);
+ //await WaitForMinimumSegmentCount(playlistPath, 1, cancellationTokenSource.Token).ConfigureAwait(false);
+ }
+ else
+ {
+ job = ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType);
+ if (job.TranscodingThrottler != null)
+ {
+ job.TranscodingThrottler.UnpauseTranscoding();
+ }
}
}
}
@@ -300,7 +324,7 @@ namespace MediaBrowser.Api.Playback.Hls
var segmentFilename = Path.GetFileName(segmentPath);
- using (var fileStream = FileSystem.GetFileStream(playlistPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
+ using (var fileStream = GetPlaylistFileStream(playlistPath))
{
using (var reader = new StreamReader(fileStream))
{
@@ -712,7 +736,7 @@ namespace MediaBrowser.Api.Playback.Hls
).Trim();
}
- return string.Format("{0} {1} -map_metadata -1 -threads {2} {3} {4} -flags -global_header -sc_threshold 0 {5} -hls_time {6} -start_number {7} -hls_list_size {8} -y \"{9}\"",
+ return string.Format("{0} {1} -map_metadata -1 -threads {2} {3} {4} -flags -global_header -copyts -sc_threshold 0 {5} -hls_time {6} -start_number {7} -hls_list_size {8} -y \"{9}\"",
inputModifier,
GetInputArgument(state),
threads,
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index b1964f4ae..8e2854c5e 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -3,12 +3,10 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.IO;
using ServiceStack;
using System;
-using System.IO;
namespace MediaBrowser.Api.Playback.Hls
{
diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs
index 08c5d56db..c71048b0d 100644
--- a/MediaBrowser.Api/Playback/MediaInfoService.cs
+++ b/MediaBrowser.Api/Playback/MediaInfoService.cs
@@ -1,4 +1,6 @@
-using MediaBrowser.Controller.Devices;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
@@ -59,23 +61,27 @@ namespace MediaBrowser.Api.Playback
private readonly IMediaSourceManager _mediaSourceManager;
private readonly IDeviceManager _deviceManager;
private readonly ILibraryManager _libraryManager;
+ private readonly IServerConfigurationManager _config;
+ private readonly INetworkManager _networkManager;
- public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager)
+ public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager)
{
_mediaSourceManager = mediaSourceManager;
_deviceManager = deviceManager;
_libraryManager = libraryManager;
+ _config = config;
+ _networkManager = networkManager;
}
public async Task<object> Get(GetPlaybackInfo request)
{
- var result = await GetPlaybackInfo(request.Id, request.UserId).ConfigureAwait(false);
+ var result = await GetPlaybackInfo(request.Id, request.UserId, new[] { MediaType.Audio, MediaType.Video }).ConfigureAwait(false);
return ToOptimizedResult(result);
}
public async Task<object> Get(GetLiveMediaInfo request)
{
- var result = await GetPlaybackInfo(request.Id, request.UserId).ConfigureAwait(false);
+ var result = await GetPlaybackInfo(request.Id, request.UserId, new[] { MediaType.Audio, MediaType.Video }).ConfigureAwait(false);
return ToOptimizedResult(result);
}
@@ -122,29 +128,32 @@ namespace MediaBrowser.Api.Playback
public async Task<object> Post(GetPostedPlaybackInfo request)
{
- var info = await GetPlaybackInfo(request.Id, request.UserId, request.MediaSourceId, request.LiveStreamId).ConfigureAwait(false);
var authInfo = AuthorizationContext.GetAuthorizationInfo(Request);
var profile = request.DeviceProfile;
- if (profile == null)
+
+ var caps = _deviceManager.GetCapabilities(authInfo.DeviceId);
+ if (caps != null)
{
- var caps = _deviceManager.GetCapabilities(authInfo.DeviceId);
- if (caps != null)
+ if (profile == null)
{
profile = caps.DeviceProfile;
}
}
+ var info = await GetPlaybackInfo(request.Id, request.UserId, new[] { MediaType.Audio, MediaType.Video }, request.MediaSourceId, request.LiveStreamId).ConfigureAwait(false);
+
if (profile != null)
{
var mediaSourceId = request.MediaSourceId;
+
SetDeviceSpecificData(request.Id, info, profile, authInfo, request.MaxStreamingBitrate, request.StartTimeTicks ?? 0, mediaSourceId, request.AudioStreamIndex, request.SubtitleStreamIndex);
}
return ToOptimizedResult(info);
}
- private async Task<PlaybackInfoResponse> GetPlaybackInfo(string id, string userId, string mediaSourceId = null, string liveStreamId = null)
+ private async Task<PlaybackInfoResponse> GetPlaybackInfo(string id, string userId, string[] supportedLiveMediaTypes, string mediaSourceId = null, string liveStreamId = null)
{
var result = new PlaybackInfoResponse();
@@ -153,7 +162,7 @@ namespace MediaBrowser.Api.Playback
IEnumerable<MediaSourceInfo> mediaSources;
try
{
- mediaSources = await _mediaSourceManager.GetPlayackMediaSources(id, userId, true, CancellationToken.None).ConfigureAwait(false);
+ mediaSources = await _mediaSourceManager.GetPlayackMediaSources(id, userId, true, supportedLiveMediaTypes, CancellationToken.None).ConfigureAwait(false);
}
catch (PlaybackException ex)
{
@@ -223,7 +232,7 @@ namespace MediaBrowser.Api.Playback
int? subtitleStreamIndex,
string playSessionId)
{
- var streamBuilder = new StreamBuilder();
+ var streamBuilder = new StreamBuilder(Logger);
var options = new VideoOptions
{
@@ -231,8 +240,7 @@ namespace MediaBrowser.Api.Playback
Context = EncodingContext.Streaming,
DeviceId = auth.DeviceId,
ItemId = item.Id.ToString("N"),
- Profile = profile,
- MaxBitrate = maxBitrate
+ Profile = profile
};
if (string.Equals(mediaSourceId, mediaSource.Id, StringComparison.OrdinalIgnoreCase))
@@ -248,6 +256,7 @@ namespace MediaBrowser.Api.Playback
// Dummy this up to fool StreamBuilder
mediaSource.SupportsDirectStream = true;
+ options.MaxBitrate = maxBitrate;
// The MediaSource supports direct stream, now test to see if the client supports it
var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ?
@@ -270,6 +279,8 @@ namespace MediaBrowser.Api.Playback
if (mediaSource.SupportsDirectStream)
{
+ options.MaxBitrate = GetMaxBitrate(maxBitrate);
+
// The MediaSource supports direct stream, now test to see if the client supports it
var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ?
streamBuilder.BuildAudioItem(options) :
@@ -288,6 +299,8 @@ namespace MediaBrowser.Api.Playback
if (mediaSource.SupportsTranscoding)
{
+ options.MaxBitrate = GetMaxBitrate(maxBitrate);
+
// The MediaSource supports direct stream, now test to see if the client supports it
var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ?
streamBuilder.BuildAudioItem(options) :
@@ -309,6 +322,18 @@ namespace MediaBrowser.Api.Playback
}
}
+ private int? GetMaxBitrate(int? clientMaxBitrate)
+ {
+ var maxBitrate = clientMaxBitrate;
+
+ if (_config.Configuration.RemoteClientBitrateLimit > 0 && !_networkManager.IsInLocalNetwork(Request.RemoteIp))
+ {
+ maxBitrate = Math.Min(maxBitrate ?? _config.Configuration.RemoteClientBitrateLimit, _config.Configuration.RemoteClientBitrateLimit);
+ }
+
+ return maxBitrate;
+ }
+
private void SetDeviceSpecificSubtitleInfo(StreamInfo info, MediaSourceInfo mediaSource, string accessToken)
{
var profiles = info.GetSubtitleProfiles(false, "-", accessToken);
diff --git a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
index 4a51f8644..6a3443f35 100644
--- a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
+++ b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
@@ -63,6 +63,13 @@ namespace MediaBrowser.Api.Playback.Progressive
new ProgressiveFileCopier(_fileSystem, _job)
.StreamFile(Path, responseStream);
}
+ catch (IOException)
+ {
+ // These error are always the same so don't dump the whole stack trace
+ Logger.Error("Error streaming media. The client has most likely disconnected or transcoding has failed.");
+
+ throw;
+ }
catch (Exception ex)
{
Logger.ErrorException("Error streaming media. The client has most likely disconnected or transcoding has failed.", ex);
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index 540c39a0c..0ded108b1 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -5,7 +5,6 @@ using MediaBrowser.Controller.Devices;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.IO;
using ServiceStack;
diff --git a/MediaBrowser.Api/Playback/TranscodingThrottler.cs b/MediaBrowser.Api/Playback/TranscodingThrottler.cs
index 58cfa086e..ece455009 100644
--- a/MediaBrowser.Api/Playback/TranscodingThrottler.cs
+++ b/MediaBrowser.Api/Playback/TranscodingThrottler.cs
@@ -70,7 +70,7 @@ namespace MediaBrowser.Api.Playback
}
}
- private void UnpauseTranscoding()
+ public void UnpauseTranscoding()
{
if (_isPaused)
{
diff --git a/MediaBrowser.Api/Session/SessionsService.cs b/MediaBrowser.Api/Session/SessionsService.cs
index 52ecb95ec..d4ea6a0eb 100644
--- a/MediaBrowser.Api/Session/SessionsService.cs
+++ b/MediaBrowser.Api/Session/SessionsService.cs
@@ -383,12 +383,12 @@ namespace MediaBrowser.Api.Session
if (!user.Policy.EnableRemoteControlOfOtherUsers)
{
- result = result.Where(i => i.ContainsUser(request.ControllableByUserId.Value));
+ result = result.Where(i => !i.UserId.HasValue || i.ContainsUser(request.ControllableByUserId.Value));
}
if (!user.Policy.EnableSharedDeviceControl)
{
- result = result.Where(i => !i.UserId.HasValue);
+ result = result.Where(i => i.UserId.HasValue);
}
result = result.Where(i =>
diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs
index e061c391a..fb04dd030 100644
--- a/MediaBrowser.Api/SimilarItemsHelper.cs
+++ b/MediaBrowser.Api/SimilarItemsHelper.cs
@@ -170,7 +170,7 @@ namespace MediaBrowser.Api
points += item1.Studios.Where(i => item2.Studios.Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 3);
var item2PeopleNames = item2.People.Select(i => i.Name)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
points += item1.People.Where(i => item2PeopleNames.ContainsKey(i.Name)).Sum(i =>
diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs
index 73589d677..a70118d3c 100644
--- a/MediaBrowser.Api/Subtitles/SubtitleService.cs
+++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs
@@ -136,11 +136,11 @@ namespace MediaBrowser.Api.Subtitles
_providerManager = providerManager;
}
- public object Get(GetSubtitlePlaylist request)
+ public async Task<object> Get(GetSubtitlePlaylist request)
{
var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
- var mediaSource = _mediaSourceManager.GetStaticMediaSource(item, request.MediaSourceId, false);
+ var mediaSource = await _mediaSourceManager.GetMediaSource(item, request.MediaSourceId, false).ConfigureAwait(false);
var builder = new StringBuilder();
diff --git a/MediaBrowser.Api/Sync/SyncService.cs b/MediaBrowser.Api/Sync/SyncService.cs
index b9dbf5946..d5f88e6a4 100644
--- a/MediaBrowser.Api/Sync/SyncService.cs
+++ b/MediaBrowser.Api/Sync/SyncService.cs
@@ -248,6 +248,9 @@ namespace MediaBrowser.Api.Sync
result.Targets = _syncManager.GetSyncTargets(request.UserId)
.ToList();
+ var auth = AuthorizationContext.GetAuthorizationInfo(Request);
+ var authenticatedUser = _userManager.GetUserById(auth.UserId);
+
if (!string.IsNullOrWhiteSpace(request.TargetId))
{
result.Targets = result.Targets
@@ -255,11 +258,11 @@ namespace MediaBrowser.Api.Sync
.ToList();
result.QualityOptions = _syncManager
- .GetQualityOptions(request.TargetId)
+ .GetQualityOptions(request.TargetId, authenticatedUser)
.ToList();
result.ProfileOptions = _syncManager
- .GetProfileOptions(request.TargetId)
+ .GetProfileOptions(request.TargetId, authenticatedUser)
.ToList();
}
@@ -277,10 +280,6 @@ namespace MediaBrowser.Api.Sync
}
};
- var auth = AuthorizationContext.GetAuthorizationInfo(Request);
-
- var authenticatedUser = _userManager.GetUserById(auth.UserId);
-
var items = request.ItemIds.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(_libraryManager.GetItemById)
.Where(i => i != null);
diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs
index dd9825deb..9f3f17465 100644
--- a/MediaBrowser.Api/UserLibrary/ArtistsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ArtistsService.cs
@@ -132,7 +132,7 @@ namespace MediaBrowser.Api.UserLibrary
.Where(i => !i.IsFolder)
.OfType<IHasAlbumArtist>()
.SelectMany(i => i.AlbumArtists)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(name =>
{
try
@@ -152,7 +152,7 @@ namespace MediaBrowser.Api.UserLibrary
.Where(i => !i.IsFolder)
.OfType<IHasArtist>()
.SelectMany(i => i.AllArtists)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(name =>
{
try
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
index 609c1048f..b2364ce3c 100644
--- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
+++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
@@ -142,7 +142,7 @@ namespace MediaBrowser.Api.UserLibrary
}
IEnumerable<Tuple<TItemType, List<BaseItem>>> tuples;
- if (dtoOptions.Fields.Contains(ItemFields.ItemCounts) || true)
+ if (dtoOptions.Fields.Contains(ItemFields.ItemCounts))
{
tuples = ibnItems.Select(i => new Tuple<TItemType, List<BaseItem>>(i, i.GetTaggedItems(libraryItems).ToList()));
}
@@ -177,7 +177,6 @@ namespace MediaBrowser.Api.UserLibrary
return true;
}
- return true;
return options.Fields.Contains(ItemFields.ItemCounts);
}
diff --git a/MediaBrowser.Api/UserLibrary/GameGenresService.cs b/MediaBrowser.Api/UserLibrary/GameGenresService.cs
index 3063e19c7..2f7430d33 100644
--- a/MediaBrowser.Api/UserLibrary/GameGenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/GameGenresService.cs
@@ -105,7 +105,7 @@ namespace MediaBrowser.Api.UserLibrary
return itemsList
.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(name => LibraryManager.GetGameGenre(name));
}
}
diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs
index c659852de..63c0575bf 100644
--- a/MediaBrowser.Api/UserLibrary/GenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/GenresService.cs
@@ -108,7 +108,7 @@ namespace MediaBrowser.Api.UserLibrary
{
return items
.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(name =>
{
try
diff --git a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
index 3733128f0..1fe9dfaaa 100644
--- a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
@@ -105,7 +105,7 @@ namespace MediaBrowser.Api.UserLibrary
return itemsList
.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(name => LibraryManager.GetMusicGenre(name));
}
}
diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs
index e9b3fa402..08ee6e462 100644
--- a/MediaBrowser.Api/UserLibrary/PersonsService.cs
+++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs
@@ -127,7 +127,7 @@ namespace MediaBrowser.Api.UserLibrary
return allPeople
.Select(i => i.Name)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(name =>
{
diff --git a/MediaBrowser.Api/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs
index 55e1681e0..4661abf4c 100644
--- a/MediaBrowser.Api/UserLibrary/PlaystateService.cs
+++ b/MediaBrowser.Api/UserLibrary/PlaystateService.cs
@@ -114,6 +114,15 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "SubtitleStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
public int? SubtitleStreamIndex { get; set; }
+
+ [ApiMember(Name = "PlayMethod", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public PlayMethod PlayMethod { get; set; }
+
+ [ApiMember(Name = "LiveStreamId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string LiveStreamId { get; set; }
+
+ [ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string PlaySessionId { get; set; }
}
/// <summary>
@@ -160,6 +169,15 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "VolumeLevel", Description = "Scale of 0-100", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
public int? VolumeLevel { get; set; }
+
+ [ApiMember(Name = "PlayMethod", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public PlayMethod PlayMethod { get; set; }
+
+ [ApiMember(Name = "LiveStreamId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string LiveStreamId { get; set; }
+
+ [ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string PlaySessionId { get; set; }
}
/// <summary>
@@ -191,6 +209,12 @@ namespace MediaBrowser.Api.UserLibrary
/// <value>The position ticks.</value>
[ApiMember(Name = "PositionTicks", Description = "Optional. The position, in ticks, where playback stopped. 1 tick = 10000 ms", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "DELETE")]
public long? PositionTicks { get; set; }
+
+ [ApiMember(Name = "LiveStreamId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string LiveStreamId { get; set; }
+
+ [ApiMember(Name = "PlaySessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string PlaySessionId { get; set; }
}
[Authenticated]
@@ -260,7 +284,10 @@ namespace MediaBrowser.Api.UserLibrary
QueueableMediaTypes = queueableMediaTypes.Split(',').ToList(),
MediaSourceId = request.MediaSourceId,
AudioStreamIndex = request.AudioStreamIndex,
- SubtitleStreamIndex = request.SubtitleStreamIndex
+ SubtitleStreamIndex = request.SubtitleStreamIndex,
+ PlayMethod = request.PlayMethod,
+ PlaySessionId = request.PlaySessionId,
+ LiveStreamId = request.LiveStreamId
});
}
@@ -288,12 +315,20 @@ namespace MediaBrowser.Api.UserLibrary
MediaSourceId = request.MediaSourceId,
AudioStreamIndex = request.AudioStreamIndex,
SubtitleStreamIndex = request.SubtitleStreamIndex,
- VolumeLevel = request.VolumeLevel
+ VolumeLevel = request.VolumeLevel,
+ PlayMethod = request.PlayMethod,
+ PlaySessionId = request.PlaySessionId,
+ LiveStreamId = request.LiveStreamId
});
}
public void Post(ReportPlaybackProgress request)
{
+ if (!string.IsNullOrWhiteSpace(request.PlaySessionId))
+ {
+ ApiEntryPoint.Instance.PingTranscodingJob(request.PlaySessionId);
+ }
+
request.SessionId = GetSession().Result.Id;
var task = _sessionManager.OnPlaybackProgress(request);
@@ -311,12 +346,19 @@ namespace MediaBrowser.Api.UserLibrary
{
ItemId = request.Id,
PositionTicks = request.PositionTicks,
- MediaSourceId = request.MediaSourceId
+ MediaSourceId = request.MediaSourceId,
+ PlaySessionId = request.PlaySessionId,
+ LiveStreamId = request.LiveStreamId
});
}
public void Post(ReportPlaybackStopped request)
{
+ if (!string.IsNullOrWhiteSpace(request.PlaySessionId))
+ {
+ ApiEntryPoint.Instance.KillTranscodingJobs(AuthorizationContext.GetAuthorizationInfo(Request).DeviceId, request.PlaySessionId, s => true);
+ }
+
request.SessionId = GetSession().Result.Id;
var task = _sessionManager.OnPlaybackStopped(request);
diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs
index a4ebef684..ae1da0346 100644
--- a/MediaBrowser.Api/UserLibrary/StudiosService.cs
+++ b/MediaBrowser.Api/UserLibrary/StudiosService.cs
@@ -109,7 +109,7 @@ namespace MediaBrowser.Api.UserLibrary
return itemsList
.SelectMany(i => i.Studios)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(name => LibraryManager.GetStudio(name));
}
}
diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
index bc1b0e785..70ed5c319 100644
--- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
+++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
@@ -102,12 +102,6 @@ namespace MediaBrowser.Common.Implementations
public List<string> FailedAssemblies { get; protected set; }
/// <summary>
- /// Gets all types within all running assemblies
- /// </summary>
- /// <value>All types.</value>
- public Type[] AllTypes { get; protected set; }
-
- /// <summary>
/// Gets all concrete types.
/// </summary>
/// <value>All concrete types.</value>
@@ -438,9 +432,10 @@ namespace MediaBrowser.Common.Implementations
Logger.Info("Loading {0}", assembly.FullName);
}
- AllTypes = assemblies.SelectMany(GetTypes).ToArray();
-
- AllConcreteTypes = AllTypes.Where(t => t.IsClass && !t.IsAbstract && !t.IsInterface && !t.IsGenericType).ToArray();
+ AllConcreteTypes = assemblies
+ .SelectMany(GetTypes)
+ .Where(t => t.IsClass && !t.IsAbstract && !t.IsInterface && !t.IsGenericType)
+ .ToArray();
}
/// <summary>
diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
index 1762ed575..0fd4e2787 100644
--- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
+++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
@@ -172,11 +172,11 @@ namespace MediaBrowser.Common.Implementations.Networking
Uri uri;
if (Uri.TryCreate(endpoint, UriKind.RelativeOrAbsolute, out uri))
{
- var host = uri.DnsSafeHost;
- Logger.Debug("Resolving host {0}", host);
-
try
{
+ var host = uri.DnsSafeHost;
+ Logger.Debug("Resolving host {0}", host);
+
address = GetIpAddresses(host).FirstOrDefault();
if (address != null)
@@ -186,9 +186,13 @@ namespace MediaBrowser.Common.Implementations.Networking
return IsInLocalNetworkInternal(address.ToString(), false);
}
}
+ catch (InvalidOperationException)
+ {
+ // Can happen with reverse proxy or IIS url rewriting
+ }
catch (Exception ex)
{
- Logger.ErrorException("Error resovling hostname {0}", ex, host);
+ Logger.ErrorException("Error resovling hostname", ex);
}
}
}
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
index 78dcea493..c2551731f 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
@@ -121,12 +121,12 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
{
if (_lastExecutionResult == null)
{
+ var path = GetHistoryFilePath();
+
lock (_lastExecutionResultSyncLock)
{
if (_lastExecutionResult == null)
{
- var path = GetHistoryFilePath();
-
try
{
return JsonSerializer.DeserializeFromFile<TaskResult>(path);
@@ -152,6 +152,14 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
private set
{
_lastExecutionResult = value;
+
+ var path = GetHistoryFilePath();
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+
+ lock (_lastExecutionResultSyncLock)
+ {
+ JsonSerializer.SerializeToFile(value, path);
+ }
}
}
@@ -582,11 +590,6 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
result.LongErrorMessage = ex.StackTrace;
}
- var path = GetHistoryFilePath();
- Directory.CreateDirectory(Path.GetDirectoryName(path));
-
- JsonSerializer.SerializeToFile(result, path);
-
LastExecutionResult = result;
((TaskManager)TaskManager).OnTaskCompleted(this, result);
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index b6514ca0a..f746d87ff 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -5,7 +5,6 @@ using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Channels
{
@@ -15,19 +14,9 @@ namespace MediaBrowser.Controller.Channels
public override bool IsVisible(User user)
{
- if (user.Policy.BlockedChannels != null)
+ if (!user.Policy.EnableAllChannels && !user.Policy.EnabledChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
{
- if (user.Policy.BlockedChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
- {
- return false;
- }
- }
- else
- {
- if (!user.Policy.EnableAllChannels && !user.Policy.EnabledChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
- {
- return false;
- }
+ return false;
}
return base.IsVisible(user);
diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
index 8d9024676..82fe66c7b 100644
--- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
@@ -100,5 +101,10 @@ namespace MediaBrowser.Controller.Channels
{
return false;
}
+
+ public override bool IsVisibleStandalone(User user)
+ {
+ return IsVisibleStandaloneInternal(user, false) && ChannelVideoItem.IsChannelVisible(this, user);
+ }
}
}
diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
index 7ba73d126..641d37161 100644
--- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
@@ -80,5 +80,10 @@ namespace MediaBrowser.Controller.Channels
{
return false;
}
+
+ public override bool IsVisibleStandalone(User user)
+ {
+ return IsVisibleStandaloneInternal(user, false) && ChannelVideoItem.IsChannelVisible(this, user);
+ }
}
}
diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
index 8eec2021b..ef3cc7cba 100644
--- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
@@ -130,5 +130,17 @@ namespace MediaBrowser.Controller.Channels
{
return false;
}
+
+ public override bool IsVisibleStandalone(User user)
+ {
+ return IsVisibleStandaloneInternal(user, false) && IsChannelVisible(this, user);
+ }
+
+ internal static bool IsChannelVisible(IChannelItem item, User user)
+ {
+ var channel = ChannelManager.GetChannel(item.ChannelId);
+
+ return channel.IsVisible(user);
+ }
}
}
diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
index 6fafc2b46..685d2706d 100644
--- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs
+++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
@@ -14,6 +14,12 @@ namespace MediaBrowser.Controller.Drawing
public interface IImageProcessor
{
/// <summary>
+ /// Gets the supported input formats.
+ /// </summary>
+ /// <value>The supported input formats.</value>
+ string[] SupportedInputFormats { get; }
+
+ /// <summary>
/// Gets the image enhancers.
/// </summary>
/// <value>The image enhancers.</value>
@@ -93,5 +99,11 @@ namespace MediaBrowser.Controller.Drawing
/// </summary>
/// <returns>ImageOutputFormat[].</returns>
ImageFormat[] GetSupportedImageOutputFormats();
+
+ /// <summary>
+ /// Creates the image collage.
+ /// </summary>
+ /// <param name="options">The options.</param>
+ void CreateImageCollage(ImageCollageOptions options);
}
}
diff --git a/MediaBrowser.Controller/Drawing/ImageCollageOptions.cs b/MediaBrowser.Controller/Drawing/ImageCollageOptions.cs
new file mode 100644
index 000000000..edc4f8558
--- /dev/null
+++ b/MediaBrowser.Controller/Drawing/ImageCollageOptions.cs
@@ -0,0 +1,32 @@
+
+namespace MediaBrowser.Controller.Drawing
+{
+ public class ImageCollageOptions
+ {
+ /// <summary>
+ /// Gets or sets the input paths.
+ /// </summary>
+ /// <value>The input paths.</value>
+ public string[] InputPaths { get; set; }
+ /// <summary>
+ /// Gets or sets the output path.
+ /// </summary>
+ /// <value>The output path.</value>
+ public string OutputPath { get; set; }
+ /// <summary>
+ /// Gets or sets the width.
+ /// </summary>
+ /// <value>The width.</value>
+ public int Width { get; set; }
+ /// <summary>
+ /// Gets or sets the height.
+ /// </summary>
+ /// <value>The height.</value>
+ public int Height { get; set; }
+ /// <summary>
+ /// Gets or sets the text.
+ /// </summary>
+ /// <value>The text.</value>
+ public string Text { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs
index ea311d993..5ec8f274b 100644
--- a/MediaBrowser.Controller/Dto/IDtoService.cs
+++ b/MediaBrowser.Controller/Dto/IDtoService.cs
@@ -36,6 +36,14 @@ namespace MediaBrowser.Controller.Dto
BaseItemDto GetBaseItemDto(BaseItem item, List<ItemFields> fields, User user = null, BaseItem owner = null);
/// <summary>
+ /// Fills the synchronize information.
+ /// </summary>
+ /// <param name="dtos">The dtos.</param>
+ /// <param name="options">The options.</param>
+ /// <param name="user">The user.</param>
+ void FillSyncInfo(IEnumerable<IHasSyncInfo> dtos, DtoOptions options, User user);
+
+ /// <summary>
/// Gets the base item dto.
/// </summary>
/// <param name="item">The item.</param>
diff --git a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs
index 56921409a..254f90376 100644
--- a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs
@@ -1,6 +1,5 @@
-using System;
+using MediaBrowser.Controller.Library;
using System.Collections.Generic;
-using System.Linq;
namespace MediaBrowser.Controller.Entities.Audio
{
@@ -20,11 +19,11 @@ namespace MediaBrowser.Controller.Entities.Audio
{
public static bool HasArtist(this IHasArtist hasArtist, string artist)
{
- return hasArtist.Artists.Contains(artist, StringComparer.OrdinalIgnoreCase);
+ return NameExtensions.EqualsAny(hasArtist.Artists, artist);
}
public static bool HasAnyArtist(this IHasArtist hasArtist, string artist)
{
- return hasArtist.AllArtists.Contains(artist, StringComparer.OrdinalIgnoreCase);
+ return NameExtensions.EqualsAny(hasArtist.AllArtists, artist);
}
}
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index cdb52ec66..b7322494d 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using System.Globalization;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Collections;
@@ -44,7 +45,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// The supported image extensions
/// </summary>
- public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg", ".tbn" };
+ public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg" };
public static readonly List<string> SupportedImageExtensionsList = SupportedImageExtensions.ToList();
@@ -1144,6 +1145,11 @@ namespace MediaBrowser.Controller.Entities
public virtual bool IsVisibleStandalone(User user)
{
+ return IsVisibleStandaloneInternal(user, true);
+ }
+
+ protected bool IsVisibleStandaloneInternal(User user, bool checkFolders)
+ {
if (!IsVisible(user))
{
return false;
@@ -1154,7 +1160,23 @@ namespace MediaBrowser.Controller.Entities
return false;
}
- // TODO: Need some work here, e.g. is in user library, for channels, can user access channel, etc.
+ if (checkFolders)
+ {
+ var topParent = Parents.LastOrDefault() ?? this;
+
+ if (string.IsNullOrWhiteSpace(topParent.Path))
+ {
+ return true;
+ }
+
+ var userCollectionFolders = user.RootFolder.GetChildren(user, true).Select(i => i.Id).ToList();
+ var itemCollectionFolders = LibraryManager.GetCollectionFolders(this).Select(i => i.Id);
+
+ if (!itemCollectionFolders.Any(userCollectionFolders.Contains))
+ {
+ return false;
+ }
+ }
return true;
}
@@ -1219,18 +1241,6 @@ namespace MediaBrowser.Controller.Entities
private BaseItem FindLinkedChild(LinkedChild info)
{
- if (!string.IsNullOrWhiteSpace(info.ItemName))
- {
- if (string.Equals(info.ItemType, "musicgenre", StringComparison.OrdinalIgnoreCase))
- {
- return LibraryManager.GetMusicGenre(info.ItemName);
- }
- if (string.Equals(info.ItemType, "musicartist", StringComparison.OrdinalIgnoreCase))
- {
- return LibraryManager.GetArtist(info.ItemName);
- }
- }
-
if (!string.IsNullOrEmpty(info.Path))
{
var itemByPath = LibraryManager.RootFolder.FindByPath(info.Path);
@@ -1243,23 +1253,6 @@ namespace MediaBrowser.Controller.Entities
return itemByPath;
}
- if (!string.IsNullOrWhiteSpace(info.ItemName) && !string.IsNullOrWhiteSpace(info.ItemType))
- {
- return LibraryManager.RootFolder.GetRecursiveChildren(i =>
- {
- if (string.Equals(i.Name, info.ItemName, StringComparison.OrdinalIgnoreCase))
- {
- if (string.Equals(i.GetType().Name, info.ItemType, StringComparison.OrdinalIgnoreCase))
- {
- return true;
- }
- }
-
- return false;
-
- }).FirstOrDefault();
- }
-
return null;
}
@@ -1540,7 +1533,7 @@ namespace MediaBrowser.Controller.Entities
}
// Remove it from the item
- ImageInfos.Remove(info);
+ RemoveImage(info);
// Delete the source file
var currentFile = new FileInfo(info.Path);
@@ -1559,6 +1552,11 @@ namespace MediaBrowser.Controller.Entities
return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
}
+ public void RemoveImage(ItemImageInfo image)
+ {
+ ImageInfos.Remove(image);
+ }
+
public virtual Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken)
{
return LibraryManager.UpdateItem(this, updateReason, cancellationToken);
@@ -1651,7 +1649,7 @@ namespace MediaBrowser.Controller.Entities
public bool AddImages(ImageType imageType, IEnumerable<FileInfo> images)
{
- return AddImages(imageType, images.Cast<FileSystemInfo>());
+ return AddImages(imageType, images.Cast<FileSystemInfo>().ToList());
}
/// <summary>
@@ -1661,7 +1659,7 @@ namespace MediaBrowser.Controller.Entities
/// <param name="images">The images.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
/// <exception cref="System.ArgumentException">Cannot call AddImages with chapter images</exception>
- public bool AddImages(ImageType imageType, IEnumerable<FileSystemInfo> images)
+ public bool AddImages(ImageType imageType, List<FileSystemInfo> images)
{
if (imageType == ImageType.Chapter)
{
@@ -1672,6 +1670,7 @@ namespace MediaBrowser.Controller.Entities
.ToList();
var newImageList = new List<FileSystemInfo>();
+ var imageAdded = false;
foreach (var newImage in images)
{
@@ -1686,14 +1685,26 @@ namespace MediaBrowser.Controller.Entities
if (existing == null)
{
newImageList.Add(newImage);
+ imageAdded = true;
}
else
{
existing.DateModified = FileSystem.GetLastWriteTimeUtc(newImage);
- existing.Length = ((FileInfo) newImage).Length;
+ existing.Length = ((FileInfo)newImage).Length;
}
}
+ if (imageAdded || images.Count != existingImages.Count)
+ {
+ var newImagePaths = images.Select(i => i.FullName).ToList();
+
+ var deleted = existingImages
+ .Where(i => !newImagePaths.Contains(i.Path, StringComparer.OrdinalIgnoreCase) && !File.Exists(i.Path))
+ .ToList();
+
+ ImageInfos = ImageInfos.Except(deleted).ToList();
+ }
+
ImageInfos.AddRange(newImageList.Select(i => GetImageInfo(i, imageType)));
return newImageList.Count > 0;
@@ -1882,5 +1893,18 @@ namespace MediaBrowser.Controller.Entities
return video.RefreshMetadata(newOptions, cancellationToken);
}
+
+ public string GetEtag()
+ {
+ return string.Join("|", GetEtagValues().ToArray()).GetMD5().ToString("N");
+ }
+
+ protected virtual List<string> GetEtagValues()
+ {
+ return new List<string>
+ {
+ DateLastSaved.Ticks.ToString(CultureInfo.InvariantCulture)
+ };
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index cffc0989a..61e5acdb3 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -334,22 +334,9 @@ namespace MediaBrowser.Controller.Entities
{
if (this is ICollectionFolder && !(this is BasePluginFolder))
{
- if (user.Policy.BlockedMediaFolders != null)
+ if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
{
- if (user.Policy.BlockedMediaFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase) ||
-
- // Backwards compatibility
- user.Policy.BlockedMediaFolders.Contains(Name, StringComparer.OrdinalIgnoreCase))
- {
- return false;
- }
- }
- else
- {
- if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
- {
- return false;
- }
+ return false;
}
}
@@ -1004,8 +991,9 @@ namespace MediaBrowser.Controller.Entities
}
var locations = user.RootFolder
- .GetChildren(user, true)
+ .Children
.OfType<CollectionFolder>()
+ .Where(i => i.IsVisible(user))
.SelectMany(i => i.PhysicalLocations)
.ToList();
diff --git a/MediaBrowser.Controller/Entities/IHasImages.cs b/MediaBrowser.Controller/Entities/IHasImages.cs
index 00a42271b..1871d7b68 100644
--- a/MediaBrowser.Controller/Entities/IHasImages.cs
+++ b/MediaBrowser.Controller/Entities/IHasImages.cs
@@ -141,7 +141,7 @@ namespace MediaBrowser.Controller.Entities
/// <param name="imageType">Type of the image.</param>
/// <param name="images">The images.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
- bool AddImages(ImageType imageType, IEnumerable<FileSystemInfo> images);
+ bool AddImages(ImageType imageType, List<FileSystemInfo> images);
/// <summary>
/// Determines whether [is save local metadata enabled].
@@ -190,6 +190,12 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <returns><c>true</c> if [is internet metadata enabled]; otherwise, <c>false</c>.</returns>
bool IsInternetMetadataEnabled();
+
+ /// <summary>
+ /// Removes the image.
+ /// </summary>
+ /// <param name="image">The image.</param>
+ void RemoveImage(ItemImageInfo image);
}
public static class HasImagesExtensions
diff --git a/MediaBrowser.Controller/Entities/LinkedChild.cs b/MediaBrowser.Controller/Entities/LinkedChild.cs
index 949c9741b..ac13657b9 100644
--- a/MediaBrowser.Controller/Entities/LinkedChild.cs
+++ b/MediaBrowser.Controller/Entities/LinkedChild.cs
@@ -9,9 +9,6 @@ namespace MediaBrowser.Controller.Entities
public string Path { get; set; }
public LinkedChildType Type { get; set; }
- public string ItemName { get; set; }
- public string ItemType { get; set; }
-
[IgnoreDataMember]
public string Id { get; set; }
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index 0778643da..02e9d4cf9 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -175,19 +175,19 @@ namespace MediaBrowser.Controller.Entities.Movies
public override bool IsVisible(User user)
{
- if (base.IsVisible(user))
- {
- var userId = user.Id.ToString("N");
-
- // Need to check Count > 0 for boxsets created prior to the introduction of Shares
- if (Shares.Count > 0 && !Shares.Any(i => string.Equals(userId, i.UserId, StringComparison.OrdinalIgnoreCase)))
- {
- //return false;
- }
+ var userId = user.Id.ToString("N");
+ // Need to check Count > 0 for boxsets created prior to the introduction of Shares
+ if (Shares.Count > 0 && Shares.Any(i => string.Equals(userId, i.UserId, StringComparison.OrdinalIgnoreCase)))
+ {
return true;
}
+ if (base.IsVisible(user))
+ {
+ return GetChildren(user, true).Any();
+ }
+
return false;
}
}
diff --git a/MediaBrowser.Controller/Entities/PhotoAlbum.cs b/MediaBrowser.Controller/Entities/PhotoAlbum.cs
index 24ebf8815..5b48a70e9 100644
--- a/MediaBrowser.Controller/Entities/PhotoAlbum.cs
+++ b/MediaBrowser.Controller/Entities/PhotoAlbum.cs
@@ -1,11 +1,15 @@
-using MediaBrowser.Model.Configuration;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Users;
+using System;
using System.Linq;
using System.Runtime.Serialization;
-using MediaBrowser.Model.Users;
+using System.Threading;
+using System.Threading.Tasks;
namespace MediaBrowser.Controller.Entities
{
- public class PhotoAlbum : Folder
+ public class PhotoAlbum : Folder, IMetadataContainer
{
public override bool SupportsLocalMetadata
{
@@ -28,5 +32,31 @@ namespace MediaBrowser.Controller.Entities
{
return config.BlockUnratedItems.Contains(UnratedItem.Other);
}
+
+ public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ var items = GetRecursiveChildren().ToList();
+
+ var totalItems = items.Count;
+ var numComplete = 0;
+
+ // Refresh songs
+ foreach (var item in items)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
+
+ numComplete++;
+ double percent = numComplete;
+ percent /= totalItems;
+ progress.Report(percent * 100);
+ }
+
+ // Refresh current item
+ await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
+
+ progress.Report(100);
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index 0e602dabe..63ce223af 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -50,6 +50,16 @@ namespace MediaBrowser.Controller.Entities
{
var user = query.User;
+ if (query.IncludeItemTypes != null &&
+ query.IncludeItemTypes.Length == 1 &&
+ string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase))
+ {
+ if (!string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
+ {
+ return await FindPlaylists(queryParent, user, query).ConfigureAwait(false);
+ }
+ }
+
switch (viewType)
{
case CollectionType.Channels:
@@ -107,9 +117,7 @@ namespace MediaBrowser.Controller.Entities
case CollectionType.LiveTv:
{
- var result = await GetLiveTvFolders(user).ConfigureAwait(false);
-
- return GetResult(result, queryParent, query);
+ return await GetLiveTvView(queryParent, user, query).ConfigureAwait(false);
}
case CollectionType.Books:
@@ -205,6 +213,9 @@ namespace MediaBrowser.Controller.Entities
case SpecialFolder.MusicLatest:
return GetMusicLatest(queryParent, user, query);
+ case SpecialFolder.MusicPlaylists:
+ return await GetMusicPlaylists(queryParent, user, query).ConfigureAwait(false);
+
case SpecialFolder.MusicAlbums:
return GetMusicAlbums(queryParent, user, query);
@@ -240,6 +251,16 @@ namespace MediaBrowser.Controller.Entities
}
}
+ private async Task<QueryResult<BaseItem>> FindPlaylists(Folder parent, User user, InternalItemsQuery query)
+ {
+ var collectionFolders = user.RootFolder.GetChildren(user, true).Select(i => i.Id).ToList();
+
+ var list = _playlistManager.GetPlaylists(user.Id.ToString("N"))
+ .Where(i => i.GetChildren(user, true).Any(media => _libraryManager.GetCollectionFolders(media).Select(c => c.Id).Any(collectionFolders.Contains)));
+
+ return GetResult(list, parent, query);
+ }
+
private int GetSpecialItemsLimit()
{
return 50;
@@ -257,12 +278,13 @@ namespace MediaBrowser.Controller.Entities
var list = new List<BaseItem>();
list.Add(await GetUserView(SpecialFolder.MusicLatest, user, "0", parent).ConfigureAwait(false));
- list.Add(await GetUserView(SpecialFolder.MusicAlbums, user, "1", parent).ConfigureAwait(false));
- list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, user, "2", parent).ConfigureAwait(false));
- list.Add(await GetUserView(SpecialFolder.MusicArtists, user, "3", parent).ConfigureAwait(false));
- list.Add(await GetUserView(SpecialFolder.MusicSongs, user, "4", parent).ConfigureAwait(false));
- list.Add(await GetUserView(SpecialFolder.MusicGenres, user, "5", parent).ConfigureAwait(false));
- list.Add(await GetUserView(SpecialFolder.MusicFavorites, user, "6", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(SpecialFolder.MusicPlaylists, user, "1", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(SpecialFolder.MusicAlbums, user, "2", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, user, "3", parent).ConfigureAwait(false));
+ //list.Add(await GetUserView(SpecialFolder.MusicArtists, user, "4", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(SpecialFolder.MusicSongs, user, "5", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(SpecialFolder.MusicGenres, user, "6", parent).ConfigureAwait(false));
+ list.Add(await GetUserView(SpecialFolder.MusicFavorites, user, "7", parent).ConfigureAwait(false));
return GetResult(list, parent, query);
}
@@ -283,7 +305,7 @@ namespace MediaBrowser.Controller.Entities
var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
.Where(i => !i.IsFolder)
.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(i =>
{
try
@@ -313,7 +335,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase))
.OfType<IHasAlbumArtist>()
.SelectMany(i => i.AlbumArtists)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(i =>
{
try
@@ -337,7 +359,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => !i.IsFolder)
.OfType<IHasAlbumArtist>()
.SelectMany(i => i.AlbumArtists)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(i =>
{
try
@@ -361,7 +383,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => !i.IsFolder)
.OfType<IHasArtist>()
.SelectMany(i => i.Artists)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(i =>
{
try
@@ -385,7 +407,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => !i.IsFolder)
.OfType<IHasAlbumArtist>()
.SelectMany(i => i.AlbumArtists)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(i =>
{
try
@@ -403,6 +425,14 @@ namespace MediaBrowser.Controller.Entities
return GetResult(artists, parent, query);
}
+ private Task<QueryResult<BaseItem>> GetMusicPlaylists(Folder parent, User user, InternalItemsQuery query)
+ {
+ query.IncludeItemTypes = new[] { "Playlist" };
+ query.Recursive = true;
+
+ return parent.GetItems(query);
+ }
+
private QueryResult<BaseItem> GetMusicAlbums(Folder parent, User user, InternalItemsQuery query)
{
var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => (i is MusicAlbum) && FilterItem(i, query));
@@ -552,7 +582,7 @@ namespace MediaBrowser.Controller.Entities
var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty })
.Where(i => i is Movie)
.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(i =>
{
try
@@ -724,7 +754,7 @@ namespace MediaBrowser.Controller.Entities
var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty })
.OfType<Series>()
.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(i =>
{
try
@@ -776,7 +806,7 @@ namespace MediaBrowser.Controller.Entities
var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.Games })
.OfType<Game>()
.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(i =>
{
try
@@ -1749,17 +1779,26 @@ namespace MediaBrowser.Controller.Entities
return parent.GetRecursiveChildren(user, filter);
}
- private async Task<IEnumerable<BaseItem>> GetLiveTvFolders(User user)
+ private async Task<QueryResult<BaseItem>> GetLiveTvView(Folder queryParent, User user, InternalItemsQuery query)
{
- var list = new List<BaseItem>();
+ if (query.Recursive)
+ {
+ return await _liveTvManager.GetInternalRecordings(new RecordingQuery
+ {
+ IsInProgress = false,
+ Status = RecordingStatus.Completed,
+ UserId = user.Id.ToString("N")
- var parent = user.RootFolder;
+ }, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ var list = new List<BaseItem>();
//list.Add(await GetUserSubView(SpecialFolder.LiveTvNowPlaying, user, "0", parent).ConfigureAwait(false));
- list.Add(await GetUserView(SpecialFolder.LiveTvChannels, user, string.Empty, parent).ConfigureAwait(false));
- list.Add(await GetUserView(SpecialFolder.LiveTvRecordingGroups, user, string.Empty, parent).ConfigureAwait(false));
+ list.Add(await GetUserView(SpecialFolder.LiveTvChannels, user, string.Empty, user.RootFolder).ConfigureAwait(false));
+ list.Add(await GetUserView(SpecialFolder.LiveTvRecordingGroups, user, string.Empty, user.RootFolder).ConfigureAwait(false));
- return list;
+ return GetResult(list, queryParent, query);
}
private async Task<UserView> GetUserView(string name, string type, User user, string sortName, BaseItem parent)
diff --git a/MediaBrowser.Server.Implementations/HttpServer/ThrottledStream.cs b/MediaBrowser.Controller/IO/ThrottledStream.cs
index 4bde30dac..1df00b45a 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/ThrottledStream.cs
+++ b/MediaBrowser.Controller/IO/ThrottledStream.cs
@@ -3,7 +3,7 @@ using System.IO;
using System.Threading;
using System.Threading.Tasks;
-namespace MediaBrowser.Server.Implementations.HttpServer
+namespace MediaBrowser.Controller.IO
{
/// <summary>
/// Class for streaming data with throttling support.
@@ -15,8 +15,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// </summary>
public const long Infinite = 0;
- public Func<long, long, long> ThrottleCallback { get; set; }
-
#region Private members
/// <summary>
/// The base stream.
@@ -293,16 +291,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return false;
}
- if (ThrottleCallback != null)
- {
- var val = ThrottleCallback(_maximumBytesPerSecond, _bytesWritten);
-
- if (val == 0)
- {
- return false;
- }
- }
-
return true;
}
diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs
index 9cbbabc8d..a77d88049 100644
--- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs
+++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs
@@ -43,18 +43,10 @@ namespace MediaBrowser.Controller.Library
/// <param name="id">The identifier.</param>
/// <param name="userId">The user identifier.</param>
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
+ /// <param name="supportedLiveMediaTypes">The supported live media types.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>IEnumerable&lt;MediaSourceInfo&gt;.</returns>
- Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, CancellationToken cancellationToken);
-
- /// <summary>
- /// Gets the playack media sources.
- /// </summary>
- /// <param name="id">The identifier.</param>
- /// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task&lt;IEnumerable&lt;MediaSourceInfo&gt;&gt;.</returns>
- Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, bool enablePathSubstitution, CancellationToken cancellationToken);
+ Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, string[] supportedLiveMediaTypes, CancellationToken cancellationToken);
/// <summary>
/// Gets the static media sources.
@@ -63,24 +55,16 @@ namespace MediaBrowser.Controller.Library
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
/// <param name="user">The user.</param>
/// <returns>IEnumerable&lt;MediaSourceInfo&gt;.</returns>
- IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user);
+ IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null);
/// <summary>
- /// Gets the static media sources.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
- /// <returns>IEnumerable&lt;MediaSourceInfo&gt;.</returns>
- IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution);
-
- /// <summary>
/// Gets the static media source.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="mediaSourceId">The media source identifier.</param>
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
/// <returns>MediaSourceInfo.</returns>
- MediaSourceInfo GetStaticMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution);
+ Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution);
/// <summary>
/// Opens the media source.
diff --git a/MediaBrowser.Controller/Library/NameExtensions.cs b/MediaBrowser.Controller/Library/NameExtensions.cs
new file mode 100644
index 000000000..b2acdc7ea
--- /dev/null
+++ b/MediaBrowser.Controller/Library/NameExtensions.cs
@@ -0,0 +1,41 @@
+using MediaBrowser.Common.Extensions;
+using MoreLinq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MediaBrowser.Controller.Library
+{
+ public static class NameExtensions
+ {
+ public static bool AreEqual(string name1, string name2)
+ {
+ name1 = NormalizeForComparison(name1);
+ name2 = NormalizeForComparison(name2);
+
+ return string.Equals(name1, name2, StringComparison.OrdinalIgnoreCase);
+ }
+
+ public static bool EqualsAny(IEnumerable<string> names, string name)
+ {
+ name = NormalizeForComparison(name);
+
+ return names.Any(i => string.Equals(NormalizeForComparison(i), name, StringComparison.OrdinalIgnoreCase));
+ }
+
+ private static string NormalizeForComparison(string name)
+ {
+ if (string.IsNullOrWhiteSpace(name))
+ {
+ return string.Empty;
+ }
+
+ return name.RemoveDiacritics();
+ }
+
+ public static IEnumerable<string> DistinctNames(this IEnumerable<string> names)
+ {
+ return names.DistinctBy(NormalizeForComparison, StringComparer.OrdinalIgnoreCase);
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index d5b5d92a6..4ee0565f9 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.LiveTv;
@@ -74,10 +75,11 @@ namespace MediaBrowser.Controller.LiveTv
/// Gets the recording.
/// </summary>
/// <param name="id">The identifier.</param>
- /// <param name="user">The user.</param>
+ /// <param name="options">The options.</param>
/// <param name="cancellationToken">The cancellation token.</param>
+ /// <param name="user">The user.</param>
/// <returns>Task{RecordingInfoDto}.</returns>
- Task<RecordingInfoDto> GetRecording(string id, CancellationToken cancellationToken, User user = null);
+ Task<RecordingInfoDto> GetRecording(string id, DtoOptions options, CancellationToken cancellationToken, User user = null);
/// <summary>
/// Gets the channel.
@@ -103,14 +105,15 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{TimerInfoDto}.</returns>
Task<SeriesTimerInfoDto> GetSeriesTimer(string id, CancellationToken cancellationToken);
-
+
/// <summary>
/// Gets the recordings.
/// </summary>
/// <param name="query">The query.</param>
+ /// <param name="options">The options.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>QueryResult{RecordingInfoDto}.</returns>
- Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, CancellationToken cancellationToken);
+ Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken);
/// <summary>
/// Gets the timers.
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs
index d7e3df4e2..4ef4847a3 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs
@@ -1,10 +1,9 @@
-using System;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Model.Dto;
+using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Controller.Channels;
-using MediaBrowser.Controller.Drawing;
-using MediaBrowser.Model.Dto;
namespace MediaBrowser.Controller.LiveTv
{
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 2fa62f79f..b9a161a9f 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -52,6 +52,10 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\morelinq.1.1.0\lib\net35\MoreLinq.dll</HintPath>
</Reference>
+ <Reference Include="Patterns.IO, Version=1.0.5580.36861, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\packages\Patterns.IO.1.0.0.3\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.IO.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
@@ -115,6 +119,7 @@
<Compile Include="Dlna\IMediaReceiverRegistrar.cs" />
<Compile Include="Dlna\IUpnpService.cs" />
<Compile Include="Drawing\IImageProcessor.cs" />
+ <Compile Include="Drawing\ImageCollageOptions.cs" />
<Compile Include="Drawing\ImageProcessingOptions.cs" />
<Compile Include="Drawing\ImageProcessorExtensions.cs" />
<Compile Include="Drawing\ImageStream.cs" />
@@ -171,6 +176,7 @@
<Compile Include="Entities\UserView.cs" />
<Compile Include="Entities\UserViewBuilder.cs" />
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
+ <Compile Include="IO\ThrottledStream.cs" />
<Compile Include="Library\DeleteOptions.cs" />
<Compile Include="Library\ILibraryPostScanTask.cs" />
<Compile Include="Library\IMediaSourceManager.cs" />
@@ -184,6 +190,7 @@
<Compile Include="Library\IUserViewManager.cs" />
<Compile Include="Library\LibraryManagerExtensions.cs" />
<Compile Include="Library\MetadataConfigurationStore.cs" />
+ <Compile Include="Library\NameExtensions.cs" />
<Compile Include="Library\PlaybackStopEventArgs.cs" />
<Compile Include="Library\UserDataSaveEventArgs.cs" />
<Compile Include="LiveTv\ILiveTvItem.cs" />
@@ -211,8 +218,8 @@
<Compile Include="MediaEncoding\IEncodingManager.cs" />
<Compile Include="MediaEncoding\ImageEncodingOptions.cs" />
<Compile Include="MediaEncoding\IMediaEncoder.cs" />
- <Compile Include="MediaEncoding\InternalMediaInfoResult.cs" />
<Compile Include="MediaEncoding\ISubtitleEncoder.cs" />
+ <Compile Include="MediaEncoding\MediaInfoRequest.cs" />
<Compile Include="MediaEncoding\MediaStreamSelector.cs" />
<Compile Include="Net\AuthenticatedAttribute.cs" />
<Compile Include="Net\AuthorizationInfo.cs" />
@@ -394,6 +401,7 @@
<Compile Include="Subtitles\SubtitleResponse.cs" />
<Compile Include="Subtitles\SubtitleSearchRequest.cs" />
<Compile Include="Sync\IHasDynamicAccess.cs" />
+ <Compile Include="Sync\IRemoteSyncProvider.cs" />
<Compile Include="Sync\IServerSyncProvider.cs" />
<Compile Include="Sync\ISyncDataProvider.cs" />
<Compile Include="Sync\ISyncManager.cs" />
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
index fe0fb3295..bb8841222 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
@@ -41,6 +41,8 @@ namespace MediaBrowser.Controller.MediaEncoding
public int? SubtitleStreamIndex { get; set; }
public int? MaxRefFrames { get; set; }
public int? MaxVideoBitDepth { get; set; }
+ public int? CpuCoreLimit { get; set; }
+ public bool ReadInputAtNativeFramerate { get; set; }
public SubtitleDeliveryMethod SubtitleMethod { get; set; }
/// <summary>
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index 47544f972..5bec7980a 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -63,16 +63,14 @@ namespace MediaBrowser.Controller.MediaEncoding
string filenamePrefix,
int? maxWidth,
CancellationToken cancellationToken);
-
+
/// <summary>
/// Gets the media info.
/// </summary>
- /// <param name="inputFiles">The input files.</param>
- /// <param name="protocol">The protocol.</param>
- /// <param name="isAudio">if set to <c>true</c> [is audio].</param>
+ /// <param name="request">The request.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task<InternalMediaInfoResult> GetMediaInfo(string[] inputFiles, MediaProtocol protocol, bool isAudio, CancellationToken cancellationToken);
+ Task<MediaInfo> GetMediaInfo(MediaInfoRequest request, CancellationToken cancellationToken);
/// <summary>
/// Gets the probe size argument.
diff --git a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
index 530c127da..da9dd4dfd 100644
--- a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
+++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
@@ -1,9 +1,7 @@
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
+using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
using System;
using System.Collections.Generic;
-using System.Globalization;
using System.IO;
using System.Linq;
@@ -46,291 +44,5 @@ namespace MediaBrowser.Controller.MediaEncoding
.Where(f => !string.IsNullOrEmpty(f))
.ToList();
}
-
- public static MediaInfo GetMediaInfo(InternalMediaInfoResult data)
- {
- var internalStreams = data.streams ?? new MediaStreamInfo[] { };
-
- var info = new MediaInfo
- {
- MediaStreams = internalStreams.Select(s => GetMediaStream(s, data.format))
- .Where(i => i != null)
- .ToList()
- };
-
- if (data.format != null)
- {
- info.Format = data.format.format_name;
-
- if (!string.IsNullOrEmpty(data.format.bit_rate))
- {
- info.TotalBitrate = int.Parse(data.format.bit_rate, UsCulture);
- }
- }
-
- return info;
- }
-
- private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
- /// <summary>
- /// Converts ffprobe stream info to our MediaStream class
- /// </summary>
- /// <param name="streamInfo">The stream info.</param>
- /// <param name="formatInfo">The format info.</param>
- /// <returns>MediaStream.</returns>
- private static MediaStream GetMediaStream(MediaStreamInfo streamInfo, MediaFormatInfo formatInfo)
- {
- var stream = new MediaStream
- {
- Codec = streamInfo.codec_name,
- Profile = streamInfo.profile,
- Level = streamInfo.level,
- Index = streamInfo.index,
- PixelFormat = streamInfo.pix_fmt
- };
-
- if (streamInfo.tags != null)
- {
- stream.Language = GetDictionaryValue(streamInfo.tags, "language");
- }
-
- if (string.Equals(streamInfo.codec_type, "audio", StringComparison.OrdinalIgnoreCase))
- {
- stream.Type = MediaStreamType.Audio;
-
- stream.Channels = streamInfo.channels;
-
- if (!string.IsNullOrEmpty(streamInfo.sample_rate))
- {
- stream.SampleRate = int.Parse(streamInfo.sample_rate, UsCulture);
- }
-
- stream.ChannelLayout = ParseChannelLayout(streamInfo.channel_layout);
- }
- else if (string.Equals(streamInfo.codec_type, "subtitle", StringComparison.OrdinalIgnoreCase))
- {
- stream.Type = MediaStreamType.Subtitle;
- }
- else if (string.Equals(streamInfo.codec_type, "video", StringComparison.OrdinalIgnoreCase))
- {
- stream.Type = (streamInfo.codec_name ?? string.Empty).IndexOf("mjpeg", StringComparison.OrdinalIgnoreCase) != -1
- ? MediaStreamType.EmbeddedImage
- : MediaStreamType.Video;
-
- stream.Width = streamInfo.width;
- stream.Height = streamInfo.height;
- stream.AspectRatio = GetAspectRatio(streamInfo);
-
- stream.AverageFrameRate = GetFrameRate(streamInfo.avg_frame_rate);
- stream.RealFrameRate = GetFrameRate(streamInfo.r_frame_rate);
-
- stream.BitDepth = GetBitDepth(stream.PixelFormat);
-
- //stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase) ||
- // string.Equals(stream.AspectRatio, "2.35:1", StringComparison.OrdinalIgnoreCase) ||
- // string.Equals(stream.AspectRatio, "2.40:1", StringComparison.OrdinalIgnoreCase);
-
- stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase);
- }
- else
- {
- return null;
- }
-
- // Get stream bitrate
- var bitrate = 0;
-
- if (!string.IsNullOrEmpty(streamInfo.bit_rate))
- {
- bitrate = int.Parse(streamInfo.bit_rate, UsCulture);
- }
- else if (formatInfo != null && !string.IsNullOrEmpty(formatInfo.bit_rate) && stream.Type == MediaStreamType.Video)
- {
- // If the stream info doesn't have a bitrate get the value from the media format info
- bitrate = int.Parse(formatInfo.bit_rate, UsCulture);
- }
-
- if (bitrate > 0)
- {
- stream.BitRate = bitrate;
- }
-
- if (streamInfo.disposition != null)
- {
- var isDefault = GetDictionaryValue(streamInfo.disposition, "default");
- var isForced = GetDictionaryValue(streamInfo.disposition, "forced");
-
- stream.IsDefault = string.Equals(isDefault, "1", StringComparison.OrdinalIgnoreCase);
-
- stream.IsForced = string.Equals(isForced, "1", StringComparison.OrdinalIgnoreCase);
- }
-
- return stream;
- }
-
- private static int? GetBitDepth(string pixelFormat)
- {
- var eightBit = new List<string>
- {
- "yuv420p",
- "yuv411p",
- "yuvj420p",
- "uyyvyy411",
- "nv12",
- "nv21",
- "rgb444le",
- "rgb444be",
- "bgr444le",
- "bgr444be",
- "yuvj411p"
- };
-
- if (!string.IsNullOrEmpty(pixelFormat))
- {
- if (eightBit.Contains(pixelFormat, StringComparer.OrdinalIgnoreCase))
- {
- return 8;
- }
- }
-
- return null;
- }
-
- /// <summary>
- /// Gets a string from an FFProbeResult tags dictionary
- /// </summary>
- /// <param name="tags">The tags.</param>
- /// <param name="key">The key.</param>
- /// <returns>System.String.</returns>
- private static string GetDictionaryValue(Dictionary<string, string> tags, string key)
- {
- if (tags == null)
- {
- return null;
- }
-
- string val;
-
- tags.TryGetValue(key, out val);
- return val;
- }
-
- private static string ParseChannelLayout(string input)
- {
- if (string.IsNullOrEmpty(input))
- {
- return input;
- }
-
- return input.Split('(').FirstOrDefault();
- }
-
- private static string GetAspectRatio(MediaStreamInfo info)
- {
- var original = info.display_aspect_ratio;
-
- int height;
- int width;
-
- var parts = (original ?? string.Empty).Split(':');
- if (!(parts.Length == 2 &&
- int.TryParse(parts[0], NumberStyles.Any, UsCulture, out width) &&
- int.TryParse(parts[1], NumberStyles.Any, UsCulture, out height) &&
- width > 0 &&
- height > 0))
- {
- width = info.width;
- height = info.height;
- }
-
- if (width > 0 && height > 0)
- {
- double ratio = width;
- ratio /= height;
-
- if (IsClose(ratio, 1.777777778, .03))
- {
- return "16:9";
- }
-
- if (IsClose(ratio, 1.3333333333, .05))
- {
- return "4:3";
- }
-
- if (IsClose(ratio, 1.41))
- {
- return "1.41:1";
- }
-
- if (IsClose(ratio, 1.5))
- {
- return "1.5:1";
- }
-
- if (IsClose(ratio, 1.6))
- {
- return "1.6:1";
- }
-
- if (IsClose(ratio, 1.66666666667))
- {
- return "5:3";
- }
-
- if (IsClose(ratio, 1.85, .02))
- {
- return "1.85:1";
- }
-
- if (IsClose(ratio, 2.35, .025))
- {
- return "2.35:1";
- }
-
- if (IsClose(ratio, 2.4, .025))
- {
- return "2.40:1";
- }
- }
-
- return original;
- }
-
- private static bool IsClose(double d1, double d2, double variance = .005)
- {
- return Math.Abs(d1 - d2) <= variance;
- }
-
- /// <summary>
- /// Gets a frame rate from a string value in ffprobe output
- /// This could be a number or in the format of 2997/125.
- /// </summary>
- /// <param name="value">The value.</param>
- /// <returns>System.Nullable{System.Single}.</returns>
- private static float? GetFrameRate(string value)
- {
- if (!string.IsNullOrEmpty(value))
- {
- var parts = value.Split('/');
-
- float result;
-
- if (parts.Length == 2)
- {
- result = float.Parse(parts[0], UsCulture) / float.Parse(parts[1], UsCulture);
- }
- else
- {
- result = float.Parse(parts[0], UsCulture);
- }
-
- return float.IsNaN(result) ? (float?)null : result;
- }
-
- return null;
- }
-
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs b/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs
new file mode 100644
index 000000000..24df7b885
--- /dev/null
+++ b/MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs
@@ -0,0 +1,25 @@
+using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Model.MediaInfo;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.MediaEncoding
+{
+ public class MediaInfoRequest
+ {
+ public string InputPath { get; set; }
+ public MediaProtocol Protocol { get; set; }
+ public bool ExtractChapters { get; set; }
+ public DlnaProfileType MediaType { get; set; }
+ public IIsoMount MountedIso { get; set; }
+ public VideoType VideoType { get; set; }
+ public List<string> PlayableStreamFileNames { get; set; }
+ public bool ExtractKeyFrameInterval { get; set; }
+
+ public MediaInfoRequest()
+ {
+ PlayableStreamFileNames = new List<string>();
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
index 6facc1074..13f83c0fc 100644
--- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
+++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
@@ -1404,24 +1404,12 @@ namespace MediaBrowser.Controller.Providers
{
switch (reader.Name)
{
- case "Name":
- {
- linkedItem.ItemName = reader.ReadElementContentAsString();
- break;
- }
-
case "Path":
{
linkedItem.Path = reader.ReadElementContentAsString();
break;
}
- case "Type":
- {
- linkedItem.ItemType = reader.ReadElementContentAsString();
- break;
- }
-
default:
reader.Skip();
break;
@@ -1435,7 +1423,7 @@ namespace MediaBrowser.Controller.Providers
return linkedItem;
}
- return string.IsNullOrWhiteSpace(linkedItem.ItemName) || string.IsNullOrWhiteSpace(linkedItem.ItemType) ? null : linkedItem;
+ return null;
}
diff --git a/MediaBrowser.Controller/Providers/IImageEnhancer.cs b/MediaBrowser.Controller/Providers/IImageEnhancer.cs
index e5a51a56e..a43941607 100644
--- a/MediaBrowser.Controller/Providers/IImageEnhancer.cs
+++ b/MediaBrowser.Controller/Providers/IImageEnhancer.cs
@@ -1,5 +1,4 @@
-using MediaBrowser.Controller.Drawing;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
using System.Threading.Tasks;
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs
index d40fa835f..d6fc39c5f 100644
--- a/MediaBrowser.Controller/Providers/IProviderManager.cs
+++ b/MediaBrowser.Controller/Providers/IProviderManager.cs
@@ -78,6 +78,19 @@ namespace MediaBrowser.Controller.Providers
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveImage(IHasImages item, Stream source, string mimeType, ImageType type, int? imageIndex, string internalCacheKey, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Saves the image.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="source">The source.</param>
+ /// <param name="mimeType">Type of the MIME.</param>
+ /// <param name="type">The type.</param>
+ /// <param name="imageIndex">Index of the image.</param>
+ /// <param name="internalCacheKey">The internal cache key.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task SaveImage(IHasImages item, string source, string mimeType, ImageType type, int? imageIndex, string internalCacheKey, CancellationToken cancellationToken);
/// <summary>
/// Adds the metadata providers.
diff --git a/MediaBrowser.Controller/Sync/IHasDynamicAccess.cs b/MediaBrowser.Controller/Sync/IHasDynamicAccess.cs
index f907de729..cf868a381 100644
--- a/MediaBrowser.Controller/Sync/IHasDynamicAccess.cs
+++ b/MediaBrowser.Controller/Sync/IHasDynamicAccess.cs
@@ -9,10 +9,10 @@ namespace MediaBrowser.Controller.Sync
/// <summary>
/// Gets the synced file information.
/// </summary>
- /// <param name="remotePath">The remote path.</param>
+ /// <param name="id">The identifier.</param>
/// <param name="target">The target.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;SyncedFileInfo&gt;.</returns>
- Task<SyncedFileInfo> GetSyncedFileInfo(string remotePath, SyncTarget target, CancellationToken cancellationToken);
+ Task<SyncedFileInfo> GetSyncedFileInfo(string id, SyncTarget target, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Sync/IRemoteSyncProvider.cs b/MediaBrowser.Controller/Sync/IRemoteSyncProvider.cs
new file mode 100644
index 000000000..aeb7a3bff
--- /dev/null
+++ b/MediaBrowser.Controller/Sync/IRemoteSyncProvider.cs
@@ -0,0 +1,10 @@
+
+namespace MediaBrowser.Controller.Sync
+{
+ /// <summary>
+ /// A marker interface
+ /// </summary>
+ public interface IRemoteSyncProvider
+ {
+ }
+}
diff --git a/MediaBrowser.Controller/Sync/IServerSyncProvider.cs b/MediaBrowser.Controller/Sync/IServerSyncProvider.cs
index 46bbbd329..6b694d26d 100644
--- a/MediaBrowser.Controller/Sync/IServerSyncProvider.cs
+++ b/MediaBrowser.Controller/Sync/IServerSyncProvider.cs
@@ -1,6 +1,7 @@
-using MediaBrowser.Model.Sync;
+using MediaBrowser.Model.Querying;
+using MediaBrowser.Model.Sync;
+using Patterns.IO;
using System;
-using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -13,46 +14,39 @@ namespace MediaBrowser.Controller.Sync
/// Transfers the file.
/// </summary>
/// <param name="stream">The stream.</param>
- /// <param name="remotePath">The remote path.</param>
+ /// <param name="pathParts">The path parts.</param>
/// <param name="target">The target.</param>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task<SyncedFileInfo> SendFile(Stream stream, string remotePath, SyncTarget target, IProgress<double> progress, CancellationToken cancellationToken);
+ Task<SyncedFileInfo> SendFile(Stream stream, string[] pathParts, SyncTarget target, IProgress<double> progress, CancellationToken cancellationToken);
/// <summary>
/// Deletes the file.
/// </summary>
- /// <param name="path">The path.</param>
+ /// <param name="id">The identifier.</param>
/// <param name="target">The target.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task DeleteFile(string path, SyncTarget target, CancellationToken cancellationToken);
+ Task DeleteFile(string id, SyncTarget target, CancellationToken cancellationToken);
/// <summary>
/// Gets the file.
/// </summary>
- /// <param name="path">The path.</param>
+ /// <param name="id">The identifier.</param>
/// <param name="target">The target.</param>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;Stream&gt;.</returns>
- Task<Stream> GetFile(string path, SyncTarget target, IProgress<double> progress, CancellationToken cancellationToken);
+ Task<Stream> GetFile(string id, SyncTarget target, IProgress<double> progress, CancellationToken cancellationToken);
/// <summary>
- /// Gets the full path.
+ /// Gets the files.
/// </summary>
- /// <param name="path">The path.</param>
+ /// <param name="query">The query.</param>
/// <param name="target">The target.</param>
- /// <returns>System.String.</returns>
- string GetFullPath(IEnumerable<string> path, SyncTarget target);
-
- /// <summary>
- /// Gets the parent directory path.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="target">The target.</param>
- /// <returns>System.String.</returns>
- string GetParentDirectoryPath(string path, SyncTarget target);
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task&lt;QueryResult&lt;FileMetadata&gt;&gt;.</returns>
+ Task<QueryResult<FileMetadata>> GetFiles(FileQuery query, SyncTarget target, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Sync/ISyncDataProvider.cs b/MediaBrowser.Controller/Sync/ISyncDataProvider.cs
index dc3edc4e4..ebff50cb0 100644
--- a/MediaBrowser.Controller/Sync/ISyncDataProvider.cs
+++ b/MediaBrowser.Controller/Sync/ISyncDataProvider.cs
@@ -7,20 +7,12 @@ namespace MediaBrowser.Controller.Sync
public interface ISyncDataProvider
{
/// <summary>
- /// Gets the server item ids.
+ /// Gets the local items.
/// </summary>
/// <param name="target">The target.</param>
/// <param name="serverId">The server identifier.</param>
- /// <returns>Task&lt;List&lt;System.String&gt;&gt;.</returns>
- Task<List<string>> GetServerItemIds(SyncTarget target, string serverId);
-
- /// <summary>
- /// Gets the synchronize job item ids.
- /// </summary>
- /// <param name="target">The target.</param>
- /// <param name="serverId">The server identifier.</param>
- /// <returns>Task&lt;List&lt;System.String&gt;&gt;.</returns>
- Task<List<string>> GetSyncJobItemIds(SyncTarget target, string serverId);
+ /// <returns>Task&lt;List&lt;LocalItem&gt;&gt;.</returns>
+ Task<List<LocalItem>> GetLocalItems(SyncTarget target, string serverId);
/// <summary>
/// Adds the or update.
diff --git a/MediaBrowser.Controller/Sync/ISyncManager.cs b/MediaBrowser.Controller/Sync/ISyncManager.cs
index 3b6e20edc..97591551c 100644
--- a/MediaBrowser.Controller/Sync/ISyncManager.cs
+++ b/MediaBrowser.Controller/Sync/ISyncManager.cs
@@ -174,6 +174,13 @@ namespace MediaBrowser.Controller.Sync
/// <param name="targetId">The target identifier.</param>
/// <returns>IEnumerable&lt;SyncQualityOption&gt;.</returns>
IEnumerable<SyncQualityOption> GetQualityOptions(string targetId);
+ /// <summary>
+ /// Gets the quality options.
+ /// </summary>
+ /// <param name="targetId">The target identifier.</param>
+ /// <param name="user">The user.</param>
+ /// <returns>IEnumerable&lt;SyncQualityOption&gt;.</returns>
+ IEnumerable<SyncQualityOption> GetQualityOptions(string targetId, User user);
/// <summary>
/// Gets the profile options.
@@ -181,5 +188,12 @@ namespace MediaBrowser.Controller.Sync
/// <param name="targetId">The target identifier.</param>
/// <returns>IEnumerable&lt;SyncQualityOption&gt;.</returns>
IEnumerable<SyncProfileOption> GetProfileOptions(string targetId);
+ /// <summary>
+ /// Gets the profile options.
+ /// </summary>
+ /// <param name="targetId">The target identifier.</param>
+ /// <param name="user">The user.</param>
+ /// <returns>IEnumerable&lt;SyncProfileOption&gt;.</returns>
+ IEnumerable<SyncProfileOption> GetProfileOptions(string targetId, User user);
}
}
diff --git a/MediaBrowser.Controller/Sync/SyncedFileInfo.cs b/MediaBrowser.Controller/Sync/SyncedFileInfo.cs
index 550af2d55..844e7d890 100644
--- a/MediaBrowser.Controller/Sync/SyncedFileInfo.cs
+++ b/MediaBrowser.Controller/Sync/SyncedFileInfo.cs
@@ -20,6 +20,11 @@ namespace MediaBrowser.Controller.Sync
/// </summary>
/// <value>The required HTTP headers.</value>
public Dictionary<string, string> RequiredHttpHeaders { get; set; }
+ /// <summary>
+ /// Gets or sets the identifier.
+ /// </summary>
+ /// <value>The identifier.</value>
+ public string Id { get; set; }
public SyncedFileInfo()
{
diff --git a/MediaBrowser.Controller/packages.config b/MediaBrowser.Controller/packages.config
index 6df166204..8d10de2f1 100644
--- a/MediaBrowser.Controller/packages.config
+++ b/MediaBrowser.Controller/packages.config
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="morelinq" version="1.1.0" targetFramework="net45" />
+ <package id="Patterns.IO" version="1.0.0.3" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
index 5ccea52ba..abd649ad7 100644
--- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
+++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
@@ -223,7 +223,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
if (string.Equals(flag, "BrowseMetadata"))
{
totalCount = 1;
-
+
if (item.IsFolder || serverItem.StubType.HasValue)
{
var childrenResult = (await GetUserItems(item, serverItem.StubType, user, sortCriteria, start, requestedCount).ConfigureAwait(false));
@@ -350,7 +350,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
};
}
- private async Task<QueryResult<BaseItem>> GetChildrenSorted(BaseItem item, User user, SearchCriteria search, SortCriteria sort, int? startIndex, int? limit)
+ private Task<QueryResult<BaseItem>> GetChildrenSorted(BaseItem item, User user, SearchCriteria search, SortCriteria sort, int? startIndex, int? limit)
{
var folder = (Folder)item;
@@ -389,7 +389,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
isFolder = true;
}
- return await folder.GetItems(new InternalItemsQuery
+ return folder.GetItems(new InternalItemsQuery
{
Limit = limit,
StartIndex = startIndex,
@@ -401,7 +401,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
IsFolder = isFolder,
MediaTypes = mediaTypes.ToArray()
- }).ConfigureAwait(false);
+ });
}
private async Task<QueryResult<ServerItem>> GetUserItems(BaseItem item, StubType? stubType, User user, SortCriteria sort, int? startIndex, int? limit)
diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
index 3b1cdb542..629b95f67 100644
--- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs
+++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
@@ -12,6 +12,7 @@ using MediaBrowser.Dlna.ContentDirectory;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using System;
using System.Globalization;
@@ -124,9 +125,9 @@ namespace MediaBrowser.Dlna.Didl
{
if (streamInfo == null)
{
- var sources = _user == null ? _mediaSourceManager.GetStaticMediaSources(video, true).ToList() : _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList();
+ var sources = _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList();
- streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
+ streamInfo = new StreamBuilder(new NullLogger()).BuildVideoItem(new VideoOptions
{
ItemId = GetClientId(video),
MediaSources = sources,
@@ -351,9 +352,9 @@ namespace MediaBrowser.Dlna.Didl
if (streamInfo == null)
{
- var sources = _user == null ? _mediaSourceManager.GetStaticMediaSources(audio, true).ToList() : _mediaSourceManager.GetStaticMediaSources(audio, true, _user).ToList();
+ var sources = _mediaSourceManager.GetStaticMediaSources(audio, true, _user).ToList();
- streamInfo = new StreamBuilder().BuildAudioItem(new AudioOptions
+ streamInfo = new StreamBuilder(new NullLogger()).BuildAudioItem(new AudioOptions
{
ItemId = GetClientId(audio),
MediaSources = sources,
diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
index 38c0f71cc..9df69b115 100644
--- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
@@ -470,7 +470,7 @@ namespace MediaBrowser.Dlna.PlayTo
var hasMediaSources = item as IHasMediaSources;
var mediaSources = hasMediaSources != null
- ? (user == null ? _mediaSourceManager.GetStaticMediaSources(hasMediaSources, true) : _mediaSourceManager.GetStaticMediaSources(hasMediaSources, true, user)).ToList()
+ ? (_mediaSourceManager.GetStaticMediaSources(hasMediaSources, true, user)).ToList()
: new List<MediaSourceInfo>();
var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId, mediaSourceId, audioStreamIndex, subtitleStreamIndex);
@@ -542,7 +542,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
return new PlaylistItem
{
- StreamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
+ StreamInfo = new StreamBuilder(_logger).BuildVideoItem(new VideoOptions
{
ItemId = item.Id.ToString("N"),
MediaSources = mediaSources,
@@ -562,7 +562,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
return new PlaylistItem
{
- StreamInfo = new StreamBuilder().BuildAudioItem(new AudioOptions
+ StreamInfo = new StreamBuilder(_logger).BuildAudioItem(new AudioOptions
{
ItemId = item.Id.ToString("N"),
MediaSources = mediaSources,
@@ -892,7 +892,7 @@ namespace MediaBrowser.Dlna.PlayTo
request.MediaSource = hasMediaSources == null ?
null :
- mediaSourceManager.GetStaticMediaSource(hasMediaSources, request.MediaSourceId, false);
+ mediaSourceManager.GetMediaSource(hasMediaSources, request.MediaSourceId, false).Result;
diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
index 8ca16832d..73bc4984c 100644
--- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
+++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
@@ -62,16 +62,22 @@ namespace MediaBrowser.Dlna.Ssdp
{
if (string.Equals(args.Method, "M-SEARCH", StringComparison.OrdinalIgnoreCase))
{
- TimeSpan delay = GetSearchDelay(args.Headers);
+ var headers = args.Headers;
+
+ TimeSpan delay = GetSearchDelay(headers);
if (_config.GetDlnaConfiguration().EnableDebugLogging)
{
_logger.Debug("Delaying search response by {0} seconds", delay.TotalSeconds);
}
- await Task.Delay(delay).ConfigureAwait(false);
+ await Task.Delay(delay).ConfigureAwait(false);
- RespondToSearch(args.EndPoint, args.Headers["st"]);
+ string st;
+ if (headers.TryGetValue("st", out st))
+ {
+ RespondToSearch(args.EndPoint, st);
+ }
}
EventHelper.FireEventIfNotNull(MessageReceived, this, args, _logger);
diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs
index afe4b5799..154d02600 100644
--- a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs
@@ -92,7 +92,7 @@ namespace MediaBrowser.LocalMetadata
{
get
{
- return "Media Browser Xml";
+ return "Emby Xml";
}
}
diff --git a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs
index 31329e6d7..0089a71d5 100644
--- a/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs
@@ -10,7 +10,7 @@ using System.Linq;
namespace MediaBrowser.LocalMetadata.Images
{
- public class EpisodeLocalLocalImageProvider : ILocalImageFileProvider
+ public class EpisodeLocalLocalImageProvider : ILocalImageFileProvider, IHasOrder
{
private readonly IFileSystem _fileSystem;
@@ -24,6 +24,11 @@ namespace MediaBrowser.LocalMetadata.Images
get { return "Local Images"; }
}
+ public int Order
+ {
+ get { return 0; }
+ }
+
public bool Supports(IHasImages item)
{
return item is Episode && item.SupportsLocalMetadata;
diff --git a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs
index 60533797a..f118c2763 100644
--- a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs
@@ -26,6 +26,11 @@ namespace MediaBrowser.LocalMetadata.Images
public bool Supports(IHasImages item)
{
+ if (item is Photo)
+ {
+ return false;
+ }
+
if (!item.IsSaveLocalMetadataEnabled())
{
return true;
diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
index 6083c88de..ba87b3c43 100644
--- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
@@ -12,7 +12,7 @@ using System.Linq;
namespace MediaBrowser.LocalMetadata.Images
{
- public class LocalImageProvider : ILocalImageFileProvider
+ public class LocalImageProvider : ILocalImageFileProvider, IHasOrder
{
private readonly IFileSystem _fileSystem;
diff --git a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
index c59d574bf..1b98e75be 100644
--- a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
+++ b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
@@ -756,11 +756,6 @@ namespace MediaBrowser.LocalMetadata.Savers
{
builder.Append("<" + singularNodeName + ">");
- if (!string.IsNullOrWhiteSpace(link.ItemType))
- {
- builder.Append("<Type>" + SecurityElement.Escape(link.ItemType) + "</Type>");
- }
-
if (!string.IsNullOrWhiteSpace(link.Path))
{
builder.Append("<Path>" + SecurityElement.Escape((link.Path)) + "</Path>");
diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
index 78ac92f25..c30ceb62d 100644
--- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
@@ -70,10 +70,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
encodingJob.OutputFilePath = GetOutputFilePath(encodingJob);
Directory.CreateDirectory(Path.GetDirectoryName(encodingJob.OutputFilePath));
- if (options.Context == EncodingContext.Static && encodingJob.IsInputVideo)
- {
- encodingJob.ReadInputAtNativeFramerate = true;
- }
+ encodingJob.ReadInputAtNativeFramerate = options.ReadInputAtNativeFramerate;
await AcquireResources(encodingJob, cancellationToken).ConfigureAwait(false);
@@ -305,19 +302,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// <returns>System.Int32.</returns>
protected int GetNumberOfThreads(EncodingJob job, bool isWebm)
{
- // Only need one thread for sync
- if (job.Options.Context == EncodingContext.Static)
- {
- return 1;
- }
-
- if (isWebm)
- {
- // Recommended per docs
- return Math.Max(Environment.ProcessorCount - 1, 2);
- }
-
- return 0;
+ return job.Options.CpuCoreLimit ?? 0;
}
protected EncodingQuality GetQualitySetting()
diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs
index 8d8201074..ea3cc6d89 100644
--- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs
@@ -59,7 +59,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
- var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(request.ItemId, false, cancellationToken).ConfigureAwait(false);
+ var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(request.ItemId, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false);
var mediaSource = string.IsNullOrEmpty(request.MediaSourceId)
? mediaSources.First()
@@ -124,10 +124,14 @@ namespace MediaBrowser.MediaEncoding.Encoder
state.InputContainer = mediaSource.Container;
state.InputFileSize = mediaSource.Size;
state.InputBitrate = mediaSource.Bitrate;
- state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate;
state.RunTimeTicks = mediaSource.RunTimeTicks;
state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
+ if (mediaSource.ReadAtNativeFramerate)
+ {
+ state.ReadInputAtNativeFramerate = true;
+ }
+
if (mediaSource.VideoType.HasValue)
{
state.VideoType = mediaSource.VideoType.Value;
@@ -148,7 +152,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
state.InputBitrate = mediaSource.Bitrate;
state.InputFileSize = mediaSource.Size;
- state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate;
if (state.ReadInputAtNativeFramerate ||
mediaSource.Protocol == MediaProtocol.File && string.Equals(mediaSource.Container, "wtv", StringComparison.OrdinalIgnoreCase))
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index 425889807..df7351ad1 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -5,12 +5,15 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Session;
+using MediaBrowser.MediaEncoding.Probing;
+using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Serialization;
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
@@ -72,6 +75,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
protected readonly Func<ISubtitleEncoder> SubtitleEncoder;
protected readonly Func<IMediaSourceManager> MediaSourceManager;
+ private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
+
public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func<ISubtitleEncoder> subtitleEncoder, Func<IMediaSourceManager> mediaSourceManager)
{
_logger = logger;
@@ -102,16 +107,19 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// <summary>
/// Gets the media info.
/// </summary>
- /// <param name="inputFiles">The input files.</param>
- /// <param name="protocol">The protocol.</param>
- /// <param name="isAudio">if set to <c>true</c> [is audio].</param>
+ /// <param name="request">The request.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- public Task<InternalMediaInfoResult> GetMediaInfo(string[] inputFiles, MediaProtocol protocol, bool isAudio,
- CancellationToken cancellationToken)
+ public Task<Model.MediaInfo.MediaInfo> GetMediaInfo(MediaInfoRequest request, CancellationToken cancellationToken)
{
- return GetMediaInfoInternal(GetInputArgument(inputFiles, protocol), !isAudio,
- GetProbeSizeArgument(inputFiles, protocol), cancellationToken);
+ var extractChapters = request.MediaType == DlnaProfileType.Video && request.ExtractChapters;
+
+ var inputFiles = MediaEncoderHelpers.GetInputArgument(request.InputPath, request.Protocol, request.MountedIso, request.PlayableStreamFileNames);
+
+ var extractKeyFrameInterval = request.ExtractKeyFrameInterval && request.Protocol == MediaProtocol.File && request.VideoType == VideoType.VideoFile;
+
+ return GetMediaInfoInternal(GetInputArgument(inputFiles, request.Protocol), request.InputPath, request.Protocol, extractChapters, extractKeyFrameInterval,
+ GetProbeSizeArgument(inputFiles, request.Protocol), request.MediaType == DlnaProfileType.Audio, cancellationToken);
}
/// <summary>
@@ -141,13 +149,22 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// Gets the media info internal.
/// </summary>
/// <param name="inputPath">The input path.</param>
+ /// <param name="primaryPath">The primary path.</param>
+ /// <param name="protocol">The protocol.</param>
/// <param name="extractChapters">if set to <c>true</c> [extract chapters].</param>
+ /// <param name="extractKeyFrameInterval">if set to <c>true</c> [extract key frame interval].</param>
/// <param name="probeSizeArgument">The probe size argument.</param>
+ /// <param name="isAudio">if set to <c>true</c> [is audio].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{MediaInfoResult}.</returns>
/// <exception cref="System.ApplicationException"></exception>
- private async Task<InternalMediaInfoResult> GetMediaInfoInternal(string inputPath, bool extractChapters,
+ private async Task<Model.MediaInfo.MediaInfo> GetMediaInfoInternal(string inputPath,
+ string primaryPath,
+ MediaProtocol protocol,
+ bool extractChapters,
+ bool extractKeyFrameInterval,
string probeSizeArgument,
+ bool isAudio,
CancellationToken cancellationToken)
{
var args = extractChapters
@@ -164,6 +181,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
// Must consume both or ffmpeg may hang due to deadlocks. See comments below.
RedirectStandardOutput = true,
RedirectStandardError = true,
+ RedirectStandardInput = true,
FileName = FFProbePath,
Arguments = string.Format(args,
probeSizeArgument, inputPath).Trim(),
@@ -177,15 +195,13 @@ namespace MediaBrowser.MediaEncoding.Encoder
_logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
- process.Exited += ProcessExited;
-
await _ffProbeResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
- InternalMediaInfoResult result;
+ var processWrapper = new ProcessWrapper(process, this);
try
{
- process.Start();
+ StartProcess(processWrapper);
}
catch (Exception ex)
{
@@ -200,19 +216,57 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
process.BeginErrorReadLine();
- result = _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream);
+ var result = _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream);
+
+ if (result != null)
+ {
+ if (result.streams != null)
+ {
+ // Normalize aspect ratio if invalid
+ foreach (var stream in result.streams)
+ {
+ if (string.Equals(stream.display_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase))
+ {
+ stream.display_aspect_ratio = string.Empty;
+ }
+ if (string.Equals(stream.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase))
+ {
+ stream.sample_aspect_ratio = string.Empty;
+ }
+ }
+ }
+
+ var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, isAudio, primaryPath, protocol);
+
+ if (extractKeyFrameInterval && mediaInfo.RunTimeTicks.HasValue)
+ {
+ foreach (var stream in mediaInfo.MediaStreams)
+ {
+ if (stream.Type == MediaStreamType.Video && string.Equals(stream.Codec, "h264", StringComparison.OrdinalIgnoreCase))
+ {
+ try
+ {
+ //stream.KeyFrames = await GetKeyFrames(inputPath, stream.Index, cancellationToken)
+ // .ConfigureAwait(false);
+ }
+ catch (OperationCanceledException)
+ {
+
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error getting key frame interval", ex);
+ }
+ }
+ }
+ }
+
+ return mediaInfo;
+ }
}
catch
{
- // Hate having to do this
- try
- {
- process.Kill();
- }
- catch (Exception ex1)
- {
- _logger.ErrorException("Error killing ffprobe", ex1);
- }
+ StopProcess(processWrapper, 100, true);
throw;
}
@@ -221,30 +275,102 @@ namespace MediaBrowser.MediaEncoding.Encoder
_ffProbeResourcePool.Release();
}
- if (result == null)
+ throw new ApplicationException(string.Format("FFProbe failed for {0}", inputPath));
+ }
+
+ private async Task<List<int>> GetKeyFrames(string inputPath, int videoStreamIndex, CancellationToken cancellationToken)
+ {
+ const string args = "-i {0} -select_streams v:{1} -show_frames -show_entries frame=pkt_dts,key_frame -print_format compact";
+
+ var process = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ CreateNoWindow = true,
+ UseShellExecute = false,
+
+ // Must consume both or ffmpeg may hang due to deadlocks. See comments below.
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ FileName = FFProbePath,
+ Arguments = string.Format(args, inputPath, videoStreamIndex.ToString(CultureInfo.InvariantCulture)).Trim(),
+
+ WindowStyle = ProcessWindowStyle.Hidden,
+ ErrorDialog = false
+ },
+
+ EnableRaisingEvents = true
+ };
+
+ _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
+
+ var processWrapper = new ProcessWrapper(process, this);
+
+ StartProcess(processWrapper);
+
+ var lines = new List<int>();
+
+ try
{
- throw new ApplicationException(string.Format("FFProbe failed for {0}", inputPath));
+ process.BeginErrorReadLine();
+
+ await StartReadingOutput(process.StandardOutput.BaseStream, lines, 120000, cancellationToken).ConfigureAwait(false);
+ }
+ catch (OperationCanceledException)
+ {
+ if (cancellationToken.IsCancellationRequested)
+ {
+ throw;
+ }
+ }
+ finally
+ {
+ StopProcess(processWrapper, 100, true);
}
- cancellationToken.ThrowIfCancellationRequested();
+ return lines;
+ }
- if (result.streams != null)
+ private async Task StartReadingOutput(Stream source, List<int> lines, int timeoutMs, CancellationToken cancellationToken)
+ {
+ try
{
- // Normalize aspect ratio if invalid
- foreach (var stream in result.streams)
+ using (var reader = new StreamReader(source))
{
- if (string.Equals(stream.display_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase))
- {
- stream.display_aspect_ratio = string.Empty;
- }
- if (string.Equals(stream.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase))
+ while (!reader.EndOfStream)
{
- stream.sample_aspect_ratio = string.Empty;
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var line = await reader.ReadLineAsync().ConfigureAwait(false);
+
+ var values = (line ?? string.Empty).Split('|')
+ .Where(i => !string.IsNullOrWhiteSpace(i))
+ .Select(i => i.Split('='))
+ .Where(i => i.Length == 2)
+ .ToDictionary(i => i[0], i => i[1]);
+
+ string pktDts;
+ int frameMs;
+ if (values.TryGetValue("pkt_dts", out pktDts) && int.TryParse(pktDts, NumberStyles.Any, CultureInfo.InvariantCulture, out frameMs))
+ {
+ string keyFrame;
+ if (values.TryGetValue("key_frame", out keyFrame) && string.Equals(keyFrame, "1", StringComparison.OrdinalIgnoreCase))
+ {
+ lines.Add(frameMs);
+ }
+ }
}
}
}
-
- return result;
+ catch (OperationCanceledException)
+ {
+ throw;
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error reading ffprobe output", ex);
+ }
}
/// <summary>
@@ -252,16 +378,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// </summary>
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
- /// <summary>
- /// Processes the exited.
- /// </summary>
- /// <param name="sender">The sender.</param>
- /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
- private void ProcessExited(object sender, EventArgs e)
- {
- ((Process)sender).Dispose();
- }
-
public Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken)
{
return ExtractImage(new[] { path }, MediaProtocol.File, true, null, null, cancellationToken);
@@ -286,6 +402,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false);
}
+ catch (ArgumentException)
+ {
+ throw;
+ }
catch
{
_logger.Error("I-frame image extraction failed, will attempt standard way. Input: {0}", inputArgument);
@@ -368,7 +488,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
- process.Start();
+ var processWrapper = new ProcessWrapper(process, this);
+
+ StartProcess(processWrapper);
var memoryStream = new MemoryStream();
@@ -384,23 +506,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (!ranToCompletion)
{
- try
- {
- _logger.Info("Killing ffmpeg process");
-
- process.StandardInput.WriteLine("q");
-
- process.WaitForExit(1000);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error killing process", ex);
- }
+ StopProcess(processWrapper, 1000, false);
}
resourcePool.Release();
- var exitCode = ranToCompletion ? process.ExitCode : -1;
+ var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1;
process.Dispose();
@@ -419,31 +530,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
return memoryStream;
}
- public Task<Stream> EncodeImage(ImageEncodingOptions options, CancellationToken cancellationToken)
- {
- throw new NotImplementedException();
- }
-
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- }
-
- /// <summary>
- /// Releases unmanaged and - optionally - managed resources.
- /// </summary>
- /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
- protected virtual void Dispose(bool dispose)
- {
- if (dispose)
- {
- _videoImageResourcePool.Dispose();
- }
- }
-
public string GetTimeParameter(long ticks)
{
var time = TimeSpan.FromTicks(ticks);
@@ -510,9 +596,11 @@ namespace MediaBrowser.MediaEncoding.Encoder
bool ranToCompletion;
+ var processWrapper = new ProcessWrapper(process, this);
+
try
{
- process.Start();
+ StartProcess(processWrapper);
// Need to give ffmpeg enough time to make all the thumbnails, which could be a while,
// but we still need to detect if the process hangs.
@@ -536,18 +624,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (!ranToCompletion)
{
- try
- {
- _logger.Info("Killing ffmpeg process");
-
- process.StandardInput.WriteLine("q");
-
- process.WaitForExit(1000);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error killing process", ex);
- }
+ StopProcess(processWrapper, 1000, false);
}
}
finally
@@ -555,7 +632,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
resourcePool.Release();
}
- var exitCode = ranToCompletion ? process.ExitCode : -1;
+ var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1;
process.Dispose();
@@ -608,5 +685,122 @@ namespace MediaBrowser.MediaEncoding.Encoder
return job.OutputFilePath;
}
+
+ private void StartProcess(ProcessWrapper process)
+ {
+ process.Process.Start();
+
+ lock (_runningProcesses)
+ {
+ _runningProcesses.Add(process);
+ }
+ }
+ private void StopProcess(ProcessWrapper process, int waitTimeMs, bool enableForceKill)
+ {
+ try
+ {
+ _logger.Info("Killing ffmpeg process");
+
+ try
+ {
+ process.Process.StandardInput.WriteLine("q");
+ }
+ catch (Exception)
+ {
+ _logger.Error("Error sending q command to process");
+ }
+
+ try
+ {
+ if (process.Process.WaitForExit(waitTimeMs))
+ {
+ return;
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.Error("Error in WaitForExit", ex);
+ }
+
+ if (enableForceKill)
+ {
+ process.Process.Kill();
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error killing process", ex);
+ }
+ }
+
+ private void StopProcesses()
+ {
+ List<ProcessWrapper> proceses;
+ lock (_runningProcesses)
+ {
+ proceses = _runningProcesses.ToList();
+ }
+ _runningProcesses.Clear();
+
+ foreach (var process in proceses)
+ {
+ if (!process.HasExited)
+ {
+ StopProcess(process, 500, true);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ /// <summary>
+ /// Releases unmanaged and - optionally - managed resources.
+ /// </summary>
+ /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+ protected virtual void Dispose(bool dispose)
+ {
+ if (dispose)
+ {
+ _videoImageResourcePool.Dispose();
+ StopProcesses();
+ }
+ }
+
+ private class ProcessWrapper
+ {
+ public readonly Process Process;
+ public bool HasExited;
+ public int? ExitCode;
+ private readonly MediaEncoder _mediaEncoder;
+
+ public ProcessWrapper(Process process, MediaEncoder mediaEncoder)
+ {
+ Process = process;
+ this._mediaEncoder = mediaEncoder;
+ Process.Exited += Process_Exited;
+ }
+
+ void Process_Exited(object sender, EventArgs e)
+ {
+ var process = (Process)sender;
+
+ HasExited = true;
+
+ ExitCode = process.ExitCode;
+
+ lock (_mediaEncoder._runningProcesses)
+ {
+ _mediaEncoder._runningProcesses.Remove(this);
+ }
+
+ process.Dispose();
+ }
+ }
}
}
diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
index 72dc0feac..ad561c484 100644
--- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
+++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
@@ -68,6 +68,9 @@
<Compile Include="Encoder\JobLogger.cs" />
<Compile Include="Encoder\MediaEncoder.cs" />
<Compile Include="Encoder\VideoEncoder.cs" />
+ <Compile Include="Probing\FFProbeHelpers.cs" />
+ <Compile Include="Probing\InternalMediaInfoResult.cs" />
+ <Compile Include="Probing\ProbeResultNormalizer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Subtitles\ISubtitleParser.cs" />
<Compile Include="Subtitles\ISubtitleWriter.cs" />
@@ -91,6 +94,10 @@
<Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
<Name>MediaBrowser.Controller</Name>
</ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.MediaInfo\MediaBrowser.MediaInfo.csproj">
+ <Project>{6e4145e4-c6d4-4e4d-94f2-87188db6e239}</Project>
+ <Name>MediaBrowser.MediaInfo</Name>
+ </ProjectReference>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
<Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
<Name>MediaBrowser.Model</Name>
@@ -99,7 +106,9 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
- <ItemGroup />
+ <ItemGroup>
+ <EmbeddedResource Include="Probing\whitelist.txt" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs
index 2044979e4..859f38950 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs
+++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs
@@ -2,7 +2,7 @@
using System;
using System.Collections.Generic;
-namespace MediaBrowser.Providers.MediaInfo
+namespace MediaBrowser.MediaEncoding.Probing
{
public static class FFProbeHelpers
{
diff --git a/MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs b/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs
index 796fdb723..9b95e83e7 100644
--- a/MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs
+++ b/MediaBrowser.MediaEncoding/Probing/InternalMediaInfoResult.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace MediaBrowser.Controller.MediaEncoding
+namespace MediaBrowser.MediaEncoding.Probing
{
/// <summary>
/// Class MediaInfoResult
@@ -89,7 +89,7 @@ namespace MediaBrowser.Controller.MediaEncoding
/// </summary>
/// <value>The channel_layout.</value>
public string channel_layout { get; set; }
-
+
/// <summary>
/// Gets or sets the avg_frame_rate.
/// </summary>
@@ -317,7 +317,7 @@ namespace MediaBrowser.Controller.MediaEncoding
/// </summary>
/// <value>The probe_score.</value>
public int probe_score { get; set; }
-
+
/// <summary>
/// Gets or sets the tags.
/// </summary>
diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
new file mode 100644
index 000000000..267ff875a
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
@@ -0,0 +1,887 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.MediaInfo;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.MediaInfo;
+
+namespace MediaBrowser.MediaEncoding.Probing
+{
+ public class ProbeResultNormalizer
+ {
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+ private readonly ILogger _logger;
+ private readonly IFileSystem _fileSystem;
+
+ public ProbeResultNormalizer(ILogger logger, IFileSystem fileSystem)
+ {
+ _logger = logger;
+ _fileSystem = fileSystem;
+ }
+
+ public Model.MediaInfo.MediaInfo GetMediaInfo(InternalMediaInfoResult data, bool isAudio, string path, MediaProtocol protocol)
+ {
+ var info = new Model.MediaInfo.MediaInfo
+ {
+ Path = path,
+ Protocol = protocol
+ };
+
+ FFProbeHelpers.NormalizeFFProbeResult(data);
+ SetSize(data, info);
+
+ var internalStreams = data.streams ?? new MediaStreamInfo[] { };
+
+ info.MediaStreams = internalStreams.Select(s => GetMediaStream(s, data.format))
+ .Where(i => i != null)
+ .ToList();
+
+ if (data.format != null)
+ {
+ info.Container = data.format.format_name;
+
+ if (!string.IsNullOrEmpty(data.format.bit_rate))
+ {
+ info.Bitrate = int.Parse(data.format.bit_rate, _usCulture);
+ }
+ }
+
+ if (isAudio)
+ {
+ SetAudioRuntimeTicks(data, info);
+
+ if (data.format != null && data.format.tags != null)
+ {
+ SetAudioInfoFromTags(info, data.format.tags);
+ }
+ }
+ else
+ {
+ if (data.format != null && !string.IsNullOrEmpty(data.format.duration))
+ {
+ info.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.format.duration, _usCulture)).Ticks;
+ }
+
+ FetchWtvInfo(info, data);
+
+ if (data.Chapters != null)
+ {
+ info.Chapters = data.Chapters.Select(GetChapterInfo).ToList();
+ }
+
+ ExtractTimestamp(info);
+
+ var videoStream = info.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
+
+ if (videoStream != null)
+ {
+ UpdateFromMediaInfo(info, videoStream);
+ }
+ }
+
+ return info;
+ }
+
+ /// <summary>
+ /// Converts ffprobe stream info to our MediaStream class
+ /// </summary>
+ /// <param name="streamInfo">The stream info.</param>
+ /// <param name="formatInfo">The format info.</param>
+ /// <returns>MediaStream.</returns>
+ private MediaStream GetMediaStream(MediaStreamInfo streamInfo, MediaFormatInfo formatInfo)
+ {
+ var stream = new MediaStream
+ {
+ Codec = streamInfo.codec_name,
+ Profile = streamInfo.profile,
+ Level = streamInfo.level,
+ Index = streamInfo.index,
+ PixelFormat = streamInfo.pix_fmt
+ };
+
+ if (streamInfo.tags != null)
+ {
+ stream.Language = GetDictionaryValue(streamInfo.tags, "language");
+ }
+
+ if (string.Equals(streamInfo.codec_type, "audio", StringComparison.OrdinalIgnoreCase))
+ {
+ stream.Type = MediaStreamType.Audio;
+
+ stream.Channels = streamInfo.channels;
+
+ if (!string.IsNullOrEmpty(streamInfo.sample_rate))
+ {
+ stream.SampleRate = int.Parse(streamInfo.sample_rate, _usCulture);
+ }
+
+ stream.ChannelLayout = ParseChannelLayout(streamInfo.channel_layout);
+ }
+ else if (string.Equals(streamInfo.codec_type, "subtitle", StringComparison.OrdinalIgnoreCase))
+ {
+ stream.Type = MediaStreamType.Subtitle;
+ }
+ else if (string.Equals(streamInfo.codec_type, "video", StringComparison.OrdinalIgnoreCase))
+ {
+ stream.Type = (streamInfo.codec_name ?? string.Empty).IndexOf("mjpeg", StringComparison.OrdinalIgnoreCase) != -1
+ ? MediaStreamType.EmbeddedImage
+ : MediaStreamType.Video;
+
+ stream.Width = streamInfo.width;
+ stream.Height = streamInfo.height;
+ stream.AspectRatio = GetAspectRatio(streamInfo);
+
+ stream.AverageFrameRate = GetFrameRate(streamInfo.avg_frame_rate);
+ stream.RealFrameRate = GetFrameRate(streamInfo.r_frame_rate);
+
+ stream.BitDepth = GetBitDepth(stream.PixelFormat);
+
+ //stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase) ||
+ // string.Equals(stream.AspectRatio, "2.35:1", StringComparison.OrdinalIgnoreCase) ||
+ // string.Equals(stream.AspectRatio, "2.40:1", StringComparison.OrdinalIgnoreCase);
+
+ stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1", StringComparison.OrdinalIgnoreCase);
+ }
+ else
+ {
+ return null;
+ }
+
+ // Get stream bitrate
+ var bitrate = 0;
+
+ if (!string.IsNullOrEmpty(streamInfo.bit_rate))
+ {
+ bitrate = int.Parse(streamInfo.bit_rate, _usCulture);
+ }
+ else if (formatInfo != null && !string.IsNullOrEmpty(formatInfo.bit_rate) && stream.Type == MediaStreamType.Video)
+ {
+ // If the stream info doesn't have a bitrate get the value from the media format info
+ bitrate = int.Parse(formatInfo.bit_rate, _usCulture);
+ }
+
+ if (bitrate > 0)
+ {
+ stream.BitRate = bitrate;
+ }
+
+ if (streamInfo.disposition != null)
+ {
+ var isDefault = GetDictionaryValue(streamInfo.disposition, "default");
+ var isForced = GetDictionaryValue(streamInfo.disposition, "forced");
+
+ stream.IsDefault = string.Equals(isDefault, "1", StringComparison.OrdinalIgnoreCase);
+
+ stream.IsForced = string.Equals(isForced, "1", StringComparison.OrdinalIgnoreCase);
+ }
+
+ return stream;
+ }
+
+ private int? GetBitDepth(string pixelFormat)
+ {
+ var eightBit = new List<string>
+ {
+ "yuv420p",
+ "yuv411p",
+ "yuvj420p",
+ "uyyvyy411",
+ "nv12",
+ "nv21",
+ "rgb444le",
+ "rgb444be",
+ "bgr444le",
+ "bgr444be",
+ "yuvj411p"
+ };
+
+ if (!string.IsNullOrEmpty(pixelFormat))
+ {
+ if (eightBit.Contains(pixelFormat, StringComparer.OrdinalIgnoreCase))
+ {
+ return 8;
+ }
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Gets a string from an FFProbeResult tags dictionary
+ /// </summary>
+ /// <param name="tags">The tags.</param>
+ /// <param name="key">The key.</param>
+ /// <returns>System.String.</returns>
+ private string GetDictionaryValue(Dictionary<string, string> tags, string key)
+ {
+ if (tags == null)
+ {
+ return null;
+ }
+
+ string val;
+
+ tags.TryGetValue(key, out val);
+ return val;
+ }
+
+ private string ParseChannelLayout(string input)
+ {
+ if (string.IsNullOrEmpty(input))
+ {
+ return input;
+ }
+
+ return input.Split('(').FirstOrDefault();
+ }
+
+ private string GetAspectRatio(MediaStreamInfo info)
+ {
+ var original = info.display_aspect_ratio;
+
+ int height;
+ int width;
+
+ var parts = (original ?? string.Empty).Split(':');
+ if (!(parts.Length == 2 &&
+ int.TryParse(parts[0], NumberStyles.Any, _usCulture, out width) &&
+ int.TryParse(parts[1], NumberStyles.Any, _usCulture, out height) &&
+ width > 0 &&
+ height > 0))
+ {
+ width = info.width;
+ height = info.height;
+ }
+
+ if (width > 0 && height > 0)
+ {
+ double ratio = width;
+ ratio /= height;
+
+ if (IsClose(ratio, 1.777777778, .03))
+ {
+ return "16:9";
+ }
+
+ if (IsClose(ratio, 1.3333333333, .05))
+ {
+ return "4:3";
+ }
+
+ if (IsClose(ratio, 1.41))
+ {
+ return "1.41:1";
+ }
+
+ if (IsClose(ratio, 1.5))
+ {
+ return "1.5:1";
+ }
+
+ if (IsClose(ratio, 1.6))
+ {
+ return "1.6:1";
+ }
+
+ if (IsClose(ratio, 1.66666666667))
+ {
+ return "5:3";
+ }
+
+ if (IsClose(ratio, 1.85, .02))
+ {
+ return "1.85:1";
+ }
+
+ if (IsClose(ratio, 2.35, .025))
+ {
+ return "2.35:1";
+ }
+
+ if (IsClose(ratio, 2.4, .025))
+ {
+ return "2.40:1";
+ }
+ }
+
+ return original;
+ }
+
+ private bool IsClose(double d1, double d2, double variance = .005)
+ {
+ return Math.Abs(d1 - d2) <= variance;
+ }
+
+ /// <summary>
+ /// Gets a frame rate from a string value in ffprobe output
+ /// This could be a number or in the format of 2997/125.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>System.Nullable{System.Single}.</returns>
+ private float? GetFrameRate(string value)
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ var parts = value.Split('/');
+
+ float result;
+
+ if (parts.Length == 2)
+ {
+ result = float.Parse(parts[0], _usCulture) / float.Parse(parts[1], _usCulture);
+ }
+ else
+ {
+ result = float.Parse(parts[0], _usCulture);
+ }
+
+ return float.IsNaN(result) ? (float?)null : result;
+ }
+
+ return null;
+ }
+
+ private void SetAudioRuntimeTicks(InternalMediaInfoResult result, Model.MediaInfo.MediaInfo data)
+ {
+ if (result.streams != null)
+ {
+ // Get the first audio stream
+ var stream = result.streams.FirstOrDefault(s => string.Equals(s.codec_type, "audio", StringComparison.OrdinalIgnoreCase));
+
+ if (stream != null)
+ {
+ // Get duration from stream properties
+ var duration = stream.duration;
+
+ // If it's not there go into format properties
+ if (string.IsNullOrEmpty(duration))
+ {
+ duration = result.format.duration;
+ }
+
+ // If we got something, parse it
+ if (!string.IsNullOrEmpty(duration))
+ {
+ data.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, _usCulture)).Ticks;
+ }
+ }
+ }
+ }
+
+ private void SetSize(InternalMediaInfoResult data, Model.MediaInfo.MediaInfo info)
+ {
+ if (data.format != null)
+ {
+ if (!string.IsNullOrEmpty(data.format.size))
+ {
+ info.Size = long.Parse(data.format.size, _usCulture);
+ }
+ else
+ {
+ info.Size = null;
+ }
+ }
+ }
+
+ private void SetAudioInfoFromTags(Model.MediaInfo.MediaInfo audio, Dictionary<string, string> tags)
+ {
+ var title = FFProbeHelpers.GetDictionaryValue(tags, "title");
+
+ // Only set Name if title was found in the dictionary
+ if (!string.IsNullOrEmpty(title))
+ {
+ audio.Title = title;
+ }
+
+ var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer");
+
+ if (!string.IsNullOrWhiteSpace(composer))
+ {
+ foreach (var person in Split(composer, false))
+ {
+ audio.People.Add(new BaseItemPerson { Name = person, Type = PersonType.Composer });
+ }
+ }
+
+ audio.Album = FFProbeHelpers.GetDictionaryValue(tags, "album");
+
+ var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists");
+
+ if (!string.IsNullOrWhiteSpace(artists))
+ {
+ audio.Artists = artists.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+ }
+ else
+ {
+ var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist");
+ if (string.IsNullOrWhiteSpace(artist))
+ {
+ audio.Artists.Clear();
+ }
+ else
+ {
+ audio.Artists = SplitArtists(artist)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+ }
+ }
+
+ var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist");
+ if (string.IsNullOrWhiteSpace(albumArtist))
+ {
+ albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album artist");
+ }
+ if (string.IsNullOrWhiteSpace(albumArtist))
+ {
+ albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album_artist");
+ }
+
+ if (string.IsNullOrWhiteSpace(albumArtist))
+ {
+ audio.AlbumArtists = new List<string>();
+ }
+ else
+ {
+ audio.AlbumArtists = SplitArtists(albumArtist)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+
+ }
+
+ // Track number
+ audio.IndexNumber = GetDictionaryDiscValue(tags, "track");
+
+ // Disc number
+ audio.ParentIndexNumber = GetDictionaryDiscValue(tags, "disc");
+
+ audio.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date");
+
+ // Several different forms of retaildate
+ audio.PremiereDate = FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ??
+ FFProbeHelpers.GetDictionaryDateTime(tags, "retail date") ??
+ FFProbeHelpers.GetDictionaryDateTime(tags, "retail_date") ??
+ FFProbeHelpers.GetDictionaryDateTime(tags, "date");
+
+ // If we don't have a ProductionYear try and get it from PremiereDate
+ if (audio.PremiereDate.HasValue && !audio.ProductionYear.HasValue)
+ {
+ audio.ProductionYear = audio.PremiereDate.Value.ToLocalTime().Year;
+ }
+
+ FetchGenres(audio, tags);
+
+ // There's several values in tags may or may not be present
+ FetchStudios(audio, tags, "organization");
+ FetchStudios(audio, tags, "ensemble");
+ FetchStudios(audio, tags, "publisher");
+
+ // These support mulitple values, but for now we only store the first.
+ audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")));
+ audio.SetProviderId(MetadataProviders.MusicBrainzArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")));
+
+ audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")));
+ audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")));
+ audio.SetProviderId(MetadataProviders.MusicBrainzTrack, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")));
+ }
+
+ private string GetMultipleMusicBrainzId(string value)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ return null;
+ }
+
+ return value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
+ .Select(i => i.Trim())
+ .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
+ }
+
+ private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' };
+
+ /// <summary>
+ /// Splits the specified val.
+ /// </summary>
+ /// <param name="val">The val.</param>
+ /// <param name="allowCommaDelimiter">if set to <c>true</c> [allow comma delimiter].</param>
+ /// <returns>System.String[][].</returns>
+ private IEnumerable<string> Split(string val, bool allowCommaDelimiter)
+ {
+ // Only use the comma as a delimeter if there are no slashes or pipes.
+ // We want to be careful not to split names that have commas in them
+ var delimeter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i) != -1) ?
+ _nameDelimiters :
+ new[] { ',' };
+
+ return val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries)
+ .Where(i => !string.IsNullOrWhiteSpace(i))
+ .Select(i => i.Trim());
+ }
+
+ private const string ArtistReplaceValue = " | ";
+
+ private IEnumerable<string> SplitArtists(string val)
+ {
+ val = val.Replace(" featuring ", ArtistReplaceValue, StringComparison.OrdinalIgnoreCase)
+ .Replace(" feat. ", ArtistReplaceValue, StringComparison.OrdinalIgnoreCase);
+
+ var artistsFound = new List<string>();
+
+ foreach (var whitelistArtist in GetSplitWhitelist())
+ {
+ var originalVal = val;
+ val = val.Replace(whitelistArtist, "|", StringComparison.OrdinalIgnoreCase);
+
+ if (!string.Equals(originalVal, val, StringComparison.OrdinalIgnoreCase))
+ {
+ artistsFound.Add(whitelistArtist);
+ }
+ }
+
+ // Only use the comma as a delimeter if there are no slashes or pipes.
+ // We want to be careful not to split names that have commas in them
+ var delimeter = _nameDelimiters;
+
+ var artists = val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries)
+ .Where(i => !string.IsNullOrWhiteSpace(i))
+ .Select(i => i.Trim());
+
+ artistsFound.AddRange(artists);
+ return artistsFound;
+ }
+
+
+ private List<string> _splitWhiteList = null;
+
+ private IEnumerable<string> GetSplitWhitelist()
+ {
+ if (_splitWhiteList == null)
+ {
+ var file = GetType().Namespace + ".whitelist.txt";
+
+ using (var stream = GetType().Assembly.GetManifestResourceStream(file))
+ {
+ using (var reader = new StreamReader(stream))
+ {
+ var list = new List<string>();
+
+ while (!reader.EndOfStream)
+ {
+ var val = reader.ReadLine();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ list.Add(val);
+ }
+ }
+
+ _splitWhiteList = list;
+ }
+ }
+ }
+
+ return _splitWhiteList;
+ }
+
+ /// <summary>
+ /// Gets the studios from the tags collection
+ /// </summary>
+ /// <param name="audio">The audio.</param>
+ /// <param name="tags">The tags.</param>
+ /// <param name="tagName">Name of the tag.</param>
+ private void FetchStudios(Model.MediaInfo.MediaInfo audio, Dictionary<string, string> tags, string tagName)
+ {
+ var val = FFProbeHelpers.GetDictionaryValue(tags, tagName);
+
+ if (!string.IsNullOrEmpty(val))
+ {
+ var studios = Split(val, true);
+
+ foreach (var studio in studios)
+ {
+ // Sometimes the artist name is listed here, account for that
+ if (audio.Artists.Contains(studio, StringComparer.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+ if (audio.AlbumArtists.Contains(studio, StringComparer.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ audio.Studios.Add(studio);
+ }
+
+ audio.Studios = audio.Studios
+ .Where(i => !string.IsNullOrWhiteSpace(i))
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+ }
+ }
+
+ /// <summary>
+ /// Gets the genres from the tags collection
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <param name="tags">The tags.</param>
+ private void FetchGenres(Model.MediaInfo.MediaInfo info, Dictionary<string, string> tags)
+ {
+ var val = FFProbeHelpers.GetDictionaryValue(tags, "genre");
+
+ if (!string.IsNullOrEmpty(val))
+ {
+ foreach (var genre in Split(val, true))
+ {
+ info.Genres.Add(genre);
+ }
+
+ info.Genres = info.Genres
+ .Where(i => !string.IsNullOrWhiteSpace(i))
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+ }
+ }
+
+ /// <summary>
+ /// Gets the disc number, which is sometimes can be in the form of '1', or '1/3'
+ /// </summary>
+ /// <param name="tags">The tags.</param>
+ /// <param name="tagName">Name of the tag.</param>
+ /// <returns>System.Nullable{System.Int32}.</returns>
+ private int? GetDictionaryDiscValue(Dictionary<string, string> tags, string tagName)
+ {
+ var disc = FFProbeHelpers.GetDictionaryValue(tags, tagName);
+
+ if (!string.IsNullOrEmpty(disc))
+ {
+ disc = disc.Split('/')[0];
+
+ int num;
+
+ if (int.TryParse(disc, out num))
+ {
+ return num;
+ }
+ }
+
+ return null;
+ }
+
+ private ChapterInfo GetChapterInfo(MediaChapter chapter)
+ {
+ var info = new ChapterInfo();
+
+ if (chapter.tags != null)
+ {
+ string name;
+ if (chapter.tags.TryGetValue("title", out name))
+ {
+ info.Name = name;
+ }
+ }
+
+ // Limit accuracy to milliseconds to match xml saving
+ var secondsString = chapter.start_time;
+ double seconds;
+
+ if (double.TryParse(secondsString, NumberStyles.Any, CultureInfo.InvariantCulture, out seconds))
+ {
+ var ms = Math.Round(TimeSpan.FromSeconds(seconds).TotalMilliseconds);
+ info.StartPositionTicks = TimeSpan.FromMilliseconds(ms).Ticks;
+ }
+
+ return info;
+ }
+
+ private const int MaxSubtitleDescriptionExtractionLength = 100; // When extracting subtitles, the maximum length to consider (to avoid invalid filenames)
+
+ private void FetchWtvInfo(Model.MediaInfo.MediaInfo video, InternalMediaInfoResult data)
+ {
+ if (data.format == null || data.format.tags == null)
+ {
+ return;
+ }
+
+ var genres = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/Genre");
+
+ if (!string.IsNullOrWhiteSpace(genres))
+ {
+ //genres = FFProbeHelpers.GetDictionaryValue(data.format.tags, "genre");
+ }
+
+ if (!string.IsNullOrWhiteSpace(genres))
+ {
+ video.Genres = genres.Split(new[] { ';', '/', ',' }, StringSplitOptions.RemoveEmptyEntries)
+ .Where(i => !string.IsNullOrWhiteSpace(i))
+ .Select(i => i.Trim())
+ .ToList();
+ }
+
+ var officialRating = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/ParentalRating");
+
+ if (!string.IsNullOrWhiteSpace(officialRating))
+ {
+ video.OfficialRating = officialRating;
+ }
+
+ var people = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/MediaCredits");
+
+ if (!string.IsNullOrEmpty(people))
+ {
+ video.People = people.Split(new[] { ';', '/' }, StringSplitOptions.RemoveEmptyEntries)
+ .Where(i => !string.IsNullOrWhiteSpace(i))
+ .Select(i => new BaseItemPerson { Name = i.Trim(), Type = PersonType.Actor })
+ .ToList();
+ }
+
+ var year = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/OriginalReleaseTime");
+ if (!string.IsNullOrWhiteSpace(year))
+ {
+ int val;
+
+ if (int.TryParse(year, NumberStyles.Integer, _usCulture, out val))
+ {
+ video.ProductionYear = val;
+ }
+ }
+
+ var premiereDateString = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/MediaOriginalBroadcastDateTime");
+ if (!string.IsNullOrWhiteSpace(premiereDateString))
+ {
+ DateTime val;
+
+ // Credit to MCEBuddy: https://mcebuddy2x.codeplex.com/
+ // DateTime is reported along with timezone info (typically Z i.e. UTC hence assume None)
+ if (DateTime.TryParse(year, null, DateTimeStyles.None, out val))
+ {
+ video.PremiereDate = val.ToUniversalTime();
+ }
+ }
+
+ var description = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/SubTitleDescription");
+
+ var subTitle = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/SubTitle");
+
+ // For below code, credit to MCEBuddy: https://mcebuddy2x.codeplex.com/
+
+ // Sometimes for TV Shows the Subtitle field is empty and the subtitle description contains the subtitle, extract if possible. See ticket https://mcebuddy2x.codeplex.com/workitem/1910
+ // The format is -> EPISODE/TOTAL_EPISODES_IN_SEASON. SUBTITLE: DESCRIPTION
+ // OR -> COMMENT. SUBTITLE: DESCRIPTION
+ // e.g. -> 4/13. The Doctor's Wife: Science fiction drama. When he follows a Time Lord distress signal, the Doctor puts Amy, Rory and his beloved TARDIS in grave danger. Also in HD. [AD,S]
+ // e.g. -> CBeebies Bedtime Hour. The Mystery: Animated adventures of two friends who live on an island in the middle of the big city. Some of Abney and Teal's favourite objects are missing. [S]
+ if (String.IsNullOrWhiteSpace(subTitle) && !String.IsNullOrWhiteSpace(description) && description.Substring(0, Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)).Contains(":")) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename
+ {
+ string[] parts = description.Split(':');
+ if (parts.Length > 0)
+ {
+ string subtitle = parts[0];
+ try
+ {
+ if (subtitle.Contains("/")) // It contains a episode number and season number
+ {
+ string[] numbers = subtitle.Split(' ');
+ video.IndexNumber = int.Parse(numbers[0].Replace(".", "").Split('/')[0]);
+ int totalEpisodesInSeason = int.Parse(numbers[0].Replace(".", "").Split('/')[1]);
+
+ description = String.Join(" ", numbers, 1, numbers.Length - 1).Trim(); // Skip the first, concatenate the rest, clean up spaces and save it
+ }
+ else
+ throw new Exception(); // Switch to default parsing
+ }
+ catch // Default parsing
+ {
+ if (subtitle.Contains(".")) // skip the comment, keep the subtitle
+ description = String.Join(".", subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first
+ else
+ description = subtitle.Trim(); // Clean up whitespaces and save it
+ }
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(description))
+ {
+ video.Overview = description;
+ }
+ }
+
+ private void ExtractTimestamp(Model.MediaInfo.MediaInfo video)
+ {
+ if (video.VideoType == VideoType.VideoFile)
+ {
+ if (string.Equals(video.Container, "mpeg2ts", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(video.Container, "m2ts", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(video.Container, "ts", StringComparison.OrdinalIgnoreCase))
+ {
+ try
+ {
+ video.Timestamp = GetMpegTimestamp(video.Path);
+
+ _logger.Debug("Video has {0} timestamp", video.Timestamp);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error extracting timestamp info from {0}", ex, video.Path);
+ video.Timestamp = null;
+ }
+ }
+ }
+ }
+
+ private TransportStreamTimestamp GetMpegTimestamp(string path)
+ {
+ var packetBuffer = new byte['Å'];
+
+ using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
+ {
+ fs.Read(packetBuffer, 0, packetBuffer.Length);
+ }
+
+ if (packetBuffer[0] == 71)
+ {
+ return TransportStreamTimestamp.None;
+ }
+
+ if ((packetBuffer[4] == 71) && (packetBuffer['Ä'] == 71))
+ {
+ if ((packetBuffer[0] == 0) && (packetBuffer[1] == 0) && (packetBuffer[2] == 0) && (packetBuffer[3] == 0))
+ {
+ return TransportStreamTimestamp.Zero;
+ }
+
+ return TransportStreamTimestamp.Valid;
+ }
+
+ return TransportStreamTimestamp.None;
+ }
+
+ private void UpdateFromMediaInfo(MediaSourceInfo video, MediaStream videoStream)
+ {
+ if (video.VideoType == VideoType.VideoFile && video.Protocol == MediaProtocol.File)
+ {
+ if (videoStream != null)
+ {
+ try
+ {
+ var result = new MediaInfoLib().GetVideoInfo(video.Path);
+
+ videoStream.IsCabac = result.IsCabac ?? videoStream.IsCabac;
+ videoStream.IsInterlaced = result.IsInterlaced ?? videoStream.IsInterlaced;
+ videoStream.BitDepth = result.BitDepth ?? videoStream.BitDepth;
+ videoStream.RefFrames = result.RefFrames;
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error running MediaInfo on {0}", ex, video.Path);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/MediaInfo/whitelist.txt b/MediaBrowser.MediaEncoding/Probing/whitelist.txt
index 1fd366551..1fd366551 100644
--- a/MediaBrowser.Providers/MediaInfo/whitelist.txt
+++ b/MediaBrowser.MediaEncoding/Probing/whitelist.txt
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index 14d3e7284..60b70ad08 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -132,7 +132,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
int subtitleStreamIndex,
CancellationToken cancellationToken)
{
- var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(itemId, false, cancellationToken).ConfigureAwait(false);
+ var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(itemId, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false);
var mediaSource = mediaSources
.First(i => string.Equals(i.Id, mediaSourceId));
diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
index fdedc51a2..1aa8d7f1f 100644
--- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
+++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
@@ -464,6 +464,9 @@
<Compile Include="..\MediaBrowser.Model\Dto\IHasServerId.cs">
<Link>Dto\IHasServerId.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dto\IHasSyncInfo.cs">
+ <Link>Dto\IHasSyncInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\IItemDto.cs">
<Link>Dto\IItemDto.cs</Link>
</Compile>
@@ -560,9 +563,6 @@
<Compile Include="..\MediaBrowser.Model\Entities\MBRegistrationRecord.cs">
<Link>Entities\MBRegistrationRecord.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Entities\MediaInfo.cs">
- <Link>Entities\MediaInfo.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\MediaStream.cs">
<Link>Entities\MediaStream.cs</Link>
</Compile>
@@ -809,6 +809,9 @@
<Compile Include="..\MediaBrowser.Model\MediaInfo\LiveStreamResponse.cs">
<Link>MediaInfo\LiveStreamResponse.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\MediaInfo\MediaInfo.cs">
+ <Link>MediaInfo\MediaInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\MediaInfo\MediaProtocol.cs">
<Link>MediaInfo\MediaProtocol.cs</Link>
</Compile>
diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
index 3618aa972..5d4633f50 100644
--- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
+++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
@@ -429,6 +429,9 @@
<Compile Include="..\MediaBrowser.Model\Dto\IHasServerId.cs">
<Link>Dto\IHasServerId.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dto\IHasSyncInfo.cs">
+ <Link>Dto\IHasSyncInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\IItemDto.cs">
<Link>Dto\IItemDto.cs</Link>
</Compile>
@@ -525,9 +528,6 @@
<Compile Include="..\MediaBrowser.Model\Entities\MBRegistrationRecord.cs">
<Link>Entities\MBRegistrationRecord.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Entities\MediaInfo.cs">
- <Link>Entities\MediaInfo.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\MediaStream.cs">
<Link>Entities\MediaStream.cs</Link>
</Compile>
@@ -765,6 +765,9 @@
<Compile Include="..\MediaBrowser.Model\MediaInfo\LiveStreamResponse.cs">
<Link>MediaInfo\LiveStreamResponse.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\MediaInfo\MediaInfo.cs">
+ <Link>MediaInfo\MediaInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\MediaInfo\MediaProtocol.cs">
<Link>MediaInfo\MediaProtocol.cs</Link>
</Compile>
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index c06aedb50..ac9bd6b08 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -200,7 +200,7 @@ namespace MediaBrowser.Model.Configuration
public PeopleMetadataOptions PeopleMetadataOptions { get; set; }
public bool FindInternetTrailers { get; set; }
- public string[] InsecureApps8 { get; set; }
+ public string[] InsecureApps9 { get; set; }
public bool SaveMetadataHidden { get; set; }
@@ -208,6 +208,7 @@ namespace MediaBrowser.Model.Configuration
public bool EnableAudioArchiveFiles { get; set; }
public bool EnableVideoArchiveFiles { get; set; }
+ public int RemoteClientBitrateLimit { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
@@ -257,7 +258,7 @@ namespace MediaBrowser.Model.Configuration
PeopleMetadataOptions = new PeopleMetadataOptions();
- InsecureApps8 = new[]
+ InsecureApps9 = new[]
{
"Chromecast",
"iOS",
@@ -266,7 +267,6 @@ namespace MediaBrowser.Model.Configuration
"Media Portal",
"iPad",
"iPhone",
- "Roku",
"Windows Phone"
};
diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs
index 7390af088..9cd8c1067 100644
--- a/MediaBrowser.Model/Configuration/UserConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs
@@ -7,12 +7,6 @@ namespace MediaBrowser.Model.Configuration
public class UserConfiguration
{
/// <summary>
- /// Gets or sets a value indicating whether this instance is administrator.
- /// </summary>
- /// <value><c>true</c> if this instance is administrator; otherwise, <c>false</c>.</value>
- public bool IsAdministrator { get; set; }
-
- /// <summary>
/// Gets or sets the audio language preference.
/// </summary>
/// <value>The audio language preference.</value>
@@ -53,7 +47,6 @@ namespace MediaBrowser.Model.Configuration
public string[] LatestItemsExcludes { get; set; }
- public bool HasMigratedToPolicy { get; set; }
public bool HidePlayedInLatest { get; set; }
/// <summary>
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index bc9f07d04..daeb50225 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions;
+using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Session;
using System;
@@ -11,13 +12,16 @@ namespace MediaBrowser.Model.Dlna
public class StreamBuilder
{
private readonly ILocalPlayer _localPlayer;
+ private readonly ILogger _logger;
- public StreamBuilder(ILocalPlayer localPlayer)
+ public StreamBuilder(ILocalPlayer localPlayer, ILogger logger)
{
_localPlayer = localPlayer;
+ _logger = logger;
}
- public StreamBuilder()
- : this(new NullLocalPlayer())
+
+ public StreamBuilder(ILogger logger)
+ : this(new NullLocalPlayer(), logger)
{
}
@@ -353,6 +357,12 @@ namespace MediaBrowser.Model.Dlna
bool isEligibleForDirectPlay = IsEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options), subtitleStream, options);
bool isEligibleForDirectStream = IsEligibleForDirectPlay(item, options.GetMaxBitrate(), subtitleStream, options);
+ _logger.Debug("Profile: {0}, Path: {1}, isEligibleForDirectPlay: {2}, isEligibleForDirectStream: {3}",
+ options.Profile.Name ?? "Unknown Profile",
+ item.Path ?? "Unknown path",
+ isEligibleForDirectPlay,
+ isEligibleForDirectStream);
+
if (isEligibleForDirectPlay || isEligibleForDirectStream)
{
// See if it can be direct played
@@ -504,6 +514,10 @@ namespace MediaBrowser.Model.Dlna
if (directPlay == null)
{
+ _logger.Debug("Profile: {0}, No direct play profiles found for Path: {1}",
+ profile.Name ?? "Unknown Profile",
+ mediaSource.Path ?? "Unknown path");
+
return null;
}
@@ -550,6 +564,11 @@ namespace MediaBrowser.Model.Dlna
{
if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams))
{
+ _logger.Debug("Profile: {0}, DirectPlay=false. Reason=VideoContainerProfile.{1} Path: {2}",
+ profile.Name ?? "Unknown Profile",
+ i.Property,
+ mediaSource.Path ?? "Unknown path");
+
return null;
}
}
@@ -558,6 +577,10 @@ namespace MediaBrowser.Model.Dlna
if (string.IsNullOrEmpty(videoCodec))
{
+ _logger.Debug("Profile: {0}, DirectPlay=false. Reason=Unknown video codec. Path: {1}",
+ profile.Name ?? "Unknown Profile",
+ mediaSource.Path ?? "Unknown path");
+
return null;
}
@@ -577,6 +600,11 @@ namespace MediaBrowser.Model.Dlna
{
if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams))
{
+ _logger.Debug("Profile: {0}, DirectPlay=false. Reason=VideoCodecProfile.{1} Path: {2}",
+ profile.Name ?? "Unknown Profile",
+ i.Property,
+ mediaSource.Path ?? "Unknown path");
+
return null;
}
}
@@ -587,6 +615,10 @@ namespace MediaBrowser.Model.Dlna
if (string.IsNullOrEmpty(audioCodec))
{
+ _logger.Debug("Profile: {0}, DirectPlay=false. Reason=Unknown audio codec. Path: {1}",
+ profile.Name ?? "Unknown Profile",
+ mediaSource.Path ?? "Unknown path");
+
return null;
}
@@ -607,6 +639,11 @@ namespace MediaBrowser.Model.Dlna
bool? isSecondaryAudio = audioStream == null ? null : mediaSource.IsSecondaryAudio(audioStream);
if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioProfile, isSecondaryAudio))
{
+ _logger.Debug("Profile: {0}, DirectPlay=false. Reason=VideoAudioCodecProfile.{1} Path: {2}",
+ profile.Name ?? "Unknown Profile",
+ i.Property,
+ mediaSource.Path ?? "Unknown path");
+
return null;
}
}
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index a908c7850..f6ff79b11 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -70,6 +70,7 @@ namespace MediaBrowser.Model.Dlna
public string SubtitleFormat { get; set; }
public string PlaySessionId { get; set; }
+ public List<MediaSourceInfo> AllMediaSources { get; set; }
public string MediaSourceId
{
diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs
index c49a1f77e..c772692a2 100644
--- a/MediaBrowser.Model/Dto/BaseItemDto.cs
+++ b/MediaBrowser.Model/Dto/BaseItemDto.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Providers;
+using MediaBrowser.Model.Sync;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -16,7 +17,7 @@ namespace MediaBrowser.Model.Dto
/// This holds information about a BaseItem in a format that is convenient for the client.
/// </summary>
[DebuggerDisplay("Name = {Name}, ID = {Id}, Type = {Type}")]
- public class BaseItemDto : IHasProviderIds, IHasPropertyChangedEvent, IItemDto, IHasServerId
+ public class BaseItemDto : IHasProviderIds, IHasPropertyChangedEvent, IItemDto, IHasServerId, IHasSyncInfo
{
/// <summary>
/// Gets or sets the name.
@@ -37,6 +38,12 @@ namespace MediaBrowser.Model.Dto
public string Id { get; set; }
/// <summary>
+ /// Gets or sets the etag.
+ /// </summary>
+ /// <value>The etag.</value>
+ public string Etag { get; set; }
+
+ /// <summary>
/// Gets or sets the playlist item identifier.
/// </summary>
/// <value>The playlist item identifier.</value>
@@ -63,6 +70,7 @@ namespace MediaBrowser.Model.Dto
public string PreferredMetadataCountryCode { get; set; }
public string AwardSummary { get; set; }
+ public string ShareUrl { get; set; }
public float? Metascore { get; set; }
@@ -86,6 +94,11 @@ namespace MediaBrowser.Model.Dto
/// </summary>
/// <value><c>null</c> if [is synced] contains no value, <c>true</c> if [is synced]; otherwise, <c>false</c>.</value>
public bool? IsSynced { get; set; }
+ /// <summary>
+ /// Gets or sets the synchronize status.
+ /// </summary>
+ /// <value>The synchronize status.</value>
+ public SyncJobItemStatus? SyncStatus { get; set; }
/// <summary>
/// Gets or sets the DVD season number.
diff --git a/MediaBrowser.Model/Dto/BaseItemPerson.cs b/MediaBrowser.Model/Dto/BaseItemPerson.cs
index 46485316e..8e7750562 100644
--- a/MediaBrowser.Model/Dto/BaseItemPerson.cs
+++ b/MediaBrowser.Model/Dto/BaseItemPerson.cs
@@ -1,7 +1,7 @@
-using System.ComponentModel;
+using MediaBrowser.Model.Extensions;
+using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.Serialization;
-using MediaBrowser.Model.Extensions;
namespace MediaBrowser.Model.Dto
{
diff --git a/MediaBrowser.Model/Dto/IHasSyncInfo.cs b/MediaBrowser.Model/Dto/IHasSyncInfo.cs
new file mode 100644
index 000000000..d2cf1f8cf
--- /dev/null
+++ b/MediaBrowser.Model/Dto/IHasSyncInfo.cs
@@ -0,0 +1,13 @@
+using MediaBrowser.Model.Sync;
+
+namespace MediaBrowser.Model.Dto
+{
+ public interface IHasSyncInfo
+ {
+ string Id { get; }
+ bool? SupportsSync { get; set; }
+ bool? HasSyncJob { get; set; }
+ bool? IsSynced { get; set; }
+ SyncJobItemStatus? SyncStatus { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Entities/CollectionType.cs b/MediaBrowser.Model/Entities/CollectionType.cs
index e51b2d311..a259f4c07 100644
--- a/MediaBrowser.Model/Entities/CollectionType.cs
+++ b/MediaBrowser.Model/Entities/CollectionType.cs
@@ -61,6 +61,7 @@
public const string MusicGenres = "MusicGenres";
public const string MusicGenre = "MusicGenre";
public const string MusicLatest = "MusicLatest";
+ public const string MusicPlaylists = "MusicPlaylists";
public const string MusicSongs = "MusicSongs";
public const string MusicFavorites = "MusicFavorites";
public const string MusicFavoriteArtists = "MusicFavoriteArtists";
diff --git a/MediaBrowser.Model/Entities/MediaInfo.cs b/MediaBrowser.Model/Entities/MediaInfo.cs
deleted file mode 100644
index ef26cfa14..000000000
--- a/MediaBrowser.Model/Entities/MediaInfo.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System.Collections.Generic;
-
-namespace MediaBrowser.Model.Entities
-{
- public class MediaInfo
- {
- /// <summary>
- /// Gets or sets the media streams.
- /// </summary>
- /// <value>The media streams.</value>
- public List<MediaStream> MediaStreams { get; set; }
-
- /// <summary>
- /// Gets or sets the format.
- /// </summary>
- /// <value>The format.</value>
- public string Format { get; set; }
-
- public int? TotalBitrate { get; set; }
-
- public MediaInfo()
- {
- MediaStreams = new List<MediaStream>();
- }
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs
index 0f3435174..11eb31c27 100644
--- a/MediaBrowser.Model/Entities/MediaStream.cs
+++ b/MediaBrowser.Model/Entities/MediaStream.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Dlna;
+using System.Collections.Generic;
+using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Extensions;
using System.Diagnostics;
@@ -59,6 +60,12 @@ namespace MediaBrowser.Model.Entities
public int? PacketLength { get; set; }
/// <summary>
+ /// Gets or sets the key frames.
+ /// </summary>
+ /// <value>The key frames.</value>
+ public List<int> KeyFrames { get; set; }
+
+ /// <summary>
/// Gets or sets the channels.
/// </summary>
/// <value>The channels.</value>
diff --git a/MediaBrowser.Model/LiveTv/ProgramQuery.cs b/MediaBrowser.Model/LiveTv/ProgramQuery.cs
index bbd396c33..c19ba54bd 100644
--- a/MediaBrowser.Model/LiveTv/ProgramQuery.cs
+++ b/MediaBrowser.Model/LiveTv/ProgramQuery.cs
@@ -54,6 +54,12 @@ namespace MediaBrowser.Model.LiveTv
public bool? IsMovie { get; set; }
/// <summary>
+ /// Gets or sets a value indicating whether this instance is sports.
+ /// </summary>
+ /// <value><c>null</c> if [is sports] contains no value, <c>true</c> if [is sports]; otherwise, <c>false</c>.</value>
+ public bool? IsSports { get; set; }
+
+ /// <summary>
/// Skips over a given number of items within the results. Use for paging.
/// </summary>
public int? StartIndex { get; set; }
diff --git a/MediaBrowser.Model/LiveTv/RecommendedProgramQuery.cs b/MediaBrowser.Model/LiveTv/RecommendedProgramQuery.cs
index 9ba8e0e5f..4a8ae2365 100644
--- a/MediaBrowser.Model/LiveTv/RecommendedProgramQuery.cs
+++ b/MediaBrowser.Model/LiveTv/RecommendedProgramQuery.cs
@@ -31,5 +31,10 @@
/// </summary>
/// <value><c>null</c> if [is movie] contains no value, <c>true</c> if [is movie]; otherwise, <c>false</c>.</value>
public bool? IsMovie { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is sports.
+ /// </summary>
+ /// <value><c>null</c> if [is sports] contains no value, <c>true</c> if [is sports]; otherwise, <c>false</c>.</value>
+ public bool? IsSports { get; set; }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs
index d6d698038..0988b11a6 100644
--- a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Library;
+using MediaBrowser.Model.Sync;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -11,7 +12,7 @@ using System.Runtime.Serialization;
namespace MediaBrowser.Model.LiveTv
{
[DebuggerDisplay("Name = {Name}, ChannelName = {ChannelName}")]
- public class RecordingInfoDto : IHasPropertyChangedEvent, IItemDto, IHasServerId
+ public class RecordingInfoDto : IHasPropertyChangedEvent, IItemDto, IHasServerId, IHasSyncInfo
{
/// <summary>
/// Id of the recording.
@@ -35,6 +36,27 @@ namespace MediaBrowser.Model.LiveTv
/// </summary>
/// <value>The original primary image aspect ratio.</value>
public double? OriginalPrimaryImageAspectRatio { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether [supports synchronize].
+ /// </summary>
+ /// <value><c>null</c> if [supports synchronize] contains no value, <c>true</c> if [supports synchronize]; otherwise, <c>false</c>.</value>
+ public bool? SupportsSync { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance has synchronize job.
+ /// </summary>
+ /// <value><c>null</c> if [has synchronize job] contains no value, <c>true</c> if [has synchronize job]; otherwise, <c>false</c>.</value>
+ public bool? HasSyncJob { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is synced.
+ /// </summary>
+ /// <value><c>null</c> if [is synced] contains no value, <c>true</c> if [is synced]; otherwise, <c>false</c>.</value>
+ public bool? IsSynced { get; set; }
+ /// <summary>
+ /// Gets or sets the synchronize status.
+ /// </summary>
+ /// <value>The synchronize status.</value>
+ public SyncJobItemStatus? SyncStatus { get; set; }
/// <summary>
/// Gets or sets the series timer identifier.
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index 067309512..eb36712c2 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -138,6 +138,7 @@
<Compile Include="Dlna\SubtitleStreamInfo.cs" />
<Compile Include="Drawing\ImageOrientation.cs" />
<Compile Include="Dto\IHasServerId.cs" />
+ <Compile Include="Dto\IHasSyncInfo.cs" />
<Compile Include="Dto\MetadataEditorInfo.cs" />
<Compile Include="Dto\NameIdPair.cs" />
<Compile Include="Dto\NameValuePair.cs" />
@@ -226,7 +227,7 @@
<Compile Include="Dto\RecommendationType.cs" />
<Compile Include="Dto\SubtitleDownloadOptions.cs" />
<Compile Include="Entities\IsoType.cs" />
- <Compile Include="Entities\MediaInfo.cs" />
+ <Compile Include="MediaInfo\MediaInfo.cs" />
<Compile Include="Entities\MediaStreamType.cs" />
<Compile Include="Entities\PackageReviewInfo.cs" />
<Compile Include="Entities\ProviderIdsExtensions.cs" />
diff --git a/MediaBrowser.Model/MediaInfo/MediaInfo.cs b/MediaBrowser.Model/MediaInfo/MediaInfo.cs
new file mode 100644
index 000000000..21f258693
--- /dev/null
+++ b/MediaBrowser.Model/MediaInfo/MediaInfo.cs
@@ -0,0 +1,66 @@
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.MediaInfo
+{
+ public class MediaInfo : MediaSourceInfo, IHasProviderIds
+ {
+ public List<ChapterInfo> Chapters { get; set; }
+
+ /// <summary>
+ /// Gets or sets the title.
+ /// </summary>
+ /// <value>The title.</value>
+ public string Title { get; set; }
+ /// <summary>
+ /// Gets or sets the album.
+ /// </summary>
+ /// <value>The album.</value>
+ public string Album { get; set; }
+ /// <summary>
+ /// Gets or sets the artists.
+ /// </summary>
+ /// <value>The artists.</value>
+ public List<string> Artists { get; set; }
+ /// <summary>
+ /// Gets or sets the album artists.
+ /// </summary>
+ /// <value>The album artists.</value>
+ public List<string> AlbumArtists { get; set; }
+ /// <summary>
+ /// Gets or sets the studios.
+ /// </summary>
+ /// <value>The studios.</value>
+ public List<string> Studios { get; set; }
+ public List<string> Genres { get; set; }
+ public int? IndexNumber { get; set; }
+ public int? ParentIndexNumber { get; set; }
+ public int? ProductionYear { get; set; }
+ public DateTime? PremiereDate { get; set; }
+ public List<BaseItemPerson> People { get; set; }
+ public Dictionary<string, string> ProviderIds { get; set; }
+ /// <summary>
+ /// Gets or sets the official rating.
+ /// </summary>
+ /// <value>The official rating.</value>
+ public string OfficialRating { get; set; }
+ /// <summary>
+ /// Gets or sets the overview.
+ /// </summary>
+ /// <value>The overview.</value>
+ public string Overview { get; set; }
+
+ public MediaInfo()
+ {
+ Chapters = new List<ChapterInfo>();
+ Artists = new List<string>();
+ AlbumArtists = new List<string>();
+ Studios = new List<string>();
+ Genres = new List<string>();
+ People = new List<BaseItemPerson>();
+ ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Notifications/NotificationOptions.cs b/MediaBrowser.Model/Notifications/NotificationOptions.cs
index e57955c9e..683f1a76c 100644
--- a/MediaBrowser.Model/Notifications/NotificationOptions.cs
+++ b/MediaBrowser.Model/Notifications/NotificationOptions.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Extensions;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Model.Notifications
{
@@ -106,7 +107,7 @@ namespace MediaBrowser.Model.Notifications
!ListHelper.ContainsIgnoreCase(opt.DisabledMonitorUsers, userId);
}
- public bool IsEnabledToSendToUser(string type, string userId, UserConfiguration userConfig)
+ public bool IsEnabledToSendToUser(string type, string userId, UserPolicy userPolicy)
{
NotificationOption opt = GetOptions(type);
@@ -117,7 +118,7 @@ namespace MediaBrowser.Model.Notifications
return true;
}
- if (opt.SendToUserMode == SendToUserType.Admins && userConfig.IsAdministrator)
+ if (opt.SendToUserMode == SendToUserType.Admins && userPolicy.IsAdministrator)
{
return true;
}
diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs
index 54c83ca15..77b3dc0ee 100644
--- a/MediaBrowser.Model/Querying/ItemFields.cs
+++ b/MediaBrowser.Model/Querying/ItemFields.cs
@@ -76,6 +76,11 @@
DisplayMediaType,
/// <summary>
+ /// The etag
+ /// </summary>
+ Etag,
+
+ /// <summary>
/// The external urls
/// </summary>
ExternalUrls,
diff --git a/MediaBrowser.Model/Querying/ItemQuery.cs b/MediaBrowser.Model/Querying/ItemQuery.cs
index 0cdf5ca7a..5a88c0d43 100644
--- a/MediaBrowser.Model/Querying/ItemQuery.cs
+++ b/MediaBrowser.Model/Querying/ItemQuery.cs
@@ -281,6 +281,13 @@ namespace MediaBrowser.Model.Querying
public int? ImageTypeLimit { get; set; }
public ImageType[] EnableImageTypes { get; set; }
+ [Obsolete]
+ public string[] Artists { get; set; }
+ [Obsolete]
+ public string[] Studios { get; set; }
+ [Obsolete]
+ public string Person { get; set; }
+
/// <summary>
/// Initializes a new instance of the <see cref="ItemQuery" /> class.
/// </summary>
@@ -299,6 +306,9 @@ namespace MediaBrowser.Model.Querying
VideoTypes = new VideoType[] { };
+ Artists = new string[] { };
+ Studios = new string[] { };
+
Genres = new string[] { };
StudioIds = new string[] { };
IncludeItemTypes = new string[] { };
diff --git a/MediaBrowser.Model/Querying/ItemSortBy.cs b/MediaBrowser.Model/Querying/ItemSortBy.cs
index fcc7e39a1..9c2926b54 100644
--- a/MediaBrowser.Model/Querying/ItemSortBy.cs
+++ b/MediaBrowser.Model/Querying/ItemSortBy.cs
@@ -43,6 +43,7 @@ namespace MediaBrowser.Model.Querying
/// The premiere date
/// </summary>
public const string PremiereDate = "PremiereDate";
+ public const string StartDate = "StartDate";
/// <summary>
/// The sort name
/// </summary>
diff --git a/MediaBrowser.Model/Session/ClientCapabilities.cs b/MediaBrowser.Model/Session/ClientCapabilities.cs
index 9361a60ea..095ad472a 100644
--- a/MediaBrowser.Model/Session/ClientCapabilities.cs
+++ b/MediaBrowser.Model/Session/ClientCapabilities.cs
@@ -19,12 +19,17 @@ namespace MediaBrowser.Model.Session
public bool SupportsOfflineAccess { get; set; }
public DeviceProfile DeviceProfile { get; set; }
+ public List<string> SupportedLiveMediaTypes { get; set; }
+
+ public string AppUrl { get; set; }
+ public string AppImageUrl { get; set; }
public ClientCapabilities()
{
PlayableMediaTypes = new List<string>();
SupportedCommands = new List<string>();
SupportsPersistentIdentifier = true;
+ SupportedLiveMediaTypes = new List<string>();
}
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Sync/LocalItem.cs b/MediaBrowser.Model/Sync/LocalItem.cs
index dbbecaf05..c5728ac97 100644
--- a/MediaBrowser.Model/Sync/LocalItem.cs
+++ b/MediaBrowser.Model/Sync/LocalItem.cs
@@ -26,6 +26,11 @@ namespace MediaBrowser.Model.Sync
/// <value>The unique identifier.</value>
public string Id { get; set; }
/// <summary>
+ /// Gets or sets the file identifier.
+ /// </summary>
+ /// <value>The file identifier.</value>
+ public string FileId { get; set; }
+ /// <summary>
/// Gets or sets the item identifier.
/// </summary>
/// <value>The item identifier.</value>
diff --git a/MediaBrowser.Model/Sync/SyncOptions.cs b/MediaBrowser.Model/Sync/SyncOptions.cs
index 294f7bcef..7f0c17b37 100644
--- a/MediaBrowser.Model/Sync/SyncOptions.cs
+++ b/MediaBrowser.Model/Sync/SyncOptions.cs
@@ -4,5 +4,13 @@ namespace MediaBrowser.Model.Sync
public class SyncOptions
{
public string TemporaryPath { get; set; }
+ public long UploadSpeedLimitBytes { get; set; }
+ public int TranscodingCpuCoreLimit { get; set; }
+ public bool EnableFullSpeedTranscoding { get; set; }
+
+ public SyncOptions()
+ {
+ TranscodingCpuCoreLimit = 1;
+ }
}
}
diff --git a/MediaBrowser.Model/Sync/SyncQualityOption.cs b/MediaBrowser.Model/Sync/SyncQualityOption.cs
index 597b98727..6eff4b9a4 100644
--- a/MediaBrowser.Model/Sync/SyncQualityOption.cs
+++ b/MediaBrowser.Model/Sync/SyncQualityOption.cs
@@ -23,5 +23,10 @@ namespace MediaBrowser.Model.Sync
/// </summary>
/// <value><c>true</c> if this instance is default; otherwise, <c>false</c>.</value>
public bool IsDefault { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is original quality.
+ /// </summary>
+ /// <value><c>true</c> if this instance is original quality; otherwise, <c>false</c>.</value>
+ public bool IsOriginalQuality { get; set; }
}
}
diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs
index 774d4a0b4..05c1b9de5 100644
--- a/MediaBrowser.Model/Users/UserPolicy.cs
+++ b/MediaBrowser.Model/Users/UserPolicy.cs
@@ -32,8 +32,6 @@ namespace MediaBrowser.Model.Users
public bool EnableUserPreferenceAccess { get; set; }
public AccessSchedule[] AccessSchedules { get; set; }
public UnratedItem[] BlockUnratedItems { get; set; }
- public string[] BlockedMediaFolders { get; set; }
- public string[] BlockedChannels { get; set; }
public bool EnableRemoteControlOfOtherUsers { get; set; }
public bool EnableSharedDeviceControl { get; set; }
@@ -41,6 +39,9 @@ namespace MediaBrowser.Model.Users
public bool EnableLiveTvAccess { get; set; }
public bool EnableMediaPlayback { get; set; }
+ public bool EnableAudioPlaybackTranscoding { get; set; }
+ public bool EnableVideoPlaybackTranscoding { get; set; }
+
public bool EnableContentDeletion { get; set; }
public bool EnableContentDownloading { get; set; }
@@ -49,6 +50,7 @@ namespace MediaBrowser.Model.Users
/// </summary>
/// <value><c>true</c> if [enable synchronize]; otherwise, <c>false</c>.</value>
public bool EnableSync { get; set; }
+ public bool EnableSyncTranscoding { get; set; }
public string[] EnabledDevices { get; set; }
public bool EnableAllDevices { get; set; }
@@ -60,13 +62,21 @@ namespace MediaBrowser.Model.Users
public bool EnableAllFolders { get; set; }
public int InvalidLoginAttemptCount { get; set; }
+
+ public bool EnablePublicSharing { get; set; }
public UserPolicy()
{
EnableSync = true;
- EnableLiveTvManagement = true;
+ EnableSyncTranscoding = true;
+
EnableMediaPlayback = true;
+ EnableAudioPlaybackTranscoding = true;
+ EnableVideoPlaybackTranscoding = true;
+
+ EnableLiveTvManagement = true;
EnableLiveTvAccess = true;
+
EnableSharedDeviceControl = true;
BlockedTags = new string[] { };
@@ -86,6 +96,7 @@ namespace MediaBrowser.Model.Users
EnableAllDevices = true;
EnableContentDownloading = true;
+ EnablePublicSharing = true;
}
}
} \ No newline at end of file
diff --git a/MediaBrowser.Mono.sln b/MediaBrowser.Mono.sln
index c5c23fe7a..2e720d095 100644
--- a/MediaBrowser.Mono.sln
+++ b/MediaBrowser.Mono.sln
@@ -35,6 +35,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaInfo", "M
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Server.Startup.Common", "MediaBrowser.Server.Startup.Common\MediaBrowser.Server.Startup.Common.csproj", "{B90AB8F2-1BFF-4568-A3FD-2A338A435A75}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing", "Emby.Drawing\Emby.Drawing.csproj", "{08FFF49B-F175-4807-A2B5-73B0EBD9F716}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -203,6 +205,15 @@ Global
{B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|Any CPU.Build.0 = Release|Any CPU
{B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|x86.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|Any CPU.Build.0 = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|x86.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.Build.0 = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
index 3ac3cccb3..92327c9bc 100644
--- a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
+++ b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
@@ -3,7 +3,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -16,11 +15,8 @@ namespace MediaBrowser.Providers.BoxSets
{
public class BoxSetMetadataService : MetadataService<BoxSet, BoxSetInfo>
{
- private readonly ILocalizationManager _iLocalizationManager;
-
- public BoxSetMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILocalizationManager iLocalizationManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager)
+ public BoxSetMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager)
{
- _iLocalizationManager = iLocalizationManager;
}
/// <summary>
diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
index 533e843ea..a3b569150 100644
--- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs
+++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
@@ -36,16 +36,15 @@ namespace MediaBrowser.Providers.Manager
public bool ValidateImages(IHasImages item, IEnumerable<IImageProvider> providers, IDirectoryService directoryService)
{
- var hasChanges = item.ValidateImages(directoryService);
+ var hasChanges = false;
- foreach (var provider in providers.OfType<ILocalImageFileProvider>())
- {
- var images = provider.GetImages(item, directoryService);
+ var images = providers.OfType<ILocalImageFileProvider>()
+ .SelectMany(i => i.GetImages(item, directoryService))
+ .ToList();
- if (MergeImages(item, images))
- {
- hasChanges = true;
- }
+ if (MergeImages(item, images))
+ {
+ hasChanges = true;
}
return hasChanges;
@@ -377,8 +376,7 @@ namespace MediaBrowser.Providers.Manager
item.SetImagePath(type, image.FileInfo);
changed = true;
}
- else if (!string.Equals(currentImage.Path, image.FileInfo.FullName,
- StringComparison.OrdinalIgnoreCase))
+ else if (!string.Equals(currentImage.Path, image.FileInfo.FullName, StringComparison.OrdinalIgnoreCase))
{
item.SetImagePath(type, image.FileInfo);
changed = true;
@@ -389,6 +387,15 @@ namespace MediaBrowser.Providers.Manager
currentImage.Length = ((FileInfo) image.FileInfo).Length;
}
}
+ else
+ {
+ var existing = item.GetImageInfo(type, 0);
+ if (existing != null && !File.Exists(existing.Path))
+ {
+ item.RemoveImage(existing);
+ changed = true;
+ }
+ }
}
if (UpdateMultiImages(item, images, ImageType.Backdrop))
@@ -412,16 +419,16 @@ namespace MediaBrowser.Providers.Manager
{
var changed = false;
- var backdrops = images.Where(i => i.Type == type).ToList();
- if (backdrops.Count > 0)
+ var newImages = images.Where(i => i.Type == type).ToList();
+ if (newImages.Count > 0)
{
- var foundImages = images.Where(i => i.Type == type)
+ var newImageFileInfos = images.Where(i => i.Type == type)
.Select(i => i.FileInfo)
.ToList();
- if (foundImages.Count > 0)
+ if (newImageFileInfos.Count > 0)
{
- if (item.AddImages(type, foundImages))
+ if (item.AddImages(type, newImageFileInfos))
{
changed = true;
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index c9ae47ad0..01a89bf26 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -148,6 +148,13 @@ namespace MediaBrowser.Providers.Manager
return new ImageSaver(ConfigurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, source, mimeType, type, imageIndex, internalCacheKey, cancellationToken);
}
+ public Task SaveImage(IHasImages item, string source, string mimeType, ImageType type, int? imageIndex, string internalCacheKey, CancellationToken cancellationToken)
+ {
+ var fileStream = _fileSystem.GetFileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true);
+
+ return new ImageSaver(ConfigurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, internalCacheKey, cancellationToken);
+ }
+
public async Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(IHasImages item, RemoteImageQuery query, CancellationToken cancellationToken)
{
var providers = GetRemoteImageProviders(item, query.IncludeDisabledProviders);
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 3b5103f20..09951b29d 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -102,7 +102,6 @@
<Compile Include="Manager\MetadataService.cs" />
<Compile Include="Manager\SeriesOrderManager.cs" />
<Compile Include="MediaInfo\FFProbeAudioInfo.cs" />
- <Compile Include="MediaInfo\FFProbeHelpers.cs" />
<Compile Include="MediaInfo\FFProbeProvider.cs" />
<Compile Include="MediaInfo\FFProbeVideoInfo.cs" />
<Compile Include="MediaInfo\SubtitleDownloader.cs" />
@@ -198,10 +197,6 @@
<Project>{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}</Project>
<Name>MediaBrowser.Controller</Name>
</ProjectReference>
- <ProjectReference Include="..\MediaBrowser.MediaInfo\MediaBrowser.MediaInfo.csproj">
- <Project>{6e4145e4-c6d4-4e4d-94f2-87188db6e239}</Project>
- <Name>MediaBrowser.MediaInfo</Name>
- </ProjectReference>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
<Project>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</Project>
<Name>MediaBrowser.Model</Name>
@@ -214,9 +209,6 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
- <ItemGroup>
- <EmbeddedResource Include="MediaInfo\whitelist.txt" />
- </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
index ea191dd08..d78f1b48e 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
@@ -1,15 +1,13 @@
using MediaBrowser.Common.Configuration;
-using MediaBrowser.Model.Extensions;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Serialization;
-using System;
-using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
@@ -49,18 +47,14 @@ namespace MediaBrowser.Providers.MediaInfo
cancellationToken.ThrowIfCancellationRequested();
- FFProbeHelpers.NormalizeFFProbeResult(result);
-
- cancellationToken.ThrowIfCancellationRequested();
-
await Fetch(item, cancellationToken, result).ConfigureAwait(false);
return ItemUpdateType.MetadataImport;
}
- private const string SchemaVersion = "1";
+ private const string SchemaVersion = "2";
- private async Task<InternalMediaInfoResult> GetMediaInfo(BaseItem item, CancellationToken cancellationToken)
+ private async Task<Model.MediaInfo.MediaInfo> GetMediaInfo(BaseItem item, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -71,7 +65,7 @@ namespace MediaBrowser.Providers.MediaInfo
try
{
- return _json.DeserializeFromFile<InternalMediaInfoResult>(cachePath);
+ return _json.DeserializeFromFile<Model.MediaInfo.MediaInfo>(cachePath);
}
catch (FileNotFoundException)
{
@@ -81,9 +75,13 @@ namespace MediaBrowser.Providers.MediaInfo
{
}
- var inputPath = new[] { item.Path };
+ var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
+ {
+ InputPath = item.Path,
+ MediaType = DlnaProfileType.Audio,
+ Protocol = MediaProtocol.File
- var result = await _mediaEncoder.GetMediaInfo(inputPath, MediaProtocol.File, false, cancellationToken).ConfigureAwait(false);
+ }, cancellationToken).ConfigureAwait(false);
Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
_json.SerializeToFile(result, cachePath);
@@ -96,61 +94,23 @@ namespace MediaBrowser.Providers.MediaInfo
/// </summary>
/// <param name="audio">The audio.</param>
/// <param name="cancellationToken">The cancellation token.</param>
- /// <param name="data">The data.</param>
+ /// <param name="mediaInfo">The media information.</param>
/// <returns>Task.</returns>
- protected Task Fetch(Audio audio, CancellationToken cancellationToken, InternalMediaInfoResult data)
+ protected Task Fetch(Audio audio, CancellationToken cancellationToken, Model.MediaInfo.MediaInfo mediaInfo)
{
- var mediaInfo = MediaEncoderHelpers.GetMediaInfo(data);
var mediaStreams = mediaInfo.MediaStreams;
- audio.FormatName = mediaInfo.Format;
- audio.TotalBitrate = mediaInfo.TotalBitrate;
+ audio.FormatName = mediaInfo.Container;
+ audio.TotalBitrate = mediaInfo.Bitrate;
audio.HasEmbeddedImage = mediaStreams.Any(i => i.Type == MediaStreamType.EmbeddedImage);
- if (data.streams != null)
- {
- // Get the first audio stream
- var stream = data.streams.FirstOrDefault(s => string.Equals(s.codec_type, "audio", StringComparison.OrdinalIgnoreCase));
-
- if (stream != null)
- {
- // Get duration from stream properties
- var duration = stream.duration;
-
- // If it's not there go into format properties
- if (string.IsNullOrEmpty(duration))
- {
- duration = data.format.duration;
- }
-
- // If we got something, parse it
- if (!string.IsNullOrEmpty(duration))
- {
- audio.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(duration, _usCulture)).Ticks;
- }
- }
- }
-
- if (data.format != null)
- {
- var extension = (Path.GetExtension(audio.Path) ?? string.Empty).TrimStart('.');
-
- audio.Container = extension;
+ audio.RunTimeTicks = mediaInfo.RunTimeTicks;
+ audio.Size = mediaInfo.Size;
- if (!string.IsNullOrEmpty(data.format.size))
- {
- audio.Size = long.Parse(data.format.size, _usCulture);
- }
- else
- {
- audio.Size = null;
- }
+ var extension = (Path.GetExtension(audio.Path) ?? string.Empty).TrimStart('.');
+ audio.Container = extension;
- if (data.format.tags != null)
- {
- FetchDataFromTags(audio, data.format.tags);
- }
- }
+ FetchDataFromTags(audio, mediaInfo);
return _itemRepo.SaveMediaStreams(audio.Id, mediaStreams, cancellationToken);
}
@@ -159,92 +119,37 @@ namespace MediaBrowser.Providers.MediaInfo
/// Fetches data from the tags dictionary
/// </summary>
/// <param name="audio">The audio.</param>
- /// <param name="tags">The tags.</param>
- private void FetchDataFromTags(Audio audio, Dictionary<string, string> tags)
+ /// <param name="data">The data.</param>
+ private void FetchDataFromTags(Audio audio, Model.MediaInfo.MediaInfo data)
{
- var title = FFProbeHelpers.GetDictionaryValue(tags, "title");
-
// Only set Name if title was found in the dictionary
- if (!string.IsNullOrEmpty(title))
+ if (!string.IsNullOrEmpty(data.Title))
{
- audio.Name = title;
+ audio.Name = data.Title;
}
if (!audio.LockedFields.Contains(MetadataFields.Cast))
{
audio.People.Clear();
- var composer = FFProbeHelpers.GetDictionaryValue(tags, "composer");
-
- if (!string.IsNullOrWhiteSpace(composer))
+ foreach (var person in data.People)
{
- foreach (var person in Split(composer, false))
+ audio.AddPerson(new PersonInfo
{
- audio.AddPerson(new PersonInfo { Name = person, Type = PersonType.Composer });
- }
+ Name = person.Name,
+ Type = person.Type,
+ Role = person.Role
+ });
}
}
- audio.Album = FFProbeHelpers.GetDictionaryValue(tags, "album");
-
- var artists = FFProbeHelpers.GetDictionaryValue(tags, "artists");
-
- if (!string.IsNullOrWhiteSpace(artists))
- {
- audio.Artists = artists.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
- }
- else
- {
- var artist = FFProbeHelpers.GetDictionaryValue(tags, "artist");
- if (string.IsNullOrWhiteSpace(artist))
- {
- audio.Artists.Clear();
- }
- else
- {
- audio.Artists = SplitArtists(artist)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
- }
- }
-
- var albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "albumartist");
- if (string.IsNullOrWhiteSpace(albumArtist))
- {
- albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album artist");
- }
- if (string.IsNullOrWhiteSpace(albumArtist))
- {
- albumArtist = FFProbeHelpers.GetDictionaryValue(tags, "album_artist");
- }
-
- if (string.IsNullOrWhiteSpace(albumArtist))
- {
- audio.AlbumArtists = new List<string>();
- }
- else
- {
- audio.AlbumArtists = SplitArtists(albumArtist)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
-
- }
-
- // Track number
- audio.IndexNumber = GetDictionaryDiscValue(tags, "track");
-
- // Disc number
- audio.ParentIndexNumber = GetDictionaryDiscValue(tags, "disc");
-
- audio.ProductionYear = FFProbeHelpers.GetDictionaryNumericValue(tags, "date");
-
- // Several different forms of retaildate
- audio.PremiereDate = FFProbeHelpers.GetDictionaryDateTime(tags, "retaildate") ??
- FFProbeHelpers.GetDictionaryDateTime(tags, "retail date") ??
- FFProbeHelpers.GetDictionaryDateTime(tags, "retail_date") ??
- FFProbeHelpers.GetDictionaryDateTime(tags, "date");
+ audio.Album = data.Album;
+ audio.Artists = data.Artists;
+ audio.AlbumArtists = data.AlbumArtists;
+ audio.IndexNumber = data.IndexNumber;
+ audio.ParentIndexNumber = data.ParentIndexNumber;
+ audio.ProductionYear = data.ProductionYear;
+ audio.PremiereDate = data.PremiereDate;
// If we don't have a ProductionYear try and get it from PremiereDate
if (audio.PremiereDate.HasValue && !audio.ProductionYear.HasValue)
@@ -254,192 +159,29 @@ namespace MediaBrowser.Providers.MediaInfo
if (!audio.LockedFields.Contains(MetadataFields.Genres))
{
- FetchGenres(audio, tags);
- }
-
- if (!audio.LockedFields.Contains(MetadataFields.Studios))
- {
- audio.Studios.Clear();
-
- // There's several values in tags may or may not be present
- FetchStudios(audio, tags, "organization");
- FetchStudios(audio, tags, "ensemble");
- FetchStudios(audio, tags, "publisher");
- }
-
- // These support mulitple values, but for now we only store the first.
- audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")));
- audio.SetProviderId(MetadataProviders.MusicBrainzArtist, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")));
-
- audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")));
- audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")));
- audio.SetProviderId(MetadataProviders.MusicBrainzTrack, GetMultipleMusicBrainzId(FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Track Id")));
- }
-
- private string GetMultipleMusicBrainzId(string value)
- {
- if (string.IsNullOrWhiteSpace(value))
- {
- return null;
- }
-
- return value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
- .Select(i => i.Trim())
- .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
- }
-
- private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' };
-
- /// <summary>
- /// Splits the specified val.
- /// </summary>
- /// <param name="val">The val.</param>
- /// <param name="allowCommaDelimiter">if set to <c>true</c> [allow comma delimiter].</param>
- /// <returns>System.String[][].</returns>
- private IEnumerable<string> Split(string val, bool allowCommaDelimiter)
- {
- // Only use the comma as a delimeter if there are no slashes or pipes.
- // We want to be careful not to split names that have commas in them
- var delimeter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i) != -1) ?
- _nameDelimiters :
- new[] { ',' };
-
- return val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .Select(i => i.Trim());
- }
-
- private const string ArtistReplaceValue = " | ";
-
- private IEnumerable<string> SplitArtists(string val)
- {
- val = val.Replace(" featuring ", ArtistReplaceValue, StringComparison.OrdinalIgnoreCase)
- .Replace(" feat. ", ArtistReplaceValue, StringComparison.OrdinalIgnoreCase);
-
- var artistsFound = new List<string>();
-
- foreach (var whitelistArtist in GetSplitWhitelist())
- {
- var originalVal = val;
- val = val.Replace(whitelistArtist, "|", StringComparison.OrdinalIgnoreCase);
-
- if (!string.Equals(originalVal, val, StringComparison.OrdinalIgnoreCase))
- {
- artistsFound.Add(whitelistArtist);
- }
- }
-
- // Only use the comma as a delimeter if there are no slashes or pipes.
- // We want to be careful not to split names that have commas in them
- var delimeter = _nameDelimiters;
-
- var artists = val.Split(delimeter, StringSplitOptions.RemoveEmptyEntries)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .Select(i => i.Trim());
-
- artistsFound.AddRange(artists);
- return artistsFound;
- }
-
-
- private List<string> _splitWhiteList = null;
-
- private IEnumerable<string> GetSplitWhitelist()
- {
- if (_splitWhiteList == null)
- {
- var file = GetType().Namespace + ".whitelist.txt";
-
- using (var stream = GetType().Assembly.GetManifestResourceStream(file))
- {
- using (var reader = new StreamReader(stream))
- {
- var list = new List<string>();
-
- while (!reader.EndOfStream)
- {
- var val = reader.ReadLine();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- list.Add(val);
- }
- }
-
- _splitWhiteList = list;
- }
- }
- }
-
- return _splitWhiteList;
- }
-
- /// <summary>
- /// Gets the studios from the tags collection
- /// </summary>
- /// <param name="audio">The audio.</param>
- /// <param name="tags">The tags.</param>
- /// <param name="tagName">Name of the tag.</param>
- private void FetchStudios(Audio audio, Dictionary<string, string> tags, string tagName)
- {
- var val = FFProbeHelpers.GetDictionaryValue(tags, tagName);
-
- if (!string.IsNullOrEmpty(val))
- {
- // Sometimes the artist name is listed here, account for that
- var studios = Split(val, true).Where(i => !audio.HasAnyArtist(i));
-
- foreach (var studio in studios)
- {
- audio.AddStudio(studio);
- }
- }
- }
-
- /// <summary>
- /// Gets the genres from the tags collection
- /// </summary>
- /// <param name="audio">The audio.</param>
- /// <param name="tags">The tags.</param>
- private void FetchGenres(Audio audio, Dictionary<string, string> tags)
- {
- var val = FFProbeHelpers.GetDictionaryValue(tags, "genre");
-
- if (!string.IsNullOrEmpty(val))
- {
audio.Genres.Clear();
- foreach (var genre in Split(val, true))
+ foreach (var genre in data.Genres)
{
audio.AddGenre(genre);
}
}
- }
-
- /// <summary>
- /// Gets the disc number, which is sometimes can be in the form of '1', or '1/3'
- /// </summary>
- /// <param name="tags">The tags.</param>
- /// <param name="tagName">Name of the tag.</param>
- /// <returns>System.Nullable{System.Int32}.</returns>
- private int? GetDictionaryDiscValue(Dictionary<string, string> tags, string tagName)
- {
- var disc = FFProbeHelpers.GetDictionaryValue(tags, tagName);
- if (!string.IsNullOrEmpty(disc))
+ if (!audio.LockedFields.Contains(MetadataFields.Studios))
{
- disc = disc.Split('/')[0];
-
- int num;
+ audio.Studios.Clear();
- if (int.TryParse(disc, out num))
+ foreach (var studio in data.Studios)
{
- return num;
+ audio.AddStudio(studio);
}
}
- return null;
+ audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, data.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist));
+ audio.SetProviderId(MetadataProviders.MusicBrainzArtist, data.GetProviderId(MetadataProviders.MusicBrainzArtist));
+ audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, data.GetProviderId(MetadataProviders.MusicBrainzAlbum));
+ audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, data.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup));
+ audio.SetProviderId(MetadataProviders.MusicBrainzTrack, data.GetProviderId(MetadataProviders.MusicBrainzTrack));
}
-
}
}
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index ca11f858a..f4d8ddb1a 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -1,5 +1,6 @@
using DvdLib.Ifo;
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Chapters;
@@ -13,7 +14,6 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
-using MediaBrowser.MediaInfo;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
@@ -116,10 +116,6 @@ namespace MediaBrowser.Providers.MediaInfo
cancellationToken.ThrowIfCancellationRequested();
- FFProbeHelpers.NormalizeFFProbeResult(result);
-
- cancellationToken.ThrowIfCancellationRequested();
-
await Fetch(item, cancellationToken, result, isoMount, blurayDiscInfo, options).ConfigureAwait(false);
}
@@ -134,9 +130,9 @@ namespace MediaBrowser.Providers.MediaInfo
return ItemUpdateType.MetadataImport;
}
- private const string SchemaVersion = "1";
+ private const string SchemaVersion = "4";
- private async Task<InternalMediaInfoResult> GetMediaInfo(Video item,
+ private async Task<Model.MediaInfo.MediaInfo> GetMediaInfo(Video item,
IIsoMount isoMount,
CancellationToken cancellationToken)
{
@@ -149,7 +145,7 @@ namespace MediaBrowser.Providers.MediaInfo
try
{
- return _json.DeserializeFromFile<InternalMediaInfoResult>(cachePath);
+ return _json.DeserializeFromFile<Model.MediaInfo.MediaInfo>(cachePath);
}
catch (FileNotFoundException)
{
@@ -163,9 +159,18 @@ namespace MediaBrowser.Providers.MediaInfo
? MediaProtocol.Http
: MediaProtocol.File;
- var inputPath = MediaEncoderHelpers.GetInputArgument(item.Path, protocol, isoMount, item.PlayableStreamFileNames);
+ var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
+ {
+ PlayableStreamFileNames = item.PlayableStreamFileNames,
+ MountedIso = isoMount,
+ ExtractChapters = true,
+ VideoType = item.VideoType,
+ MediaType = DlnaProfileType.Video,
+ InputPath = item.Path,
+ Protocol = protocol,
+ ExtractKeyFrameInterval = true
- var result = await _mediaEncoder.GetMediaInfo(inputPath, protocol, false, cancellationToken).ConfigureAwait(false);
+ }, cancellationToken).ConfigureAwait(false);
Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
_json.SerializeToFile(result, cachePath);
@@ -175,52 +180,37 @@ namespace MediaBrowser.Providers.MediaInfo
protected async Task Fetch(Video video,
CancellationToken cancellationToken,
- InternalMediaInfoResult data,
+ Model.MediaInfo.MediaInfo mediaInfo,
IIsoMount isoMount,
BlurayDiscInfo blurayInfo,
MetadataRefreshOptions options)
{
- var mediaInfo = MediaEncoderHelpers.GetMediaInfo(data);
var mediaStreams = mediaInfo.MediaStreams;
- video.TotalBitrate = mediaInfo.TotalBitrate;
- video.FormatName = (mediaInfo.Format ?? string.Empty)
+ video.TotalBitrate = mediaInfo.Bitrate;
+ video.FormatName = (mediaInfo.Container ?? string.Empty)
.Replace("matroska", "mkv", StringComparison.OrdinalIgnoreCase);
- if (data.format != null)
- {
- // For dvd's this may not always be accurate, so don't set the runtime if the item already has one
- var needToSetRuntime = video.VideoType != VideoType.Dvd || video.RunTimeTicks == null || video.RunTimeTicks.Value == 0;
-
- if (needToSetRuntime && !string.IsNullOrEmpty(data.format.duration))
- {
- video.RunTimeTicks = TimeSpan.FromSeconds(double.Parse(data.format.duration, _usCulture)).Ticks;
- }
+ // For dvd's this may not always be accurate, so don't set the runtime if the item already has one
+ var needToSetRuntime = video.VideoType != VideoType.Dvd || video.RunTimeTicks == null || video.RunTimeTicks.Value == 0;
- if (video.VideoType == VideoType.VideoFile)
- {
- var extension = (Path.GetExtension(video.Path) ?? string.Empty).TrimStart('.');
+ if (needToSetRuntime)
+ {
+ video.RunTimeTicks = mediaInfo.RunTimeTicks;
+ }
- video.Container = extension;
- }
- else
- {
- video.Container = null;
- }
+ if (video.VideoType == VideoType.VideoFile)
+ {
+ var extension = (Path.GetExtension(video.Path) ?? string.Empty).TrimStart('.');
- if (!string.IsNullOrEmpty(data.format.size))
- {
- video.Size = long.Parse(data.format.size, _usCulture);
- }
- else
- {
- video.Size = null;
- }
+ video.Container = extension;
+ }
+ else
+ {
+ video.Container = null;
}
- var mediaChapters = (data.Chapters ?? new MediaChapter[] { }).ToList();
- var chapters = mediaChapters.Select(GetChapterInfo).ToList();
-
+ var chapters = mediaInfo.Chapters ?? new List<ChapterInfo>();
if (video.VideoType == VideoType.BluRay || (video.IsoType.HasValue && video.IsoType.Value == IsoType.BluRay))
{
FetchBdInfo(video, chapters, mediaStreams, blurayInfo);
@@ -228,7 +218,7 @@ namespace MediaBrowser.Providers.MediaInfo
await AddExternalSubtitles(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
- FetchWtvInfo(video, data);
+ FetchEmbeddedInfo(video, mediaInfo);
video.IsHD = mediaStreams.Any(i => i.Type == MediaStreamType.Video && i.Width.HasValue && i.Width.Value >= 1270);
@@ -238,9 +228,7 @@ namespace MediaBrowser.Providers.MediaInfo
video.DefaultVideoStreamIndex = videoStream == null ? (int?)null : videoStream.Index;
video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle);
-
- ExtractTimestamp(video);
- UpdateFromMediaInfo(video, videoStream);
+ video.Timestamp = mediaInfo.Timestamp;
await _itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken).ConfigureAwait(false);
@@ -283,29 +271,6 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
- private void UpdateFromMediaInfo(Video video, MediaStream videoStream)
- {
- if (video.VideoType == VideoType.VideoFile && video.LocationType != LocationType.Remote && video.LocationType != LocationType.Virtual)
- {
- if (videoStream != null)
- {
- try
- {
- var result = new MediaInfoLib().GetVideoInfo(video.Path);
-
- videoStream.IsCabac = result.IsCabac ?? videoStream.IsCabac;
- videoStream.IsInterlaced = result.IsInterlaced ?? videoStream.IsInterlaced;
- videoStream.BitDepth = result.BitDepth ?? videoStream.BitDepth;
- videoStream.RefFrames = result.RefFrames;
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error running MediaInfo on {0}", ex, video.Path);
- }
- }
- }
- }
-
private void NormalizeChapterNames(List<ChapterInfo> chapters)
{
var index = 1;
@@ -325,32 +290,6 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
- private ChapterInfo GetChapterInfo(MediaChapter chapter)
- {
- var info = new ChapterInfo();
-
- if (chapter.tags != null)
- {
- string name;
- if (chapter.tags.TryGetValue("title", out name))
- {
- info.Name = name;
- }
- }
-
- // Limit accuracy to milliseconds to match xml saving
- var secondsString = chapter.start_time;
- double seconds;
-
- if (double.TryParse(secondsString, NumberStyles.Any, CultureInfo.InvariantCulture, out seconds))
- {
- var ms = Math.Round(TimeSpan.FromSeconds(seconds).TotalMilliseconds);
- info.StartPositionTicks = TimeSpan.FromMilliseconds(ms).Ticks;
- }
-
- return info;
- }
-
private void FetchBdInfo(BaseItem item, List<ChapterInfo> chapters, List<MediaStream> mediaStreams, BlurayDiscInfo blurayInfo)
{
var video = (Video)item;
@@ -419,129 +358,79 @@ namespace MediaBrowser.Providers.MediaInfo
return _blurayExaminer.GetDiscInfo(path);
}
- public const int MaxSubtitleDescriptionExtractionLength = 100; // When extracting subtitles, the maximum length to consider (to avoid invalid filenames)
-
- private void FetchWtvInfo(Video video, InternalMediaInfoResult data)
+ private void FetchEmbeddedInfo(Video video, Model.MediaInfo.MediaInfo data)
{
- if (data.format == null || data.format.tags == null)
- {
- return;
- }
-
- if (!video.LockedFields.Contains(MetadataFields.Genres))
- {
- var genres = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/Genre");
-
- if (!string.IsNullOrWhiteSpace(genres))
- {
- //genres = FFProbeHelpers.GetDictionaryValue(data.format.tags, "genre");
- }
-
- if (!string.IsNullOrWhiteSpace(genres))
- {
- video.Genres = genres.Split(new[] { ';', '/', ',' }, StringSplitOptions.RemoveEmptyEntries)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .Select(i => i.Trim())
- .ToList();
- }
- }
-
if (!video.LockedFields.Contains(MetadataFields.OfficialRating))
{
- var officialRating = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/ParentalRating");
-
- if (!string.IsNullOrWhiteSpace(officialRating))
+ if (!string.IsNullOrWhiteSpace(data.OfficialRating))
{
- video.OfficialRating = officialRating;
+ video.OfficialRating = data.OfficialRating;
}
}
if (!video.LockedFields.Contains(MetadataFields.Cast))
{
- var people = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/MediaCredits");
+ video.People.Clear();
- if (!string.IsNullOrEmpty(people))
+ foreach (var person in data.People)
{
- video.People = people.Split(new[] { ';', '/' }, StringSplitOptions.RemoveEmptyEntries)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .Select(i => new PersonInfo { Name = i.Trim(), Type = PersonType.Actor })
- .ToList();
+ video.AddPerson(new PersonInfo
+ {
+ Name = person.Name,
+ Type = person.Type,
+ Role = person.Role
+ });
}
}
- var year = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/OriginalReleaseTime");
- if (!string.IsNullOrWhiteSpace(year))
+ if (!video.LockedFields.Contains(MetadataFields.Genres))
{
- int val;
+ video.Genres.Clear();
- if (int.TryParse(year, NumberStyles.Integer, _usCulture, out val))
+ foreach (var genre in data.Genres)
{
- video.ProductionYear = val;
+ video.AddGenre(genre);
}
}
- var premiereDateString = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/MediaOriginalBroadcastDateTime");
- if (!string.IsNullOrWhiteSpace(premiereDateString))
+ if (!video.LockedFields.Contains(MetadataFields.Studios))
{
- DateTime val;
+ video.Studios.Clear();
- // Credit to MCEBuddy: https://mcebuddy2x.codeplex.com/
- // DateTime is reported along with timezone info (typically Z i.e. UTC hence assume None)
- if (DateTime.TryParse(year, null, DateTimeStyles.None, out val))
+ foreach (var studio in data.Studios)
{
- video.PremiereDate = val.ToUniversalTime();
+ video.AddStudio(studio);
}
}
- var description = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/SubTitleDescription");
-
- var episode = video as Episode;
- if (episode != null)
+ if (data.ProductionYear.HasValue)
{
- var subTitle = FFProbeHelpers.GetDictionaryValue(data.format.tags, "WM/SubTitle");
-
- // For below code, credit to MCEBuddy: https://mcebuddy2x.codeplex.com/
-
- // Sometimes for TV Shows the Subtitle field is empty and the subtitle description contains the subtitle, extract if possible. See ticket https://mcebuddy2x.codeplex.com/workitem/1910
- // The format is -> EPISODE/TOTAL_EPISODES_IN_SEASON. SUBTITLE: DESCRIPTION
- // OR -> COMMENT. SUBTITLE: DESCRIPTION
- // e.g. -> 4/13. The Doctor's Wife: Science fiction drama. When he follows a Time Lord distress signal, the Doctor puts Amy, Rory and his beloved TARDIS in grave danger. Also in HD. [AD,S]
- // e.g. -> CBeebies Bedtime Hour. The Mystery: Animated adventures of two friends who live on an island in the middle of the big city. Some of Abney and Teal's favourite objects are missing. [S]
- if (String.IsNullOrWhiteSpace(subTitle) && !String.IsNullOrWhiteSpace(description) && description.Substring(0, Math.Min(description.Length, MaxSubtitleDescriptionExtractionLength)).Contains(":")) // Check within the Subtitle size limit, otherwise from description it can get too long creating an invalid filename
- {
- string[] parts = description.Split(':');
- if (parts.Length > 0)
- {
- string subtitle = parts[0];
- try
- {
- if (subtitle.Contains("/")) // It contains a episode number and season number
- {
- string[] numbers = subtitle.Split(' ');
- episode.IndexNumber = int.Parse(numbers[0].Replace(".", "").Split('/')[0]);
- int totalEpisodesInSeason = int.Parse(numbers[0].Replace(".", "").Split('/')[1]);
+ video.ProductionYear = data.ProductionYear;
+ }
+ if (data.PremiereDate.HasValue)
+ {
+ video.PremiereDate = data.PremiereDate;
+ }
+ if (data.IndexNumber.HasValue)
+ {
+ video.IndexNumber = data.IndexNumber;
+ }
+ if (data.ParentIndexNumber.HasValue)
+ {
+ video.ParentIndexNumber = data.ParentIndexNumber;
+ }
- description = String.Join(" ", numbers, 1, numbers.Length - 1).Trim(); // Skip the first, concatenate the rest, clean up spaces and save it
- }
- else
- throw new Exception(); // Switch to default parsing
- }
- catch // Default parsing
- {
- if (subtitle.Contains(".")) // skip the comment, keep the subtitle
- description = String.Join(".", subtitle.Split('.'), 1, subtitle.Split('.').Length - 1).Trim(); // skip the first
- else
- description = subtitle.Trim(); // Clean up whitespaces and save it
- }
- }
- }
+ // If we don't have a ProductionYear try and get it from PremiereDate
+ if (video.PremiereDate.HasValue && !video.ProductionYear.HasValue)
+ {
+ video.ProductionYear = video.PremiereDate.Value.ToLocalTime().Year;
}
if (!video.LockedFields.Contains(MetadataFields.Overview))
{
- if (!string.IsNullOrWhiteSpace(description))
+ if (!string.IsNullOrWhiteSpace(data.Overview))
{
- video.Overview = description;
+ video.Overview = data.Overview;
}
}
}
@@ -709,56 +598,6 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
- private void ExtractTimestamp(Video video)
- {
- if (video.VideoType == VideoType.VideoFile)
- {
- if (string.Equals(video.Container, "mpeg2ts", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(video.Container, "m2ts", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(video.Container, "ts", StringComparison.OrdinalIgnoreCase))
- {
- try
- {
- video.Timestamp = GetMpegTimestamp(video.Path);
-
- _logger.Debug("Video has {0} timestamp", video.Timestamp);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error extracting timestamp info from {0}", ex, video.Path);
- video.Timestamp = null;
- }
- }
- }
- }
-
- private TransportStreamTimestamp GetMpegTimestamp(string path)
- {
- var packetBuffer = new byte['Å'];
-
- using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
- {
- fs.Read(packetBuffer, 0, packetBuffer.Length);
- }
-
- if (packetBuffer[0] == 71)
- {
- return TransportStreamTimestamp.None;
- }
-
- if ((packetBuffer[4] == 71) && (packetBuffer['Ä'] == 71))
- {
- if ((packetBuffer[0] == 0) && (packetBuffer[1] == 0) && (packetBuffer[2] == 0) && (packetBuffer[3] == 0))
- {
- return TransportStreamTimestamp.Zero;
- }
-
- return TransportStreamTimestamp.Valid;
- }
-
- return TransportStreamTimestamp.None;
- }
-
private void FetchFromDvdLib(Video item, IIsoMount mount)
{
var path = mount == null ? item.Path : mount.MountedPath;
diff --git a/MediaBrowser.Providers/Music/ArtistMetadataService.cs b/MediaBrowser.Providers/Music/ArtistMetadataService.cs
index 2497cc1ec..790529371 100644
--- a/MediaBrowser.Providers/Music/ArtistMetadataService.cs
+++ b/MediaBrowser.Providers/Music/ArtistMetadataService.cs
@@ -54,7 +54,7 @@ namespace MediaBrowser.Providers.Music
var currentList = item.Genres.ToList();
item.Genres = taggedItems.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.ToList();
if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index e22bf2e7f..6a0e1208a 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -330,7 +330,7 @@ namespace MediaBrowser.Server.Implementations.Channels
{
files = files.Where(i => _libraryManager.IsAudioFile(i.FullName));
}
-
+
var file = files
.FirstOrDefault(i => i.Name.StartsWith(filenamePrefix, StringComparison.OrdinalIgnoreCase));
@@ -1454,7 +1454,14 @@ namespace MediaBrowser.Server.Implementations.Channels
var host = new Uri(source.Path).Host.ToLower();
var channel = GetChannel(item.ChannelId);
var channelProvider = GetChannelProvider(channel);
- var limit = channelProvider.GetChannelFeatures().DailyDownloadLimit;
+ var features = channelProvider.GetChannelFeatures();
+
+ if (!features.SupportsContentDownloading)
+ {
+ throw new ArgumentException("The channel does not support downloading.");
+ }
+
+ var limit = features.DailyDownloadLimit;
if (!ValidateDownloadLimit(host, limit))
{
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs
index 80a7c50d1..f5ddbdb78 100644
--- a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
@@ -16,7 +17,7 @@ namespace MediaBrowser.Server.Implementations.Collections
{
public class CollectionImageProvider : BaseDynamicImageProvider<BoxSet>
{
- public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths)
+ public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor)
{
}
diff --git a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
index bbe37cb50..8f5d8fe9b 100644
--- a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
+++ b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
@@ -14,9 +14,7 @@ namespace MediaBrowser.Server.Implementations.Collections
public override bool IsVisible(User user)
{
- return base.IsVisible(user) && GetChildren(user, false)
- .OfType<BoxSet>()
- .Any(i => i.IsVisible(user));
+ return base.IsVisible(user) && GetChildren(user, false).Any();
}
public override bool IsHidden
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
index b1b6cd899..2d39f760e 100644
--- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
@@ -517,7 +517,7 @@ namespace MediaBrowser.Server.Implementations.Connect
if (!connectUser.IsActive)
{
- throw new ArgumentException("The Emby account has been disabled.");
+ throw new ArgumentException("The Emby account is not active. Please ensure the account has been activated by following the instructions within the email confirmation.");
}
connectUserId = connectUser.Id;
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index 8934c9c8f..c4501564f 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -97,7 +97,7 @@ namespace MediaBrowser.Server.Implementations.Dto
if (byName != null && !(item is LiveTvChannel))
{
- //if (options.Fields.Contains(ItemFields.ItemCounts))
+ if (options.Fields.Contains(ItemFields.ItemCounts))
{
var itemFilter = byName.GetItemFilter();
@@ -125,7 +125,7 @@ namespace MediaBrowser.Server.Implementations.Dto
if (byName != null && !(item is LiveTvChannel))
{
- //if (options.Fields.Contains(ItemFields.ItemCounts))
+ if (options.Fields.Contains(ItemFields.ItemCounts))
{
var itemFilter = byName.GetItemFilter();
@@ -188,7 +188,22 @@ namespace MediaBrowser.Server.Implementations.Dto
return new Tuple<IEnumerable<string>, IEnumerable<string>>(result1.Items, result2.Items);
}
- private void FillSyncInfo(BaseItemDto dto, BaseItem item, DtoOptions options, User user)
+ public void FillSyncInfo(IEnumerable<IHasSyncInfo> dtos, DtoOptions options, User user)
+ {
+ if (options.Fields.Contains(ItemFields.SyncInfo))
+ {
+ var tuple = GetItemIdsWithSyncJobs(options);
+
+ foreach (var dto in dtos)
+ {
+ var item = _libraryManager.GetItemById(dto.Id);
+
+ FillSyncInfo(dto, item, tuple.Item1, tuple.Item2, options, user);
+ }
+ }
+ }
+
+ private void FillSyncInfo(IHasSyncInfo dto, BaseItem item, DtoOptions options, User user)
{
if (options.Fields.Contains(ItemFields.SyncInfo))
{
@@ -202,10 +217,20 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.HasSyncJob = tuple.Item1.Contains(dto.Id, StringComparer.OrdinalIgnoreCase);
dto.IsSynced = tuple.Item2.Contains(dto.Id, StringComparer.OrdinalIgnoreCase);
+
+ if (dto.IsSynced.Value)
+ {
+ dto.SyncStatus = SyncJobItemStatus.Synced;
+ }
+
+ else if (dto.HasSyncJob.Value)
+ {
+ dto.SyncStatus = SyncJobItemStatus.Queued;
+ }
}
}
- private void FillSyncInfo(BaseItemDto dto, BaseItem item, IEnumerable<string> itemIdsWithPendingSyncJobs, IEnumerable<string> syncedItemIds, DtoOptions options, User user)
+ private void FillSyncInfo(IHasSyncInfo dto, BaseItem item, IEnumerable<string> itemIdsWithPendingSyncJobs, IEnumerable<string> syncedItemIds, DtoOptions options, User user)
{
if (options.Fields.Contains(ItemFields.SyncInfo))
{
@@ -217,6 +242,16 @@ namespace MediaBrowser.Server.Implementations.Dto
{
dto.HasSyncJob = itemIdsWithPendingSyncJobs.Contains(dto.Id, StringComparer.OrdinalIgnoreCase);
dto.IsSynced = syncedItemIds.Contains(dto.Id, StringComparer.OrdinalIgnoreCase);
+
+ if (dto.IsSynced.Value)
+ {
+ dto.SyncStatus = SyncJobItemStatus.Synced;
+ }
+
+ else if (dto.HasSyncJob.Value)
+ {
+ dto.SyncStatus = SyncJobItemStatus.Queued;
+ }
}
}
@@ -322,6 +357,8 @@ namespace MediaBrowser.Server.Implementations.Dto
: item.CanDownload(user);
}
+
+
return dto;
}
@@ -330,7 +367,7 @@ namespace MediaBrowser.Server.Implementations.Dto
{
var dto = GetBaseItemDtoInternal(item, options, user);
- //if (options.Fields.Contains(ItemFields.ItemCounts))
+ if (options.Fields.Contains(ItemFields.ItemCounts))
{
SetItemByNameInfo(item, dto, taggedItems, user);
}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
index 5c69db3e1..966e0a3e4 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller;
+using System.Linq;
+using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging;
@@ -47,7 +48,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
void _config_ConfigurationUpdated(object sender, EventArgs e)
{
_config.ConfigurationUpdated -= _config_ConfigurationUpdated;
-
+
if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase))
{
if (_isStarted)
@@ -88,7 +89,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
NatUtility.UnhandledException += NatUtility_UnhandledException;
NatUtility.StartDiscovery();
- _timer = new Timer(s => _createdRules = new List<string>(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
+ _timer = new Timer(s => _createdRules = new List<string>(), null, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3));
_lastConfigIdentifier = GetConfigIdentifier();
@@ -119,7 +120,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
CreateRules(device);
}
- catch (Exception)
+ catch (Exception ex)
{
// I think it could be a good idea to log the exception because
// you are using permanent portmapping here (never expire) and that means that next time
@@ -128,7 +129,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
// It also can fail with others like 727-ExternalPortOnlySupportsWildcard, 728-NoPortMapsAvailable
// and those errors (upnp errors) could be useful for diagnosting.
- //_logger.ErrorException("Error creating port forwarding rules", ex);
+ _logger.ErrorException("Error creating port forwarding rules", ex);
}
}
@@ -138,25 +139,55 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
// On some systems the device discovered event seems to fire repeatedly
// This check will help ensure we're not trying to port map the same device over and over
+ List<Mapping> currentMappings = null;
+
+ try
+ {
+ currentMappings = device.GetAllMappings().ToList();
+ }
+ catch (NotSupportedException)
+ {
+ }
+
var address = device.LocalAddress.ToString();
if (!_createdRules.Contains(address))
{
_createdRules.Add(address);
- CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort);
- CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort);
+ CreatePortMap(device, currentMappings, _appHost.HttpPort, _config.Configuration.PublicPort);
+ CreatePortMap(device, currentMappings, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort);
}
}
- private void CreatePortMap(INatDevice device, int privatePort, int publicPort)
+ private void CreatePortMap(INatDevice device, List<Mapping> currentMappings, int privatePort, int publicPort)
{
- _logger.Debug("Creating port map on port {0}", privatePort);
+ var hasMapping = false;
+
+ if (currentMappings != null)
+ {
+ hasMapping = currentMappings.Any(i => i.PublicPort == publicPort && i.PrivatePort == privatePort);
+ }
+ else
+ {
+ try
+ {
+ var mapping = device.GetSpecificMapping(Protocol.Tcp, publicPort);
+ hasMapping = mapping != null;
+ }
+ catch (NotSupportedException)
+ {
+ }
+ }
- device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort)
+ if (!hasMapping)
{
- Description = _appHost.Name
- });
+ _logger.Debug("Creating port map on port {0}", privatePort);
+ device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort)
+ {
+ Description = _appHost.Name
+ });
+ }
}
// As I said before, this method will be never invoked. You can remove it.
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
index 090f1e756..03daa4c2a 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
@@ -69,7 +70,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
void libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
{
- if (e.Item.LocationType == LocationType.Virtual)
+ if (!FilterItem(e.Item))
{
return;
}
@@ -102,7 +103,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
void libraryManager_ItemUpdated(object sender, ItemChangeEventArgs e)
{
- if (e.Item.LocationType == LocationType.Virtual)
+ if (!FilterItem(e.Item))
{
return;
}
@@ -130,7 +131,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
void libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
{
- if (e.Item.LocationType == LocationType.Virtual)
+ if (!FilterItem(e.Item))
{
return;
}
@@ -243,39 +244,39 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{
var user = _userManager.GetUserById(userId);
- var collections = user.RootFolder.GetChildren(user, true).ToList();
-
- var allRecursiveChildren = user.RootFolder
- .GetRecursiveChildren(user)
- .Select(i => i.Id)
- .Distinct()
- .ToDictionary(i => i);
-
return new LibraryUpdateInfo
{
- ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
+ ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
- ItemsUpdated = itemsUpdated.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
+ ItemsUpdated = itemsUpdated.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
- ItemsRemoved = itemsRemoved.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren, true)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
+ ItemsRemoved = itemsRemoved.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, true)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
- FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
+ FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
- FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id.ToString("N")).Distinct().ToList()
+ FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user)).Select(i => i.Id.ToString("N")).Distinct().ToList()
};
}
+ private bool FilterItem(BaseItem item)
+ {
+ if (item.LocationType == LocationType.Virtual)
+ {
+ return false;
+ }
+
+ return !(item is IChannelItem);
+ }
+
/// <summary>
/// Translates the physical item to user library.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="item">The item.</param>
/// <param name="user">The user.</param>
- /// <param name="collections">The collections.</param>
- /// <param name="allRecursiveChildren">All recursive children.</param>
/// <param name="includeIfNotFound">if set to <c>true</c> [include if not found].</param>
/// <returns>IEnumerable{``0}.</returns>
- private IEnumerable<T> TranslatePhysicalItemToUserLibrary<T>(T item, User user, IEnumerable<BaseItem> collections, Dictionary<Guid, Guid> allRecursiveChildren, bool includeIfNotFound = false)
+ private IEnumerable<T> TranslatePhysicalItemToUserLibrary<T>(T item, User user, bool includeIfNotFound = false)
where T : BaseItem
{
// If the physical root changed, return the user root
@@ -284,17 +285,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
return new[] { user.RootFolder as T };
}
- // Need to find what user collection folder this belongs to
- if (item.Parent is AggregateFolder)
- {
- if (item.LocationType == LocationType.FileSystem)
- {
- return collections.Where(i => i.PhysicalLocations.Contains(item.Path)).Cast<T>();
- }
- }
-
// Return it only if it's in the user's library
- if (includeIfNotFound || allRecursiveChildren.ContainsKey(item.Id) || (item.Parents.Any(i => i is BasePluginFolder) && item.IsVisibleStandalone(user)))
+ if (includeIfNotFound || item.IsVisibleStandalone(user))
{
return new[] { item };
}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
index f91054206..dc9656f80 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -305,7 +305,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer
var operationName = httpReq.OperationName;
var localPath = url.LocalPath;
- if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase))
{
httpRes.RedirectToUrl(DefaultRedirectPath);
return Task.FromResult(true);
@@ -315,6 +316,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer
httpRes.RedirectToUrl("mediabrowser/" + DefaultRedirectPath);
return Task.FromResult(true);
}
+ if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase))
+ {
+ httpRes.RedirectToUrl("emby/" + DefaultRedirectPath);
+ return Task.FromResult(true);
+ }
if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase))
{
httpRes.RedirectToUrl(DefaultRedirectPath);
@@ -384,6 +390,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer
foreach (var route in clone)
{
+ routes.Add(new RouteAttribute(NormalizeEmbyRoutePath(route.Path), route.Verbs)
+ {
+ Notes = route.Notes,
+ Priority = route.Priority,
+ Summary = route.Summary
+ });
routes.Add(new RouteAttribute(NormalizeRoutePath(route.Path), route.Verbs)
{
Notes = route.Notes,
@@ -398,11 +410,37 @@ namespace MediaBrowser.Server.Implementations.HttpServer
Priority = route.Priority,
Summary = route.Summary
});
+ routes.Add(new RouteAttribute(DoubleNormalizeEmbyRoutePath(route.Path), route.Verbs)
+ {
+ Notes = route.Notes,
+ Priority = route.Priority,
+ Summary = route.Summary
+ });
}
return routes.ToArray();
}
+ private string NormalizeEmbyRoutePath(string path)
+ {
+ if (path.StartsWith("/", StringComparison.OrdinalIgnoreCase))
+ {
+ return "/emby" + path;
+ }
+
+ return "emby/" + path;
+ }
+
+ private string DoubleNormalizeEmbyRoutePath(string path)
+ {
+ if (path.StartsWith("/", StringComparison.OrdinalIgnoreCase))
+ {
+ return "/emby/emby" + path;
+ }
+
+ return "emby/emby/" + path;
+ }
+
private string NormalizeRoutePath(string path)
{
if (path.StartsWith("/", StringComparison.OrdinalIgnoreCase))
diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
index 3903c62b1..b4da40702 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
@@ -140,7 +140,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
return true;
}
- return _config.Configuration.InsecureApps8.Contains(auth.Client ?? string.Empty,
+ return _config.Configuration.InsecureApps9.Contains(auth.Client ?? string.Empty,
StringComparer.OrdinalIgnoreCase);
}
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index f9fa1aae3..02c16d0d4 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -732,7 +732,12 @@ namespace MediaBrowser.Server.Implementations.Library
}
}
- folder = GetItemById(folder.Id) as BasePluginFolder ?? folder;
+ var dbItem = GetItemById(folder.Id) as BasePluginFolder;
+
+ if (dbItem != null && string.Equals(dbItem.Path, folder.Path, StringComparison.OrdinalIgnoreCase))
+ {
+ folder = dbItem;
+ }
rootFolder.AddVirtualChild(folder);
@@ -921,10 +926,8 @@ namespace MediaBrowser.Server.Implementations.Library
if (isArtist)
{
- var validFilename = _fileSystem.GetValidFilename(name).Trim();
-
var existing = RootFolder
- .GetRecursiveChildren(i => i is T && string.Equals(_fileSystem.GetValidFilename(i.Name).Trim(), validFilename, StringComparison.OrdinalIgnoreCase))
+ .GetRecursiveChildren(i => i is T && NameExtensions.AreEqual(i.Name, name))
.Cast<T>()
.FirstOrDefault();
@@ -1510,7 +1513,7 @@ namespace MediaBrowser.Server.Implementations.Library
return GetUserRootFolder().Children
.OfType<Folder>()
- .Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path));
+ .Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path, StringComparer.OrdinalIgnoreCase));
}
public string GetContentType(BaseItem item)
diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
index 4fab95263..71fd4127b 100644
--- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
@@ -129,29 +129,19 @@ namespace MediaBrowser.Server.Implementations.Library
return list;
}
- public Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, bool enablePathSubstitution, CancellationToken cancellationToken)
- {
- return GetPlayackMediaSources(id, null, enablePathSubstitution, cancellationToken);
- }
-
- public async Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, CancellationToken cancellationToken)
+ public async Task<IEnumerable<MediaSourceInfo>> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, string[] supportedLiveMediaTypes, CancellationToken cancellationToken)
{
var item = _libraryManager.GetItemById(id);
- IEnumerable<MediaSourceInfo> mediaSources;
var hasMediaSources = (IHasMediaSources)item;
User user = null;
- if (string.IsNullOrWhiteSpace(userId))
- {
- mediaSources = hasMediaSources.GetMediaSources(enablePathSubstitution);
- }
- else
+ if (!string.IsNullOrWhiteSpace(userId))
{
user = _userManager.GetUserById(userId);
- mediaSources = GetStaticMediaSources(hasMediaSources, enablePathSubstitution, user);
}
+ var mediaSources = GetStaticMediaSources(hasMediaSources, enablePathSubstitution, user);
var dynamicMediaSources = await GetDynamicMediaSources(hasMediaSources, cancellationToken).ConfigureAwait(false);
var list = new List<MediaSourceInfo>();
@@ -166,9 +156,11 @@ namespace MediaBrowser.Server.Implementations.Library
}
if (source.Protocol == MediaProtocol.File)
{
- source.SupportsDirectStream = File.Exists(source.Path);
-
// TODO: Path substitution
+ if (!File.Exists(source.Path))
+ {
+ source.SupportsDirectStream = false;
+ }
}
else if (source.Protocol == MediaProtocol.Http)
{
@@ -183,6 +175,27 @@ namespace MediaBrowser.Server.Implementations.Library
list.Add(source);
}
+ foreach (var source in list)
+ {
+ if (user != null)
+ {
+ if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
+ {
+ if (!user.Policy.EnableAudioPlaybackTranscoding)
+ {
+ source.SupportsTranscoding = false;
+ }
+ }
+ else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
+ {
+ if (!user.Policy.EnableVideoPlaybackTranscoding)
+ {
+ source.SupportsTranscoding = false;
+ }
+ }
+ }
+ }
+
return SortMediaSources(list).Where(i => i.Type != MediaSourceType.Placeholder);
}
@@ -230,27 +243,15 @@ namespace MediaBrowser.Server.Implementations.Library
}
}
- public MediaSourceInfo GetStaticMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution)
+ public async Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution)
{
- return GetStaticMediaSources(item, enablePathSubstitution).FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
- }
-
- public IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution)
- {
- if (item == null)
- {
- throw new ArgumentNullException("item");
- }
-
- if (!(item is Video))
- {
- return item.GetMediaSources(enablePathSubstitution);
- }
+ var sources = await GetPlayackMediaSources(item.Id.ToString("N"), null, enablePathSubstitution, new[] { MediaType.Audio, MediaType.Video },
+ CancellationToken.None).ConfigureAwait(false);
- return item.GetMediaSources(enablePathSubstitution);
+ return sources.FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
}
- public IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user)
+ public IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null)
{
if (item == null)
{
@@ -262,16 +263,14 @@ namespace MediaBrowser.Server.Implementations.Library
return item.GetMediaSources(enablePathSubstitution);
}
- if (user == null)
- {
- throw new ArgumentNullException("user");
- }
-
var sources = item.GetMediaSources(enablePathSubstitution).ToList();
- foreach (var source in sources)
+ if (user != null)
{
- SetUserProperties(source, user);
+ foreach (var source in sources)
+ {
+ SetUserProperties(source, user);
+ }
}
return sources;
@@ -360,6 +359,7 @@ namespace MediaBrowser.Server.Implementations.Library
}
var json = _jsonSerializer.SerializeToString(mediaSource);
+ _logger.Debug("Live stream opened: " + json);
var clone = _jsonSerializer.DeserializeFromString<MediaSourceInfo>(json);
if (!string.IsNullOrWhiteSpace(request.UserId))
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
index 71daf2b0c..f88293b2a 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
@@ -64,7 +64,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
if (string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
{
- return ResolveVideos<Video>(parent, files, directoryService, collectionType, false);
+ //return ResolveVideos<Video>(parent, files, directoryService, collectionType, false);
}
if (string.IsNullOrEmpty(collectionType))
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
index acae5b801..e7f239780 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
@@ -10,6 +11,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
{
public class PhotoAlbumResolver : FolderResolver<PhotoAlbum>
{
+ private readonly IImageProcessor _imageProcessor;
+ public PhotoAlbumResolver(IImageProcessor imageProcessor)
+ {
+ _imageProcessor = imageProcessor;
+ }
+
/// <summary>
/// Resolves the specified args.
/// </summary>
@@ -32,9 +39,9 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
return null;
}
- private static bool HasPhotos(ItemResolveArgs args)
+ private bool HasPhotos(ItemResolveArgs args)
{
- return args.FileSystemChildren.Any(i => ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory) && PhotoResolver.IsImageFile(i.FullName));
+ return args.FileSystemChildren.Any(i => ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory) && PhotoResolver.IsImageFile(i.FullName, _imageProcessor));
}
public override ResolverPriority Priority
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
index b714e968b..407aac53d 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using System;
@@ -9,6 +10,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
{
public class PhotoResolver : ItemResolver<Photo>
{
+ private readonly IImageProcessor _imageProcessor;
+ public PhotoResolver(IImageProcessor imageProcessor)
+ {
+ _imageProcessor = imageProcessor;
+ }
+
/// <summary>
/// Resolves the specified args.
/// </summary>
@@ -19,7 +26,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
// Must be an image file within a photo collection
if (string.Equals(args.GetCollectionType(), CollectionType.Photos, StringComparison.OrdinalIgnoreCase) &&
!args.IsDirectory &&
- IsImageFile(args.Path))
+ IsImageFile(args.Path, _imageProcessor))
{
return new Photo
{
@@ -30,9 +37,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
return null;
}
- // Some common file name extensions for RAW picture files include: .cr2, .crw, .dng, .nef, .orf, .rw2, .pef, .arw, .sr2, .srf, and .tif.
- protected static string[] ImageExtensions = { ".tiff", ".jpeg", ".jpg", ".png", ".aiff", ".cr2", ".crw", ".dng", ".nef", ".orf", ".pef", ".arw", ".webp" };
-
private static readonly string[] IgnoreFiles =
{
"folder",
@@ -43,12 +47,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
"poster"
};
- internal static bool IsImageFile(string path)
+ internal static bool IsImageFile(string path, IImageProcessor imageProcessor)
{
var filename = Path.GetFileNameWithoutExtension(path) ?? string.Empty;
return !IgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase)
- && ImageExtensions.Contains(Path.GetExtension(path) ?? string.Empty, StringComparer.OrdinalIgnoreCase);
+ && imageProcessor.SupportedInputFormats.Contains((Path.GetExtension(path) ?? string.Empty).TrimStart('.'), StringComparer.OrdinalIgnoreCase);
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs
index 51cad7a35..72bbefae4 100644
--- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs
+++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs
@@ -122,7 +122,7 @@ namespace MediaBrowser.Server.Implementations.Library
var artists = items.OfType<Audio>()
.SelectMany(i => i.AllArtists)
.Where(i => !string.IsNullOrWhiteSpace(i))
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.ToList();
foreach (var item in artists)
diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs
index b101f6ae1..03471a8e9 100644
--- a/MediaBrowser.Server.Implementations/Library/UserManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs
@@ -166,11 +166,6 @@ namespace MediaBrowser.Server.Implementations.Library
var users = Users.ToList();
- foreach (var user in users)
- {
- await DoPolicyMigration(user).ConfigureAwait(false);
- }
-
// If there are no local users with admin rights, make them all admins
if (!users.Any(i => i.Policy.IsAdministrator))
{
@@ -286,10 +281,10 @@ namespace MediaBrowser.Server.Implementations.Library
if (newValue >= maxCount)
{
- //_logger.Debug("Disabling user {0} due to {1} unsuccessful login attempts.", user.Name, newValue.ToString(CultureInfo.InvariantCulture));
- //user.Policy.IsDisabled = true;
+ _logger.Debug("Disabling user {0} due to {1} unsuccessful login attempts.", user.Name, newValue.ToString(CultureInfo.InvariantCulture));
+ user.Policy.IsDisabled = true;
- //fireLockout = true;
+ fireLockout = true;
}
await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false);
@@ -366,19 +361,6 @@ namespace MediaBrowser.Server.Implementations.Library
return users;
}
- private async Task DoPolicyMigration(User user)
- {
- if (!user.Configuration.HasMigratedToPolicy)
- {
- user.Policy.IsAdministrator = user.Configuration.IsAdministrator;
-
- await UpdateUserPolicy(user, user.Policy, false);
-
- user.Configuration.HasMigratedToPolicy = true;
- await UpdateConfiguration(user, user.Configuration, true).ConfigureAwait(false);
- }
- }
-
public UserDto GetUserDto(User user, string remoteEndPoint = null)
{
if (user == null)
@@ -953,8 +935,6 @@ namespace MediaBrowser.Server.Implementations.Library
user.Policy = userPolicy;
}
- user.Configuration.IsAdministrator = user.Policy.IsAdministrator;
-
await UpdateConfiguration(user, user.Configuration, true).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs
index a964738e6..c9440bb27 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/ArtistsValidator.cs
@@ -49,7 +49,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
.ToList();
var allArtists = allSongs.SelectMany(i => i.AllArtists)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.ToList();
var numComplete = 0;
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs
index 757936aa7..fe2e6a114 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/GameGenresValidator.cs
@@ -36,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
{
var items = _libraryManager.RootFolder.GetRecursiveChildren(i => (i is Game))
.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.ToList();
var numComplete = 0;
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs
index 3a06fac1b..fac5cfc35 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/GenresValidator.cs
@@ -37,7 +37,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
{
var items = _libraryManager.RootFolder.GetRecursiveChildren(i => !(i is IHasMusicGenres) && !(i is Game))
.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.ToList();
var numComplete = 0;
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs
index 25eddb48a..e3be75e9b 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/MusicGenresValidator.cs
@@ -36,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
{
var items = _libraryManager.RootFolder.GetRecursiveChildren(i => (i is IHasMusicGenres))
.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.ToList();
var numComplete = 0;
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs
index 5feebab9c..066b96853 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs
@@ -35,7 +35,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
{
var items = _libraryManager.RootFolder.GetRecursiveChildren()
.SelectMany(i => i.Studios)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.ToList();
var numComplete = 0;
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
index 401cf8765..61017ffb3 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
@@ -8,12 +8,12 @@ using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Querying;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Model.Querying;
namespace MediaBrowser.Server.Implementations.LiveTv
{
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index a39781d6a..3f164ee6f 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -761,6 +761,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
programs = programs.Where(p => p.IsMovie == query.IsMovie);
}
+ if (query.IsSports.HasValue)
+ {
+ programs = programs.Where(p => p.IsSports == query.IsSports);
+ }
+
programs = _libraryManager.Sort(programs, user, query.SortBy, query.SortOrder ?? SortOrder.Ascending)
.Cast<LiveTvProgram>();
@@ -826,10 +831,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv
programs = programs.Where(p => p.IsMovie == query.IsMovie.Value);
}
+ if (query.IsSports.HasValue)
+ {
+ programs = programs.Where(p => p.IsSports == query.IsSports.Value);
+ }
+
var programList = programs.ToList();
var genres = programList.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
+ .DistinctNames()
.Select(i => _libraryManager.GetGenre(i))
.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
@@ -996,6 +1006,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
innerProgress = new ActionableProgress<double>();
innerProgress.RegisterAction(p => progress.Report(90 + (p * .1)));
await CleanDatabaseInternal(progress, cancellationToken).ConfigureAwait(false);
+
+ foreach (var program in _programs.Values
+ .Where(i => (i.StartDate - DateTime.UtcNow).TotalDays <= 1)
+ .ToList())
+ {
+ RefreshIfNeeded(program);
+ }
}
finally
{
@@ -1128,8 +1145,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
_refreshedPrograms.Clear();
progress.Report(90);
+ RefreshIfNeeded(programs.Take(500));
+
// Load these now which will prefetch metadata
- await GetRecordings(new RecordingQuery(), cancellationToken).ConfigureAwait(false);
+ var dtoOptions = new DtoOptions();
+ dtoOptions.Fields.Remove(ItemFields.SyncInfo);
+ await GetRecordings(new RecordingQuery(), dtoOptions, cancellationToken).ConfigureAwait(false);
progress.Report(100);
}
@@ -1195,8 +1216,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var days = Math.Round(((double)maxPrograms) / programsPerDay);
- // No less than 2, no more than 7
- return Math.Max(2, Math.Min(days, 7));
+ return Math.Max(3, Math.Min(days, 14));
}
private async Task<IEnumerable<Tuple<string, ChannelInfo>>> GetChannels(ILiveTvService service, CancellationToken cancellationToken)
@@ -1304,7 +1324,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
};
}
- public async Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, CancellationToken cancellationToken)
+ public async Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, DtoOptions options, CancellationToken cancellationToken)
{
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(query.UserId);
@@ -1320,6 +1340,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
})
.ToArray();
+ if (user != null)
+ {
+ _dtoService.FillSyncInfo(returnArray, new DtoOptions(), user);
+ }
+
return new QueryResult<RecordingInfoDto>
{
Items = returnArray,
@@ -1392,7 +1417,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public async Task DeleteRecording(string recordingId)
{
- var recording = await GetRecording(recordingId, CancellationToken.None).ConfigureAwait(false);
+ var dtoOptions = new DtoOptions();
+ dtoOptions.Fields.Remove(ItemFields.SyncInfo);
+
+ var recording = await GetRecording(recordingId, dtoOptions, CancellationToken.None).ConfigureAwait(false);
if (recording == null)
{
@@ -1432,14 +1460,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv
await service.CancelSeriesTimerAsync(timer.ExternalId, CancellationToken.None).ConfigureAwait(false);
}
- public async Task<RecordingInfoDto> GetRecording(string id, CancellationToken cancellationToken, User user = null)
+ public async Task<RecordingInfoDto> GetRecording(string id, DtoOptions options, CancellationToken cancellationToken, User user = null)
{
var results = await GetRecordings(new RecordingQuery
{
UserId = user == null ? null : user.Id.ToString("N"),
Id = id
- }, cancellationToken).ConfigureAwait(false);
+ }, options, cancellationToken).ConfigureAwait(false);
return results.Items.FirstOrDefault();
}
@@ -1719,11 +1747,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public async Task<QueryResult<RecordingGroupDto>> GetRecordingGroups(RecordingGroupQuery query, CancellationToken cancellationToken)
{
+ var dtoOptions = new DtoOptions();
+ dtoOptions.Fields.Remove(ItemFields.SyncInfo);
+
var recordingResult = await GetRecordings(new RecordingQuery
{
UserId = query.UserId
- }, cancellationToken).ConfigureAwait(false);
+ }, dtoOptions, cancellationToken).ConfigureAwait(false);
var recordings = recordingResult.Items;
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
index d549cad46..84b4053a1 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
@@ -1,6 +1,8 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.MediaEncoding;
+using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
@@ -18,12 +20,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private readonly IJsonSerializer _jsonSerializer;
private readonly ILogger _logger;
private readonly IMediaSourceManager _mediaSourceManager;
+ private readonly IMediaEncoder _mediaEncoder;
- public LiveTvMediaSourceProvider(ILiveTvManager liveTvManager, IJsonSerializer jsonSerializer, ILogManager logManager, IMediaSourceManager mediaSourceManager)
+ public LiveTvMediaSourceProvider(ILiveTvManager liveTvManager, IJsonSerializer jsonSerializer, ILogManager logManager, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder)
{
_liveTvManager = liveTvManager;
_jsonSerializer = jsonSerializer;
_mediaSourceManager = mediaSourceManager;
+ _mediaEncoder = mediaEncoder;
_logger = logManager.GetLogger(GetType().Name);
}
@@ -90,14 +94,93 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public async Task<MediaSourceInfo> OpenMediaSource(string openToken, CancellationToken cancellationToken)
{
+ MediaSourceInfo stream;
+ var isAudio = false;
+
var keys = openToken.Split(new[] { '|' }, 2);
if (string.Equals(keys[0], typeof(LiveTvChannel).Name, StringComparison.OrdinalIgnoreCase))
{
- return await _liveTvManager.GetChannelStream(keys[1], cancellationToken).ConfigureAwait(false);
+ stream = await _liveTvManager.GetChannelStream(keys[1], cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ stream = await _liveTvManager.GetRecordingStream(keys[1], cancellationToken).ConfigureAwait(false);
+ }
+
+ try
+ {
+ await AddMediaInfo(stream, isAudio, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error probing live tv stream", ex);
+ }
+
+ return stream;
+ }
+
+ private async Task AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
+ {
+ var inputPaths = new[] { mediaSource.Path };
+
+ var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
+ {
+ InputPath = mediaSource.Path,
+ Protocol = mediaSource.Protocol,
+ MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
+ ExtractChapters = false
+
+ }, cancellationToken)
+ .ConfigureAwait(false);
+
+ mediaSource.Bitrate = info.Bitrate;
+ mediaSource.Container = info.Container;
+ mediaSource.Formats = info.Formats;
+ mediaSource.MediaStreams = info.MediaStreams;
+ mediaSource.RunTimeTicks = info.RunTimeTicks;
+ mediaSource.Size = info.Size;
+ mediaSource.Timestamp = info.Timestamp;
+ mediaSource.Video3DFormat = info.Video3DFormat;
+ mediaSource.VideoType = info.VideoType;
+
+ mediaSource.DefaultSubtitleStreamIndex = null;
+
+ var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio);
+
+ if (audioStream == null || audioStream.Index == -1)
+ {
+ mediaSource.DefaultAudioStreamIndex = null;
+ }
+ else
+ {
+ mediaSource.DefaultAudioStreamIndex = audioStream.Index;
}
- return await _liveTvManager.GetRecordingStream(keys[1], cancellationToken).ConfigureAwait(false);
+ // Try to estimate this
+ if (!mediaSource.Bitrate.HasValue)
+ {
+ var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video);
+ if (videoStream != null)
+ {
+ var width = videoStream.Width ?? 1920;
+
+ if (width >= 1900)
+ {
+ mediaSource.Bitrate = 10000000;
+ }
+
+ else if (width >= 1260)
+ {
+ mediaSource.Bitrate = 6000000;
+ }
+
+ else if (width >= 700)
+ {
+ mediaSource.Bitrate = 4000000;
+ }
+ }
+ }
}
public Task CloseMediaSource(string liveStreamId, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs
index d29b67a8a..b01dddb94 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs
@@ -12,7 +12,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.LiveTv
{
- public class ProgramImageProvider : IDynamicImageProvider, IHasItemChangeMonitor
+ public class ProgramImageProvider : IDynamicImageProvider, IHasItemChangeMonitor, IHasOrder
{
private readonly ILiveTvManager _liveTvManager;
private readonly IHttpClient _httpClient;
@@ -100,7 +100,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public int Order
{
- get { return 0; }
+ get
+ {
+ // Let the better providers run first
+ return 100;
+ }
}
public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService)
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json
index 856a88501..07b0022c8 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "\u0627\u0644\u062e\u0645\u064a\u0633",
"OptionFriday": "\u0627\u0644\u062c\u0645\u0639\u0629",
"OptionSaturday": "\u0627\u0644\u0633\u0628\u062a",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/bg_BG.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/bg_BG.json
index 5b036d4d0..e7cad3695 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/bg_BG.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/bg_BG.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "\u041f\u043e\u0434\u043a\u0440\u0435\u043f\u0435\u0442\u0435 Emby \u041e\u0442\u0431\u043e\u0440\u044a\u0442",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "\u0422V \u043d\u0430 \u0436\u0438\u0432\u043e",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "\u0418\u0437\u0432\u0435\u0441\u0442\u0438\u044f",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "\u0427\u0435\u0442\u0432\u044a\u0440\u0442\u044a\u043a",
"OptionFriday": "\u041f\u0435\u0442\u044a\u043a",
"OptionSaturday": "\u0421\u044a\u0431\u043e\u0442\u0430",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json
index ecf55bdb0..335dbd3df 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json
index 67b9ca26f..ea141645c 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Potvrzen\u00ed",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "\u017div\u00e1 TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "\u010ctvrtek",
"OptionFriday": "P\u00e1tek",
"OptionSaturday": "Sobota",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Potvrdit smaz\u00e1n\u00ed",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Aktualizace dostupn\u00e1)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Chyba",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json
index 0d4d1bbfa..f4983f8dd 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Direkte TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -62,10 +67,10 @@
"LabelMovie": "Movie",
"LabelMusicVideo": "Music Video",
"LabelEpisode": "Episode",
- "LabelSeries": "Series",
+ "LabelSeries": "Serier",
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
- "LabelFailed": "(failed)",
+ "LabelFailed": "(fejlede)",
"ButtonHelp": "Help",
"ButtonSave": "Gem",
"ButtonDownload": "Download",
@@ -79,8 +84,8 @@
"SyncJobStatusCompletedWithError": "Synced with errors",
"SyncJobItemStatusReadyToTransfer": "Ready to Transfer",
"LabelCollection": "Collection",
- "HeaderAddToCollection": "Add to Collection",
- "NewCollectionNameExample": "Example: Star Wars Collection",
+ "HeaderAddToCollection": "Tilf\u00f8j til samling",
+ "NewCollectionNameExample": "Eksempel: Star Wars Collection",
"OptionSearchForInternetMetadata": "Search the internet for artwork and metadata",
"LabelSelectCollection": "Select collection:",
"HeaderDevices": "Devices",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -138,7 +143,7 @@
"ButtonPlay": "Afspil",
"ButtonEdit": "Rediger",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "Play trailer",
+ "ButtonPlayTrailer": "Afspil trailer",
"ButtonPlaylist": "Playlist",
"ButtonPreviousTrack": "Previous Track",
"LabelEnabled": "Enabled",
@@ -174,6 +179,9 @@
"OptionThursday": "Torsdag",
"OptionFriday": "Fredag",
"OptionSaturday": "L\u00f8rdag",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
@@ -394,7 +403,7 @@
"TabAdvanced": "Advanceret",
"TabHelp": "Help",
"TabScheduledTasks": "Scheduled Tasks",
- "ButtonFullscreen": "Fullscreen",
+ "ButtonFullscreen": "Fuld sk\u00e6rm",
"ButtonAudioTracks": "Audio Tracks",
"ButtonSubtitles": "Undertekster",
"ButtonScenes": "Scener",
@@ -467,7 +476,7 @@
"PersonTypePerson": "Person",
"LabelTitleDisplayOrder": "Title display order:",
"OptionSortName": "Sort name",
- "OptionReleaseDate": "Release date",
+ "OptionReleaseDate": "Udgivelsesdato",
"LabelSeasonNumber": "Season number:",
"LabelDiscNumber": "Disc number",
"LabelParentNumber": "Parent number",
@@ -496,14 +505,14 @@
"LabelContentTypeValue": "Content type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
"FolderTypeUnset": "Unset (mixed content)",
- "FolderTypeMovies": "Movies",
- "FolderTypeMusic": "Music",
- "FolderTypeAdultVideos": "Adult videos",
- "FolderTypePhotos": "Photos",
- "FolderTypeMusicVideos": "Music videos",
- "FolderTypeHomeVideos": "Home videos",
- "FolderTypeGames": "Games",
- "FolderTypeBooks": "Books",
+ "FolderTypeMovies": "FIlm",
+ "FolderTypeMusic": "Musik",
+ "FolderTypeAdultVideos": "Voksenfilm",
+ "FolderTypePhotos": "Fotos",
+ "FolderTypeMusicVideos": "Musikvideoer",
+ "FolderTypeHomeVideos": "Hjemmevideoer",
+ "FolderTypeGames": "Spil",
+ "FolderTypeBooks": "B\u00f8ger",
"FolderTypeTvShows": "TV",
"TabMovies": "Film",
"TabSeries": "Serier",
@@ -611,7 +620,7 @@
"HeaderAlbums": "Albums",
"HeaderGames": "Games",
"HeaderBooks": "Books",
- "HeaderEpisodes": "Episodes",
+ "HeaderEpisodes": "Afsnit",
"HeaderSeasons": "Seasons",
"HeaderTracks": "Tracks",
"HeaderItems": "Items",
@@ -649,7 +658,7 @@
"MediaInfoStreamTypeEmbeddedImage": "Embedded Image",
"MediaInfoRefFrames": "Ref frames",
"TabPlayback": "Playback",
- "TabNotifications": "Notifications",
+ "TabNotifications": "Notifikationer",
"TabExpert": "Expert",
"HeaderSelectCustomIntrosPath": "Select Custom Intros Path",
"HeaderRateAndReview": "Rate and Review",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json
index 9431bf07f..1a68eed35 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Best\u00e4tigung",
"MessageKeyUpdated": "Danke. Dein Unterst\u00fctzerschl\u00fcssel wurde aktualisiert.",
"MessageKeyRemoved": "Danke. Ihr Unterst\u00fctzerschl\u00fcssel wurde entfernt.",
+ "HeaderSupportTheTeam": "Unterst\u00fctzen Sie das Emby Team",
+ "TextEnjoyBonusFeatures": "Erleben Sie Bonus Funktionen",
"TitleLiveTV": "Live-TV",
"TitleSync": "Synchronisation",
+ "ButtonDonate": "Spenden",
+ "HeaderMyMedia": "Meine Medien",
+ "TitleNotifications": "Benachrichtigungen",
"ErrorLaunchingChromecast": "W\u00e4hrend des startens von Chromecast ist ein Fehler aufgetreten. Bitte stelle sicher, dass dein Ger\u00e4te mit dem WLAN verbunden ist.",
"MessageErrorLoadingSupporterInfo": "Es trat ein Fehler beim laden der Unterst\u00fctzer-Informationen auf. Bitte versuchen Sie es sp\u00e4ter erneut.",
"MessageLinkYourSupporterKey": "Verbinden Sie Ihren Unterst\u00fctzer-Schl\u00fcssel mit bis zu {0} Emby Connect Benutzern um kostenfreien Zugriff auf die folgenden Apps zu erhalten:",
@@ -120,7 +125,7 @@
"MessagePlaybackErrorNotAllowed": "Sie sind nicht befugt diese Inhalte wiederzugeben. Bitte kontaktieren Sie Ihren Systemadministrator f\u00fcr weitere Details.",
"MessagePlaybackErrorNoCompatibleStream": "Es sind aktuell keine kompatiblen Streams verf\u00fcgbar. Bitte versuchen Sie es sp\u00e4ter erneut.",
"MessagePlaybackErrorRateLimitExceeded": "Ihr Wiedergabelimit wurde \u00fcberschritten. Bitte kontaktieren Sie Ihren Systemadministrator f\u00fcr weitere Details.",
- "MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
+ "MessagePlaybackErrorPlaceHolder": "Der gew\u00e4hlte Inhalt kann auf diesem Ger\u00e4t nicht abgespielt werden.",
"HeaderSelectAudio": "W\u00e4hle Audio",
"HeaderSelectSubtitles": "W\u00f6hle Untertitel",
"ButtonMarkForRemoval": "Entferne von Ger\u00e4t",
@@ -174,6 +179,9 @@
"OptionThursday": "Donnerstag",
"OptionFriday": "Freitag",
"OptionSaturday": "Samstag",
+ "OptionEveryday": "T\u00e4glich",
+ "OptionWeekend": "Wochenenden",
+ "OptionWeekday": "Wochentage",
"HeaderConfirmDeletion": "Best\u00e4tige L\u00f6schung",
"MessageConfirmPathSubstitutionDeletion": "Bist du dir sicher die Pfadsubstitution l\u00f6schen zu wollen?",
"LiveTvUpdateAvailable": "(Update verf\u00fcgbar)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Trenne Medien ab",
"MessageConfirmSplitMedia": "Bist du dir sicher, dass du die Medienquellen in separate Elemente aufteilen m\u00f6chtest?",
"HeaderError": "Fehler",
+ "MessageChromecastConnectionError": "Ihr Chromecast kann keine Verbindung mit dem Emby Server herstellen. Bitte \u00fcberpr\u00fcfen Sie die Verbindung und probieren Sie es erneut.",
"MessagePleaseSelectOneItem": "Bitte w\u00e4hle mindestens eine Option aus.",
"MessagePleaseSelectTwoItems": "Bitte w\u00e4hle mindestens zwei Optionen aus.",
"MessageTheFollowingItemsWillBeGrouped": "Die folgenden Titel werden zu einem Element gruppiert:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json
index 336e311e6..70fdf8e25 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json
@@ -23,8 +23,8 @@
"PasswordSaved": "\u039f \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2 \u03b1\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c4\u03b7\u03ba\u03b5",
"PasswordMatchError": "\u039f \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2 \u03ba\u03b1\u03b9 \u03c4\u03bf\u03bd \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03b5\u03c0\u03b9\u03b2\u03b5\u03b2\u03b1\u03af\u03c9\u03c3\u03b7\u03c2 \u03c0\u03c1\u03ad\u03c0\u03b5\u03b9 \u03bd\u03b1 \u03c4\u03b1\u03b9\u03c1\u03b9\u03ac\u03b6\u03bf\u03c5\u03bd",
"OptionRelease": "\u0397 \u03b5\u03c0\u03af\u03c3\u03b7\u03bc\u03b7 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7",
- "OptionBeta": "\u03b2\u03ae\u03c4\u03b1",
- "OptionDev": "\u03b1\u03bd\u03ac\u03c0\u03c4\u03c5\u03be\u03b7 (\u03b1\u03c3\u03c4\u03b1\u03b8\u03ae\u03c2)",
+ "OptionBeta": "\u0394\u03bf\u03ba\u03b9\u03bc\u03b1\u03c3\u03c4\u03b9\u03ba\u03ae",
+ "OptionDev": "\u0391\u03bd\u03ac\u03c0\u03c4\u03c5\u03be\u03b7 (\u03b1\u03c3\u03c4\u03b1\u03b8\u03ae\u03c2)",
"UninstallPluginHeader": "\u03b1\u03c0\u03b5\u03b3\u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b7\u03c3\u03b5\u03c4\u03b5 \u03c4\u03bf plugin",
"UninstallPluginConfirmation": "\u0395\u03af\u03c3\u03c4\u03b5 \u03c3\u03af\u03b3\u03bf\u03c5\u03c1\u03bf\u03b9 \u03cc\u03c4\u03b9 \u03b8\u03ad\u03bb\u03b5\u03c4\u03b5 \u03bd\u03b1 \u03b1\u03c0\u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03ae\u03c3\u03b5\u03c4\u03b5;",
"NoPluginConfigurationMessage": "\u0391\u03c5\u03c4\u03cc \u03c4\u03bf plugin \u03ad\u03c7\u03b5\u03b9 \u03c4\u03af\u03c0\u03bf\u03c4\u03b1 \u03bd\u03b1 \u03b4\u03b9\u03b1\u03bc\u03bf\u03c1\u03c6\u03ce\u03c3\u03b5\u03c4\u03b5",
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "\u0395\u03b9\u03b4\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03b9\u03c2",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -62,12 +67,12 @@
"LabelMovie": "Movie",
"LabelMusicVideo": "Music Video",
"LabelEpisode": "Episode",
- "LabelSeries": "Series",
+ "LabelSeries": "\u03a3\u03b5\u03b9\u03c1\u03ad\u03c2",
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
- "LabelFailed": "(failed)",
- "ButtonHelp": "Help",
- "ButtonSave": "\u0391\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c3\u03c4\u03b5",
+ "LabelFailed": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1",
+ "ButtonHelp": "\u0392\u03bf\u03ae\u03b8\u03b5\u03b9\u03b1",
+ "ButtonSave": "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7",
"ButtonDownload": "Download",
"SyncJobStatusQueued": "Queued",
"SyncJobStatusConverting": "Converting",
@@ -79,10 +84,10 @@
"SyncJobStatusCompletedWithError": "Synced with errors",
"SyncJobItemStatusReadyToTransfer": "Ready to Transfer",
"LabelCollection": "Collection",
- "HeaderAddToCollection": "Add to Collection",
- "NewCollectionNameExample": "Example: Star Wars Collection",
- "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata",
- "LabelSelectCollection": "Select collection:",
+ "HeaderAddToCollection": "\u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c3\u03b5 \u03c3\u03c4\u03b7\u03bd \u03a3\u03c5\u03bb\u03bb\u03bf\u03b3\u03ae",
+ "NewCollectionNameExample": "\u03a0\u03b1\u03c1\u03ac\u03b4\u03b5\u03b9\u03b3\u03bc\u03b1: \u03a3\u03c5\u03bb\u03bb\u03bf\u03b3\u03ae \"\u03a0\u03cc\u03bb\u03b5\u03bc\u03bf\u03c2 \u03c4\u03c9\u03bd \u0386\u03c3\u03c4\u03c1\u03c9\u03bd\"",
+ "OptionSearchForInternetMetadata": "\u0391\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7 \u03c3\u03c4\u03bf \u03b4\u03b9\u03b1\u03b4\u03af\u03ba\u03c4\u03c5\u03bf \u03b3\u03b9\u03b1 \u03b5\u03be\u03ce\u03c6\u03c5\u03bb\u03bb\u03bf \u03ba\u03b1\u03b9 \u03c0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2",
+ "LabelSelectCollection": "\u0395\u03c0\u03ad\u03bb\u03b5\u03be\u03b5 \u03c3\u03c5\u03bb\u03bb\u03bf\u03b3\u03ae:",
"HeaderDevices": "Devices",
"ButtonScheduledTasks": "Scheduled tasks",
"MessageItemsAdded": "Items added",
@@ -93,14 +98,14 @@
"LabelSyncNoTargetsHelp": "It looks like you don't currently have any apps that support sync.",
"HeaderWelcomeToProjectServerDashboard": "Welcome to the Emby Server Dashboard",
"HeaderWelcomeToProjectWebClient": "Welcome to the Emby Web Client",
- "ButtonTakeTheTour": "Take the tour",
+ "ButtonTakeTheTour": "\u039a\u03ac\u03bd\u03c4\u03b5 \u03c4\u03b7\u03bd \u039e\u03b5\u03bd\u03ac\u03b3\u03b7\u03c3\u03b7",
"HeaderWelcomeBack": "Welcome back!",
- "TitlePlugins": "Plugins",
+ "TitlePlugins": "\u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03b1",
"ButtonTakeTheTourToSeeWhatsNew": "Take the tour to see what's new",
"MessageNoSyncJobsFound": "No sync jobs found. Create sync jobs using the Sync buttons found throughout the web interface.",
"HeaderLibraryAccess": "Library Access",
"HeaderChannelAccess": "Channel Access",
- "HeaderDeviceAccess": "Device Access",
+ "HeaderDeviceAccess": "\u03a0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03a3\u03c5\u03c3\u03ba\u03b5\u03c5\u03ae\u03c2",
"HeaderSelectDevices": "Select Devices",
"ButtonCancelItem": "Cancel item",
"ButtonQueueForRetry": "Queue for retry",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -133,14 +138,14 @@
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
"ButtonStop": "Stop",
- "ButtonNextTrack": "Next Track",
+ "ButtonNextTrack": "\u0395\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf \u039a\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9",
"ButtonPause": "Pause",
"ButtonPlay": "Play",
"ButtonEdit": "Edit",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "Play trailer",
+ "ButtonPlayTrailer": "\u0391\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03ae trailer",
"ButtonPlaylist": "Playlist",
- "ButtonPreviousTrack": "Previous Track",
+ "ButtonPreviousTrack": "\u03a0\u03c1\u03bf\u03b7\u03b3\u03bf\u03cd\u03bc\u03b5\u03bd\u03bf \u039a\u03bf\u03bc\u03bc\u03ac\u03c4\u03b9",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
@@ -174,6 +179,9 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,11 +199,12 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
"MessageConfirmItemGrouping": "Emby apps will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?",
- "HeaderResume": "\u03a3\u03c5\u03bd\u03b5\u03c7\u03af\u03c3\u03b5\u03b9 ",
+ "HeaderResume": "\u0395\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7",
"HeaderMyViews": "My Views",
"HeaderLibraryFolders": "Media Folders",
"HeaderLatestMedia": "Latest Media",
@@ -219,7 +228,7 @@
"HeaderSelectChannelDownloadPath": "Select Channel Download Path",
"HeaderSelectChannelDownloadPathHelp": "Browse or enter the path to use for storing channel cache files. The folder must be writeable.",
"OptionNewCollection": "New...",
- "ButtonAdd": "Add",
+ "ButtonAdd": "\u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c3\u03b5",
"ButtonRemove": "Remove",
"LabelChapterDownloaders": "Chapter downloaders:",
"LabelChapterDownloadersHelp": "Enable and rank your preferred chapter downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
@@ -266,7 +275,7 @@
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
"HeaderLatestTvRecordings": "Latest Recordings",
- "ButtonOk": "\u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9",
+ "ButtonOk": "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9",
"ButtonCancel": "\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7 ",
"ButtonRefresh": "Refresh",
"LabelCurrentPath": "Current path:",
@@ -280,7 +289,7 @@
"ButtonShuffle": "Shuffle",
"ButtonInstantMix": "Instant mix",
"ButtonResume": "Resume",
- "HeaderScenes": "Scenes",
+ "HeaderScenes": "\u03a3\u03ba\u03b7\u03bd\u03ad\u03c2",
"HeaderAudioTracks": "Audio Tracks",
"HeaderLibraries": "Libraries",
"HeaderSubtitles": "Subtitles",
@@ -298,8 +307,8 @@
"HeaderArtist": "Artist",
"LabelAddedOnDate": "Added {0}",
"ButtonStart": "Start",
- "HeaderChannels": "Channels",
- "HeaderMediaFolders": "Media Folders",
+ "HeaderChannels": "\u039a\u03b1\u03bd\u03ac\u03bb\u03b9\u03b1",
+ "HeaderMediaFolders": "\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03b9 \u03a0\u03bf\u03bb\u03c5\u03bc\u03ad\u03c3\u03c9\u03bd",
"HeaderBlockItemsWithNoRating": "Block content with no rating information:",
"OptionBlockOthers": "Others",
"OptionBlockTvShows": "TV Shows",
@@ -383,7 +392,7 @@
"LabelPackageInstallCompleted": "{0} installation completed.",
"LabelPackageInstallFailed": "{0} installation failed.",
"LabelPackageInstallCancelled": "{0} installation cancelled.",
- "TabServer": "Server",
+ "TabServer": "\u0394\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae\u03c2",
"TabUsers": "Users",
"TabLibrary": "Library",
"TabMetadata": "Metadata",
@@ -394,20 +403,20 @@
"TabAdvanced": "Advanced",
"TabHelp": "Help",
"TabScheduledTasks": "Scheduled Tasks",
- "ButtonFullscreen": "Fullscreen",
- "ButtonAudioTracks": "Audio Tracks",
+ "ButtonFullscreen": "\u039f\u03bb\u03cc\u03ba\u03bb\u03b7\u03c1\u03b7 \u03bf\u03b8\u03cc\u03bd\u03b7",
+ "ButtonAudioTracks": "\u0397\u03c7\u03b7\u03c4\u03b9\u03ba\u03ac \u039a\u03cc\u03bc\u03bc\u03ac\u03c4\u03b9\u03b1",
"ButtonSubtitles": "Subtitles",
"ButtonScenes": "Scenes",
"ButtonQuality": "Quality",
"HeaderNotifications": "Notifications",
"HeaderSelectPlayer": "Select Player:",
- "ButtonSelect": "Select",
- "ButtonNew": "New",
+ "ButtonSelect": "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae",
+ "ButtonNew": "\u039d\u03ad\u03bf",
"MessageInternetExplorerWebm": "For best results with Internet Explorer please install the WebM playback plugin.",
"HeaderVideoError": "Video Error",
"ButtonAddToPlaylist": "Add to playlist",
"HeaderAddToPlaylist": "Add to Playlist",
- "LabelName": "Name:",
+ "LabelName": "\u038c\u03bd\u03bf\u03bc\u03b1:",
"ButtonSubmit": "Submit",
"LabelSelectPlaylist": "Playlist:",
"OptionNewPlaylist": "New playlist...",
@@ -418,9 +427,9 @@
"ButtonRemoveFromPlaylist": "Remove from playlist",
"HeaderSpecials": "Specials",
"HeaderTrailers": "Trailers",
- "HeaderAudio": "Audio",
+ "HeaderAudio": "\u0389\u03c7\u03bf\u03c2",
"HeaderResolution": "Resolution",
- "HeaderVideo": "Video",
+ "HeaderVideo": "\u0392\u03af\u03bd\u03c4\u03b5\u03bf",
"HeaderRuntime": "Runtime",
"HeaderCommunityRating": "Community rating",
"HeaderParentalRating": "Parental rating",
@@ -436,11 +445,11 @@
"HeaderEmbeddedImage": "Embedded image",
"HeaderTrack": "Track",
"HeaderDisc": "Disc",
- "OptionMovies": "Movies",
+ "OptionMovies": "\u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2",
"OptionCollections": "Collections",
"OptionSeries": "Series",
"OptionSeasons": "Seasons",
- "OptionEpisodes": "Episodes",
+ "OptionEpisodes": "\u0395\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1",
"OptionGames": "Games",
"OptionGameSystems": "Game systems",
"OptionMusicArtists": "Music artists",
@@ -467,7 +476,7 @@
"PersonTypePerson": "Person",
"LabelTitleDisplayOrder": "Title display order:",
"OptionSortName": "Sort name",
- "OptionReleaseDate": "Release date",
+ "OptionReleaseDate": "\u03a0\u03c1\u03ce\u03c4\u03b7 \u03a0\u03c1\u03bf\u03b2\u03bf\u03bb\u03ae",
"LabelSeasonNumber": "Season number:",
"LabelDiscNumber": "Disc number",
"LabelParentNumber": "Parent number",
@@ -496,22 +505,22 @@
"LabelContentTypeValue": "Content type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
"FolderTypeUnset": "Unset (mixed content)",
- "FolderTypeMovies": "Movies",
- "FolderTypeMusic": "Music",
- "FolderTypeAdultVideos": "Adult videos",
- "FolderTypePhotos": "Photos",
- "FolderTypeMusicVideos": "Music videos",
- "FolderTypeHomeVideos": "Home videos",
- "FolderTypeGames": "Games",
- "FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV",
- "TabMovies": "Movies",
+ "FolderTypeMovies": "\u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2",
+ "FolderTypeMusic": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ae",
+ "FolderTypeAdultVideos": "\u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2 \u0395\u03bd\u03b7\u03bb\u03af\u03ba\u03c9\u03bd",
+ "FolderTypePhotos": "\u03a6\u03c9\u03c4\u03bf\u03b3\u03c1\u03b1\u03c6\u03af\u03b5\u03c2",
+ "FolderTypeMusicVideos": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ac \u0392\u03af\u03bd\u03c4\u03b5\u03bf",
+ "FolderTypeHomeVideos": "\u03a0\u03c1\u03bf\u03c3\u03c9\u03c0\u03b9\u03ba\u03ac \u0392\u03af\u03bd\u03c4\u03b5\u03bf",
+ "FolderTypeGames": "\u03a0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9\u03b1",
+ "FolderTypeBooks": "\u0392\u03b9\u03b2\u03bb\u03af\u03b1",
+ "FolderTypeTvShows": "\u03a4\u03b7\u03bb\u03b5\u03cc\u03c1\u03b1\u03c3\u03b7",
+ "TabMovies": "\u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2",
"TabSeries": "Series",
"TabEpisodes": "\u0395\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1",
"TabTrailers": "Trailers",
- "TabGames": "Games",
- "TabAlbums": "\u03ac\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc",
- "TabSongs": "\u03c4\u03c1\u03b1\u03b3\u03bf\u03cd\u03b4\u03b9\u03b1",
+ "TabGames": "\u03a0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9\u03b1",
+ "TabAlbums": "\u0386\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc",
+ "TabSongs": "\u03a4\u03c1\u03b1\u03b3\u03bf\u03cd\u03b4\u03b9\u03b1",
"TabMusicVideos": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ac \u03b2\u03af\u03bd\u03c4\u03b5\u03bf",
"BirthPlaceValue": "Birth place: {0}",
"DeathDateValue": "Died: {0}",
@@ -611,7 +620,7 @@
"HeaderAlbums": "Albums",
"HeaderGames": "Games",
"HeaderBooks": "Books",
- "HeaderEpisodes": "Episodes",
+ "HeaderEpisodes": "\u0395\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1",
"HeaderSeasons": "Seasons",
"HeaderTracks": "Tracks",
"HeaderItems": "Items",
@@ -649,7 +658,7 @@
"MediaInfoStreamTypeEmbeddedImage": "Embedded Image",
"MediaInfoRefFrames": "Ref frames",
"TabPlayback": "Playback",
- "TabNotifications": "Notifications",
+ "TabNotifications": "\u0395\u03b9\u03b4\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03b9\u03c2",
"TabExpert": "Expert",
"HeaderSelectCustomIntrosPath": "Select Custom Intros Path",
"HeaderRateAndReview": "Rate and Review",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json
index e6509b9da..b18eb9d40 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json
index bc6c5aaf1..227de4f26 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json
index 981286e12..9568be9b3 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmaci\u00f3n",
"MessageKeyUpdated": "Gracias. Su clave de seguidor ha sido actualizada.",
"MessageKeyRemoved": "Gracias. Su clave de seguidor ha sido eliminada.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Tv en vivo",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "Ha habido un error al lanzar chromecast. Asegurese que su dispositivo est\u00e1 conectado a su red inal\u00e1mbrica.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Libre",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Seleccionar Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Jueves",
"OptionFriday": "Viernes",
"OptionSaturday": "S\u00e1bado",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirmar borrado",
"MessageConfirmPathSubstitutionDeletion": "\u00bfEst\u00e1 seguro que desea borrar esta ruta de sustituci\u00f3n?",
"LiveTvUpdateAvailable": "(Actualizaci\u00f3n disponible)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Divisi\u00f3n de medios",
"MessageConfirmSplitMedia": "\u00bfEst\u00e1 seguro que desea dividir los medios en partes separadas?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Seleccione al menos un elemento.",
"MessagePleaseSelectTwoItems": "Seleccione al menos dos elementos.",
"MessageTheFollowingItemsWillBeGrouped": "Los siguientes t\u00edtulos se agrupar\u00e1n en un elemento.",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json
index b0700c49c..21e9d4188 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmaci\u00f3n",
"MessageKeyUpdated": "Gracias. Su clave de aficionado ha sido actualizada.",
"MessageKeyRemoved": "Gracias. Su clave de aficionado ha sido eliminada.",
+ "HeaderSupportTheTeam": "Apoye al equipo de Emby",
+ "TextEnjoyBonusFeatures": "Disfruta de Caracter\u00edsticas Premium",
"TitleLiveTV": "TV en Vivo",
"TitleSync": "Sinc",
+ "ButtonDonate": "Donar",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notificaciones",
"ErrorLaunchingChromecast": "Hubo un error iniciando chromecast. Por favor aseg\u00farate de que tu dispositivo este conectado a tu red inalambrica",
"MessageErrorLoadingSupporterInfo": "Se present\u00f3 un error al cargar la informaci\u00f3n del aficionado. Por favor int\u00e9ntelo m\u00e1s tarde.",
"MessageLinkYourSupporterKey": "Enlaza tu clave de aficionado con hasta {0} miembros de Emby Connect para disfrutar de acceso gratuito a la siguientes aplicaciones:",
@@ -118,9 +123,9 @@
"LabelFree": "Gratis",
"HeaderPlaybackError": "Error de Reproducci\u00f3n",
"MessagePlaybackErrorNotAllowed": "Actualmente no esta autorizado para reproducir este contenido. Por favor contacte a su administrador de sistema para mas informaci\u00f3n.",
- "MessagePlaybackErrorNoCompatibleStream": "No hay streams compatibles en este en este momento. Por favor intente de nuevo mas tarde.",
+ "MessagePlaybackErrorNoCompatibleStream": "No hay streams compatibles en este en este momento. Por favor intente de nuevo mas tarde o contacte a su administrador de sistema para mas detalles.",
"MessagePlaybackErrorRateLimitExceeded": "Su limite de transferencia ha sido excedido. Por favor contacte a su administrador de sistema para mas informaci\u00f3n.",
- "MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
+ "MessagePlaybackErrorPlaceHolder": "No es posible reproducir el contenido seleccionado en este dispositivo.",
"HeaderSelectAudio": "Seleccionar Audio",
"HeaderSelectSubtitles": "Seleccionar Subtitulos",
"ButtonMarkForRemoval": "Remover de dispositivo",
@@ -174,6 +179,9 @@
"OptionThursday": "Jueves",
"OptionFriday": "Viernes",
"OptionSaturday": "S\u00e1bado",
+ "OptionEveryday": "Todos los d\u00edas",
+ "OptionWeekend": "Fines de Semana",
+ "OptionWeekday": "D\u00edas de semana",
"HeaderConfirmDeletion": "Confirmar Eliminaci\u00f3n",
"MessageConfirmPathSubstitutionDeletion": "\u00bfEst\u00e1 seguro de querer eliminar esta ruta alternativa?",
"LiveTvUpdateAvailable": "(Actualizaci\u00f3n disponible)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Dividir y Separar Medios",
"MessageConfirmSplitMedia": "\u00bfEst\u00e1 seguro de querer dividir y separar estos medios en elementos individuales?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Su receptor Chromecast no puede conectarse con su Servidor Emby. Por favor revise las conexiones e intent\u00e9lo nuevamente.",
"MessagePleaseSelectOneItem": "Por favor selecciona al menos un elemento.",
"MessagePleaseSelectTwoItems": "Por favor selecciona al menos dos elementos.",
"MessageTheFollowingItemsWillBeGrouped": "Los siguientes t\u00edtulos ser\u00e1n agrupados en un solo elemento.",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json
index 7fcd26b32..f980dda8f 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json
index 48b51da03..12ad2a595 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Merci. Votre cl\u00e9 de supporteur a \u00e9t\u00e9 mise \u00e0 jour.",
"MessageKeyRemoved": "Merci. Votre cl\u00e9 de supporteur a \u00e9t\u00e9 supprim\u00e9e.",
+ "HeaderSupportTheTeam": "Aidez l'\u00e9quipe Emby",
+ "TextEnjoyBonusFeatures": "Profitez bien des fonctionnalit\u00e9s bonus",
"TitleLiveTV": "TV en direct",
"TitleSync": "Sync.",
+ "ButtonDonate": "Faire un don",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "Une erreur a \u00e9t\u00e9 rencontr\u00e9e lors du lancement de Chromecast. Veuillez vous assurer que votre appareil est bien connect\u00e9 \u00e0 votre r\u00e9seau sans-fil.",
"MessageErrorLoadingSupporterInfo": "Il y a eu une erreur lors du chargement des informations de supporter. Veuillez r\u00e9essayer plus tard.",
"MessageLinkYourSupporterKey": "Liez votre cl\u00e9 de supporteur avec un maximum de {0} membres Emby Connect pour b\u00e9n\u00e9ficier de l'acc\u00e8s gratuit aux applications suivantes :",
@@ -118,9 +123,9 @@
"LabelFree": "Gratuit",
"HeaderPlaybackError": "Erreur de lecture",
"MessagePlaybackErrorNotAllowed": "Vous n'\u00eates pas autoris\u00e9 \u00e0 lire ce contenu. Veuillez contacter votre administrateur syst\u00e8me pour plus de d\u00e9tails.",
- "MessagePlaybackErrorNoCompatibleStream": "Aucun flux compatible n'est actuellement disponible. Veuillez r\u00e9essayer plus tard.",
+ "MessagePlaybackErrorNoCompatibleStream": "Aucun flux compatible n'est actuellement disponible. Veuillez r\u00e9essayer plus tard ou contactez votre administrateur pour plus de d\u00e9tails.",
"MessagePlaybackErrorRateLimitExceeded": "Vous avez d\u00e9pass\u00e9 votre limite de lecture. Veuillez contacter votre administrateur syst\u00e8me pour plus de d\u00e9tails.",
- "MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
+ "MessagePlaybackErrorPlaceHolder": "Impossible de lire le contenu choisi sur cet appareil",
"HeaderSelectAudio": "S\u00e9lectionner audio",
"HeaderSelectSubtitles": "S\u00e9lectionner sous-titres",
"ButtonMarkForRemoval": "Supprimer de l'appareil",
@@ -174,6 +179,9 @@
"OptionThursday": "Jeudi",
"OptionFriday": "Vendredi",
"OptionSaturday": "Samedi",
+ "OptionEveryday": "Tous les jours",
+ "OptionWeekend": "Week-ends",
+ "OptionWeekday": "Jours de semaine",
"HeaderConfirmDeletion": "Confirmer la suppression",
"MessageConfirmPathSubstitutionDeletion": "\u00cates-vous s\u00fbr de vouloir supprimer cette substitution de chemin d'acc\u00e8s?",
"LiveTvUpdateAvailable": "(Mise \u00e0 jour disponible)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "S\u00e9parer les m\u00e9dias",
"MessageConfirmSplitMedia": "\u00cates vous s\u00fbrs de vouloir diviser les sources de m\u00e9dia dans des items s\u00e9par\u00e9s ?",
"HeaderError": "Erreur",
+ "MessageChromecastConnectionError": "Votre cl\u00e9 Chromecast ne peut pas se connecter \u00e0 votre serveur Emby. Veuillez v\u00e9rifier les connections et recommencer.",
"MessagePleaseSelectOneItem": "Veuillez s\u00e9lectionner au moins un item.",
"MessagePleaseSelectTwoItems": "Veuillez s\u00e9lectionner au moins deux items.",
"MessageTheFollowingItemsWillBeGrouped": "Les titres suivants seront group\u00e9s en un seul item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json
index a92346cb2..3c461177f 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "\u05d8\u05dc\u05d5\u05d5\u05d9\u05d6\u05d9\u05d4 \u05d7\u05d9\u05d9\u05d4",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "\u05d7\u05de\u05d9\u05e9\u05d9",
"OptionFriday": "\u05e9\u05d9\u05e9\u05d9",
"OptionSaturday": "\u05e9\u05d1\u05ea",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json
index 3d2255b83..64b518013 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "\u010cetvrtak",
"OptionFriday": "Petak",
"OptionSaturday": "Subota",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/hu.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/hu.json
index f9ddac88f..9a98b1951 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/hu.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/hu.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json
index 76d29661b..8ccad5645 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json
@@ -6,8 +6,8 @@
"Administrator": "Amministratore",
"Password": "Password",
"DeleteImage": "Elimina immagine",
- "MessageThankYouForSupporting": "Thank you for supporting Emby.",
- "MessagePleaseSupportProject": "Please support Emby.",
+ "MessageThankYouForSupporting": "Grazie per il tuo sostegno a Emby.",
+ "MessagePleaseSupportProject": "Per favore, sostieni Emby.",
"DeleteImageConfirmation": "Sei sicuro di voler eliminare questa immagine?",
"FileReadCancelled": "Il file letto \u00e8 stato cancellato.",
"FileNotFound": "File non trovato",
@@ -35,14 +35,19 @@
"HeaderConfirmation": "Conferma",
"MessageKeyUpdated": "Grazie. La vostra chiave supporter \u00e8 stato aggiornato.",
"MessageKeyRemoved": "Grazie. La vostra chiave supporter \u00e8 stata rimossa.",
+ "HeaderSupportTheTeam": "Supporta il Team di Emby",
+ "TextEnjoyBonusFeatures": "Goditi le caratteristiche aggiuntive",
"TitleLiveTV": "Tv in diretta",
"TitleSync": "Sincronizza",
+ "ButtonDonate": "Donazione",
+ "HeaderMyMedia": "I mei media",
+ "TitleNotifications": "Notifiche",
"ErrorLaunchingChromecast": "Si \u00e8 verificato un errore all'avvio di chromecast. Assicurati che il tuo dispositivo sia connesso alla rete wireless.",
- "MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
+ "MessageErrorLoadingSupporterInfo": "Si \u00e8 verificato un errore caricando le informazioni sui supporter. Si prega di riprovare pi\u00f9 tardi.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
- "HeaderConfirmRemoveUser": "Remove User",
+ "HeaderConfirmRemoveUser": "Cancellazione utente",
"MessageSwipeDownOnRemoteControl": "Welcome to remote control. Swipe down anywhere on this screen to go back to where you came from.",
- "MessageConfirmRemoveConnectSupporter": "Are you sure you wish to remove additional supporter benefits from this user?",
+ "MessageConfirmRemoveConnectSupporter": "Sei sicuro di voler rimuovere da questo utente i benefici aggiuntivi da supporter?",
"ValueTimeLimitSingleHour": "Tempo limite: 1 ora",
"ValueTimeLimitMultiHour": "Tempo limite: {0} ore",
"HeaderUsers": "Utenti",
@@ -89,18 +94,18 @@
"ButtonAddToCollection": "Aggiungi alla collezione",
"HeaderSelectCertificatePath": "Seleziona il percorso del Certificato",
"ConfirmMessageScheduledTaskButton": "L'operazione viene normalmente eseguita come operazione pianificata. Pu\u00f2 anche essere avviata manualmente da qui. Per configurare le operazioni pianificate, vedi:",
- "HeaderSupporterBenefit": "L'iscrizione come supporter da benefici addizionali, come l'accesso alla sincronizzazione, i plugin premium, canali con contenuto internet, e altro. {0}Scopri di pi\u00f9{1}.",
+ "HeaderSupporterBenefit": "L'iscrizione come supporter garantisce benefici aggiuntivi, come l'accesso alla sincronizzazione, i plugin premium, canali con contenuto internet, e altro ancora. {0}Scopri di pi\u00f9{1}.",
"LabelSyncNoTargetsHelp": "Sembra che al momento non avete applicazioni che supportano la sincronizzazione.",
- "HeaderWelcomeToProjectServerDashboard": "Welcome to the Emby Server Dashboard",
- "HeaderWelcomeToProjectWebClient": "Welcome to the Emby Web Client",
- "ButtonTakeTheTour": "Fai il tour",
+ "HeaderWelcomeToProjectServerDashboard": "Benvenuto nel Pannello di controllo del Server Emby",
+ "HeaderWelcomeToProjectWebClient": "Benvenuto nel client web Emby",
+ "ButtonTakeTheTour": "Fai una visita",
"HeaderWelcomeBack": "Ben tornato!",
"TitlePlugins": "Plugins",
"ButtonTakeTheTourToSeeWhatsNew": "Fai un tour per vedere cosa \u00e8 cambiato",
"MessageNoSyncJobsFound": "Nessuna sincronizzazione pianificata. Creane una utilizzando i pulsanti sull'interfaccia web",
"HeaderLibraryAccess": "Accesso libreria",
"HeaderChannelAccess": "Accesso canali",
- "HeaderDeviceAccess": "Accesso dispositivo",
+ "HeaderDeviceAccess": "Accesso al dispositivo",
"HeaderSelectDevices": "Seleziona periferiche",
"ButtonCancelItem": "Cancella oggetto",
"ButtonQueueForRetry": "In attesa di riprovare",
@@ -118,9 +123,9 @@
"LabelFree": "Gratis",
"HeaderPlaybackError": "Errore di riproduzione",
"MessagePlaybackErrorNotAllowed": "Al momento non sei autorizzato a riprodurre questo contenuto. Per favore contatta l'amministratore del sistema per ulteriori dettagli",
- "MessagePlaybackErrorNoCompatibleStream": "Nessuna trasmissione compatibile \u00e8 al momento disponibile. Per favore riprova in seguito",
+ "MessagePlaybackErrorNoCompatibleStream": "Nessuna trasmissione compatibile \u00e8 al momento disponibile. Per favore riprova in seguito o contatta il tuo Amministratore di sistema per chiarimenti",
"MessagePlaybackErrorRateLimitExceeded": "La tua quota di riproduzione \u00e8 stata raggiunta. Per favore contatta l'amministratore del sistema per ulteriori dettagli",
- "MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
+ "MessagePlaybackErrorPlaceHolder": "Il contenuto scelto non pu\u00f2 essere riprodotto su questo dispositivo",
"HeaderSelectAudio": "Seleziona audio",
"HeaderSelectSubtitles": "Seleziona sottotitoli",
"ButtonMarkForRemoval": "Rimuovi dal dispositivo",
@@ -174,6 +179,9 @@
"OptionThursday": "Gioved\u00ec",
"OptionFriday": "Venerd\u00ec",
"OptionSaturday": "Sabato",
+ "OptionEveryday": "Tutti i giorni",
+ "OptionWeekend": "weekend",
+ "OptionWeekday": "Giorni feriali",
"HeaderConfirmDeletion": "Conferma Cancellazione",
"MessageConfirmPathSubstitutionDeletion": "Sei sicuro di voler cancellare questa sostituzione percorso?",
"LiveTvUpdateAvailable": "(Aggiornamento disponibile)",
@@ -191,10 +199,11 @@
"HeaderSplitMedia": "Dividi Media",
"MessageConfirmSplitMedia": "Sei sicuro di voler dividere le fonti dei media in voci separate?",
"HeaderError": "Errore",
+ "MessageChromecastConnectionError": "Il tuo ricevitore Chromecast non \u00e8 in grado di collegarsi al tuo Server Emby. Si prega di verificare la connessione e provare di nuovo",
"MessagePleaseSelectOneItem": "Si prega di selezionare almeno un elemento.",
"MessagePleaseSelectTwoItems": "Seleziona almeno due elementi.",
"MessageTheFollowingItemsWillBeGrouped": "I seguenti titoli saranno raggruppati in un unico elemento:",
- "MessageConfirmItemGrouping": "Emby apps will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?",
+ "MessageConfirmItemGrouping": "Le app Emby scieglieranno automaticamente la versione ottimale per la riproduzione basandosi sulle prestazioni del dispositivo e della rete. Sei sicuro di voler continuare?",
"HeaderResume": "Riprendi",
"HeaderMyViews": "Mie viste",
"HeaderLibraryFolders": "Cartelle dei mediati",
@@ -242,8 +251,8 @@
"OrganizePatternResult": "Risultati: {0}",
"HeaderRestart": "Riavvia",
"HeaderShutdown": "Spegni",
- "MessageConfirmRestart": "Are you sure you wish to restart Emby Server?",
- "MessageConfirmShutdown": "Are you sure you wish to shutdown Emby Server?",
+ "MessageConfirmRestart": "Sei sicuro di voler riavviare il Server Emby?",
+ "MessageConfirmShutdown": "Sei sicuro di voler spegnere il Server Emby?",
"ButtonUpdateNow": "Aggiorna Adesso",
"ValueItemCount": "{0} elemento",
"ValueItemCountPlural": "{0} elementi",
@@ -288,7 +297,7 @@
"MessageErrorPlayingVideo": "Si \u00e8 verificato un errore nella riproduzione del video.",
"MessageEnsureOpenTuner": "Si prega di assicurarsi che ci sia un sintonizzatore disponibile.",
"ButtonHome": "Home",
- "ButtonDashboard": "Dashboard",
+ "ButtonDashboard": "Pannello",
"ButtonReports": "Reports",
"ButtonMetadataManager": "Manager Metadati",
"HeaderTime": "Tempo",
@@ -312,7 +321,7 @@
"OptionBlockLiveTvChannels": "Canali TV in onda",
"OptionBlockChannelContent": "Contenuto di Canali Internet",
"ButtonRevoke": "Revocare",
- "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Emby Server will be abruptly terminated.",
+ "MessageConfirmRevokeApiKey": "Sei sicuro di voler revocare questa chiave api? La connessione dell'applicazione al Server Emby terminer\u00e0 immediatamente",
"HeaderConfirmRevokeApiKey": "Revocare Chiave Api",
"ValueContainer": "Contenitore: {0}",
"ValueAudioCodec": "Audio Codec: {0}",
@@ -526,17 +535,17 @@
"MessageInstallPluginFromApp": "Questo Plugin deve essere installato dall'app in cui vuoi farlo funzionare",
"ValuePriceUSD": "Prezzo: {0} (USD)",
"MessageFeatureIncludedWithSupporter": "Siete registrati per questa funzione, e sarete in grado di continuare ad usarlo con un abbonamento attivo sostenitore.",
- "MessageChangeRecurringPlanConfirm": "After completing this transaction you will need to cancel your previous recurring donation from within your PayPal account. Thank you for supporting Emby.",
+ "MessageChangeRecurringPlanConfirm": "Dopo aver completato questa transazione dovrai cancellare dal tuo account PayPal la tua precedente donazione ricorrente. Grazie per aver sostenuto Emby.",
"MessageSupporterMembershipExpiredOn": "La tua iscrizione supporter scaduto il {0}.",
- "MessageYouHaveALifetimeMembership": "You have a lifetime supporter membership. You can provide additional donations on a one-time or recurring basis using the options below. Thank you for supporting Emby.",
+ "MessageYouHaveALifetimeMembership": "Tu hai un abbonamento come Supporter che non ha scadenza. Puoi fare ulteriori donazioni, singole o ricorrenti, scegliendo le opzioni sottostanti. Grazie per il tuo sostegno a Emby",
"MessageYouHaveAnActiveRecurringMembership": "Si dispone di un attivo {0} appartenenza. \u00c8 possibile aggiornare il vostro piano utilizzando le opzioni di seguito.",
"ButtonDelete": "Elimina",
- "HeaderEmbyAccountAdded": "Emby Account Added",
- "MessageEmbyAccountAdded": "The Emby account has been added to this user.",
- "MessagePendingEmbyAccountAdded": "The Emby account has been added to this user. An email will be sent to the owner of the account. The invitation will need to be confirmed by clicking a link within the email.",
- "HeaderEmbyAccountRemoved": "Emby Account Removed",
- "MessageEmbyAccontRemoved": "The Emby account has been removed from this user.",
- "TooltipLinkedToEmbyConnect": "Linked to Emby Connect",
+ "HeaderEmbyAccountAdded": "Account Emby aggiunto",
+ "MessageEmbyAccountAdded": "L'account Emby \u00e8 stato aggiunto a questo utente",
+ "MessagePendingEmbyAccountAdded": "L'account Emby \u00e8 stato aggiunto a questo utente. Un'email sar\u00e0 inviata al proprietario dell'account. L'invito dovr\u00e0 essere confermato selezionando il link contenuto nell'email",
+ "HeaderEmbyAccountRemoved": "Account Emby rimosso",
+ "MessageEmbyAccontRemoved": "L'account Emby \u00e8 stato rimosso da questo utente",
+ "TooltipLinkedToEmbyConnect": "Collegato ad Emby Connect",
"HeaderUnrated": "Non votato",
"ValueDiscNumber": "Disco {0}",
"HeaderUnknownDate": "Data Sconosciuta",
@@ -584,7 +593,7 @@
"ValuePremieres": "Debuttato {0}",
"ValueStudio": "Studio: {0}",
"ValueStudios": "Studi: {0}",
- "ValueStatus": "Status: {0}",
+ "ValueStatus": "Stato {0}",
"ValueSpecialEpisodeName": "Speciali - {0}",
"LabelLimit": "Limite:",
"ValueLinks": "Collegamenti: {0}",
@@ -666,12 +675,12 @@
"WebClientTourMetadataManager": "Fare clic su Modifica per aprire la gestione dei metadati",
"WebClientTourPlaylists": "Facile creazione di playlist , e riprodurli su qualsiasi dispositivo",
"WebClientTourCollections": "Creare collezioni di film di casella di gruppo imposta insieme",
- "WebClientTourUserPreferences1": "User preferences allow you to customize the way your library is presented in all of your Emby apps",
- "WebClientTourUserPreferences2": "Configure your audio and subtitle language settings once, for every Emby app",
+ "WebClientTourUserPreferences1": "Le Preferenze Utente consentono di personalizzare il modo in cui la tua libreria viene presentata in tutte le app Emby",
+ "WebClientTourUserPreferences2": "Configura le impostazioni audio e la lingua dei sottotitoli valide per tutte le app Emby",
"WebClientTourUserPreferences3": "Progettare la home page del client web a proprio piacimento",
"WebClientTourUserPreferences4": "Configurare fondali, sigle e lettori esterni",
"WebClientTourMobile1": "Il client web funziona alla grande su smartphone e tablet ...",
- "WebClientTourMobile2": "and easily controls other devices and Emby apps",
+ "WebClientTourMobile2": "e controlla facilmente altri dispositivi e app Emby",
"WebClientTourMySync": "Sincronizza il tuo personal media per i dispositivi per la visualizzazione offline.",
"MessageEnjoyYourStay": "Godetevi il vostro soggiorno",
"DashboardTourDashboard": "Il pannello di controllo del server consente di monitorare il vostro server e gli utenti. Potrai sempre sapere chi sta facendo cosa e dove sono.",
@@ -683,7 +692,7 @@
"DashboardTourPlugins": "Installare il plugin come canali internet video, live tv, scanner metadati e altro ancora.",
"DashboardTourNotifications": "Inviare automaticamente notifiche di eventi server al vostro dispositivo mobile, e-mail e altro ancora.",
"DashboardTourScheduledTasks": "Gestire facilmente le operazioni di lunga esecuzione con le operazioni pianificate. Decidere quando corrono, e con quale frequenza.",
- "DashboardTourMobile": "The Emby Server dashboard works great on smartphones and tablets. Manage your server from the palm of your hand anytime, anywhere.",
+ "DashboardTourMobile": "Il Pannello di Controllo del Server Emby funziona bene su smartphone e tablet. Gestisci il tuo server con il palmo della tua mano, quando vuoi, dove vuoi",
"DashboardTourSync": "Sincronizza il tuo personal media per i dispositivi per la visualizzazione offline.",
"MessageRefreshQueued": "Aggiornamento programmato",
"TabDevices": "Dispositivi",
@@ -693,13 +702,13 @@
"DeleteDeviceConfirmation": "Sei sicuro di voler cancellare questo dispositivo? Esso riapparir\u00e0 la prossima volta che un utente accede con esso.",
"LabelEnableCameraUploadFor": "Abilita caricamento macchina fotografica per:",
"HeaderSelectUploadPath": "Seleziona cartella upload",
- "LabelEnableCameraUploadForHelp": "Uploads will occur automatically in the background when signed into Emby.",
+ "LabelEnableCameraUploadForHelp": "Gli upload saranno eseguiti automaticamente in background quando sei collegato a Emby",
"ErrorMessageStartHourGreaterThanEnd": "Ora di fine deve essere maggiore del tempo di avvio.",
"ButtonLibraryAccess": "Accesso biblioteca",
"ButtonParentalControl": "Controllo parentale",
"HeaderInvitationSent": "Invito inviato",
"MessageInvitationSentToUser": "Una e-mail \u00e8 stata inviata a {0}, invitandoli ad accettare l'invito di condivisione.",
- "MessageInvitationSentToNewUser": "An email has been sent to {0} inviting them to sign up with Emby.",
+ "MessageInvitationSentToNewUser": "Un'email \u00e8 stata inviata a {0} invitandolo a registrarsi a Emby",
"HeaderConnectionFailure": "Errore di connessione",
"MessageUnableToConnectToServer": "Non siamo in grado di connettersi al server selezionato al momento. Per favore assicurati che sia in esecuzione e riprova.",
"ButtonSelectServer": "Selezionare il server",
@@ -716,12 +725,12 @@
"MessageInvalidForgotPasswordPin": "Un pin Invalido o scaduto \u00e8 stato inserito. Riprova.",
"MessagePasswordResetForUsers": "Le password per i seguenti utenti sono state rimosse:",
"HeaderInviteGuest": "Invita Ospite",
- "ButtonLinkMyEmbyAccount": "Link my account now",
- "MessageConnectAccountRequiredToInviteGuest": "In order to invite guests you need to first link your Emby account to this server.",
+ "ButtonLinkMyEmbyAccount": "Collega il mio account ora",
+ "MessageConnectAccountRequiredToInviteGuest": "Per invitare gli amici \u00e8 necessario innanzitutto collegare l'account Emby a questo server.",
"ButtonSync": "Sinc.",
"SyncMedia": "Sync media",
"HeaderCancelSyncJob": "Cancel Sync",
- "CancelSyncJobConfirmation": "Cancelling the sync job will remove synced media from the device during the next sync process. Are you sure you wish to proceed?",
+ "CancelSyncJobConfirmation": "La cancellazione dell'attivit\u00e0 di sincronizzazione causer\u00e0 la rimozione dal dispositivo dei media sincronizzati durante il prossimo processo di sincronizzazione. Sei sicuro di voler comunque procedere?",
"TabSync": "Sinc",
"MessagePleaseSelectDeviceToSyncTo": "Selezionare un dispositivo per la sincronizzazione",
"MessageSyncJobCreated": "Attivit\u00e0 di Sincronizz. Creata",
@@ -745,6 +754,6 @@
"SyncJobItemStatusFailed": "Fallito",
"SyncJobItemStatusRemovedFromDevice": "Rimosso dal dispositivo",
"SyncJobItemStatusCancelled": "Cancellato",
- "LabelProfile": "Profile:",
+ "LabelProfile": "Profilo:",
"LabelBitrateMbps": "Bitrate (Mbps):"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
index ae20fafba..49ca737fe 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -175,6 +180,9 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -192,6 +200,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json
index 596a9bdd7..ecdd36c0e 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "\u0420\u0430\u0441\u0442\u0430\u0443",
"MessageKeyUpdated": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u04a3\u0456\u0437 \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b.",
"MessageKeyRemoved": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u04a3\u0456\u0437 \u0430\u043b\u0430\u0441\u0442\u0430\u043b\u0434\u044b.",
+ "HeaderSupportTheTeam": "Emby \u0442\u043e\u0431\u044b\u043d \u049b\u043e\u043b\u0434\u0430\u04a3\u044b\u0437",
+ "TextEnjoyBonusFeatures": "\u0421\u044b\u0439\u0430\u049b\u044b \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440\u0434\u0456 \u0442\u0430\u043c\u0430\u0448\u0430\u043b\u0430\u043d\u044b\u04a3\u044b\u0437",
"TitleLiveTV": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414",
"TitleSync": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443",
+ "ButtonDonate": "\u049a\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0430\u0443",
+ "HeaderMyMedia": "\u041c\u0435\u043d\u0456\u04a3 \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043c",
+ "TitleNotifications": "\u0425\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443\u043b\u0430\u0440",
"ErrorLaunchingChromecast": "Chromecast \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u049b\u0430\u0442\u0435 \u043e\u0440\u044b\u043d \u0430\u043b\u0434\u044b. \u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u04a3\u044b\u0437 \u0441\u044b\u043c\u0441\u044b\u0437 \u0436\u0435\u043b\u0456\u0433\u0435 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u044b\u043d\u0430 \u043a\u04e9\u0437 \u0436\u0435\u0442\u043a\u0456\u0437\u0456\u04a3\u0456\u0437.",
"MessageErrorLoadingSupporterInfo": "\u0416\u0430\u049b\u0442\u0430\u0443\u0448\u044b \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u044b\u043d \u0436\u04af\u043a\u0442\u0435\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u049b\u0430\u0442\u0435 \u043e\u0440\u044b\u043d \u0430\u043b\u0434\u044b. \u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u043a\u0435\u0439\u0456\u043d \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437.",
"MessageLinkYourSupporterKey": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0431\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430\u043b\u0430\u0440\u0493\u0430 \u0442\u0435\u0433\u0456\u043d \u049b\u0430\u0442\u044b\u043d\u0430\u0443\u0434\u044b \u0442\u0430\u043c\u0430\u0448\u0430\u043b\u0430\u0443 \u04af\u0448\u0456\u043d {0} Emby Connect \u043c\u04af\u0448\u0435\u0441\u0456\u043d\u0435 \u0434\u0435\u0439\u0456\u043d \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u044b\u04a3\u044b\u0437.",
@@ -66,7 +71,7 @@
"LabelStopping": "\u0422\u043e\u049b\u0442\u0430\u0442\u044b\u043b\u0443\u0434\u0430",
"LabelCancelled": "(\u0431\u043e\u043b\u0434\u044b\u0440\u044b\u043b\u043c\u0430\u0434\u044b)",
"LabelFailed": "(\u0441\u04d9\u0442\u0441\u0456\u0437)",
- "ButtonHelp": "\u0410\u043d\u044b\u049b\u0442\u0430\u043c\u0430\u0493\u0430",
+ "ButtonHelp": "\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435\u0433\u0456 \u0430\u043d\u044b\u049b\u0442\u0430\u043c\u0430\u0493\u0430",
"ButtonSave": "\u0421\u0430\u049b\u0442\u0430\u0443",
"ButtonDownload": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443",
"SyncJobStatusQueued": "\u041a\u0435\u0437\u0435\u043a\u0442\u0435",
@@ -81,7 +86,7 @@
"LabelCollection": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b",
"HeaderAddToCollection": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u049b\u0430 \u04af\u0441\u0442\u0435\u0443",
"NewCollectionNameExample": "\u041c\u044b\u0441\u0430\u043b: \u0416\u04b1\u043b\u0434\u044b\u0437 \u0441\u043e\u0493\u044b\u0441\u0442\u0430\u0440\u044b (\u0436\u0438\u044b\u043d\u0442\u044b\u049b)",
- "OptionSearchForInternetMetadata": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435\u043b\u0435\u0440 \u0431\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435\u043d \u0456\u0437\u0434\u0435\u0443",
+ "OptionSearchForInternetMetadata": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435\u043b\u0435\u0440 \u0431\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435\u043d \u0456\u0437\u0434\u0435\u0443",
"LabelSelectCollection": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u044b \u0442\u0430\u04a3\u0434\u0430\u0443:",
"HeaderDevices": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440",
"ButtonScheduledTasks": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043b\u0430\u0440\u0493\u0430 \u04e9\u0442\u0443",
@@ -117,9 +122,9 @@
"LabelNumberReviews": "{0} \u043f\u0456\u043a\u0456\u0440",
"LabelFree": "\u0422\u0435\u0433\u0456\u043d",
"HeaderPlaybackError": "\u041e\u0439\u043d\u0430\u0442\u0443 \u049b\u0430\u0442\u0435\u0441\u0456",
- "MessagePlaybackErrorNotAllowed": "\u041e\u0441\u044b \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u0430\u0493\u044b\u043c\u0434\u0430 \u0441\u0456\u0437\u0433\u0435 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0456\u043b\u043c\u0435\u0433\u0435\u043d. \u041c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440 \u04af\u0448\u0456\u043d \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u04d9\u043a\u0456\u043c\u0448\u0456\u04a3\u0456\u0437\u0433\u0435 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u044b\u04a3\u044b\u0437.",
- "MessagePlaybackErrorNoCompatibleStream": "\u0410\u0493\u044b\u043c\u0434\u0430 \u0435\u0448\u049b\u0430\u043d\u0434\u0430\u0439 \u0441\u044b\u0439\u044b\u0441\u044b\u043c\u0434\u044b \u0430\u0493\u044b\u043d\u0434\u0430\u0440 \u049b\u0430\u0442\u044b\u043d\u0430\u0443\u043b\u044b \u0435\u043c\u0435\u0441. \u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u043a\u0435\u0439\u0456\u043d \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437.",
- "MessagePlaybackErrorRateLimitExceeded": "\u041e\u0439\u043d\u0430\u0442\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b\u04a3\u044b\u0437 \u0448\u0435\u043a\u0442\u0435\u043d \u0430\u0441\u044b\u043f \u043a\u0435\u0442\u043a\u0435\u043d. \u041c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440 \u04af\u0448\u0456\u043d \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u04d9\u043a\u0456\u043c\u0448\u0456\u04a3\u0456\u0437\u0433\u0435 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u044b\u04a3\u044b\u0437.",
+ "MessagePlaybackErrorNotAllowed": "\u041e\u0441\u044b \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u0430\u0493\u044b\u043c\u0434\u0430 \u0441\u0456\u0437\u0433\u0435 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0456\u043b\u043c\u0435\u0433\u0435\u043d. \u0422\u043e\u043b\u044b\u049b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440 \u04af\u0448\u0456\u043d \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u04d9\u043a\u0456\u043c\u0448\u0456\u04a3\u0456\u0437\u0433\u0435 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u044b\u04a3\u044b\u0437.",
+ "MessagePlaybackErrorNoCompatibleStream": "\u0410\u0493\u044b\u043c\u0434\u0430 \u0435\u0448\u049b\u0430\u043d\u0434\u0430\u0439 \u0441\u044b\u0439\u044b\u0441\u044b\u043c\u0434\u044b \u0430\u0493\u044b\u043d\u0434\u0430\u0440 \u049b\u0430\u0442\u044b\u043d\u0430\u0443\u043b\u044b \u0435\u043c\u0435\u0441. \u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u043a\u0435\u0439\u0456\u043d \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0442\u043e\u043b\u044b\u049b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440 \u04af\u0448\u0456\u043d \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u04d9\u043a\u0456\u043c\u0448\u0456\u04a3\u0456\u0437\u0433\u0435 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u044b\u04a3\u044b\u0437.",
+ "MessagePlaybackErrorRateLimitExceeded": "\u041e\u0439\u043d\u0430\u0442\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b\u04a3\u044b\u0437 \u0448\u0435\u043a\u0442\u0435\u043d \u0430\u0441\u044b\u043f \u043a\u0435\u0442\u043a\u0435\u043d. \u0422\u043e\u043b\u044b\u049b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440 \u04af\u0448\u0456\u043d \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u04d9\u043a\u0456\u043c\u0448\u0456\u04a3\u0456\u0437\u0433\u0435 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u044b\u04a3\u044b\u0437.",
"MessagePlaybackErrorPlaceHolder": "\u0422\u0430\u04a3\u0434\u0430\u043b\u0493\u0430\u043d \u043c\u0430\u0437\u043c\u04b1\u043d \u0431\u04b1\u043b \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u0434\u0430\u043d \u043e\u0439\u043d\u0430\u0442\u044b\u043b\u0430\u0442\u044b\u043d \u0435\u043c\u0435\u0441.",
"HeaderSelectAudio": "\u0414\u044b\u0431\u044b\u0441 \u0442\u0430\u04a3\u0434\u0430\u0443",
"HeaderSelectSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 \u0442\u0430\u04a3\u0434\u0430\u0443",
@@ -174,6 +179,9 @@
"OptionThursday": "\u0431\u0435\u0439\u0441\u0435\u043d\u0431\u0456",
"OptionFriday": "\u0436\u04b1\u043c\u0430",
"OptionSaturday": "\u0441\u0435\u043d\u0431\u0456",
+ "OptionEveryday": "\u041a\u04af\u043d \u0441\u0430\u0439\u044b\u043d",
+ "OptionWeekend": "\u0414\u0435\u043c\u0430\u043b\u044b\u0441 \u043a\u04af\u043d\u0434\u0435\u0440\u0456",
+ "OptionWeekday": "\u0410\u043f\u0442\u0430 \u043a\u04af\u043d\u0434\u0435\u0440\u0456",
"HeaderConfirmDeletion": "\u0416\u043e\u044e\u0434\u044b \u0440\u0430\u0441\u0442\u0430\u0443",
"MessageConfirmPathSubstitutionDeletion": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u0436\u043e\u043b \u0430\u043b\u043c\u0430\u0441\u0442\u044b\u0440\u0443\u0434\u044b \u0436\u043e\u044e \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
"LiveTvUpdateAvailable": "(\u0416\u0430\u04a3\u0430\u0440\u0442\u0443 \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "\u0422\u0430\u0441\u044b\u0493\u044b\u0448\u043d\u044b \u0431\u04e9\u043b\u0435\u043a\u0442\u0435\u043f \u0431\u04e9\u043b\u0443",
"MessageConfirmSplitMedia": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u0493\u044b\u0448 \u043a\u04e9\u0437\u0434\u0435\u0440\u0456\u043d \u0431\u04e9\u043b\u0435\u043a \u0442\u0430\u0440\u043c\u0430\u049b\u0442\u0430\u0440\u0493\u0430 \u0431\u04e9\u043b\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
"HeaderError": "\u049a\u0430\u0442\u0435",
+ "MessageChromecastConnectionError": "Chromecast \u049b\u0430\u0431\u044b\u043b\u0434\u0430\u0493\u044b\u0448\u044b Emby Server \u04af\u0448\u0456\u043d \u049b\u043e\u0441\u044b\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d \u0435\u043c\u0435\u0441. \u041e\u043b\u0430\u0440\u0434\u044b\u04a3 \u049b\u043e\u0441\u044b\u043b\u044b\u043c\u0434\u0430\u0440\u044b\u043d \u0442\u0435\u043a\u0441\u0435\u0440\u0456\u04a3\u0456\u0437 \u0434\u0435 \u0436\u04d9\u043d\u0435 \u04d9\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u043a\u0435\u0439\u0456\u043d \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437.",
"MessagePleaseSelectOneItem": "\u0415\u04a3 \u043a\u0435\u043c\u0456\u043d\u0434\u0435 \u0431\u0456\u0440 \u0442\u0430\u0440\u043c\u0430\u049b\u0442\u044b \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437.",
"MessagePleaseSelectTwoItems": "\u0415\u04a3 \u043a\u0435\u043c\u0456\u043d\u0434\u0435 \u0435\u043a\u0456 \u0442\u0430\u0440\u043c\u0430\u049b\u0442\u044b \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437.",
"MessageTheFollowingItemsWillBeGrouped": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0442\u0443\u044b\u043d\u0434\u044b\u043b\u0430\u0440 \u0431\u0456\u0440 \u0442\u0430\u0440\u043c\u0430\u049b\u049b\u0430 \u0442\u043e\u043f\u0442\u0430\u0441\u0442\u044b\u0440\u044b\u043b\u0430\u0434\u044b:",
@@ -705,12 +714,12 @@
"ButtonSelectServer": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u0442\u0430\u04a3\u0434\u0430\u0443",
"MessagePluginConfigurationRequiresLocalAccess": "\u041e\u0441\u044b \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0456 \u0442\u0435\u04a3\u0448\u0435\u0443 \u04af\u0448\u0456\u043d \u0436\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u0441\u0435\u0440\u0432\u0435\u0440\u0456\u04a3\u0456\u0437\u0433\u0435 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043a\u0456\u0440\u0456\u04a3\u0456\u0437.",
"MessageLoggedOutParentalControl": "\u0410\u0493\u044b\u043c\u0434\u0430 \u049b\u0430\u0442\u044b\u043d\u0430\u0443 \u0448\u0435\u043a\u0442\u0435\u043b\u0433\u0435\u043d. \u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u043a\u0435\u0439\u0456\u043d \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437.",
- "DefaultErrorMessage": "\u0421\u0430\u0443\u0430\u043b\u0434\u044b \u04e9\u04a3\u0434\u0435\u0442\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u049b\u0430\u0442\u0435 \u043e\u0440\u044b\u043d \u0430\u043b\u0434\u044b. \u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u043a\u0435\u0439\u0456\u043d \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437.",
+ "DefaultErrorMessage": "\u0421\u0430\u0443\u0430\u043b \u04e9\u04a3\u0434\u0435\u043b\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u049b\u0430\u0442\u0435 \u043e\u0440\u044b\u043d \u0430\u043b\u0434\u044b. \u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u043a\u0435\u0439\u0456\u043d \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437.",
"ButtonAccept": "\u049a\u0430\u0431\u044b\u043b\u0434\u0430\u0443",
"ButtonReject": "\u049a\u0430\u0431\u044b\u043b\u0434\u0430\u043c\u0430\u0443",
"HeaderForgotPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u04b1\u043c\u044b\u0442\u044b\u04a3\u044b\u0437 \u0431\u0430?",
"MessageContactAdminToResetPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0456\u04a3\u0456\u0437\u0434\u0456 \u044b\u0441\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u04d9\u043a\u0456\u043c\u0448\u0456\u04a3\u0456\u0437\u0433\u0435 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u044b\u04a3\u044b\u0437.",
- "MessageForgotPasswordInNetworkRequired": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u044b\u0441\u044b\u0440\u0443 \u04af\u0434\u0435\u0440\u0456\u0441\u0456 \u04af\u0448\u0456\u043d \u04d9\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u04af\u0439\u043b\u0456\u043a \u0436\u0435\u043b\u0456\u04a3\u0456\u0437\u0434\u0456\u04a3 \u0456\u0448\u0456\u043d\u0434\u0435 \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437.",
+ "MessageForgotPasswordInNetworkRequired": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u044b\u0441\u044b\u0440\u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0456 \u04af\u0448\u0456\u043d \u04d9\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u04af\u0439\u043b\u0456\u043a \u0436\u0435\u043b\u0456\u04a3\u0456\u0437\u0434\u0456\u04a3 \u0456\u0448\u0456\u043d\u0434\u0435 \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437.",
"MessageForgotPasswordFileCreated": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0444\u0430\u0439\u043b \u0441\u0435\u0440\u0432\u0435\u0440\u0456\u04a3\u0456\u0437\u0434\u0435 \u0436\u0430\u0441\u0430\u043b\u0434\u044b \u0436\u04d9\u043d\u0435 \u049b\u0430\u043b\u0430\u0439 \u043a\u0456\u0440\u0456\u0441\u0443 \u0442\u0443\u0440\u0430\u043b\u044b \u043d\u04b1\u0441\u049b\u0430\u0443\u043b\u0430\u0440 \u0456\u0448\u0456\u043d\u0434\u0435 \u0431\u0430\u0440:",
"MessageForgotPasswordFileExpiration": "PIN \u044b\u0441\u044b\u0440\u0443 \u043c\u0435\u0437\u0433\u0456\u043b\u0456 {0} \u0431\u0456\u0442\u0435\u0434\u0456.",
"MessageInvalidForgotPasswordPin": "\u0416\u0430\u0440\u0430\u043c\u0441\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u043c\u0435\u0440\u0437\u0456\u043c\u0456 \u0430\u044f\u049b\u0442\u0430\u043b\u0493\u0430\u043d PIN \u0435\u043d\u0433\u0456\u0437\u0456\u043b\u0434\u0456. \u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437.",
@@ -721,7 +730,7 @@
"ButtonSync": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443",
"SyncMedia": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443",
"HeaderCancelSyncJob": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443\u0434\u0456 \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443",
- "CancelSyncJobConfirmation": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u0436\u04b1\u043c\u044b\u0441\u044b\u043d \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443 \u043a\u0435\u043b\u0435\u0441\u0456 \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u04af\u0434\u0435\u0440\u0456\u0441\u0456\u043d\u0434\u0435 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u0434\u0430\u043d \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0456\u043b\u0433\u0435\u043d \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u0436\u043e\u044e\u0493\u0430 \u04d9\u043a\u0435\u043b\u0435\u0434\u0456. \u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043a\u0456\u0440\u0456\u0441\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
+ "CancelSyncJobConfirmation": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u0436\u04b1\u043c\u044b\u0441\u044b\u043d \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443\u044b \u043a\u0435\u043b\u0435\u0441\u0456 \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0456 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u0434\u0430\u043d \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0456\u043b\u0433\u0435\u043d \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u0436\u043e\u044f\u0434\u044b. \u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043a\u0456\u0440\u0456\u0441\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
"TabSync": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443",
"MessagePleaseSelectDeviceToSyncTo": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0456\u043b\u0435\u0442\u0456\u043d \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043d\u044b \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437.",
"MessageSyncJobCreated": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u0436\u04b1\u043c\u044b\u0441\u044b \u0436\u0430\u0441\u0430\u043b\u0434\u044b.",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json
index 4da140d1d..92c83e8c7 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json
index b2c86d218..31c6ec66c 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Bekreftelse",
"MessageKeyUpdated": "Takk. Din supportern\u00f8kkel har blitt oppdatert.",
"MessageKeyRemoved": "Takk. Din supportern\u00f8kkel har blitt fjernet.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Synk",
+ "ButtonDonate": "Don\u00e9r",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Beskjeder",
"ErrorLaunchingChromecast": "Det var en feil ved start av Chromecast. Vennligst forsikre deg om at enheten har korrekt forbindelse til ditt tr\u00e5dl\u00f8se nettverk.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Gratis",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Velg Lyd",
@@ -174,6 +179,9 @@
"OptionThursday": "Torsdag",
"OptionFriday": "Fredag",
"OptionSaturday": "L\u00f8rdag",
+ "OptionEveryday": "Hver dag",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Bekreft Kansellering",
"MessageConfirmPathSubstitutionDeletion": "Er du sikker p\u00e5 at du vil slette sti erstatter?",
"LiveTvUpdateAvailable": "(Oppdatering tilgjengelig)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Del Media Fra Hverandre",
"MessageConfirmSplitMedia": "Er du sikker at du vil splitte mediakilden i separerte elementer?",
"HeaderError": "Feil",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Vennligst velg minst ett element.",
"MessagePleaseSelectTwoItems": "Vennligst velg minst to elementer.",
"MessageTheFollowingItemsWillBeGrouped": "F\u00f8lgende titler vil bli gruppert til ett element:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json
index 3709b6bc2..9020d9232 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Bevestiging",
"MessageKeyUpdated": "Dank u. Uw supporter sleutel is bijgewerkt.",
"MessageKeyRemoved": "Dank u. Uw supporter sleutel is verwijderd.",
+ "HeaderSupportTheTeam": "Ondersteun het Emby Team",
+ "TextEnjoyBonusFeatures": "Geniet van Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Synchroniseer",
+ "ButtonDonate": "Doneren",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Meldingen",
"ErrorLaunchingChromecast": "Er is een fout opgetreden bij het starten van chromecast. Zorg ervoor dat uw apparaat is aangesloten op uw draadloze netwerk.",
"MessageErrorLoadingSupporterInfo": "Er is een fout opgetreden bij het laden van uw supporter informatie. Probeer het later opnieuw.",
"MessageLinkYourSupporterKey": "Koppel uw supporters sleutel met maximaal {0} Emby Connect leden om te genieten van gratis toegang tot de volgende apps:",
@@ -119,8 +124,8 @@
"HeaderPlaybackError": "Afspeel Fout",
"MessagePlaybackErrorNotAllowed": "U bent niet bevoegd om deze content af te spelen. Neem contact op met uw systeembeheerder voor meer informatie.",
"MessagePlaybackErrorNoCompatibleStream": "Geen compatibele streams beschikbaar. Probeer het later opnieuw.",
- "MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
- "MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
+ "MessagePlaybackErrorRateLimitExceeded": "Je afspeel rate limiet is overschreden. Neem contact op met de beheerder van de server voor details.",
+ "MessagePlaybackErrorPlaceHolder": "De gekozen content is niet af te spelen vanaf dit apparaat.",
"HeaderSelectAudio": "Selecteer Audio",
"HeaderSelectSubtitles": "Selecteer Ondertitels",
"ButtonMarkForRemoval": "Van apparaat verwijderen",
@@ -174,6 +179,9 @@
"OptionThursday": "Donderdag",
"OptionFriday": "Vrijdag",
"OptionSaturday": "Zaterdag",
+ "OptionEveryday": "Elke dag",
+ "OptionWeekend": "Weekenden",
+ "OptionWeekday": "Weekdagen",
"HeaderConfirmDeletion": "Bevestigen Verwijdering",
"MessageConfirmPathSubstitutionDeletion": "Weet u zeker dat u dit pad vervanging wilt verwijderen?",
"LiveTvUpdateAvailable": "(Update beschikbaar)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Splits Media Apart",
"MessageConfirmSplitMedia": "Weet u zeker dat u de media bronnen wilt splitsen in afzonderlijke items?",
"HeaderError": "Fout",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Selecteer ten minste een item.",
"MessagePleaseSelectTwoItems": "Selecteer ten minste twee items.",
"MessageTheFollowingItemsWillBeGrouped": "De volgende titels worden gegroepeerd in \u00e9\u00e9n item:",
@@ -693,7 +702,7 @@
"DeleteDeviceConfirmation": "Weet u zeker dat u dit apparaat wilt verwijderen? Het zal opnieuw verschijnen als een gebruiker zich hiermee aanmeldt.",
"LabelEnableCameraUploadFor": "Schakel camera upload in voor:",
"HeaderSelectUploadPath": "Kies upload pad",
- "LabelEnableCameraUploadForHelp": "Uploads will occur automatically in the background when signed into Emby.",
+ "LabelEnableCameraUploadForHelp": "Uploads zullen automatisch op de achtergrond plaatsvinden wanneer bij Emby aangemeld is.",
"ErrorMessageStartHourGreaterThanEnd": "Eind tijd moet na de start tijd liggen.",
"ButtonLibraryAccess": "Bibliotheek toegang",
"ButtonParentalControl": "Ouderlijk toezicht",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json
index da54b8c1d..6d15e132b 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Czwartek",
"OptionFriday": "Pi\u0105tek",
"OptionSaturday": "Sobota",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json
index 0f7e35454..facd1f79d 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirma\u00e7\u00e3o",
"MessageKeyUpdated": "Obrigado. Sua chave de colaborador foi atualizada.",
"MessageKeyRemoved": "Obrigado. Sua chave de colaborador foi removida.",
+ "HeaderSupportTheTeam": "Colabore com o Time do Emby",
+ "TextEnjoyBonusFeatures": "Aproveite Funcionalidades Extras",
"TitleLiveTV": "TV ao Vivo",
"TitleSync": "Sinc",
+ "ButtonDonate": "Doar",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifica\u00e7\u00f5es",
"ErrorLaunchingChromecast": "Ocorreu um erro ao iniciar o chromecast. Por favor verifique se seu dispositivo est\u00e1 conectado \u00e0 sua rede sem fio.",
"MessageErrorLoadingSupporterInfo": "Ocorreu um erro ao carregar a informa\u00e7\u00e3o do colaborador. Por favor, tente novamente mais tarde.",
"MessageLinkYourSupporterKey": "Associe sua chave de colaborador com at\u00e9 {0} membros do Emby Connect para desfrutar acesso gr\u00e1tis \u00e0s seguintes apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Gr\u00e1tis",
"HeaderPlaybackError": "Erro na Reprodu\u00e7\u00e3o",
"MessagePlaybackErrorNotAllowed": "Voc\u00ea n\u00e3o est\u00e1 autorizado a reproduzir este conte\u00fado. Por favor, entre em contato com o administrador do sistema para mais detalhes.",
- "MessagePlaybackErrorNoCompatibleStream": "N\u00e3o existem streams compat\u00edveis dispon\u00edveis. Por favor, tente novamente mais tarde.",
+ "MessagePlaybackErrorNoCompatibleStream": "N\u00e3o existem streams compat\u00edveis. Por favor, tente novamente mais tarde ou contate o administrador do sistema para mais detalhes.",
"MessagePlaybackErrorRateLimitExceeded": "Seu limite da taxa de reprodu\u00e7\u00e3o foi excedido. Por favor, entre em contato com o administrador do sistema para mais detalhes.",
"MessagePlaybackErrorPlaceHolder": "O conte\u00fado escolhido n\u00e3o \u00e9 reproduz\u00edvel neste dispositivo.",
"HeaderSelectAudio": "Selecione \u00c1udio",
@@ -174,6 +179,9 @@
"OptionThursday": "Quinta-feira",
"OptionFriday": "Sexta-feira",
"OptionSaturday": "S\u00e1bado",
+ "OptionEveryday": "Todos os dias",
+ "OptionWeekend": "Fins-de-semana",
+ "OptionWeekday": "Dias da semana",
"HeaderConfirmDeletion": "Confirmar Exclus\u00e3o",
"MessageConfirmPathSubstitutionDeletion": "Deseja realmente excluir esta substitui\u00e7\u00e3o de caminho?",
"LiveTvUpdateAvailable": "(Atualiza\u00e7\u00e3o dispon\u00edvel)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Separar M\u00eddia",
"MessageConfirmSplitMedia": "Deseja realmente dividir as fontes de m\u00eddia em itens separados?",
"HeaderError": "Erro",
+ "MessageChromecastConnectionError": "Seu receptor Chromecast n\u00e3o pode se conectar com seu Servidor Emby. Por favor, verifique suas conex\u00f5es e tente novamente.",
"MessagePleaseSelectOneItem": "Por favor selecione pelo menos um item.",
"MessagePleaseSelectTwoItems": "Por favor selecione pelo menos dois itens.",
"MessageTheFollowingItemsWillBeGrouped": "Os seguintes t\u00edtulos ser\u00e3o agrupados em um \u00fanico item:",
@@ -380,7 +389,7 @@
"ButtonMyPreferences": "Minhas Prefer\u00eancias",
"MessageBrowserDoesNotSupportWebSockets": "Este navegador n\u00e3o suporta web sockets. Para uma melhor experi\u00eancia, tente um navegador mais atual como o Chrome, Firefox, IE10+, Safari (iOS) ou Opera.",
"LabelInstallingPackage": "Instalando {0}",
- "LabelPackageInstallCompleted": "Instala\u00e7\u00e3o de {0} completa.",
+ "LabelPackageInstallCompleted": "Instala\u00e7\u00e3o de {0} conclu\u00edda.",
"LabelPackageInstallFailed": "Instala\u00e7\u00e3o de {0} falhou.",
"LabelPackageInstallCancelled": "Instala\u00e7\u00e3o de {0} cancelada.",
"TabServer": "Servidor",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json
index 6a1092c89..525bd440e 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "TV ao Vivo",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -79,7 +84,7 @@
"SyncJobStatusCompletedWithError": "Synced with errors",
"SyncJobItemStatusReadyToTransfer": "Ready to Transfer",
"LabelCollection": "Collection",
- "HeaderAddToCollection": "Add to Collection",
+ "HeaderAddToCollection": "Adicionar \u00e0 Cole\u00e7\u00e3o",
"NewCollectionNameExample": "Exemplo: Cole\u00e7\u00e3o Guerra das Estrelas",
"OptionSearchForInternetMetadata": "Procurar na internet por imagens e metadados",
"LabelSelectCollection": "Select collection:",
@@ -116,9 +121,9 @@
"LabelVersionInstalled": "{0} installed",
"LabelNumberReviews": "{0} Reviews",
"LabelFree": "Free",
- "HeaderPlaybackError": "Playback Error",
- "MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "HeaderPlaybackError": "Erro na Reprodu\u00e7\u00e3o",
+ "MessagePlaybackErrorNotAllowed": "N\u00e3o est\u00e1 autorizado a reproduzir este conte\u00fado. Por favor, contacte o administrador do sistema para mais detalhes.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Quinta",
"OptionFriday": "Sexta",
"OptionSaturday": "S\u00e1bado",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,13 +199,14 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
"MessageConfirmItemGrouping": "Emby apps will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?",
"HeaderResume": "Resumir",
"HeaderMyViews": "My Views",
- "HeaderLibraryFolders": "Media Folders",
+ "HeaderLibraryFolders": "Pastas multim\u00e9dia",
"HeaderLatestMedia": "Latest Media",
"ButtonMoreItems": "More...",
"ButtonMore": "More",
@@ -385,7 +394,7 @@
"LabelPackageInstallCancelled": "{0} installation cancelled.",
"TabServer": "Servidor",
"TabUsers": "Users",
- "TabLibrary": "Library",
+ "TabLibrary": "Biblioteca",
"TabMetadata": "Metadados",
"TabDLNA": "DLNA",
"TabLiveTV": "Live TV",
@@ -648,7 +657,7 @@
"MediaInfoStreamTypeSubtitle": "Subtitle",
"MediaInfoStreamTypeEmbeddedImage": "Embedded Image",
"MediaInfoRefFrames": "Ref frames",
- "TabPlayback": "Playback",
+ "TabPlayback": "Reprodu\u00e7\u00e3o",
"TabNotifications": "Notifica\u00e7\u00f5es",
"TabExpert": "Expert",
"HeaderSelectCustomIntrosPath": "Select Custom Intros Path",
@@ -677,7 +686,7 @@
"DashboardTourDashboard": "O Painel Principal do servidor permite monitorizar o seu servidor e os seus utilizadores. Poder\u00e1 sempre saber onde est\u00e3o e o que est\u00e3o a fazer.",
"DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
- "DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
+ "DashboardTourCinemaMode": "O modo cinema traz a experi\u00eancia do cinema para a sua sala, possibilitando reproduzir trailers e introdu\u00e7\u00f5es personalizadas antes da longa-metragem.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
"DashboardTourSubtitles": "Automatically download subtitles for your videos in any language.",
"DashboardTourPlugins": "Install plugins such as internet video channels, live tv, metadata scanners, and more.",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json
index 4718e8930..383fc7355 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435",
"MessageKeyUpdated": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u0431\u044b\u043b \u043e\u0431\u043d\u043e\u0432\u043b\u0451\u043d.",
"MessageKeyRemoved": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u0431\u044b\u043b \u0443\u0434\u0430\u043b\u0451\u043d.",
+ "HeaderSupportTheTeam": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 Emby",
+ "TextEnjoyBonusFeatures": "\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u0431\u043e\u043d\u0443\u0441\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438",
"TitleLiveTV": "\u0422\u0412-\u044d\u0444\u0438\u0440",
"TitleSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f",
+ "ButtonDonate": "\u041f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u0442\u044c",
+ "HeaderMyMedia": "\u041c\u043e\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435",
+ "TitleNotifications": "\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f",
"ErrorLaunchingChromecast": "\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 Chromecast. \u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0432\u0430\u0448\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043e \u043a \u0431\u0435\u0441\u043f\u0440\u043e\u0432\u043e\u0434\u043d\u043e\u0439 \u0441\u0435\u0442\u0438.",
"MessageErrorLoadingSupporterInfo": "\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0435. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u043f\u043e\u0437\u0436\u0435.",
"MessageLinkYourSupporterKey": "\u0421\u0432\u044f\u0436\u0438\u0442\u0435 \u0432\u0430\u0448 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u0441\u043e \u0432\u043f\u043b\u043e\u0442\u044c \u0434\u043e {0} \u0447\u043b\u0435\u043d\u043e\u0432 Emby Connect, \u0447\u0442\u043e\u0431\u044b \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c:",
@@ -66,7 +71,7 @@
"LabelStopping": "\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430",
"LabelCancelled": "(\u043e\u0442\u043c\u0435\u043d\u0435\u043d\u043e)",
"LabelFailed": "(\u043d\u0435\u0443\u0434\u0430\u0447\u043d\u043e)",
- "ButtonHelp": "\u041a \u0441\u043f\u0440\u0430\u0432\u043a\u0435",
+ "ButtonHelp": "\u041a \u0441\u043f\u0440\u0430\u0432\u043a\u0435 \u0432 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435",
"ButtonSave": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c",
"ButtonDownload": "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c",
"SyncJobStatusQueued": "\u0412 \u043e\u0447\u0435\u0440\u0435\u0434\u0438",
@@ -81,7 +86,7 @@
"LabelCollection": "\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f",
"HeaderAddToCollection": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438",
"NewCollectionNameExample": "\u041f\u0440\u0438\u043c\u0435\u0440: \u0417\u0432\u0451\u0437\u0434\u043d\u044b\u0435 \u0432\u043e\u0439\u043d\u044b (\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f)",
- "OptionSearchForInternetMetadata": "\u0418\u0441\u043a\u0430\u0442\u044c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435",
+ "OptionSearchForInternetMetadata": "\u0418\u0441\u043a\u0430\u0442\u044c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435",
"LabelSelectCollection": "\u0412\u044b\u0431\u043e\u0440 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438:",
"HeaderDevices": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430",
"ButtonScheduledTasks": "\u041a \u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0443",
@@ -117,10 +122,10 @@
"LabelNumberReviews": "\u041e\u0442\u0437\u044b\u0432\u044b: {0}",
"LabelFree": "\u0411\u0435\u0441\u043f\u043b.",
"HeaderPlaybackError": "\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
- "MessagePlaybackErrorNotAllowed": "\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b \u043d\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f. \u0414\u043b\u044f \u0434\u0435\u0442\u0430\u043b\u0435\u0439 \u0441\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0441 \u0432\u0430\u0448\u0438\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c.",
- "MessagePlaybackErrorNoCompatibleStream": "\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u043f\u043e\u0437\u0436\u0435.",
- "MessagePlaybackErrorRateLimitExceeded": "\u0412\u0430\u0448\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0431\u044b\u043b\u0430 \u043f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u0430. \u0414\u043b\u044f \u0434\u0435\u0442\u0430\u043b\u0435\u0439 \u0441\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0441 \u0432\u0430\u0448\u0438\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c.",
- "MessagePlaybackErrorPlaceHolder": "\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0441 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430.",
+ "MessagePlaybackErrorNotAllowed": "\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b \u043d\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f. \u0417\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0441\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0441 \u0432\u0430\u0448\u0438\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c.",
+ "MessagePlaybackErrorNoCompatibleStream": "\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u043f\u043e\u0437\u0436\u0435 \u0438\u043b\u0438 \u0437\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0441\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0441 \u0432\u0430\u0448\u0438\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c.",
+ "MessagePlaybackErrorRateLimitExceeded": "\u0412\u0430\u0448\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0431\u044b\u043b\u0430 \u043f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u0430. \u0417\u0430 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0441\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0441 \u0432\u0430\u0448\u0438\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u043c.",
+ "MessagePlaybackErrorPlaceHolder": "\u0412\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u043d\u0435\u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u043e \u0441 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430.",
"HeaderSelectAudio": "\u0412\u044b\u0431\u043e\u0440 \u0430\u0443\u0434\u0438\u043e",
"HeaderSelectSubtitles": "\u0412\u044b\u0431\u043e\u0440 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432",
"ButtonMarkForRemoval": "\u0418\u0437\u044a\u044f\u0442\u044c \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430",
@@ -174,6 +179,9 @@
"OptionThursday": "\u0447\u0435\u0442\u0432\u0435\u0440\u0433",
"OptionFriday": "\u043f\u044f\u0442\u043d\u0438\u0446\u0430",
"OptionSaturday": "\u0441\u0443\u0431\u0431\u043e\u0442\u0430",
+ "OptionEveryday": "\u0415\u0436\u0435\u0434\u043d\u0435\u0432\u043d\u043e",
+ "OptionWeekend": "\u0412\u044b\u0445\u043e\u0434\u043d\u044b\u0435",
+ "OptionWeekday": "\u0414\u043d\u0438 \u043d\u0435\u0434\u0435\u043b\u0438",
"HeaderConfirmDeletion": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f",
"MessageConfirmPathSubstitutionDeletion": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u043f\u0443\u0442\u0438?",
"LiveTvUpdateAvailable": "(\u0418\u043c\u0435\u0435\u0442\u0441\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435)",
@@ -191,11 +199,12 @@
"HeaderSplitMedia": "\u0420\u0430\u0437\u0431\u0438\u0435\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0440\u043e\u0437\u044c",
"MessageConfirmSplitMedia": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0440\u0430\u0437\u0431\u0438\u0442\u044c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c?",
"HeaderError": "\u041e\u0448\u0438\u0431\u043a\u0430",
+ "MessageChromecastConnectionError": "\u041f\u0440\u0438\u0435\u043c\u043d\u0438\u043a Chromecast \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0434\u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c\u0441\u044f \u043a Emby Server. \u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0438\u0445 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u043f\u043e\u0437\u0436\u0435.",
"MessagePleaseSelectOneItem": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u0438\u043d \u044d\u043b\u0435\u043c\u0435\u043d\u0442.",
"MessagePleaseSelectTwoItems": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0445\u043e\u0442\u044f \u0431\u044b \u0434\u0432\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430.",
"MessageTheFollowingItemsWillBeGrouped": "\u0412 \u0435\u0434\u0438\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0431\u0443\u0434\u0443\u0442 \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f :",
"MessageConfirmItemGrouping": "\u0412 Emby-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f, \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0441\u0435\u0442\u0438. \u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c?",
- "HeaderResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u044b\u0435",
+ "HeaderResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u043e\u0435",
"HeaderMyViews": "\u041c\u043e\u0438 \u0430\u0441\u043f\u0435\u043a\u0442\u044b",
"HeaderLibraryFolders": "\u041c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438",
"HeaderLatestMedia": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435",
@@ -287,7 +296,7 @@
"HeaderVideoQuality": "\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0438\u0434\u0435\u043e",
"MessageErrorPlayingVideo": "\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u0432\u0438\u0434\u0435\u043e.",
"MessageEnsureOpenTuner": "\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u044e\u043d\u0435\u0440.",
- "ButtonHome": "\u041a \u0433\u043b\u0430\u0432\u043d\u043e\u043c\u0443",
+ "ButtonHome": "\u041a\u043e \u0433\u043b\u0430\u0432\u043d\u043e\u043c\u0443",
"ButtonDashboard": "\u041a \u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u0438",
"ButtonReports": "\u041a \u043e\u0442\u0447\u0451\u0442\u0430\u043c",
"ButtonMetadataManager": "\u041a \u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0443 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
@@ -678,7 +687,7 @@
"DashboardTourHelp": "\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u043a\u043d\u043e\u043f\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0432\u0438\u043a\u0438-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0445\u0441\u044f \u043a \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044e \u044d\u043a\u0440\u0430\u043d\u0430.",
"DashboardTourUsers": "\u0421\u0432\u043e\u0431\u043e\u0434\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0447\u0451\u0442\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0434\u043b\u044f \u0432\u0430\u0448\u0438\u0445 \u0434\u0440\u0443\u0437\u0435\u0439 \u0438 \u0447\u043b\u0435\u043d\u043e\u0432 \u0441\u0435\u043c\u044c\u0438, \u043a\u0430\u0436\u0434\u0443\u044e \u0441 \u0438\u0445 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u0430\u0432\u0430\u043c\u0438, \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c \u0438 \u0442.\u0434.",
"DashboardTourCinemaMode": "\u0420\u0435\u0436\u0438\u043c \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430 \u043f\u0440\u0438\u0432\u043d\u043e\u0441\u0438\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u0438\u043d\u043e\u0437\u0430\u043b\u0430 \u043f\u0440\u044f\u043c\u0438\u043a\u043e\u043c \u0432\u043e \u0432\u0430\u0448\u0443 \u0433\u043e\u0441\u0442\u0438\u043d\u0443\u044e, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0438 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u0433\u043b\u0430\u0432\u043d\u044b\u043c \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u043c.",
- "DashboardTourChapters": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0441\u0446\u0435\u043d \u043a \u0432\u0438\u0434\u0435\u043e, \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430.",
+ "DashboardTourChapters": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0441\u0446\u0435\u043d \u043a \u0432\u0438\u0434\u0435\u043e, \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430.",
"DashboardTourSubtitles": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0439\u0442\u0435 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u0434\u043b\u044f \u0432\u0438\u0434\u0435\u043e \u043d\u0430 \u043b\u044e\u0431\u043e\u043c \u044f\u0437\u044b\u043a\u0435.",
"DashboardTourPlugins": "\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043a\u0430\u043d\u0430\u043b\u043e\u0432 \u0432\u0438\u0434\u0435\u043e, \u0422\u0412-\u044d\u0444\u0438\u0440\u0430, \u0441\u043a\u0430\u043d\u043d\u0435\u0440\u043e\u0432 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442.\u043f.",
"DashboardTourNotifications": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043e \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u0445 \u043d\u0430 \u0432\u0430\u0448\u0435 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430, \u044d-\u043f\u043e\u0447\u0442\u0443 \u0438 \u0442.\u043f.",
@@ -693,7 +702,7 @@
"DeleteDeviceConfirmation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e? \u041e\u043d\u043e \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0441\u043d\u043e\u0432\u0430 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u043e\u0439\u0434\u0451\u0442 \u0441 \u043d\u0435\u0433\u043e.",
"LabelEnableCameraUploadFor": "\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u044f \u0441 \u043a\u0430\u043c\u0435\u0440\u044b \u0434\u043b\u044f:",
"HeaderSelectUploadPath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c\u043e\u0433\u043e",
- "LabelEnableCameraUploadForHelp": "\u0412\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0443\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435, \u043f\u0440\u0438 \u0432\u0445\u043e\u0434\u0435 \u0432 Emby.",
+ "LabelEnableCameraUploadForHelp": "\u0412\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0443\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u043e \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435, \u043f\u0440\u0438 \u0432\u0445\u043e\u0434\u0435 \u0432 Emby.",
"ErrorMessageStartHourGreaterThanEnd": "\u041a\u043e\u043d\u0435\u0447\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043f\u043e\u0437\u0436\u0435, \u0447\u0435\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f.",
"ButtonLibraryAccess": "\u041a \u0434\u043e\u0441\u0442\u0443\u043f\u0443 \u043a \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435",
"ButtonParentalControl": "\u041a \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c",
@@ -719,7 +728,7 @@
"ButtonLinkMyEmbyAccount": "\u0421\u0432\u044f\u0437\u0430\u0442\u044c \u043c\u043e\u044e \u0443\u0447\u0451\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c",
"MessageConnectAccountRequiredToInviteGuest": "\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u0433\u043b\u0430\u0448\u0430\u0442\u044c \u0433\u043e\u0441\u0442\u0435\u0439, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u0432\u0430\u0448\u0443 \u0443\u0447\u0451\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c Emby \u0441 \u0434\u0430\u043d\u043d\u044b\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c.",
"ButtonSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c",
- "SyncMedia": "\u0421\u0438\u043d\u0445\u0440-\u0438\u044f",
+ "SyncMedia": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f",
"HeaderCancelSyncJob": "\u041e\u0442\u043c\u0435\u043d\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438",
"CancelSyncJobConfirmation": "\u041e\u0442\u043c\u0435\u043d\u0430 \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438. \u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c?",
"TabSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f",
@@ -741,10 +750,10 @@
"SyncJobItemStatusQueued": "\u0412 \u043e\u0447\u0435\u0440\u0435\u0434\u0438",
"SyncJobItemStatusConverting": "\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044f",
"SyncJobItemStatusTransferring": "\u041f\u0435\u0440\u0435\u0432\u043e\u0434\u0438\u0442\u0441\u044f",
- "SyncJobItemStatusSynced": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043e",
+ "SyncJobItemStatusSynced": "\u0421\u0438\u043d\u0445\u0440-\u043d\u043e",
"SyncJobItemStatusFailed": "\u041d\u0435\u0443\u0434\u0430\u0447\u043d\u043e",
"SyncJobItemStatusRemovedFromDevice": "\u0418\u0437\u044a\u044f\u0442\u043e \u0438\u0437 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430",
"SyncJobItemStatusCancelled": "\u041e\u0442\u043c\u0435\u043d\u0435\u043d\u043e",
"LabelProfile": "\u041f\u0440\u043e\u0444\u0438\u043b\u044c:",
- "LabelBitrateMbps": "\u041f\u043e\u0442\u043e\u043a\u043e\u0432\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c (\u041c\u0431\u0438\u0442\/\u0441):"
+ "LabelBitrateMbps": "\u041f\u043e\u0442\u043e\u043a\u043e\u0432\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c, \u041c\u0431\u0438\u0442\/\u0441:"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/sl_SI.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/sl_SI.json
index 16df937c9..0dd275cd5 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/sl_SI.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/sl_SI.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json
index 458890307..182d21653 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Bekr\u00e4ftelse",
"MessageKeyUpdated": "Tack. Din donationskod har uppdaterats.",
"MessageKeyRemoved": "Tack. Din donationskod har raderats.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live-TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donera",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "Det gick inte att starta Chromecast. Kontrollera att enheten \u00e4r ansluten till det tr\u00e5dl\u00f6sa n\u00e4tverket.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Gratis",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "V\u00e4lj ljudsp\u00e5r",
@@ -174,6 +179,9 @@
"OptionThursday": "Torsdag",
"OptionFriday": "Fredag",
"OptionSaturday": "L\u00f6rdag",
+ "OptionEveryday": "Varje dag",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Bekr\u00e4fta radering",
"MessageConfirmPathSubstitutionDeletion": "Vill du verkligen ta bort detta s\u00f6kv\u00e4gsutbyte?",
"LiveTvUpdateAvailable": "(Uppdatering tillg\u00e4nglig)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Dela upp media",
"MessageConfirmSplitMedia": "\u00c4r du s\u00e4ker p\u00e5 att du vill dela upp dessa media i separata objekt?",
"HeaderError": "Fel",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Var god v\u00e4lj minst ett objekt.",
"MessagePleaseSelectTwoItems": "Var god v\u00e4lj minst tv\u00e5 objekt.",
"MessageTheFollowingItemsWillBeGrouped": "F\u00f6ljande titlar kommer att grupperas till ett enda objekt:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json
index 2e2f58a77..f52e9a425 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Canl\u0131 TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Per\u015fembe",
"OptionFriday": "Cuma",
"OptionSaturday": "Cumartesi",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/uk.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/uk.json
index 9a8f4b57a..b15a0005f 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/uk.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/uk.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "\u041f\u043e\u0432\u0456\u0434\u043e\u043c\u043b\u0435\u043d\u043d\u044f",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json
index 71e353329..b449590a6 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "Live TV",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Th\u1ee9 B\u1ea3y",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json
index bfa2b3e24..2a29a8f49 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "\u786e\u8ba4",
"MessageKeyUpdated": "\u8c22\u8c22\u3002\u4f60\u7684\u652f\u6301\u8005\u5e8f\u53f7\u5df2\u66f4\u65b0\u3002",
"MessageKeyRemoved": "\u8c22\u8c22\u3002\u4f60\u7684\u652f\u6301\u8005\u5e8f\u53f7\u5df2\u79fb\u9664\u3002",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "\u4eab\u53d7\u5956\u52b1\u529f\u80fd",
"TitleLiveTV": "\u7535\u89c6\u76f4\u64ad",
"TitleSync": "\u540c\u6b65",
+ "ButtonDonate": "\u6350\u8d60",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "\u901a\u77e5",
"ErrorLaunchingChromecast": "\u542f\u52a8chromecast\u9047\u5230\u9519\u8bef\uff0c\u8bf7\u786e\u8ba4\u8bbe\u5907\u5df2\u7ecf\u8fde\u63a5\u5230\u4f60\u7684\u65e0\u7ebf\u7f51\u7edc\u3002",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "\u514d\u8d39",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "\u9009\u62e9\u97f3\u9891",
@@ -174,6 +179,9 @@
"OptionThursday": "\u661f\u671f\u56db",
"OptionFriday": "\u661f\u671f\u4e94",
"OptionSaturday": "\u661f\u671f\u516d",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "\u786e\u8ba4\u5220\u9664",
"MessageConfirmPathSubstitutionDeletion": "\u4f60\u786e\u5b9a\u5e0c\u671b\u5220\u9664\u6b64\u8def\u5f84\u66ff\u4ee3\uff1f",
"LiveTvUpdateAvailable": "(\u66f4\u65b0\u53ef\u7528)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "\u62c6\u5206\u5a92\u4f53",
"MessageConfirmSplitMedia": "\u60a8\u786e\u5b9a\u8981\u628a\u5a92\u4f53\u6e90\u62c6\u5206\u4e3a\u5355\u72ec\u7684\u9879\u76ee\uff1f",
"HeaderError": "\u9519\u8bef",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "\u8bf7\u81f3\u5c11\u9009\u62e9\u4e00\u4e2a\u9879\u76ee\u3002",
"MessagePleaseSelectTwoItems": "\u8bf7\u81f3\u5c11\u9009\u62e92\u4e2a\u9879\u76ee\u3002",
"MessageTheFollowingItemsWillBeGrouped": "\u4ee5\u4e0b\u6807\u9898\u5c06\u88ab\u5f52\u5165\u4e00\u4e2a\u9879\u76ee\uff1a",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json
index 68437bb68..bdd3b6cf6 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json
@@ -35,8 +35,13 @@
"HeaderConfirmation": "Confirmation",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "HeaderSupportTheTeam": "Support the Emby Team",
+ "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"TitleLiveTV": "\u96fb\u8996\u529f\u80fd",
"TitleSync": "Sync",
+ "ButtonDonate": "Donate",
+ "HeaderMyMedia": "My Media",
+ "TitleNotifications": "Notifications",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
"MessageErrorLoadingSupporterInfo": "There was an error loading supporter information. Please try again later.",
"MessageLinkYourSupporterKey": "Link your supporter key with up to {0} Emby Connect members to enjoy free access to the following apps:",
@@ -118,7 +123,7 @@
"LabelFree": "Free",
"HeaderPlaybackError": "Playback Error",
"MessagePlaybackErrorNotAllowed": "You're currently not authorized to play this content. Please contact your system administrator for details.",
- "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later.",
+ "MessagePlaybackErrorNoCompatibleStream": "No compatible streams are currently available. Please try again later or contact your system administrator for details.",
"MessagePlaybackErrorRateLimitExceeded": "Your playback rate limit has been exceeded. Please contact your system administrator for details.",
"MessagePlaybackErrorPlaceHolder": "The content chosen is not playable from this device.",
"HeaderSelectAudio": "Select Audio",
@@ -174,6 +179,9 @@
"OptionThursday": "\u661f\u671f\u56db",
"OptionFriday": "\u661f\u671f\u4e94",
"OptionSaturday": "\u661f\u671f\u516d",
+ "OptionEveryday": "Every day",
+ "OptionWeekend": "Weekends",
+ "OptionWeekday": "Weekdays",
"HeaderConfirmDeletion": "Confirm Deletion",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
"LiveTvUpdateAvailable": "(Update available)",
@@ -191,6 +199,7 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
+ "MessageChromecastConnectionError": "Your Chromecast receiver is unable to connect to your Emby Server. Please check their connections and try again.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ar.json b/MediaBrowser.Server.Implementations/Localization/Server/ar.json
index 61aaea0f8..38179123b 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ar.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ar.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "\u0645\u0648\u0627\u0641\u0642",
"ButtonCancel": "\u0627\u0644\u063a\u0627\u0621",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "\u0644\u0627 \u0634\u0649\u0621 \u0647\u0646\u0627.",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"TabSuggested": "\u0645\u0642\u062a\u0631\u062d",
+ "TabSuggestions": "Suggestions",
"TabLatest": "\u0627\u0644\u0627\u062e\u064a\u0631",
"TabUpcoming": "\u0627\u0644\u0642\u0627\u062f\u0645",
"TabShows": "\u0627\u0644\u0645\u0633\u0644\u0633\u0644\u0627\u062a",
@@ -401,9 +404,10 @@
"ButtonRefresh": "Refresh",
"ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnAllChannels": "Record on all channels",
+ "OptionRecordAnytime": "Record at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/bg_BG.json b/MediaBrowser.Server.Implementations/Localization/Server/bg_BG.json
index 5831f3d10..a40e1520c 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/bg_BG.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/bg_BG.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "\u0417\u0430 \u0434\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b \u043a\u043e\u0439\u0442\u043e \u043d\u0435 \u0435 \u0432 \u043b\u0438\u0441\u0442\u0438\u0442\u0435, \u0449\u0435 \u0442\u0440\u044f\u0431\u0432\u0430 \u043f\u044a\u0440\u0432\u043e \u0434\u0430 \u0437\u0430\u043a\u0430\u0447\u0438\u0442\u0435 \u0442\u0435\u0445\u043d\u0438\u044f \u043f\u0440\u043e\u0444\u0438\u043b \u043a\u044a\u043c Emby Connect \u043e\u0442 \u0442\u044f\u0445\u043d\u0430\u0442\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "\u041e\u043a",
"ButtonCancel": "\u041e\u0442\u043c\u0435\u043d\u0438",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "\u0422\u0443\u043a \u043d\u044f\u043c\u0430 \u043d\u0438\u0449\u043e.",
"MessagePleaseEnsureInternetMetadata": "\u041c\u043e\u043b\u044f, \u0443\u0432\u0435\u0440\u0435\u0442\u0435 \u0441\u0435 \u0447\u0435 \u0441\u0432\u0430\u043b\u044f\u043d\u0435\u0442\u043e \u043d\u0430 \u043c\u0435\u0442\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u043e.",
"TabSuggested": "\u041f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f",
+ "TabSuggestions": "Suggestions",
"TabLatest": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438",
"TabUpcoming": "\u041f\u0440\u0435\u0434\u0441\u0442\u043e\u044f\u0449\u0438",
"TabShows": "\u041f\u0440\u0435\u0434\u0430\u0432\u0430\u043d\u0438\u044f",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "\u0417\u0430\u043f\u0438\u0441\u0432\u0430\u0439 \u043f\u0440\u0435\u0434\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0432\u0441\u0438\u0447\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u0438",
"OptionRecordAnytime": "\u0417\u0430\u043f\u0438\u0441\u0432\u0430\u0439 \u043f\u0440\u0435\u0434\u0430\u0432\u0430\u043d\u0435\u0442\u043e \u043f\u043e \u0432\u0441\u044f\u043a\u043e \u0432\u0440\u0435\u043c\u0435",
"OptionRecordOnlyNewEpisodes": "\u0417\u0430\u043f\u0438\u0441\u0432\u0430\u0439 \u0441\u0430\u043c\u043e \u043d\u043e\u0432\u0438 \u0435\u043f\u0438\u0437\u043e\u0434\u0438",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "\u0414\u043d\u0438",
"HeaderActiveRecordings": "\u0410\u043a\u0442\u0438\u0432\u043d\u0438 \u0417\u0430\u043f\u0438\u0441\u0438",
"HeaderLatestRecordings": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0417\u0430\u043f\u0438\u0441\u0438",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "TCP \u043f\u043e\u0440\u0442\u044a\u0442 \u043d\u0430 \u043a\u043e\u0439\u0442\u043e HTTPS \u0441\u044a\u0440\u0432\u044a\u0440\u044a\u0442 \u043d\u0430 Emby \u0442\u0440\u044f\u0431\u0432\u0430 \u0434\u0430 \u0441\u0435 \u0437\u0430\u043a\u0430\u0447\u0438.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ca.json b/MediaBrowser.Server.Implementations/Localization/Server/ca.json
index 65f8df592..7845573fa 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ca.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ca.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nothing here.",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"TabSuggested": "Suggested",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Latest",
"TabUpcoming": "Upcoming",
"TabShows": "Shows",
@@ -401,9 +404,10 @@
"ButtonRefresh": "Refresh",
"ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnAllChannels": "Record on all channels",
+ "OptionRecordAnytime": "Record at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/cs.json b/MediaBrowser.Server.Implementations/Localization/Server/cs.json
index 8d9ccff49..da5f5c9c4 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/cs.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/cs.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Zru\u0161it",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Tady nic nen\u00ed.",
"MessagePleaseEnsureInternetMetadata": "Pros\u00edm zkontrolujte, zda m\u00e1te povoleno stahov\u00e1n\u00ed metadat z internetu.",
"TabSuggested": "Doporu\u010den\u00e9",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Posledn\u00ed",
"TabUpcoming": "Nadch\u00e1zej\u00edc\u00ed",
"TabShows": "Seri\u00e1ly",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Nahr\u00e1vat program na v\u0161ech kan\u00e1lech",
"OptionRecordAnytime": "Nahr\u00e1vat program v jak\u00fdkoliv \u010das",
"OptionRecordOnlyNewEpisodes": "Nahr\u00e1vat pouze nov\u00e9 epizody",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Dny",
"HeaderActiveRecordings": "Aktivn\u00ed nahr\u00e1v\u00e1n\u00ed",
"HeaderLatestRecordings": "Posledn\u00ed nahr\u00e1v\u00e1n\u00ed",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "\u010c\u00edslo portu web socketu:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Pokra\u010dovat",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Nejsledovan\u011bj\u0161\u00ed",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/da.json b/MediaBrowser.Server.Implementations/Localization/Server/da.json
index 0dda45289..82bf80c7f 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/da.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/da.json
@@ -4,7 +4,7 @@
"LabelGithub": "Github",
"LabelSwagger": "Swagger",
"LabelStandard": "Standard",
- "LabelApiDocumentation": "Api Documentation",
+ "LabelApiDocumentation": "Api dokumentation",
"LabelDeveloperResources": "Developer Resources",
"LabelBrowseLibrary": "Gennemse biblitek",
"LabelConfigureServer": "Configure Emby",
@@ -15,7 +15,7 @@
"LabelFinish": "Slut",
"LabelNext": "N\u00e6ste",
"LabelYoureDone": "Du er f\u00e6rdig!",
- "WelcomeToProject": "Welcome to Emby!",
+ "WelcomeToProject": "Velkommen til Emby!",
"ThisWizardWillGuideYou": "Denne guide vil hj\u00e6lpe dig igennem ops\u00e6tningen. For at begynde, venligst v\u00e6lg dit fortrukne sprog.",
"TellUsAboutYourself": "Fort\u00e6l os lidt om dig selv",
"ButtonQuickStartGuide": "Quick start guide",
@@ -49,17 +49,19 @@
"ButtonOrganize": "Organize",
"LinkedToEmbyConnect": "Linked to Emby Connect",
"HeaderSupporterBenefits": "Supporter Benefits",
- "HeaderAddUser": "Add User",
+ "HeaderAddUser": "Tilf\u00f8j bruger",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
- "LabelPinCode": "Pin code:",
+ "LabelPinCode": "Pin kode:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Annuller",
- "ButtonExit": "Exit",
+ "ButtonExit": "Afslut",
"ButtonNew": "Ny",
"HeaderTV": "TV",
"HeaderAudio": "Audio",
"HeaderVideo": "Video",
- "HeaderPaths": "Paths",
+ "HeaderPaths": "Stier",
"CategorySync": "Sync",
"TabPlaylist": "Playlist",
"HeaderEasyPinCode": "Easy Pin Code",
@@ -80,23 +82,23 @@
"LabelCustomCertificatePath": "Custom certificate path:",
"LabelCustomCertificatePathHelp": "Supply your own ssl certificate .pfx file. If omitted, the server will create a self-signed certificate.",
"TitleNotifications": "Notifications",
- "ButtonDonateWithPayPal": "Donate with PayPal",
+ "ButtonDonateWithPayPal": "Doner via PayPal",
"OptionDetectArchiveFilesAsMedia": "Detect archive files as media",
"OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.",
- "LabelEnterConnectUserName": "User name or email:",
+ "LabelEnterConnectUserName": "Brugernavn eller e-mail:",
"LabelEnterConnectUserNameHelp": "This is your Emby online account user name or password.",
"LabelEnableEnhancedMovies": "Enable enhanced movie displays",
"LabelEnableEnhancedMoviesHelp": "When enabled, movies will be displayed as folders to include trailers, extras, cast & crew, and other related content.",
"HeaderSyncJobInfo": "Sync Job",
"FolderTypeMixed": "Mixed content",
- "FolderTypeMovies": "Movies",
- "FolderTypeMusic": "Music",
- "FolderTypeAdultVideos": "Adult videos",
- "FolderTypePhotos": "Photos",
- "FolderTypeMusicVideos": "Music videos",
- "FolderTypeHomeVideos": "Home videos",
- "FolderTypeGames": "Games",
- "FolderTypeBooks": "Books",
+ "FolderTypeMovies": "FIlm",
+ "FolderTypeMusic": "Musik",
+ "FolderTypeAdultVideos": "Voksenfilm",
+ "FolderTypePhotos": "Fotos",
+ "FolderTypeMusicVideos": "Musikvideoer",
+ "FolderTypeHomeVideos": "Hjemmevideoer",
+ "FolderTypeGames": "Spil",
+ "FolderTypeBooks": "B\u00f8ger",
"FolderTypeTvShows": "TV",
"FolderTypeInherit": "Inherit",
"LabelContentType": "Content type:",
@@ -122,7 +124,7 @@
"TabProfile": "Profil",
"TabMetadata": "Metadata",
"TabImages": "Billeder",
- "TabNotifications": "Notifications",
+ "TabNotifications": "Notifikationer",
"TabCollectionTitles": "Titler",
"HeaderDeviceAccess": "Device Access",
"OptionEnableAccessFromAllDevices": "Enable access from all devices",
@@ -146,8 +148,8 @@
"TabProfiles": "Profiler",
"TabSecurity": "Sikkerhed",
"ButtonAddUser": "Tilf\u00f8j bruger",
- "ButtonAddLocalUser": "Add Local User",
- "ButtonInviteUser": "Invite User",
+ "ButtonAddLocalUser": "Tilf\u00f8j lokal bruger",
+ "ButtonInviteUser": "Inviter bruger",
"ButtonSave": "Gem",
"ButtonResetPassword": "Nulstil kode",
"LabelNewPassword": "Ny kode:",
@@ -159,7 +161,7 @@
"LibraryAccessHelp": "V\u00e6lg hvilke medie mapper der skal deles med denne bruger. Administratorer vil kunne redigere alle mapper ved hj\u00e6lp af metadata administratoren.",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
"ButtonDeleteImage": "Slet Billede",
- "LabelSelectUsers": "Select users:",
+ "LabelSelectUsers": "V\u00e6lg brugere:",
"ButtonUpload": "Upload",
"HeaderUploadNewImage": "Upload Nyt Billede",
"LabelDropImageHere": "Drop image here",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Her er ingenting.",
"MessagePleaseEnsureInternetMetadata": "V\u00e6r venligst sikker p\u00e5 at hentning af internet metadata er aktiveret.",
"TabSuggested": "Foresl\u00e5et",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Seneste",
"TabUpcoming": "Kommende",
"TabShows": "Shows",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Optag program p\u00e5 alle kanaler",
"OptionRecordAnytime": "Optag program uanset tidpunkt",
"OptionRecordOnlyNewEpisodes": "Optag kun nye episoder",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Dage",
"HeaderActiveRecordings": "Aktive Optagelser",
"HeaderLatestRecordings": "Seneste Optagelse",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/de.json b/MediaBrowser.Server.Implementations/Localization/Server/de.json
index d69bede29..0e560651a 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/de.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/de.json
@@ -29,7 +29,7 @@
"WizardCompleted": "Das ist alles was wir bis jetzt brauchen. Emby hat nun angefangen Informationen \u00fcber Ihre Medienbibliothek zu sammeln. Schauen Sie sich ein paar unserer Apps an, dann Klicken Sie auf <b>Fertig<\/b> um das <b>Server Dashboard<\/b> anzuzeigen.",
"LabelConfigureSettings": "Konfiguriere Einstellungen",
"LabelEnableVideoImageExtraction": "Aktiviere Videobild-Extrahierung",
- "VideoImageExtractionHelp": "F\u00fcr Videos die noch keien Bilder haben, und f\u00fcr die wir keine Internetbilder finden k\u00f6nnen. Hierdurch wird der erste Bibliothekenscan etwas mehr Zeit beanspruchen, f\u00fchrt aber zu einer ansprechenderen Pr\u00e4sentation.",
+ "VideoImageExtractionHelp": "F\u00fcr Videos die noch keinen Bilder haben, und f\u00fcr die wir keine Internetbilder finden k\u00f6nnen. Hierdurch wird der erste Bibliotheken scan etwas mehr Zeit beanspruchen, f\u00fchrt aber zu einer ansprechenderen Pr\u00e4sentation.",
"LabelEnableChapterImageExtractionForMovies": "Extrahiere Kapitelbilder f\u00fcr Filme",
"LabelChapterImageExtractionForMoviesHelp": "Das Extrahieren von Kapitel-Bildern erm\u00f6glicht es den Clients eine grafische Szenenauswahl anzubieten. Das Erstellen ist recht langsam, rechenintensiv und erfordert einige Gigabyte an freien Speicherplatz. Diese Aufgabe startet jede Nacht, das kann aber in den geplanten Aufgaben ge\u00e4ndert werden. Es wird nicht empfohlen diese Aufgabe in Zeiten hoher Server-Auslastung zu starten.",
"LabelEnableAutomaticPortMapping": "Aktiviere automatische Portweiterleitung",
@@ -52,6 +52,8 @@
"HeaderAddUser": "Benutzer hinzuf\u00fcgen",
"LabelAddConnectSupporterHelp": "Um einen Benutzer hinzuzuf\u00fcgen, der nicht angezeigt wird, m\u00fcssen Sie diesen erst mit Emby Connect von seinem Benutzerprofil verbinden.",
"LabelPinCode": "PIN Code:",
+ "OptionHideWatchedContentFromLatestMedia": "Verberge gesehene Inhalte von zuletzt hinzugef\u00fcgten.",
+ "HeaderSync": "Synchronisiere",
"ButtonOk": "Ok",
"ButtonCancel": "Abbrechen",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nichts hier.",
"MessagePleaseEnsureInternetMetadata": "Bitte sicherstellen, dass das Herunterladen von Internet Metadaten aktiviert ist.",
"TabSuggested": "Vorgeschlagen",
+ "TabSuggestions": "Empfehlungen",
"TabLatest": "Neueste",
"TabUpcoming": "Bevorstehend",
"TabShows": "Serien",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Nehme Programm auf allen Kan\u00e4len auf",
"OptionRecordAnytime": "Neme Programm zu jeder Zeit auf",
"OptionRecordOnlyNewEpisodes": "Nehme nur neue Episoden auf",
+ "HeaderRepeatingOptions": "Wiederholungs Einstellungen",
"HeaderDays": "Tage",
"HeaderActiveRecordings": "Aktive Aufnahmen",
"HeaderLatestRecordings": "Neueste Aufnahmen",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Startseite Bereich 2:",
"LabelHomePageSection3": "Startseite Bereich 3:",
"LabelHomePageSection4": "Startseite Bereich 4:",
- "OptionMyViewsButtons": "Meine Ansichten (Tasten)",
- "OptionMyViews": "Meine Ansichten",
- "OptionMyViewsSmall": "Meine Ansichten (Klein)",
+ "OptionMyMediaButtons": "Meine Medien (Schaltfl\u00e4chen)",
+ "OptionMyMedia": "Meine Medien",
+ "OptionMyMediaSmall": "Meine Medien (Klein)",
"OptionResumablemedia": "Wiederhole",
"OptionLatestMedia": "Neuste Medien",
"OptionLatestChannelMedia": "Neueste Channel Inhalte:",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Meistgesehen",
"TabNextUp": "Als N\u00e4chstes",
+ "PlaceholderUsername": "Benutzername",
"HeaderBecomeProjectSupporter": "Werden Sie Emby Unterst\u00fctzer",
- "TextEnjoyBonusFeatures": "Erleben Sie Bonus Funktionen",
"MessageNoMovieSuggestionsAvailable": "Momentan sind keine Filmvorschl\u00e4ge verf\u00fcgbar. Schaue und bewerte zuerst deine Filme. Komme danach zur\u00fcck, um deine Filmvorschl\u00e4ge anzuschauen.",
"MessageNoCollectionsAvailable": "Sammlungen erlauben Ihnen eine personalisierte Gruppierung von Filmen, Serien, Alben, B\u00fcchern und Spielen. Klicken Sie die + Schaltfl\u00e4che um Sammlungen zu erstellen.",
"MessageNoPlaylistsAvailable": "Wiedergabeliste erlauben es dir eine Liste mit Inhalt zu erstellen der fortlaufend abgespielt wird. Um einer Wiedergabeliste Inhalte hinzuzuf\u00fcgen klicke rechts oder mache einen langen Tap und w\u00e4hle daraufhin \"Zur Wiedergabeliste hinzuf\u00fcgen\" aus.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Lade Internet Metadaten f\u00fcr:",
"OptionTVMovies": "TV Filme",
"HeaderUpcomingMovies": "Bevorstehende Filme",
+ "HeaderUpcomingSports": "Folgende Sportveranstaltungen",
"HeaderUpcomingPrograms": "Bevorstehende Programme",
"ButtonMoreItems": "Mehr...",
"LabelShowLibraryTileNames": "Zeige Bibliothek Kachelnamen.",
"LabelShowLibraryTileNamesHelp": "Legen Sie fest, ob Beschriftungen unter den Kacheln der Startseite angezeigt werden sollen.",
- "OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottle": "aktiviere Drosselung",
+ "OptionEnableTranscodingThrottleHelp": "Die Drosselung justiert die Transkodier-Geschwindigkeit, um die Server CPU Auslastung w\u00e4hrend der Wiedergabe zu minimieren.",
+ "LabelUploadSpeedLimit": "Upload Geschwindigkeitslimit (mbps):",
+ "OptionAllowSyncTranscoding": "Erlaube Synchronisation die Transkodierung ben\u00f6tigen",
+ "HeaderPlayback": "Medien Wiedergabe",
+ "OptionAllowAudioPlaybackTranscoding": "Erlaube Audio-Wiedergabe die Transkodierung ben\u00f6tigt",
+ "OptionAllowVideoPlaybackTranscoding": "Erlaube Video-Wiedergabe die Transkodierung ben\u00f6tigt",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Benutzer erhalten aussagekr\u00e4ftige Fehlermeldungen gem\u00e4\u00df den Einstellungen, wenn Medien nicht wiedergegeben werden k\u00f6nnen.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Limitierte Client-Fernzugriff Datenrate (in mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "Eine optionale Streaming Datengrenze f\u00fcr alle Clients mit Fernzugriff. Dies verhindert, dass Clients eine h\u00f6here Bandbreite als die zur Verf\u00fcgung stehende Verbindung, anfragen.",
+ "LabelConversionCpuCoreLimit": "CPU Kerne Limit:",
+ "LabelConversionCpuCoreLimitHelp": "Begrenzt die Anzahl der verwendeten CPU Kerne w\u00e4hrend der Konvertierung f\u00fcr die Synchronisation.",
+ "OptionEnableFullSpeedConversion": "Aktiviere Hochleistung-Konvertierung.",
+ "OptionEnableFullSpeedConversionHelp": "In der Grundeinstellung wird die Konvertierung f\u00fcr die Synchronisation mit niedriger Geschwindigkeit durchgef\u00fchrt und spart damit System Ressourcen.",
+ "HeaderPlaylists": "Wiedergabeliste",
+ "HeaderSelectDate": "Datum w\u00e4hlen",
+ "HeaderWelcomeExclamation": "Willkommen!",
+ "HeaderMyPreferences": "Meine Einstellungen",
+ "ButtonMyPreferencesWelcomeYes": "Ja, ich m\u00f6chte meine Einstellungen nun festlegen.",
+ "ButtonMyPreferencesWelcomeNo": "Nein danke, das mache ich sp\u00e4ter.",
+ "MyPreferencesWelcomeMessage1": "Wir pr\u00e4sentieren Ihnen Ihre Bibliothek in einer Art, wie wir denken, dass es Ihnen gefallen d\u00fcrfte. Die Darstellung und Gruppierung des Inhaltes kann jederzeit in Ihren Einstellungen angepasst werden. Ihre Einstellungen werden auf alle Empy Apps \u00fcbertragen.",
+ "MyPreferencesWelcomeMessage2": "M\u00f6chten Sie Ihre Einstellungen nun festlegen?",
+ "ToAccessPreferencesHelp": "Um Ihre Einstellungen sp\u00e4ter zu \u00e4ndern, klicken Sie ihr Benutzer-Icon im oberen rechten Bereich oder w\u00e4hlen Sie \"Meine Einstellungen\"."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/el.json b/MediaBrowser.Server.Implementations/Localization/Server/el.json
index 96b67ae6e..2522765ca 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/el.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/el.json
@@ -1,113 +1,115 @@
{
- "LabelExit": "\u03ad\u03be\u03bf\u03b4\u03bf\u03c2",
- "LabelVisitCommunity": "\u0395\u03c0\u03af\u03c3\u03ba\u03b5\u03c8\u03b7 \u039a\u03bf\u03b9\u03bd\u03cc\u03c4\u03b7\u03c4\u03b1",
+ "LabelExit": "\u0388\u03be\u03bf\u03b4\u03bf\u03c2",
+ "LabelVisitCommunity": "\u039a\u03bf\u03b9\u03bd\u03cc\u03c4\u03b7\u03c4\u03b1",
"LabelGithub": "Github",
"LabelSwagger": "Swagger",
- "LabelStandard": "\u03c0\u03c1\u03cc\u03c4\u03c5\u03c0\u03bf",
+ "LabelStandard": "\u03a0\u03c1\u03cc\u03c4\u03c5\u03c0\u03bf",
"LabelApiDocumentation": "Api Documentation",
- "LabelDeveloperResources": "Developer Resources",
- "LabelBrowseLibrary": "\u03c0\u03b5\u03c1\u03b9\u03b7\u03b3\u03b7\u03b8\u03b5\u03af\u03c4\u03b5 \u03c3\u03c4\u03b7 \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7",
- "LabelConfigureServer": "Configure Emby",
+ "LabelDeveloperResources": "\u03a0\u03b7\u03b3\u03ad\u03c2 \u03a0\u03c1\u03bf\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03b9\u03c3\u03c4\u03ae",
+ "LabelBrowseLibrary": "\u03a0\u03b5\u03c1\u03b9\u03b7\u03b3\u03b7\u03b8\u03b5\u03af\u03c4\u03b5 \u03c3\u03c4\u03b7 \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7",
+ "LabelConfigureServer": "\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 Emby",
"LabelOpenLibraryViewer": "\u03b1\u03bd\u03bf\u03af\u03be\u03b5\u03c4\u03b5 \u03c4\u03b7\u03bd \u0392\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7 \u03b8\u03b5\u03b1\u03c4\u03ae",
- "LabelRestartServer": "\u03b5\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03b4\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae",
- "LabelShowLogWindow": "\u0394\u03b5\u03af\u03c7\u03bd\u03bf\u03c5\u03bd \u03c4\u03bf \u03b7\u03bc\u03b5\u03c1\u03bf\u03bb\u03cc\u03b3\u03b9\u03bf \u03c0\u03b1\u03c1\u03ac\u03b8\u03c5\u03c1\u03bf",
+ "LabelRestartServer": "\u0395\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03b4\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae",
+ "LabelShowLogWindow": "\u0391\u03c1\u03c7\u03b5\u03af\u03bf \u039a\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2",
"LabelPrevious": "\u03c0\u03c1\u03bf\u03b7\u03b3\u03bf\u03cd\u03bc\u03b5\u03bd\u03bf\u03c2",
- "LabelFinish": "\u03c4\u03ad\u03bb\u03bf\u03c2",
- "LabelNext": "\u03b5\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf\u03c2 ",
- "LabelYoureDone": "\u03a4\u03b5\u03bb\u03b5\u03b9\u03ce\u03c3\u03b1\u03c4\u03b5",
- "WelcomeToProject": "Welcome to Emby!",
+ "LabelFinish": "\u03a4\u03ad\u03bb\u03bf\u03c2",
+ "LabelNext": "\u0395\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf",
+ "LabelYoureDone": "\u0395\u03af\u03c3\u03c4\u03b5 \u0388\u03c4\u03bf\u03b9\u03bc\u03bf\u03b9!",
+ "WelcomeToProject": "\u039a\u03b1\u03bb\u03c9\u03c2 \u03ae\u03c1\u03b8\u03b1\u03c4\u03b5 \u03c3\u03c4\u03bf Emby!",
"ThisWizardWillGuideYou": "\u0391\u03c5\u03c4\u03cc\u03c2 \u03bf \u03bf\u03b4\u03b7\u03b3\u03cc\u03c2 \u03b8\u03b1 \u03c3\u03b1\u03c2 \u03ba\u03b1\u03b8\u03bf\u03b4\u03b7\u03b3\u03ae\u03c3\u03b5\u03b9 \u03bc\u03ad\u03c3\u03c9 \u03c4\u03b7\u03c2 \u03b4\u03b9\u03b1\u03b4\u03b9\u03ba\u03b1\u03c3\u03af\u03b1\u03c2 \u03b5\u03b3\u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7\u03c2. \u0393\u03b9\u03b1 \u03bd\u03b1 \u03be\u03b5\u03ba\u03b9\u03bd\u03ae\u03c3\u03b5\u03c4\u03b5, \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03b7 \u03b3\u03bb\u03ce\u03c3\u03c3\u03b1 \u03c4\u03b7\u03c2 \u03c0\u03c1\u03bf\u03c4\u03af\u03bc\u03b7\u03c3\u03ae\u03c2 \u03c3\u03b1\u03c2.",
"TellUsAboutYourself": "\u03a0\u03b5\u03af\u03c4\u03b5 \u03bc\u03b1\u03c2 \u03b3\u03b9\u03b1 \u03b5\u03c3\u03ac\u03c2",
- "ButtonQuickStartGuide": "Quick start guide",
+ "ButtonQuickStartGuide": "\u039f\u03b4\u03b7\u03b3\u03cc\u03c2 \u03b3\u03c1\u03ae\u03b3\u03bf\u03c1\u03b7\u03c2 \u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7\u03c2",
"LabelYourFirstName": "\u03a4\u03bf \u03cc\u03bd\u03bf\u03bc\u03ac \u03c3\u03b1\u03c2",
"MoreUsersCanBeAddedLater": "\u03a0\u03b5\u03c1\u03b9\u03c3\u03c3\u03cc\u03c4\u03b5\u03c1\u03bf\u03c5\u03c2 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b5\u03c2 \u03bc\u03c0\u03bf\u03c1\u03bf\u03cd\u03bd \u03bd\u03b1 \u03c0\u03c1\u03bf\u03c3\u03c4\u03b5\u03b8\u03bf\u03cd\u03bd \u03b1\u03c1\u03b3\u03cc\u03c4\u03b5\u03c1\u03b1 \u03bc\u03b5 \u03c4\u03bf \u03c4\u03b1\u03bc\u03c0\u03bb\u03cc",
"UserProfilesIntro": "Emby includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.",
- "LabelWindowsService": "Windows \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 ",
- "AWindowsServiceHasBeenInstalled": "\u039c\u03b9\u03b1 \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 Windows \u03ad\u03c7\u03bf\u03c5\u03bd \u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03b1\u03b8\u03b5\u03af",
- "WindowsServiceIntro1": "Emby Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.",
+ "LabelWindowsService": "\u03a5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 Windows",
+ "AWindowsServiceHasBeenInstalled": "\u039c\u03b9\u03b1 \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 Windows \u03ad\u03c7\u03b5\u03b9 \u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03b1\u03b8\u03b5\u03af",
+ "WindowsServiceIntro1": "\u039f \u0394\u03b9\u03b1\u03c7\u03b5\u03b9\u03c1\u03b9\u03c3\u03c4\u03ae\u03c2 Emby \u03ba\u03b1\u03bd\u03bf\u03bd\u03b9\u03ba\u03ac \u03bb\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03b5\u03af \u03c3\u03b1\u03bd \u03bc\u03b9\u03b1 \u03b5\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae \u03bc\u03b5 \u03b5\u03b9\u03ba\u03bf\u03bd\u03af\u03b4\u03b9\u03bf, \u03b1\u03bb\u03bb\u03ac \u03b1\u03bd \u03c0\u03c1\u03bf\u03c4\u03b9\u03bc\u03ac\u03c4\u03b5 \u03bd\u03b1 \u03bb\u03b5\u03b9\u03c4\u03bf\u03c5\u03c1\u03b3\u03b5\u03af \u03c3\u03b1\u03bd \u03bc\u03b9\u03b1 \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 \u03c3\u03c4\u03bf \u03b2\u03ac\u03b8\u03bf\u03c2, \u03bc\u03c0\u03bf\u03c1\u03b5\u03af \u03bd\u03b1 \u03b5\u03ba\u03ba\u03b9\u03bd\u03b7\u03b8\u03b5\u03af \u03b1\u03c0\u03cc \u03c4\u03bf\u03bd \u03c0\u03af\u03bd\u03b1\u03ba\u03b1 \u03b5\u03bb\u03ad\u03b3\u03c7\u03bf\u03c5 \u03c4\u03c9\u03bd \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03b9\u03ce\u03bd \u03c4\u03c9\u03bd Windows",
"WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.",
"WizardCompleted": "That's all we need for now. Emby has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Server Dashboard<\/b>.",
- "LabelConfigureSettings": "\u03b4\u03b9\u03b1\u03bc\u03bf\u03c1\u03c6\u03ce\u03c3\u03b5\u03c4\u03b5 \u03c4\u03b9\u03c2 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2",
- "LabelEnableVideoImageExtraction": "Enable video image extraction",
- "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.",
- "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
+ "LabelConfigureSettings": "\u0394\u03b9\u03b1\u03bc\u03bf\u03c1\u03c6\u03ce\u03c3\u03b5\u03c4\u03b5 \u03c4\u03b9\u03c2 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2",
+ "LabelEnableVideoImageExtraction": "\u0395\u03be\u03b1\u03b3\u03c9\u03b3\u03ae \u0395\u03b9\u03ba\u03cc\u03bd\u03b1\u03c2 \u03b1\u03c0\u03cc \u0392\u03af\u03bd\u03c4\u03b5\u03bf",
+ "VideoImageExtractionHelp": "\u0393\u03b9\u03b1 \u03c4\u03b1 \u03b2\u03af\u03bd\u03c4\u03b5\u03bf \u03c0\u03bf\u03c5 \u03b4\u03b5\u03bd \u03ad\u03c7\u03bf\u03c5\u03bd \u03ae\u03b4\u03b7 \u03b5\u03b9\u03ba\u03cc\u03bd\u03b5\u03c2, \u03ba\u03b1\u03b9 \u03b4\u03b5\u03bd \u03bc\u03c0\u03bf\u03c1\u03ad\u03c3\u03b1\u03bc\u03b5 \u03bd\u03b1 \u03b2\u03c1\u03bf\u03cd\u03bc\u03b5 \u03c3\u03c4\u03bf \u03b4\u03b9\u03b1\u03b4\u03af\u03ba\u03c4\u03c5\u03bf. \u0391\u03c5\u03c4\u03cc \u03b8\u03b1 \u03ba\u03b1\u03b8\u03c5\u03c3\u03c4\u03b5\u03c1\u03ae\u03c3\u03b5\u03b9 \u03bb\u03af\u03b3\u03bf \u03c4\u03b7\u03bd \u03b1\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b7 \u03c3\u03c4\u03b7\u03bd \u03b1\u03c1\u03c7\u03b9\u03ba\u03ae \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7 \u03b1\u03bb\u03bb\u03b1 \u03b8\u03b1 \u03b5\u03af\u03bd\u03b1\u03b9 \u03b7 \u03c4\u03b5\u03bb\u03b9\u03ba\u03ae \u03bc\u03bf\u03c1\u03c6\u03ae \u03c0\u03b9\u03bf \u03cc\u03bc\u03bf\u03c1\u03c6\u03b7.",
+ "LabelEnableChapterImageExtractionForMovies": "\u0395\u03be\u03b1\u03b3\u03c9\u03b3\u03ae \u0395\u03b9\u03ba\u03cc\u03bd\u03b1\u03c2 \u039a\u03b5\u03c6\u03b1\u03bb\u03bb\u03b1\u03af\u03c9\u03bd \u03b3\u03b9\u03b1 \u03c4\u03b9\u03c2 \u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2",
"LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
- "LabelEnableAutomaticPortMapping": "\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03bb\u03b9\u03bc\u03ac\u03bd\u03b9 \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b7 \u03c7\u03b1\u03c1\u03c4\u03bf\u03b3\u03c1\u03ac\u03c6\u03b7\u03c3\u03b7",
- "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "LabelEnableAutomaticPortMapping": "\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03c4\u03b7\u03c2 \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b7\u03c2 \u03ba\u03b1\u03c4\u03b1\u03c7\u03ce\u03c1\u03b7\u03c3\u03b7\u03c2 \u0398\u03c5\u03c1\u03ce\u03bd",
+ "LabelEnableAutomaticPortMappingHelp": "To UPnP \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03b5\u03b9 \u03c4\u03b7\u03bd \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b7 \u03c1\u03cd\u03b8\u03bc\u03b9\u03c3\u03b7 \u03c4\u03bf\u03c5 \u03b4\u03c1\u03bf\u03bc\u03bf\u03bb\u03bf\u03b3\u03b7\u03c4\u03ae \u03b3\u03b9\u03b1 \u03b5\u03cd\u03ba\u03bf\u03bb\u03b7 \u03b1\u03c0\u03bf\u03bc\u03b1\u03ba\u03c1\u03c5\u03c3\u03bc\u03ad\u03bd\u03b7 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7. \u0391\u03c5\u03c4\u03ae \u03b7 \u03c1\u03cd\u03b8\u03bc\u03b9\u03c3\u03b7 \u03bc\u03c0\u03bf\u03c1\u03b5\u03af \u03bd\u03b1 \u03bc\u03b7\u03bd \u03b4\u03bf\u03c5\u03bb\u03ad\u03c8\u03b5\u03b9 \u03bc\u03b5 \u03ba\u03ac\u03c0\u03bf\u03b9\u03b1 \u03bc\u03bf\u03bd\u03c4\u03ad\u03bb\u03b1 \u03b4\u03c1\u03bf\u03bc\u03bf\u03bb\u03bf\u03b3\u03b7\u03c4\u03ce\u03bd",
"HeaderTermsOfService": "Emby Terms of Service",
- "MessagePleaseAcceptTermsOfService": "Please accept the terms of service and privacy policy before continuing.",
- "OptionIAcceptTermsOfService": "I accept the terms of service",
- "ButtonPrivacyPolicy": "Privacy policy",
- "ButtonTermsOfService": "Terms of Service",
+ "MessagePleaseAcceptTermsOfService": "\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03ce \u03b1\u03c0\u03bf\u03b4\u03b5\u03c7\u03c4\u03b5\u03af\u03c4\u03b5 \u03c4\u03bf\u03c5\u03c2 \u038c\u03c1\u03bf\u03c5\u03c2 \u03a7\u03c1\u03ae\u03c3\u03b7\u03c2 \u03ba\u03b1\u03b9 \u03a0\u03c1\u03bf\u03c3\u03c4\u03b1\u03c3\u03af\u03b1\u03c2 \u0394\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd \u03c0\u03c1\u03b9\u03bd \u03c0\u03c1\u03bf\u03c7\u03c9\u03c1\u03ae\u03c3\u03b5\u03c4\u03b5.",
+ "OptionIAcceptTermsOfService": "\u0391\u03c0\u03cc\u03b4\u03b5\u03c7\u03bf\u03bc\u03b1\u03b9 \u03c4\u03bf\u03c5\u03c2 \u038c\u03c1\u03bf\u03c5\u03c2 \u03a7\u03c1\u03ae\u03c3\u03b7\u03c2",
+ "ButtonPrivacyPolicy": "\u03a0\u03c1\u03bf\u03c3\u03c4\u03b1\u03c3\u03af\u03b1 \u0394\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd",
+ "ButtonTermsOfService": "\u038c\u03c1\u03bf\u03b9 \u03a7\u03c1\u03ae\u03c3\u03b7\u03c2",
"HeaderDeveloperOptions": "Developer Options",
- "OptionEnableWebClientResponseCache": "Enable web client response caching",
+ "OptionEnableWebClientResponseCache": "Ene",
"OptionDisableForDevelopmentHelp": "Configure these as needed for web client development purposes.",
"OptionEnableWebClientResourceMinification": "Enable web client resource minification",
"LabelDashboardSourcePath": "Web client source path:",
"LabelDashboardSourcePathHelp": "If running the server from source, specify the path to the dashboard-ui folder. All web client files will be served from this location.",
"ButtonConvertMedia": "Convert media",
- "ButtonOrganize": "Organize",
+ "ButtonOrganize": "\u039f\u03c1\u03b3\u03ac\u03bd\u03c9\u03c3\u03b7",
"LinkedToEmbyConnect": "Linked to Emby Connect",
"HeaderSupporterBenefits": "Supporter Benefits",
- "HeaderAddUser": "Add User",
+ "HeaderAddUser": "\u03a0\u03c1\u03bf\u03c3\u03b8\u03ae\u03ba\u03b7 \u03a7\u03c1\u03ae\u03c3\u03c4\u03b7",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
- "ButtonOk": "\u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
+ "ButtonOk": "\u0395\u03bd\u03c4\u03ac\u03be\u03b5\u03b9",
"ButtonCancel": "\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7 ",
- "ButtonExit": "Exit",
- "ButtonNew": "New",
- "HeaderTV": "TV",
- "HeaderAudio": "Audio",
- "HeaderVideo": "Video",
- "HeaderPaths": "Paths",
- "CategorySync": "Sync",
- "TabPlaylist": "Playlist",
+ "ButtonExit": "\u0388\u03be\u03bf\u03b4\u03bf\u03c2",
+ "ButtonNew": "\u039d\u03ad\u03bf",
+ "HeaderTV": "\u03a4\u03b7\u03bb\u03b5\u03cc\u03c1\u03b1\u03c3\u03b7",
+ "HeaderAudio": "\u0389\u03c7\u03bf\u03c2",
+ "HeaderVideo": "\u0392\u03af\u03bd\u03c4\u03b5\u03bf",
+ "HeaderPaths": "\u0394\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae",
+ "CategorySync": "\u03a3\u03c5\u03c7\u03c1\u03bf\u03bd\u03b9\u03c3\u03bc\u03cc\u03c2",
+ "TabPlaylist": "\u039b\u03af\u03c3\u03c4\u03b1",
"HeaderEasyPinCode": "Easy Pin Code",
- "HeaderGrownupsOnly": "Grown-ups Only!",
- "DividerOr": "-- or --",
- "HeaderInstalledServices": "Installed Services",
- "HeaderAvailableServices": "Available Services",
- "MessageNoServicesInstalled": "No services are currently installed.",
- "HeaderToAccessPleaseEnterEasyPinCode": "To access, please enter your easy pin code",
+ "HeaderGrownupsOnly": "\u0395\u03bd\u03ae\u03bb\u03b9\u03ba\u03bf\u03b9 \u03bc\u03cc\u03bd\u03bf!",
+ "DividerOr": "--\u03ae--",
+ "HeaderInstalledServices": "\u0395\u03b3\u03ba\u03b1\u03c4\u03b5\u03c3\u03c4\u03b7\u03bc\u03ad\u03bd\u03b5\u03c2 \u03a5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b5\u03c2",
+ "HeaderAvailableServices": "\u0394\u03b9\u03b1\u03b8\u03ad\u03c3\u03b9\u03bc\u03b5\u03c2 \u03a5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b5\u03c2",
+ "MessageNoServicesInstalled": "\u039a\u03b1\u03bc\u03af\u03b1 \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 \u03b4\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b5\u03b3\u03ba\u03b1\u03c4\u03b5\u03c3\u03c4\u03b7\u03bc\u03ad\u03bd\u03b7.",
+ "HeaderToAccessPleaseEnterEasyPinCode": "\u0393\u03b9\u03b1 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7, \u03c0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03ce \u03b4\u03ce\u03c3\u03c4\u03b5 \u03c4\u03bf\u03bd \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c3\u03b1\u03c2",
"KidsModeAdultInstruction": "Click the lock icon in the bottom right to configure or leave kids mode. Your pin code will be required.",
"ButtonConfigurePinCode": "Configure pin code",
- "HeaderAdultsReadHere": "Adults Read Here!",
- "RegisterWithPayPal": "Register with PayPal",
+ "HeaderAdultsReadHere": "\u039f\u03b9 \u03b5\u03bd\u03ae\u03bb\u03b9\u03ba\u03bf\u03b9 \u03b4\u03b9\u03b1\u03b2\u03ac\u03c3\u03c4\u03b5!",
+ "RegisterWithPayPal": "\u0395\u03b3\u03b3\u03c1\u03b1\u03c6\u03ae \u03bc\u03b5 Paypal",
"HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership",
- "HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial",
- "LabelSyncTempPath": "Temporary file path:",
+ "HeaderEnjoyDayTrial": "\u0391\u03c0\u03bf\u03bb\u03b1\u03cd\u03c3\u03c4\u03b5 14 \u039c\u03ad\u03c1\u03b5\u03c2 \u0394\u03bf\u03ba\u03b9\u03bc\u03b1\u03c3\u03c4\u03b9\u03ba\u03ae\u03c2 \u03a0\u03b5\u03c1\u03b9\u03cc\u03b4\u03bf\u03c5",
+ "LabelSyncTempPath": "\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03c2 \u03a0\u03c1\u03bf\u03c3\u03c9\u03c1\u03b9\u03bd\u03ce\u03bd \u0391\u03c1\u03c7\u03b5\u03af\u03c9\u03bd",
"LabelSyncTempPathHelp": "Specify a custom sync working folder. Converted media created during the sync process will be stored here.",
"LabelCustomCertificatePath": "Custom certificate path:",
"LabelCustomCertificatePathHelp": "Supply your own ssl certificate .pfx file. If omitted, the server will create a self-signed certificate.",
- "TitleNotifications": "Notifications",
- "ButtonDonateWithPayPal": "Donate with PayPal",
- "OptionDetectArchiveFilesAsMedia": "Detect archive files as media",
- "OptionDetectArchiveFilesAsMediaHelp": "If enabled, files with .rar and .zip extensions will be detected as media files.",
- "LabelEnterConnectUserName": "User name or email:",
+ "TitleNotifications": "\u0395\u03b9\u03b4\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03b9\u03c2",
+ "ButtonDonateWithPayPal": "\u0394\u03c9\u03c1\u03b5\u03ac \u03bc\u03ad\u03c3\u03c9 Paypal",
+ "OptionDetectArchiveFilesAsMedia": "\u0391\u03bd\u03b1\u03b3\u03bd\u03ce\u03c1\u03b9\u03c3\u03b5 \u03a3\u03c5\u03bc\u03c0\u03b9\u03b5\u03c3\u03bc\u03ad\u03bd\u03b1 \u03b1\u03c1\u03c7\u03b5\u03af\u03b1 \u03c9\u03c2 \u03c0\u03bf\u03bb\u03c5\u03bc\u03ad\u03c3\u03b1.",
+ "OptionDetectArchiveFilesAsMediaHelp": "\u0391\u03c1\u03c7\u03b5\u03af\u03b1 \u03bc\u03b5 .rar \u03ba\u03b1\u03b9 .zip \u03ba\u03b1\u03c4\u03b1\u03bb\u03ae\u03be\u03b5\u03b9\u03c2 \u03b8\u03b1 \u03b1\u03bd\u03b1\u03b3\u03bd\u03c9\u03c1\u03af\u03b6\u03bf\u03bd\u03c4\u03b1\u03b9 \u03c9\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03b1 \u03c0\u03bf\u03bb\u03c5\u03bc\u03ad\u03c3\u03c9\u03bd.",
+ "LabelEnterConnectUserName": "\u038c\u03bd\u03bf\u03bc\u03b1 \u03a7\u03c1\u03ae\u03c3\u03c4\u03b7 \u03ae email:",
"LabelEnterConnectUserNameHelp": "This is your Emby online account user name or password.",
"LabelEnableEnhancedMovies": "Enable enhanced movie displays",
"LabelEnableEnhancedMoviesHelp": "When enabled, movies will be displayed as folders to include trailers, extras, cast & crew, and other related content.",
- "HeaderSyncJobInfo": "Sync Job",
- "FolderTypeMixed": "Mixed content",
- "FolderTypeMovies": "Movies",
- "FolderTypeMusic": "Music",
- "FolderTypeAdultVideos": "Adult videos",
- "FolderTypePhotos": "Photos",
- "FolderTypeMusicVideos": "Music videos",
- "FolderTypeHomeVideos": "Home videos",
- "FolderTypeGames": "Games",
- "FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV",
+ "HeaderSyncJobInfo": "\u0395\u03c1\u03b3\u03b1\u03c3\u03af\u03b1 \u03a3\u03c5\u03b3\u03c7\u03c1\u03bf\u03bd\u03b9\u03c3\u03bc\u03bf\u03cd",
+ "FolderTypeMixed": "\u0391\u03bd\u03ac\u03bc\u03b5\u03b9\u03ba\u03c4\u03bf \u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03bf",
+ "FolderTypeMovies": "\u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2",
+ "FolderTypeMusic": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ae",
+ "FolderTypeAdultVideos": "\u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2 \u0395\u03bd\u03b7\u03bb\u03af\u03ba\u03c9\u03bd",
+ "FolderTypePhotos": "\u03a6\u03c9\u03c4\u03bf\u03b3\u03c1\u03b1\u03c6\u03af\u03b5\u03c2",
+ "FolderTypeMusicVideos": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ac \u0392\u03af\u03bd\u03c4\u03b5\u03bf",
+ "FolderTypeHomeVideos": "\u03a0\u03c1\u03bf\u03c3\u03c9\u03c0\u03b9\u03ba\u03ac \u0392\u03af\u03bd\u03c4\u03b5\u03bf",
+ "FolderTypeGames": "\u03a0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9\u03b1",
+ "FolderTypeBooks": "\u0392\u03b9\u03b2\u03bb\u03af\u03b1",
+ "FolderTypeTvShows": "\u03a4\u03b7\u03bb\u03b5\u03cc\u03c1\u03b1\u03c3\u03b7",
"FolderTypeInherit": "Inherit",
- "LabelContentType": "Content type:",
- "TitleScheduledTasks": "Scheduled Tasks",
+ "LabelContentType": "\u03a4\u03cd\u03c0\u03bf\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd:",
+ "TitleScheduledTasks": "\u03a0\u03c1\u03bf\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03ad\u03bd\u03b5\u03c2 \u0395\u03c1\u03b3\u03b1\u03c3\u03af\u03b5\u03c2",
"HeaderSetupLibrary": "Setup your media library",
"ButtonAddMediaFolder": "\u03a0\u03c1\u03bf\u03c3\u03b8\u03ad\u03c3\u03c4\u03b5 \u03c4\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03c4\u03bf\u03c5 Media",
- "LabelFolderType": "\u03a4\u03cd\u03c0\u03bf \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5 ",
+ "LabelFolderType": "\u03a4\u03cd\u03c0\u03bf\u03c2 \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5",
"ReferToMediaLibraryWiki": "\u0391\u03bd\u03b1\u03c4\u03c1\u03b5\u03be\u03c4\u03b5 \u03c3\u03c4\u03bf media \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7 wiki",
- "LabelCountry": "T\u03b7 \u03c7\u03ce\u03c1\u03b1",
- "LabelLanguage": "\u03a4\u03b7 \u03b3\u03bb\u03ce\u03c3\u03c3\u03b1",
- "LabelTimeLimitHours": "Time limit (hours):",
+ "LabelCountry": "\u03a7\u03ce\u03c1\u03b1",
+ "LabelLanguage": "\u0393\u03bb\u03ce\u03c3\u03c3\u03b1",
+ "LabelTimeLimitHours": "\u038c\u03c1\u03b9\u03bf \u03a7\u03c1\u03cc\u03bd\u03bf\u03c5 (\u038f\u03c1\u03b5\u03c2)",
"ButtonJoinTheDevelopmentTeam": "Join the Development Team",
"HeaderPreferredMetadataLanguage": "\u03a0\u03c1\u03bf\u03c4\u03b9\u03bc\u03ce\u03bc\u03b5\u03bd\u03b7 \u03b3\u03bb\u03ce\u03c3\u03c3\u03b1 \u03bc\u03b5\u03c4\u03b1",
"LabelSaveLocalMetadata": "\u0391\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c3\u03b5\u03c4\u03b5 \u03c4\u03bf \u03ad\u03c1\u03b3\u03bf \u03c4\u03ad\u03c7\u03bd\u03b7\u03c2 \u03ba\u03b1\u03b9 \u03c4\u03b1 \u03bc\u03b5\u03c4\u03b1\u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1 \u03c3\u03b5 \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5\u03c2 \u03c0\u03bf\u03bb\u03c5\u03bc\u03ad\u03c3\u03c9\u03bd",
@@ -115,59 +117,60 @@
"LabelDownloadInternetMetadata": "\u039a\u03b1\u03c4\u03b5\u03b2\u03ac\u03c3\u03c4\u03b5 \u03ad\u03c1\u03b3\u03b1 \u03c4\u03ad\u03c7\u03bd\u03b7\u03c2 \u03ba\u03b1\u03b9 \u03c4\u03b1 \u03bc\u03b5\u03c4\u03b1-\u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1 \u03b1\u03c0\u03cc \u03c4\u03bf internet ",
"LabelDownloadInternetMetadataHelp": "Emby Server can download information about your media to enable rich presentations.",
"TabPreferences": "\u03a0\u03c1\u03bf\u03c4\u03b9\u03bc\u03ae\u03c3\u03b5\u03b9\u03c2 ",
- "TabPassword": "\u03c4\u03bf\u03bd \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc",
+ "TabPassword": "\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2",
"TabLibraryAccess": "\u03a0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03c3\u03c4\u03b7 \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7",
- "TabAccess": "Access",
- "TabImage": "\u03b5\u03b9\u03ba\u03cc\u03bd\u03b1",
- "TabProfile": "\u03c0\u03c1\u03bf\u03c6\u03af\u03bb ",
+ "TabAccess": "\u03a0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7",
+ "TabImage": "\u0395\u03b9\u03ba\u03cc\u03bd\u03b1",
+ "TabProfile": "\u03a0\u03c1\u03bf\u03c6\u03af\u03bb",
"TabMetadata": "Metadata",
- "TabImages": "Images",
- "TabNotifications": "Notifications",
- "TabCollectionTitles": "Titles",
- "HeaderDeviceAccess": "Device Access",
- "OptionEnableAccessFromAllDevices": "Enable access from all devices",
+ "TabImages": "\u0395\u03b9\u03ba\u03cc\u03bd\u03b5\u03c2",
+ "TabNotifications": "\u0395\u03b9\u03b4\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03b9\u03c2",
+ "TabCollectionTitles": "\u03a4\u03af\u03c4\u03bb\u03bf\u03b9",
+ "HeaderDeviceAccess": "\u03a0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03a3\u03c5\u03c3\u03ba\u03b5\u03c5\u03ae\u03c2",
+ "OptionEnableAccessFromAllDevices": "\u03a0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03b1\u03c0\u03cc \u03cc\u03bb\u03b5\u03c2 \u03c4\u03b9\u03c2 \u03c3\u03c5\u03c3\u03ba\u03b5\u03c5\u03ad\u03c2",
"OptionEnableAccessToAllChannels": "Enable access to all channels",
- "OptionEnableAccessToAllLibraries": "Enable access to all libraries",
+ "OptionEnableAccessToAllLibraries": "\u03a0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03c3\u03b5 \u03cc\u03bb\u03b5\u03c2 \u03c4\u03b9\u03c2 \u0392\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b5\u03c2",
"DeviceAccessHelp": "This only applies to devices that can be uniquely identified and will not prevent browser access. Filtering user device access will prevent them from using new devices until they've been approved here.",
- "LabelDisplayMissingEpisodesWithinSeasons": "\u03b4\u03b5\u03af\u03c7\u03bd\u03bf\u03c5\u03bd \u03bb\u03b5\u03af\u03c0\u03b5\u03b9 \u03b5\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1 \u03b5\u03bd\u03c4\u03cc\u03c2 \u03b5\u03c0\u03bf\u03c7\u03ad\u03c2",
- "LabelUnairedMissingEpisodesWithinSeasons": "\u03b4\u03b5\u03af\u03c7\u03bd\u03bf\u03c5\u03bd unaired \u03b5\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1 \u03b5\u03bd\u03c4\u03cc\u03c2 \u03b5\u03c0\u03bf\u03c7\u03ad\u03c2",
- "HeaderVideoPlaybackSettings": "\u0391\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03ae \u03b2\u03af\u03bd\u03c4\u03b5\u03bf \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2.",
- "HeaderPlaybackSettings": "Playback Settings",
- "LabelAudioLanguagePreference": "\u039f\u03bc\u03b9\u03bb\u03bf\u03cd\u03bc\u03b5\u03bd\u03b7 \u03b3\u03bb\u03ce\u03c3\u03c3\u03b1 \u03c0\u03c1\u03bf\u03c4\u03af\u03bc\u03b7\u03c3\u03b7\u03c2",
+ "LabelDisplayMissingEpisodesWithinSeasons": "\u0395\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 \u03b5\u03c0\u03b5\u03b9\u03c3\u03bf\u03b4\u03af\u03c9\u03bd \u03c0\u03bf\u03c5 \u03bb\u03b5\u03af\u03c0\u03bf\u03c5\u03bd \u03b1\u03c0\u03cc \u03c4\u03b7\u03bd \u03c3\u03b1\u03b9\u03b6\u03cc\u03bd",
+ "LabelUnairedMissingEpisodesWithinSeasons": "\u0395\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 \u03ac\u03c0\u03b1\u03b9\u03c7\u03c4\u03c9\u03bd \u03b5\u03c0\u03b5\u03b9\u03c3\u03bf\u03b4\u03af\u03c9\u03bd \u03b1\u03c0\u03cc \u03c4\u03b7\u03bd \u03c3\u03b1\u03b9\u03b6\u03cc\u03bd",
+ "HeaderVideoPlaybackSettings": "\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u0391\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2 \u0392\u03af\u03bd\u03c4\u03b5\u03bf",
+ "HeaderPlaybackSettings": "\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u0391\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2",
+ "LabelAudioLanguagePreference": "\u03a0\u03c1\u03bf\u03c4\u03af\u03bc\u03b7\u03c3\u03b7 \u0393\u03bb\u03ce\u03c3\u03c3\u03b1\u03c2 \u0389\u03c7\u03bf\u03c5",
"LabelSubtitleLanguagePreference": "\u0393\u03bb\u03ce\u03c3\u03c3\u03b1 \u03c5\u03c0\u03cc\u03c4\u03b9\u03c4\u03bb\u03c9\u03bd \u03c0\u03c1\u03bf\u03c4\u03af\u03bc\u03b7\u03c3\u03b7\u03c2",
- "OptionDefaultSubtitles": "Default",
+ "OptionDefaultSubtitles": "\u03a0\u03c1\u03bf\u03b5\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
- "OptionAlwaysPlaySubtitles": "Always play subtitles",
- "OptionNoSubtitles": "No Subtitles",
+ "OptionAlwaysPlaySubtitles": "\u03a0\u03ac\u03bd\u03c4\u03b1 \u03b1\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03ae \u03a5\u03c0\u03bf\u03c4\u03af\u03c4\u03bb\u03c9\u03bd",
+ "OptionNoSubtitles": "\u03a7\u03c9\u03c1\u03af\u03c2 \u03a5\u03c0\u03cc\u03c4\u03b9\u03c4\u03bb\u03bf\u03c5\u03c2",
"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",
+ "TabProfiles": "\u03a0\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",
- "ButtonAddLocalUser": "Add Local User",
- "ButtonInviteUser": "Invite User",
- "ButtonSave": "\u0391\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c3\u03c4\u03b5",
+ "ButtonAddLocalUser": "\u03a0\u03c1\u03bf\u03c3\u03b8\u03ae\u03ba\u03b7 \u03a4\u03bf\u03c0\u03b9\u03ba\u03bf\u03cd \u03a7\u03c1\u03ae\u03c3\u03c4\u03b7",
+ "ButtonInviteUser": "\u03a0\u03c1\u03cc\u03c3\u03ba\u03bb\u03b7\u03c3\u03b7 \u03a7\u03c1\u03ae\u03c3\u03c4\u03b7",
+ "ButtonSave": "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7",
"ButtonResetPassword": "\u0395\u03c0\u03b1\u03bd\u03b1\u03c6\u03bf\u03c1\u03ac \u03c4\u03bf\u03c5 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03cd \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
- "LabelNewPassword": "\u039d\u03ad\u03bf \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2 ",
- "LabelNewPasswordConfirm": "\u0395\u03c0\u03b9\u03b2\u03b5\u03b2\u03b1\u03b9\u03ce\u03c3\u03c4\u03b5 \u03c4\u03bf \u03bd\u03ad\u03bf \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2 ",
+ "LabelNewPassword": "\u039d\u03ad\u03bf\u03c2 \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
+ "LabelNewPasswordConfirm": "\u0395\u03c0\u03b9\u03b2\u03b5\u03b2\u03b1\u03af\u03c9\u03c3\u03b7 \u03bd\u03ad\u03bf\u03c5 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03cd \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
"HeaderCreatePassword": "\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03cd \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2 ",
- "LabelCurrentPassword": "\u03a4\u03c1\u03ad\u03c7\u03bf\u03bd\u03c4\u03b1 \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
+ "LabelCurrentPassword": "\u03a4\u03c1\u03ad\u03c7\u03bf\u03bd\u03c4\u03b1\u03c2 \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
"LabelMaxParentalRating": "\u039c\u03ad\u03b3\u03b9\u03c3\u03c4\u03bf \u03b5\u03c0\u03b9\u03c4\u03c1\u03b5\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf \u03b3\u03bf\u03bd\u03b9\u03ba\u03ae \u03b2\u03b1\u03b8\u03bc\u03bf\u03bb\u03bf\u03b3\u03af\u03b1:",
"MaxParentalRatingHelp": "\u03a4\u03bf \u03c0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03bf \u03bc\u03b5 \u03c4\u03b7\u03bd \u03c5\u03c8\u03b7\u03bb\u03cc\u03c4\u03b5\u03c1\u03b7 \u03b2\u03b1\u03b8\u03bc\u03bf\u03bb\u03bf\u03b3\u03af\u03b1 \u03b8\u03b1 \u03b5\u03af\u03bd\u03b1\u03b9 \u03ba\u03c1\u03c5\u03bc\u03bc\u03ad\u03bd\u03b1 \u03b1\u03c0\u03cc \u03b1\u03c5\u03c4\u03cc\u03bd \u03c4\u03bf\u03bd \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7",
"LibraryAccessHelp": "\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03bf\u03c5\u03c2 \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5\u03c2 \u03bc\u03ad\u03c3\u03c9\u03bd \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03c4\u03bf \u03bc\u03bf\u03b9\u03c1\u03b1\u03c3\u03c4\u03b5\u03af\u03c4\u03b5 \u03bc\u03b5 \u03b1\u03c5\u03c4\u03cc\u03bd \u03c4\u03bf \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7. \u039f\u03b9 \u03b4\u03b9\u03b1\u03c7\u03b5\u03b9\u03c1\u03b9\u03c3\u03c4\u03ad\u03c2 \u03b8\u03b1 \u03ad\u03c7\u03bf\u03c5\u03bd \u03c4\u03b7 \u03b4\u03c5\u03bd\u03b1\u03c4\u03cc\u03c4\u03b7\u03c4\u03b1 \u03bd\u03b1 \u03b5\u03c0\u03b5\u03be\u03b5\u03c1\u03b3\u03ac\u03b6\u03b5\u03c3\u03c4\u03b5 \u03cc\u03bb\u03b1 \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5\u03c2 \u03c7\u03c1\u03b7\u03c3\u03b9\u03bc\u03bf\u03c0\u03bf\u03b9\u03ce\u03bd\u03c4\u03b1\u03c2 \u03c4\u03b1 \u03bc\u03b5\u03c4\u03b1\u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1 manager.",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
"ButtonDeleteImage": "\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae \u03b5\u03b9\u03ba\u03cc\u03bd\u03b1\u03c2",
- "LabelSelectUsers": "Select users:",
+ "LabelSelectUsers": "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u03a7\u03c1\u03b7\u03c3\u03c4\u03ce\u03bd:",
"ButtonUpload": "\u0391\u03bd\u03b5\u03b2\u03ac\u03c3\u03c4\u03b5 ",
"HeaderUploadNewImage": "\u0391\u03bd\u03b5\u03b2\u03ac\u03c3\u03c4\u03b5 \u03bd\u03ad\u03b1 \u03b5\u03b9\u03ba\u03cc\u03bd\u03b1",
- "LabelDropImageHere": "Drop image here",
- "ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only",
+ "LabelDropImageHere": "\u0391\u03c0\u03bf\u03b8\u03ad\u03c3\u03c4\u03b5 \u03b5\u03b9\u03ba\u03cc\u03bd\u03b1 \u03b5\u03b4\u03ce",
+ "ImageUploadAspectRatioHelp": "\u03a0\u03c1\u03bf\u03c4\u03b5\u03b9\u03bd\u03cc\u03bc\u03b5\u03bd\u03bf 1:1 Aspect Ratio. JPG\/PNG \u03bc\u03cc\u03bd\u03bf",
"MessageNothingHere": "\u03a4\u03af\u03c0\u03bf\u03c4\u03b1 \u03b5\u03b4\u03ce ",
"MessagePleaseEnsureInternetMetadata": "\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03ce \u03b5\u03be\u03b1\u03c3\u03c6\u03b1\u03bb\u03af\u03c3\u03c4\u03b5 \u03c4\u03b7 \u03bb\u03ae\u03c8\u03b7 \u03bc\u03b5\u03c4\u03b1\u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03c9\u03bd \u03c3\u03c4\u03bf internet \u03b5\u03af\u03bd\u03b1\u03b9 \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03b7\u03bc\u03ad\u03bd\u03b7.\n",
"TabSuggested": "\u03a0\u03c1\u03bf\u03c4\u03b5\u03b9\u03bd\u03cc\u03bc\u03b5\u03bd\u03b7",
- "TabLatest": "\u03c4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03bf\u03c2",
+ "TabSuggestions": "Suggestions",
+ "TabLatest": "\u03a4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03bf\u03c2",
"TabUpcoming": "\u0395\u03c0\u03b5\u03c1\u03c7\u03cc\u03bc\u03b5\u03bd\u03b7",
"TabShows": "\u0395\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1",
"TabEpisodes": "\u0395\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1",
@@ -176,88 +179,88 @@
"TabNetworks": "\u0394\u03af\u03ba\u03c4\u03c5\u03b1",
"HeaderUsers": "\u03a7\u03c1\u03ae\u03c3\u03c4\u03b5\u03c2 ",
"HeaderFilters": "\u03a6\u03af\u03bb\u03c4\u03c1\u03b1",
- "ButtonFilter": "\u03c6\u03af\u03bb\u03c4\u03c1\u03bf",
+ "ButtonFilter": "\u03a6\u03af\u03bb\u03c4\u03c1\u03bf",
"OptionFavorite": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03b1",
"OptionLikes": "\u03a3\u03c5\u03bc\u03c0\u03b1\u03b8\u03b5\u03af",
"OptionDislikes": "\u0391\u03bd\u03c4\u03b9\u03c0\u03b1\u03b8\u03b5\u03af",
"OptionActors": "\u0397\u03b8\u03bf\u03c0\u03bf\u03b9\u03bf\u03af",
- "OptionGuestStars": "\u0393\u03ba\u03b5\u03c3\u03c4 \u03c3\u03c4\u03b1\u03c1",
+ "OptionGuestStars": "\u03a6\u03b9\u03bb\u03b9\u03ba\u03ae \u03a3\u03c5\u03bc\u03bc\u03b5\u03c4\u03bf\u03c7\u03ae",
"OptionDirectors": "\u03b4\u03b9\u03b5\u03c5\u03b8\u03c5\u03bd\u03c4\u03ad\u03c2",
"OptionWriters": "\u03a3\u03c5\u03b3\u03b3\u03c1\u03b1\u03c6\u03b5\u03af\u03c2",
- "OptionProducers": "\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03bf\u03af",
- "HeaderResume": "\u03a3\u03c5\u03bd\u03b5\u03c7\u03af\u03c3\u03b5\u03b9 ",
+ "OptionProducers": "\u03a0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03bf\u03af",
+ "HeaderResume": "\u0395\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7",
"HeaderNextUp": "\u0395\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf",
- "NoNextUpItemsMessage": "\u0394\u03b5\u03bd \u03b2\u03c1\u03ad\u03b8\u03b7\u03ba\u03b5 \u03ba\u03b1\u03bd\u03ad\u03bd\u03b1. \u039e\u03b5\u03ba\u03b9\u03bd\u03ae\u03c3\u03c4\u03b5 \u03c0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03c5\u03b8\u03ce\u03bd\u03c4\u03b1\u03c2 \u03b5\u03c0\u03b9\u03b4\u03b5\u03af\u03be\u03b5\u03b9\u03c2 \u03c3\u03b1\u03c2!",
- "HeaderLatestEpisodes": "\u03c4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03b1 \u03b5\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1",
+ "NoNextUpItemsMessage": "\u0394\u03b5\u03bd \u03b2\u03c1\u03ad\u03b8\u03b7\u03ba\u03b5 \u03ba\u03b1\u03bd\u03ad\u03bd\u03b1. \u039e\u03b5\u03ba\u03b9\u03bd\u03ae\u03c3\u03c4\u03b5 \u03c0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03c5\u03b8\u03ce\u03bd\u03c4\u03b1\u03c2 \u03c4\u03b9\u03c2 \u03b5\u03ba\u03c0\u03bf\u03bc\u03c0\u03ad\u03c2 \u03c3\u03b1\u03c2!",
+ "HeaderLatestEpisodes": "\u03a4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03b1 \u03b5\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1",
"HeaderPersonTypes": "Person Types:",
- "TabSongs": "\u03c4\u03c1\u03b1\u03b3\u03bf\u03cd\u03b4\u03b9\u03b1",
- "TabAlbums": "\u03ac\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc",
+ "TabSongs": "\u03a4\u03c1\u03b1\u03b3\u03bf\u03cd\u03b4\u03b9\u03b1",
+ "TabAlbums": "\u0386\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc",
"TabArtists": "\u039a\u03b1\u03bb\u03bb\u03b9\u03c4\u03ad\u03c7\u03bd\u03b5\u03c2",
- "TabAlbumArtists": "\u03ac\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc \u039a\u03b1\u03bb\u03bb\u03b9\u03c4\u03ad\u03c7\u03bd\u03b5\u03c2",
+ "TabAlbumArtists": "\u0386\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc \u039a\u03b1\u03bb\u03bb\u03b9\u03c4\u03ad\u03c7\u03bd\u03b5\u03c2",
"TabMusicVideos": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ac \u03b2\u03af\u03bd\u03c4\u03b5\u03bf",
- "ButtonSort": "\u03c4\u03b1\u03be\u03b9\u03bd\u03bf\u03bc\u03ae\u03c3\u03b5\u03c4\u03b5",
- "HeaderSortBy": "\u03a4\u03b1\u03be\u03b9\u03bd\u03cc\u03bc\u03b7\u03c3\u03b7 \u03ba\u03b1\u03c4\u03ac",
- "HeaderSortOrder": "\u03a3\u03b5\u03b9\u03c1\u03ac \u03c4\u03b1\u03be\u03b9\u03bd\u03cc\u03bc\u03b7\u03c3\u03b7\u03c2",
- "OptionPlayed": "\u03a0\u03b1\u03af\u03c7\u03b8\u03b7\u03ba\u03b5",
- "OptionUnplayed": "\u03b4\u03b5\u03bd \u03c0\u03b1\u03af\u03c7\u03b8\u03b7\u03ba\u03b5",
- "OptionAscending": "\u03b1\u03cd\u03be\u03bf\u03c5\u03c3\u03b1",
- "OptionDescending": "\u03c6\u03b8\u03af\u03bd\u03bf\u03c5\u03c3\u03b1 ",
+ "ButtonSort": "\u03a4\u03b1\u03be\u03b9\u03bd\u03cc\u03bc\u03b7\u03c3\u03b7",
+ "HeaderSortBy": "\u03a4\u03b1\u03be\u03b9\u03bd\u03cc\u03bc\u03b7\u03c3\u03b7 \u03ba\u03b1\u03c4\u03ac:",
+ "HeaderSortOrder": "\u03a3\u03b5\u03b9\u03c1\u03ac \u03c4\u03b1\u03be\u03b9\u03bd\u03cc\u03bc\u03b7\u03c3\u03b7\u03c2:",
+ "OptionPlayed": "\u0391\u03bd\u03b1\u03c0\u03b1\u03c1\u03ac\u03c7\u03b8\u03b7\u03ba\u03b5",
+ "OptionUnplayed": "\u0394\u03b5\u03bd \u03c0\u03b1\u03af\u03c7\u03b8\u03b7\u03ba\u03b5",
+ "OptionAscending": "\u0391\u03cd\u03be\u03bf\u03c5\u03c3\u03b1",
+ "OptionDescending": "\u03a6\u03b8\u03af\u03bd\u03bf\u03c5\u03c3\u03b1",
"OptionRuntime": "Runtime",
- "OptionReleaseDate": "Release Date",
- "OptionPlayCount": "Play Count",
- "OptionDatePlayed": "Date Played",
- "OptionDateAdded": "\u03b7\u03bc\u03b5\u03c1\u03bf\u03bc\u03b7\u03bd\u03af\u03b1 \u03c0\u03c1\u03bf\u03c3\u03b8\u03ae\u03ba\u03b7\u03c2",
+ "OptionReleaseDate": "\u0397\u03bc\u03b5\u03c1\u03bf\u03bc\u03b7\u03bd\u03af\u03b1 \u03a0\u03c1\u03bf\u03b2\u03bf\u03bb\u03ae\u03c2",
+ "OptionPlayCount": "\u03a6\u03bf\u03c1\u03ad\u03c2 \u0391\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2",
+ "OptionDatePlayed": "\u0397\u03bc\u03b5\u03c1\u03bf\u03bc\u03b7\u03bd\u03af\u03b1 \u0391\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2",
+ "OptionDateAdded": "\u0397\u03bc\u03b5\u03c1\u03bf\u03bc\u03b7\u03bd\u03af\u03b1 \u03c0\u03c1\u03bf\u03c3\u03b8\u03ae\u03ba\u03b7\u03c2",
"OptionAlbumArtist": "\u03ac\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc \u039a\u03b1\u03bb\u03bb\u03b9\u03c4\u03ad\u03c7\u03bd\u03b5\u03c2",
"OptionArtist": " \u039a\u03b1\u03bb\u03bb\u03b9\u03c4\u03ad\u03c7\u03bd\u03b5\u03c2",
- "OptionAlbum": "\u03ac\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc",
- "OptionTrackName": "Track Name",
- "OptionCommunityRating": "Community Rating",
- "OptionNameSort": "Name",
- "OptionFolderSort": "Folders",
- "OptionBudget": "Budget",
+ "OptionAlbum": "\u0386\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc",
+ "OptionTrackName": "\u038c\u03bd\u03bf\u03bc\u03b1 \u0391\u03c1\u03c7\u03b5\u03af\u03bf\u03c5",
+ "OptionCommunityRating": "\u0392\u03b1\u03b8\u03bc\u03bf\u03bb\u03bf\u03b3\u03af\u03b1 \u039a\u03bf\u03b9\u03bd\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2",
+ "OptionNameSort": "\u038c\u03bd\u03bf\u03bc\u03b1",
+ "OptionFolderSort": "\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03b9",
+ "OptionBudget": "\u03a0\u03c1\u03bf\u03c5\u03c0\u03bf\u03bb\u03bf\u03b3\u03b9\u03c3\u03bc\u03cc\u03c2",
"OptionRevenue": "Revenue",
- "OptionPoster": "Poster",
+ "OptionPoster": "\u0391\u03c6\u03af\u03c3\u03b1",
"OptionPosterCard": "Poster card",
"OptionBackdrop": "Backdrop",
- "OptionTimeline": "Timeline",
+ "OptionTimeline": "\u03a7\u03c1\u03bf\u03bd\u03bf\u03b4\u03b9\u03ac\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1",
"OptionThumb": "Thumb",
"OptionThumbCard": "Thumb card",
"OptionBanner": "Banner",
- "OptionCriticRating": "Critic Rating",
+ "OptionCriticRating": "\u0392\u03b1\u03b8\u03bc\u03bf\u03bb\u03bf\u03b3\u03af\u03b1 \u03ba\u03c1\u03b9\u03c4\u03b9\u03ba\u03ce\u03bd",
"OptionVideoBitrate": "Video Bitrate",
"OptionResumable": "Resumable",
- "ScheduledTasksHelp": "Click a task to adjust its schedule.",
- "ScheduledTasksTitle": "Scheduled Tasks",
- "TabMyPlugins": "My Plugins",
- "TabCatalog": "Catalog",
- "TitlePlugins": "Plugins",
- "HeaderAutomaticUpdates": "Automatic Updates",
- "HeaderNowPlaying": "Now Playing",
- "HeaderLatestAlbums": "Latest Albums",
- "HeaderLatestSongs": "Latest Songs",
+ "ScheduledTasksHelp": "\u0395\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u0395\u03c1\u03b3\u03b1\u03c3\u03af\u03b1 \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03c4\u03b5 \u03c4\u03bf \u03c0\u03c1\u03cc\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1",
+ "ScheduledTasksTitle": "\u03a0\u03c1\u03bf\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03ad\u03bd\u03b5\u03c2 \u0395\u03c1\u03b3\u03b1\u03c3\u03af\u03b5\u03c2",
+ "TabMyPlugins": "\u03a4\u03b1 \u03c0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03b1 \u03bc\u03bf\u03c5",
+ "TabCatalog": "\u039a\u03b1\u03c4\u03ac\u03bb\u03bf\u03b3\u03bf\u03c2",
+ "TitlePlugins": "\u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03b1",
+ "HeaderAutomaticUpdates": "\u0391\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b5\u03c2 \u0391\u03bd\u03b1\u03bd\u03b5\u03ce\u03c3\u03b5\u03b9\u03c2",
+ "HeaderNowPlaying": "\u03a4\u03ce\u03c1\u03b1 \u03a0\u03b1\u03af\u03b6\u03b5\u03b9:",
+ "HeaderLatestAlbums": "\u03a4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03b1 \u0386\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc",
+ "HeaderLatestSongs": "\u03a4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03b1 \u03a4\u03c1\u03b1\u03b3\u03bf\u03cd\u03b4\u03b9\u03b1",
"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.",
- "LabelVideoType": "Video Type:",
+ "LabelVideoType": "\u03a4\u03cd\u03c0\u03bf\u03c2 \u0392\u03af\u03bd\u03c4\u03b5\u03bf:",
"OptionBluray": "Bluray",
"OptionDvd": "Dvd",
"OptionIso": "Iso",
"Option3D": "3D",
"LabelFeatures": "Features:",
- "LabelService": "Service:",
- "LabelStatus": "Status:",
- "LabelVersion": "Version:",
- "LabelLastResult": "Last result:",
- "OptionHasSubtitles": "Subtitles",
- "OptionHasTrailer": "Trailer",
+ "LabelService": "\u03a5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1:",
+ "LabelStatus": "\u039a\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7:",
+ "LabelVersion": "\u0388\u03ba\u03b4\u03bf\u03c3\u03b7:",
+ "LabelLastResult": "\u03a4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03bf \u03b1\u03c0\u03bf\u03c4\u03ad\u03bb\u03b5\u03c3\u03bc\u03b1:",
+ "OptionHasSubtitles": "\u03a5\u03c0\u03cc\u03c4\u03b9\u03c4\u03bb\u03bf\u03b9",
+ "OptionHasTrailer": "\u03a4\u03c1\u03ad\u03ca\u03bb\u03b5\u03c1",
"OptionHasThemeSong": "Theme Song",
"OptionHasThemeVideo": "Theme Video",
- "TabMovies": "Movies",
- "TabStudios": "Studios",
+ "TabMovies": "\u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2",
+ "TabStudios": "\u03a3\u03c4\u03bf\u03cd\u03bd\u03c4\u03b9\u03bf",
"TabTrailers": "Trailers",
- "LabelArtists": "Artists:",
+ "LabelArtists": "\u039a\u03b1\u03bb\u03bb\u03b9\u03c4\u03ad\u03c7\u03bd\u03b5\u03c2",
"LabelArtistsHelp": "Separate multiple using ;",
- "HeaderLatestMovies": "Latest Movies",
+ "HeaderLatestMovies": "\u03a4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03b5\u03c2 \u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2",
"HeaderLatestTrailers": "Latest Trailers",
"OptionHasSpecialFeatures": "Special Features",
"OptionImdbRating": "IMDb Rating",
@@ -284,23 +287,23 @@
"OptionFileMetadataYearMismatch": "File\/Metadata Years Mismatched",
"TabGeneral": "General",
"TitleSupport": "Support",
- "TabLog": "Log",
- "TabAbout": "About",
- "TabSupporterKey": "Supporter Key",
- "TabBecomeSupporter": "Become a Supporter",
+ "TabLog": "\u0391\u03c1\u03c7\u03b5\u03af\u03bf \u039a\u03b1\u03c4\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae\u03c2",
+ "TabAbout": "\u03a0\u03b5\u03c1\u03af..",
+ "TabSupporterKey": "\u03a3\u03b5\u03b9\u03c1\u03b9\u03b1\u03ba\u03cc\u03c2 \u03a5\u03c0\u03bf\u03c3\u03c4\u03ae\u03c1\u03b9\u03be\u03b7\u03c2",
+ "TabBecomeSupporter": "\u0393\u03af\u03bd\u03b5 \u03a5\u03c0\u03bf\u03c3\u03c4\u03b7\u03c1\u03b9\u03ba\u03c4\u03ae\u03c2",
"ProjectHasCommunity": "Emby has a thriving community of users and contributors.",
"CheckoutKnowledgeBase": "Check out our knowledge base to help you get the most out of Emby.",
- "SearchKnowledgeBase": "Search the Knowledge Base",
+ "SearchKnowledgeBase": "\u0391\u03bd\u03b1\u03b6\u03ae\u03c4\u03b7\u03c3\u03b5 \u03c3\u03c4\u03b7 \u0392\u03ac\u03c3\u03b7",
"VisitTheCommunity": "Visit the Community",
- "VisitProjectWebsite": "Visit the Emby Web Site",
+ "VisitProjectWebsite": "\u0395\u03c0\u03b9\u03c3\u03ba\u03ad\u03c8\u03bf\u03c5 \u03c4\u03b7 \u03a3\u03b5\u03bb\u03af\u03b4\u03b1 \u03c4\u03bf\u03c5 Emby",
"VisitProjectWebsiteLong": "Visit the Emby Web site to catch the latest news and keep up with the developer blog.",
"OptionHideUser": "Hide this user from login screens",
"OptionHideUserFromLoginHelp": "Useful for private or hidden administrator accounts. The user will need to sign in manually by entering their username and password.",
- "OptionDisableUser": "Disable this user",
+ "OptionDisableUser": "\u0391\u03c0\u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b7 \u03a7\u03c1\u03ae\u03c3\u03c4\u03b7",
"OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.",
"HeaderAdvancedControl": "Advanced Control",
- "LabelName": "Name:",
- "ButtonHelp": "Help",
+ "LabelName": "\u038c\u03bd\u03bf\u03bc\u03b1:",
+ "ButtonHelp": "\u0392\u03bf\u03ae\u03b8\u03b5\u03b9\u03b1",
"OptionAllowUserToManageServer": "Allow this user to manage the server",
"HeaderFeatureAccess": "Feature Access",
"OptionAllowMediaPlayback": "Allow media playback",
@@ -310,33 +313,33 @@
"OptionAllowRemoteControlOthers": "Allow remote control of other users",
"OptionAllowRemoteSharedDevices": "Allow remote control of shared devices",
"OptionAllowRemoteSharedDevicesHelp": "Dlna devices are considered shared until a user begins controlling it.",
- "HeaderRemoteControl": "Remote Control",
+ "HeaderRemoteControl": "\u03a4\u03b7\u03bb\u03b5\u03c7\u03b5\u03b9\u03c1\u03b9\u03c3\u03c4\u03ae\u03c1\u03b9\u03bf",
"OptionMissingTmdbId": "Missing Tmdb Id",
"OptionIsHD": "HD",
"OptionIsSD": "SD",
- "OptionMetascore": "Metascore",
- "ButtonSelect": "Select",
+ "OptionMetascore": "\u0392\u03b1\u03b8\u03bc\u03bf\u03bb\u03bf\u03b3\u03af\u03b1",
+ "ButtonSelect": "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae",
"ButtonGroupVersions": "Group Versions",
- "ButtonAddToCollection": "Add to Collection",
+ "ButtonAddToCollection": "\u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c3\u03b5 \u03c3\u03c4\u03b7 \u03a3\u03c5\u03bb\u03bb\u03bf\u03b3\u03ae",
"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",
- "TabServer": "Server",
+ "VersionNumber": "\u0388\u03ba\u03b4\u03bf\u03c3\u03b7 {0}",
+ "TabPaths": "\u0394\u03b9\u03b1\u03b4\u03c1\u03bf\u03bc\u03ae",
+ "TabServer": "\u0394\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae\u03c2",
"TabTranscoding": "Transcoding",
"TitleAdvanced": "Advanced",
"LabelAutomaticUpdateLevel": "Automatic update level",
"OptionRelease": "\u0397 \u03b5\u03c0\u03af\u03c3\u03b7\u03bc\u03b7 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7",
- "OptionBeta": "\u03b2\u03ae\u03c4\u03b1",
- "OptionDev": "\u03b1\u03bd\u03ac\u03c0\u03c4\u03c5\u03be\u03b7 (\u03b1\u03c3\u03c4\u03b1\u03b8\u03ae\u03c2)",
- "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates",
- "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods, when no users are active.",
+ "OptionBeta": "\u0394\u03bf\u03ba\u03b9\u03bc\u03b1\u03c3\u03c4\u03b9\u03ba\u03ae",
+ "OptionDev": "\u0391\u03bd\u03ac\u03c0\u03c4\u03c5\u03be\u03b7 (\u03b1\u03c3\u03c4\u03b1\u03b8\u03ae\u03c2)",
+ "LabelAllowServerAutoRestart": "\u0391\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b7 \u03b5\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03c4\u03bf\u03c5 \u03c3\u03ad\u03c1\u03b2\u03b5\u03c1 \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03ae\u03c3\u03b5\u03b9 \u03c4\u03b9\u03c2 \u03b1\u03bd\u03b1\u03b2\u03b1\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2",
+ "LabelAllowServerAutoRestartHelp": "\u039f \u03a3\u03b5\u03c1\u03b2\u03b5\u03c1 \u03b8\u03b1 \u03ba\u03ac\u03bd\u03b5\u03b9 \u03bc\u03cc\u03bd\u03bf \u03b5\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03b9\u03bd\u03ae\u03c3\u03b5\u03b9\u03c2 \u03c4\u03b9\u03c2 \u03bc\u03b7 \u03b5\u03bd\u03b5\u03c1\u03b3\u03ad\u03c2 \u03c0\u03b5\u03c1\u03b9\u03cc\u03b4\u03bf\u03c5\u03c2, \u03cc\u03c4\u03b1\u03bd \u03ba\u03b1\u03bd\u03b5\u03af\u03c2 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2 \u03b4\u03b5\u03bd \u03b5\u03af\u03bd\u03b1\u03b9 \u03b5\u03bd\u03b5\u03c1\u03b3\u03cc\u03c2.",
"LabelEnableDebugLogging": "Enable debug logging",
- "LabelRunServerAtStartup": "Run server at startup",
+ "LabelRunServerAtStartup": "\u039e\u03b5\u03ba\u03af\u03bd\u03b7\u03c3\u03b5 \u03c4\u03bf\u03bd \u03a3\u03b5\u03c1\u03b2\u03b5\u03c1 \u03ba\u03b1\u03c4\u03ac \u03c4\u03b7\u03bd \u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7",
"LabelRunServerAtStartupHelp": "This will start the tray icon on windows startup. To start the windows service, uncheck this and run the service from the windows control panel. Please note that you cannot run both at the same time, so you will need to exit the tray icon before starting the service.",
- "ButtonSelectDirectory": "Select Directory",
+ "ButtonSelectDirectory": "\u0395\u03c0\u03b9\u03bb\u03bf\u03b3\u03ae \u03a6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5",
"LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.",
"LabelCachePath": "Cache path:",
"LabelCachePathHelp": "Specify a custom location for server cache files, such as images.",
@@ -346,17 +349,17 @@
"LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.",
"LabelTranscodingTempPath": "Transcoding temporary path:",
"LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder. Specify a custom path, or leave empty to use the default within the server's data folder.",
- "TabBasics": "Basics",
- "TabTV": "TV",
- "TabGames": "Games",
- "TabMusic": "Music",
- "TabOthers": "Others",
+ "TabBasics": "\u0392\u03b1\u03c3\u03b9\u03ba\u03ac",
+ "TabTV": "\u03a4\u03b7\u03bb\u03b5\u03cc\u03c1\u03b1\u03c3\u03b7",
+ "TabGames": "\u03a0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9\u03b1",
+ "TabMusic": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ae",
+ "TabOthers": "\u0386\u03bb\u03bb\u03b1",
"HeaderExtractChapterImagesFor": "Extract chapter images for:",
- "OptionMovies": "Movies",
- "OptionEpisodes": "Episodes",
- "OptionOtherVideos": "Other Videos",
+ "OptionMovies": "\u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2",
+ "OptionEpisodes": "\u0395\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1",
+ "OptionOtherVideos": "\u0386\u03bb\u03bb\u03b1 \u0392\u03af\u03bd\u03c4\u03b5\u03bf",
"TitleMetadata": "Metadata",
- "LabelAutomaticUpdates": "Enable automatic updates",
+ "LabelAutomaticUpdates": "\u0391\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b5\u03c2 \u0395\u03bd\u03b7\u03bc\u03b5\u03c1\u03ce\u03c3\u03b5\u03b9\u03c2",
"LabelAutomaticUpdatesTmdb": "Enable automatic updates from TheMovieDB.org",
"LabelAutomaticUpdatesTvdb": "Enable automatic updates from TheTVDB.com",
"LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.",
@@ -371,19 +374,19 @@
"LabelImageSavingConventionHelp": "Emby recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
"OptionImageSavingCompatible": "Compatible - Emby\/Kodi\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
- "ButtonSignIn": "Sign In",
- "TitleSignIn": "Sign In",
- "HeaderPleaseSignIn": "Please sign in",
- "LabelUser": "User:",
- "LabelPassword": "Password:",
- "ButtonManualLogin": "Manual Login",
+ "ButtonSignIn": "\u0395\u03af\u03c3\u03bf\u03b4\u03bf\u03c2",
+ "TitleSignIn": "\u0395\u03af\u03c3\u03bf\u03b4\u03bf\u03c2",
+ "HeaderPleaseSignIn": "\u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03ce \u03b5\u03b9\u03c3\u03ad\u03bb\u03b8\u03b5\u03c4\u03b5",
+ "LabelUser": "\u03a7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2:",
+ "LabelPassword": "\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2:",
+ "ButtonManualLogin": "\u03a7\u03b5\u03b9\u03c1\u03bf\u03ba\u03af\u03bd\u03b7\u03c4\u03b7 \u0395\u03af\u03c3\u03bf\u03b4\u03bf\u03c2",
"PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
- "TabGuide": "Guide",
- "TabChannels": "Channels",
- "TabCollections": "Collections",
- "HeaderChannels": "Channels",
- "TabRecordings": "Recordings",
- "TabScheduled": "Scheduled",
+ "TabGuide": "\u039f\u03b4\u03b7\u03b3\u03cc\u03c2",
+ "TabChannels": "\u039a\u03b1\u03bd\u03ac\u03bb\u03b9\u03b1",
+ "TabCollections": "\u03a3\u03c5\u03bb\u03bb\u03bf\u03b3\u03ad\u03c2",
+ "HeaderChannels": "\u039a\u03b1\u03bd\u03ac\u03bb\u03b9\u03b1",
+ "TabRecordings": "\u0395\u03b3\u03b3\u03c1\u03b1\u03c6\u03ad\u03c2",
+ "TabScheduled": "\u03a0\u03c1\u03bf\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03ad\u03bd\u03b1",
"TabSeries": "Series",
"TabFavorites": "Favorites",
"TabMyLibrary": "My Library",
@@ -401,9 +404,10 @@
"ButtonRefresh": "Refresh",
"ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnAllChannels": "Record on all channels",
+ "OptionRecordAnytime": "Record at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -430,65 +434,65 @@
"OptionDownloadDiscImage": "Disc",
"OptionDownloadBannerImage": "Banner",
"OptionDownloadBackImage": "Back",
- "OptionDownloadArtImage": "Art",
- "OptionDownloadPrimaryImage": "Primary",
+ "OptionDownloadArtImage": "\u03a4\u03ad\u03c7\u03bd\u03b7",
+ "OptionDownloadPrimaryImage": "\u03a0\u03c1\u03ce\u03c4\u03bf",
"HeaderFetchImages": "Fetch Images:",
- "HeaderImageSettings": "Image Settings",
- "TabOther": "Other",
+ "HeaderImageSettings": "\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u0395\u03b9\u03ba\u03cc\u03bd\u03b1\u03c2",
+ "TabOther": "\u0386\u03bb\u03bb\u03b1",
"LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
"LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
"LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
"LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:",
"ButtonAddScheduledTaskTrigger": "Add Trigger",
"HeaderAddScheduledTaskTrigger": "Add Trigger",
- "ButtonAdd": "Add",
+ "ButtonAdd": "\u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c3\u03b5",
"LabelTriggerType": "Trigger Type:",
- "OptionDaily": "Daily",
- "OptionWeekly": "Weekly",
+ "OptionDaily": "\u039a\u03b1\u03b8\u03b7\u03bc\u03b5\u03c1\u03b9\u03bd\u03ac",
+ "OptionWeekly": "\u0395\u03b2\u03b4\u03bf\u03bc\u03b1\u03b4\u03b9\u03b1\u03af\u03b1",
"OptionOnInterval": "On an interval",
"OptionOnAppStartup": "On application startup",
"OptionAfterSystemEvent": "After a system event",
- "LabelDay": "Day:",
- "LabelTime": "Time:",
- "LabelEvent": "Event:",
- "OptionWakeFromSleep": "Wake from sleep",
- "LabelEveryXMinutes": "Every:",
+ "LabelDay": "\u0397\u03bc\u03ad\u03c1\u03b1:",
+ "LabelTime": "\u038f\u03c1\u03b1:",
+ "LabelEvent": "\u0393\u03b5\u03b3\u03bf\u03bd\u03cc\u03c2:",
+ "OptionWakeFromSleep": "\u0395\u03c0\u03b1\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b7",
+ "LabelEveryXMinutes": "\u039a\u03ac\u03b8\u03b5:",
"HeaderTvTuners": "Tuners",
"HeaderGallery": "Gallery",
- "HeaderLatestGames": "Latest Games",
- "HeaderRecentlyPlayedGames": "Recently Played Games",
+ "HeaderLatestGames": "\u03a4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03b1 \u03a0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9\u03b1",
+ "HeaderRecentlyPlayedGames": "\u03a4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03b1 \u03a0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9\u03b1 \u03c0\u03bf\u03c5 \u03c0\u03b1\u03af\u03c7\u03c4\u03b7\u03ba\u03b1\u03bd",
"TabGameSystems": "Game Systems",
- "TitleMediaLibrary": "Media Library",
- "TabFolders": "Folders",
+ "TitleMediaLibrary": "\u0392\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7 \u03a0\u03bf\u03bb\u03c5\u03bc\u03ad\u03c3\u03c9\u03bd",
+ "TabFolders": "\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03b9",
"TabPathSubstitution": "Path Substitution",
"LabelSeasonZeroDisplayName": "Season 0 display name:",
"LabelEnableRealtimeMonitor": "Enable real time monitoring",
"LabelEnableRealtimeMonitorHelp": "Changes will be processed immediately, on supported file systems.",
- "ButtonScanLibrary": "Scan Library",
- "HeaderNumberOfPlayers": "Players:",
- "OptionAnyNumberOfPlayers": "Any",
+ "ButtonScanLibrary": "\u03a8\u03ac\u03be\u03b5 \u0392\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7",
+ "HeaderNumberOfPlayers": "\u03a0\u03c1\u03bf\u03b3\u03c1\u03ac\u03bc\u03bc\u03b1\u03c4\u03b1 \u0391\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2:",
+ "OptionAnyNumberOfPlayers": "\u038c\u03bb\u03b1",
"Option1Player": "1+",
"Option2Player": "2+",
"Option3Player": "3+",
"Option4Player": "4+",
- "HeaderMediaFolders": "Media Folders",
- "HeaderThemeVideos": "Theme Videos",
- "HeaderThemeSongs": "Theme Songs",
- "HeaderScenes": "Scenes",
- "HeaderAwardsAndReviews": "Awards and Reviews",
- "HeaderSoundtracks": "Soundtracks",
- "HeaderMusicVideos": "Music Videos",
- "HeaderSpecialFeatures": "Special Features",
- "HeaderCastCrew": "Cast & Crew",
- "HeaderAdditionalParts": "Additional Parts",
+ "HeaderMediaFolders": "\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03b9 \u03a0\u03bf\u03bb\u03c5\u03bc\u03ad\u03c3\u03c9\u03bd",
+ "HeaderThemeVideos": "\u0398\u03b5\u03bc\u03b1\u03c4\u03b9\u03ba\u03ac \u0392\u03af\u03bd\u03c4\u03b5\u03bf",
+ "HeaderThemeSongs": "\u0398\u03b5\u03bc\u03b1\u03c4\u03b9\u03ba\u03ac \u03a4\u03c1\u03b1\u03b3\u03bf\u03cd\u03b4\u03b9\u03b1",
+ "HeaderScenes": "\u03a3\u03ba\u03b7\u03bd\u03ad\u03c2",
+ "HeaderAwardsAndReviews": "\u0392\u03c1\u03b1\u03b2\u03b5\u03af\u03b1 \u03ba\u03b1\u03b9 \u0392\u03b1\u03b8\u03bc\u03bf\u03bb\u03bf\u03b3\u03af\u03b1",
+ "HeaderSoundtracks": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ae \u03a4\u03b1\u03b9\u03bd\u03af\u03b1\u03c2",
+ "HeaderMusicVideos": "\u0392\u03af\u03bd\u03c4\u03b5\u03bf \u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ae\u03c2",
+ "HeaderSpecialFeatures": "\u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03b5\u03c2 \u03a3\u03ba\u03b7\u03bd\u03ad\u03c2",
+ "HeaderCastCrew": "\u0397\u03b8\u03bf\u03c0\u03bf\u03b9\u03bf\u03af \u03ba\u03b1\u03b9 \u03c3\u03c5\u03bd\u03b5\u03c1\u03b3\u03b5\u03af\u03bf",
+ "HeaderAdditionalParts": "\u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03b1 \u039c\u03ad\u03c1\u03b7",
"ButtonSplitVersionsApart": "Split Versions Apart",
"ButtonPlayTrailer": "Trailer",
"LabelMissing": "Missing",
- "LabelOffline": "Offline",
+ "LabelOffline": "\u0395\u03ba\u03c4\u03cc\u03c2",
"PathSubstitutionHelp": "Path substitutions are used for mapping a path on the server to a path that clients are able to access. By allowing clients direct access to media on the server they may be able to play them directly over the network and avoid using server resources to stream and transcode them.",
- "HeaderFrom": "From",
+ "HeaderFrom": "\u0391\u03c0\u03cc",
"HeaderTo": "To",
- "LabelFrom": "From:",
+ "LabelFrom": "\u0391\u03c0\u03cc:",
"LabelFromHelp": "Example: D:\\Movies (on the server)",
"LabelTo": "To:",
"LabelToHelp": "Example: \\\\MyServer\\Movies (a path clients can access)",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json
index 81bee1153..22f1f6c32 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nothing here.",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"TabSuggested": "Suggested",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Latest",
"TabUpcoming": "Upcoming",
"TabShows": "Shows",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Record programme on all channels",
"OptionRecordAnytime": "Record programme at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json
index 86cb406b5..9232bafa5 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nothing here.",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"TabSuggested": "Suggested",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Latest",
"TabUpcoming": "Upcoming",
"TabShows": "Shows",
@@ -401,9 +404,10 @@
"ButtonRefresh": "Refresh",
"ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnAllChannels": "Record on all channels",
+ "OptionRecordAnytime": "Record at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es.json b/MediaBrowser.Server.Implementations/Localization/Server/es.json
index c1c3605b7..4664c9489 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/es.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/es.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "OK",
"ButtonCancel": "Cancelar",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nada aqu\u00ed.",
"MessagePleaseEnsureInternetMetadata": "Por favor aseg\u00farese que la descarga de metadata de internet esta habilitada",
"TabSuggested": "Sugerencia",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Novedades",
"TabUpcoming": "Pr\u00f3ximos",
"TabShows": "Programas",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Grabar programa en cualquier canal",
"OptionRecordAnytime": "Grabar programa a cualquier hora",
"OptionRecordOnlyNewEpisodes": "Grabar s\u00f3lo nuevos episodios",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "D\u00edas",
"HeaderActiveRecordings": "Grabaciones activas",
"HeaderLatestRecordings": "\u00daltimas grabaciones",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "N\u00famero de puerto WebSocket:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "Mis vistas (botones)",
- "OptionMyViews": "Mis vistas",
- "OptionMyViewsSmall": "Mis vistas (peque\u00f1o)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Continuar",
"OptionLatestMedia": "\u00daltimos medios",
"OptionLatestChannelMedia": "Ultimos elementos de canales",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Por defecto",
"OptionCommunityMostWatchedSort": "M\u00e1s visto",
"TabNextUp": "Siguiendo",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No hay sugerencias de pel\u00edculas disponibles. Comience ver y calificar sus pel\u00edculas y vuelva para ver las recomendaciones.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json
index 26a7e7f17..f77d42978 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Agregar Usuario",
"LabelAddConnectSupporterHelp": "Para agregar un usuario que no esta listado, necesita primero enlazar su cuenta a Emby Connect desde su pagina de perfil de usuario.",
"LabelPinCode": "C\u00f3digo pin:",
+ "OptionHideWatchedContentFromLatestMedia": "Ocultar contenido ya visto de medios recientes",
+ "HeaderSync": "Sinc",
"ButtonOk": "Ok",
"ButtonCancel": "Cancelar",
"ButtonExit": "Salir",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nada aqu\u00ed.",
"MessagePleaseEnsureInternetMetadata": "Por favor aseg\u00farese que la descarga de metadatos de internet esta habilitada.",
"TabSuggested": "Sugerencias",
+ "TabSuggestions": "Sugerencias",
"TabLatest": "Recientes",
"TabUpcoming": "Por Estrenar",
"TabShows": "Programas",
@@ -401,9 +404,10 @@
"ButtonRefresh": "Actualizar",
"ButtonAdvancedRefresh": "Actualizaci\u00f3n Avanzada",
"OptionPriority": "Prioridad",
- "OptionRecordOnAllChannels": "Grabar programa en todos los canales",
- "OptionRecordAnytime": "Grabar programa en cualquier momento",
+ "OptionRecordOnAllChannels": "Grabar en todos los canales",
+ "OptionRecordAnytime": "Grabar en cualquier momento",
"OptionRecordOnlyNewEpisodes": "Grabar s\u00f3lo nuevos episodios",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "D\u00edas",
"HeaderActiveRecordings": "Grabaciones Activas",
"HeaderLatestRecordings": "Grabaciones Recientes",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "N\u00famero de puerto https publico:",
"LabelPublicHttpsPortHelp": "El n\u00famero de puerto p\u00fablico que deber\u00e1 ser mapeado al puerto local de https.",
"LabelEnableHttps": "Reportar https como una direcci\u00f3n externa",
- "LabelEnableHttpsHelp": "Si se habilita, el servidor reportara a los clientes una url https como su direcci\u00f3n externa. Esto podr\u00eda inutilizar a los clientes que aun no soporten https.",
+ "LabelEnableHttpsHelp": "Al habilitarse, el servidor reportara un URL https a los clientes como su direcci\u00f3n externa.",
"LabelHttpsPort": "N\u00famero de puerto https local:",
"LabelHttpsPortHelp": "El numero de puerto tcp con el que se deber\u00e1 vincular el servidor https de Emby.",
"LabelWebSocketPortNumber": "N\u00famero de puerto WebSocket:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Pagina de Inicio secci\u00f3n dos:",
"LabelHomePageSection3": "Pagina de Inicio secci\u00f3n tres:",
"LabelHomePageSection4": "Pagina de Inicio secci\u00f3n cuatro:",
- "OptionMyViewsButtons": "Mis vistas (botones)",
- "OptionMyViews": "Mis vistas",
- "OptionMyViewsSmall": "Mis vistas (peque\u00f1o)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Continuar",
"OptionLatestMedia": "Medios recientes",
"OptionLatestChannelMedia": "Elementos recientes de canales",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Por defecto",
"OptionCommunityMostWatchedSort": "M\u00e1s Visto",
"TabNextUp": "A Continuaci\u00f3n",
+ "PlaceholderUsername": "Nombre de Usuario",
"HeaderBecomeProjectSupporter": "Convi\u00e9rtete en un Fan\u00e1tico Emby",
- "TextEnjoyBonusFeatures": "Disfruta de Caracter\u00edsticas Premium",
"MessageNoMovieSuggestionsAvailable": "No hay sugerencias de pel\u00edculas disponibles en este momento. Comienza a ver y a calificar tus pel\u00edculas, y regresa para ver tus recomendaciones.",
"MessageNoCollectionsAvailable": "Las colecciones le permiten disfrutar de agrupaciones personalizadas de Pel\u00edculas, Series, \u00c1lbumes, Libros y Juegos. Haga clic en el bot\u00f3n + para iniciar la creaci\u00f3n de Colecciones.",
"MessageNoPlaylistsAvailable": "Las listas de reproducci\u00f3n le permiten crear listas de contenidos a ser reproducidos de manera consecutiva. Para agregar \u00edtems a una lista de reproducci\u00f3n, haga clic derecho o seleccione y mantenga, despu\u00e9s seleccione Agregar a Lista de Reproducci\u00f3n.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Descargar metadatos de Internet para:",
"OptionTVMovies": "Pel\u00edculas de TV",
"HeaderUpcomingMovies": "Pel\u00edculas por Estrenar",
+ "HeaderUpcomingSports": "Deportes por Estrenar",
"HeaderUpcomingPrograms": "Programas por Estrenar",
"ButtonMoreItems": "M\u00e1s...",
"LabelShowLibraryTileNames": "Mostrar nombres de t\u00edtulo de las bibliotecas",
"LabelShowLibraryTileNamesHelp": "Determina si se desplegar\u00e1n etiquetas debajo de los t\u00edtulos de las bibliotecas con la p\u00e1gina principal",
- "OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottle": "Habilitar contenci\u00f3n",
+ "OptionEnableTranscodingThrottleHelp": "La contenci\u00f3n permite ajustar autom\u00e1ticamente la velocidad de transcodificaci\u00f3n para minimizar la utilizaci\u00f3n del procesador en el servidor durante la reproducci\u00f3n.",
+ "LabelUploadSpeedLimit": "L\u00edmite de velocidad de subida (mbps):",
+ "OptionAllowSyncTranscoding": "Permitir sincronizaci\u00f3n que requiera de transcodificaci\u00f3n",
+ "HeaderPlayback": "Reproducci\u00f3n de Medios",
+ "OptionAllowAudioPlaybackTranscoding": "Permitir la reproducci\u00f3n de audio que requiera de transcodificaci\u00f3n",
+ "OptionAllowVideoPlaybackTranscoding": "Permitir la reproducci\u00f3n de video que requiera de transcodificaci\u00f3n",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Los usuarios recibir\u00e1n mensajes amigables cuando el contenido no pueda ser reproducido de acuerdo a su pol\u00edtica.",
+ "TabStreaming": "Transmisi\u00f3n",
+ "LabelRemoteClientBitrateLimit": "Limite de tasa de bits para clientes remotos (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "L\u00edmite opcional en la tasa de bits de transmisi\u00f3n para todos los clientes remotos. Esto es \u00fatil para evitar que los clientes soliciten una tasa de bits mayor a la que su conexi\u00f3n puede soportar.",
+ "LabelConversionCpuCoreLimit": "L\u00edmite de n\u00facleos de CPU:",
+ "LabelConversionCpuCoreLimitHelp": "L\u00edmitar el n\u00famero de n\u00facleos del CPI que ser\u00e1n utilizados durante la conversi\u00f3n de sincronizaci\u00f3n.",
+ "OptionEnableFullSpeedConversion": "Habilitar conversi\u00f3n a m\u00e1xima velocidad",
+ "OptionEnableFullSpeedConversionHelp": "Por defecto, la conversi\u00f3n es realizada a baja velocidad para minimizar el consumo de recursos.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/fi.json b/MediaBrowser.Server.Implementations/Localization/Server/fi.json
index 4e7d9b552..1265b3c4a 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/fi.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/fi.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Lopeta",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nothing here.",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"TabSuggested": "Suggested",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Latest",
"TabUpcoming": "Upcoming",
"TabShows": "Shows",
@@ -401,9 +404,10 @@
"ButtonRefresh": "Refresh",
"ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnAllChannels": "Record on all channels",
+ "OptionRecordAnytime": "Record at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/fr.json b/MediaBrowser.Server.Implementations/Localization/Server/fr.json
index 9b7a58996..cd2d2571e 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/fr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/fr.json
@@ -24,7 +24,7 @@
"UserProfilesIntro": "Emby supporte nativement les profils utilisateurs, les pr\u00e9f\u00e9rences d'affichage, la sauvegarde de l'\u00e9tat de lecture et le contr\u00f4le parental.",
"LabelWindowsService": "Service Windows",
"AWindowsServiceHasBeenInstalled": "Un service Windows a \u00e9t\u00e9 install\u00e9.",
- "WindowsServiceIntro1": "Le serveur Emby fonctionne comme une application de bureau avec une icone de notification, mais si vous pr\u00e9f\u00e9rer qu'il tourne comme un service en tache de fond, il peut \u00eatre d\u00e9marrer \u00e0 partir du panneau de controle des services windows.",
+ "WindowsServiceIntro1": "Le serveur Emby fonctionne comme une application de bureau avec une icone de notification, mais si vous pr\u00e9f\u00e9rez qu'il tourne comme un service en tache de fond, il peut \u00eatre d\u00e9marrer \u00e0 partir du panneau de controle des services windows.",
"WindowsServiceIntro2": "Si le service Windows est utilis\u00e9, veuillez noter qu'il ne peut pas fonctionner en m\u00eame temps que l'application dans la barre des t\u00e2ches, vous devrez donc fermer l'application de la barre des t\u00e2ches pour pouvoir ex\u00e9cuter le service. Le service devra aussi \u00eatre configur\u00e9 avec les droits administrateurs via le panneau de configuration. Veuillez noter qu'actuellement, la mise \u00e0 jour automatique du service n'est pas disponible, les mises \u00e0 jour devront donc se faire manuellement.",
"WizardCompleted": "C'est tout ce dont nous avons besoin pour l'instant. Emby a commenc\u00e9 \u00e0 collecter les informations de votre biblioth\u00e8que de m\u00e9dias. Jetez un oeil \u00e0 quelques unes de nos applications, puis cliquez sur <b>Terminer<\/b> pour consulter le <b>Tableau de bord du serveur<\/b>.",
"LabelConfigureSettings": "Configurer les param\u00e8tres",
@@ -52,6 +52,8 @@
"HeaderAddUser": "Ajouter un utilisateur",
"LabelAddConnectSupporterHelp": "Pour ajouter un utilisateur non list\u00e9, vous devrez d'abord lier son compte \u00e0 Emby Connect depuis sa page de profil utilisateur.",
"LabelPinCode": "Code PIN:",
+ "OptionHideWatchedContentFromLatestMedia": "Masquer le contenu d\u00e9j\u00e0 vu dans les derniers m\u00e9dias",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Annuler",
"ButtonExit": "Sortie",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Rien ici.",
"MessagePleaseEnsureInternetMetadata": "Veuillez vous assurer que le t\u00e9l\u00e9chargement des m\u00e9tadonn\u00e9es depuis Internet est activ\u00e9.",
"TabSuggested": "Sugg\u00e9r\u00e9s",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Plus r\u00e9cents",
"TabUpcoming": "\u00c0 venir",
"TabShows": "S\u00e9ries",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Enregistrer le programme sur toutes les cha\u00eenes",
"OptionRecordAnytime": "Enregistrer le programme \u00e0 n'importe quelle heure\/journ\u00e9e",
"OptionRecordOnlyNewEpisodes": "Enregistrer seulement les nouveaux \u00e9pisodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Jours",
"HeaderActiveRecordings": "Enregistrements actifs",
"HeaderLatestRecordings": "Derniers enregistrements",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Seconde section du portail :",
"LabelHomePageSection3": "Troisi\u00e8me section du portail :",
"LabelHomePageSection4": "Quatri\u00e8me section du portail:",
- "OptionMyViewsButtons": "Mes vues (bouttons)",
- "OptionMyViews": "Mes vues",
- "OptionMyViewsSmall": "Mes vues (petit)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Reprendre",
"OptionLatestMedia": "Les plus r\u00e9cents",
"OptionLatestChannelMedia": "Items de cha\u00eene les plus r\u00e9cents",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Par d\u00e9faut",
"OptionCommunityMostWatchedSort": "Les plus lus",
"TabNextUp": "Prochains \u00e0 voir",
+ "PlaceholderUsername": "Identifiant",
"HeaderBecomeProjectSupporter": "Devenir un fan d'Emby",
- "TextEnjoyBonusFeatures": "Profitez bien des fonctionnalit\u00e9s bonus",
"MessageNoMovieSuggestionsAvailable": "Aucune suggestion de film n'est actuellement disponible. Commencez \u00e0 regarder et notez vos films pour avoir des suggestions.",
"MessageNoCollectionsAvailable": "Les collections vous permettent de tirer parti de groupements personnalis\u00e9s de films, de s\u00e9ries, d'albums audio, de livres et de jeux. Cliquez sur le bouton + pour commencer \u00e0 cr\u00e9er des Collections.",
"MessageNoPlaylistsAvailable": "Les listes de lectures vous permettent de cr\u00e9er des listes de contenus \u00e0 lire en continu en une fois. Pour ajouter un \u00e9l\u00e9ment \u00e0 la liste, faire un clic droit ou appuyer et maintenez, puis s\u00e9lectionnez Ajouter \u00e0 la liste de lecture",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "T\u00e9l\u00e9charger les m\u00e9ta-donn\u00e9es depuis Internet pour :",
"OptionTVMovies": "T\u00e9l\u00e9films",
"HeaderUpcomingMovies": "Films \u00e0 venir",
+ "HeaderUpcomingSports": "Ev\u00e9nements sportifs \u00e0 venir",
"HeaderUpcomingPrograms": "Programmes \u00e0 venir",
"ButtonMoreItems": "Plus...",
"LabelShowLibraryTileNames": "Voir les noms des affiches de la biblioth\u00e8que",
"LabelShowLibraryTileNamesHelp": "D\u00e9termine si les noms doivent \u00eatre affich\u00e9s en dessous des affiches de la biblioth\u00e8que sur la page d'accueil",
- "OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottle": "Activer le throttling",
+ "OptionEnableTranscodingThrottleHelp": "Le throttling consiste \u00e0 ajuster automatiquement la fr\u00e9quence de transcodage afin de minimiser l'utilisation CPU pendant la lecture.",
+ "LabelUploadSpeedLimit": "D\u00e9bit max d'upload (mbps) :",
+ "OptionAllowSyncTranscoding": "Autoriser la synchronisation quand elle n\u00e9cessite un transcodage",
+ "HeaderPlayback": "Lecture du m\u00e9dia",
+ "OptionAllowAudioPlaybackTranscoding": "Autoriser la lecture de musique n\u00e9cessitant un transcodage",
+ "OptionAllowVideoPlaybackTranscoding": "Autoriser la lecture de vid\u00e9os n\u00e9cessitant un transcodage",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Les utilisateurs recevront un message d'erreur compr\u00e9hensible lorsque le contenu n'est pas lisible en raison des restrictions appliqu\u00e9es.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Limite de d\u00e9bit du client distant (mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "Une limite de d\u00e9bit optionnelle du streaming pour tous les clients distant. Utile pour \u00e9viter que les clients demandent une bande passante sup\u00e9rieure \u00e0 ce que votre connexion peu fournir.",
+ "LabelConversionCpuCoreLimit": "Limite de c\u0153ur CPU:",
+ "LabelConversionCpuCoreLimitHelp": "Limite le nombre de c\u0153ur du processeur utilis\u00e9s pendant le transcodage.",
+ "OptionEnableFullSpeedConversion": "Autoriser le transcodage rapide",
+ "OptionEnableFullSpeedConversionHelp": "Par d\u00e9faut, le transcodage est r\u00e9alis\u00e9 de mani\u00e8re lente pour r\u00e9duire la consommation de ressources.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/he.json b/MediaBrowser.Server.Implementations/Localization/Server/he.json
index 6ccbee4a7..dd8dd35e2 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/he.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/he.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "\u05d0\u05e9\u05e8",
"ButtonCancel": "\u05d1\u05d8\u05dc",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "\u05d0\u05d9\u05df \u05db\u05d0\u05df \u05db\u05dc\u05d5\u05dd.",
"MessagePleaseEnsureInternetMetadata": "\u05d1\u05d1\u05e7\u05e9\u05d4 \u05d5\u05d5\u05d3\u05d0 \u05db\u05d9 \u05d4\u05d5\u05e8\u05d3\u05ea \u05de\u05d9\u05d3\u05e2 \u05de\u05d4\u05d0\u05d9\u05e0\u05d8\u05e8\u05e0\u05d8 \u05de\u05d0\u05d5\u05e4\u05e9\u05e8\u05ea",
"TabSuggested": "\u05de\u05de\u05d5\u05dc\u05e5",
+ "TabSuggestions": "Suggestions",
"TabLatest": "\u05d0\u05d7\u05e8\u05d5\u05df",
"TabUpcoming": "\u05d1\u05e7\u05e8\u05d5\u05d1",
"TabShows": "\u05ea\u05d5\u05db\u05e0\u05d9\u05d5\u05ea",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "\u05d4\u05e7\u05dc\u05d8 \u05ea\u05d5\u05db\u05e0\u05d9\u05d5\u05ea \u05d1\u05db\u05dc \u05d4\u05e2\u05e8\u05d5\u05e6\u05d9\u05dd",
"OptionRecordAnytime": "\u05d4\u05e7\u05dc\u05d8 \u05ea\u05d5\u05db\u05e0\u05d9\u05ea \u05d1\u05db\u05dc \u05d6\u05de\u05df",
"OptionRecordOnlyNewEpisodes": "\u05d4\u05e7\u05dc\u05d8 \u05e8\u05e7 \u05e4\u05e8\u05e7\u05d9\u05dd \u05d7\u05d3\u05e9\u05d9\u05dd",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "\u05d9\u05de\u05d9\u05dd",
"HeaderActiveRecordings": "\u05d4\u05e7\u05dc\u05d8\u05d5\u05ea \u05e4\u05e2\u05d9\u05dc\u05d5\u05ea",
"HeaderLatestRecordings": "\u05d4\u05e7\u05dc\u05d8\u05d5\u05ea \u05d0\u05d7\u05e8\u05d5\u05e0\u05d5\u05ea",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "\u05e4\u05d5\u05e8\u05d8 Web socket:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/hr.json b/MediaBrowser.Server.Implementations/Localization/Server/hr.json
index c9de0acda..a22df842b 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/hr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/hr.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Odustani",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Ni\u0161ta ovdje.",
"MessagePleaseEnsureInternetMetadata": "Molimo provjerite da je preuzimanje metadata sa interneta omogu\u0107eno.",
"TabSuggested": "Preporu\u010deno",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Zadnje",
"TabUpcoming": "Uskoro",
"TabShows": "Emisije",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Snimi emisiju na svim kanalima",
"OptionRecordAnytime": "Snimi emisiju u bilo koje vrijeme",
"OptionRecordOnlyNewEpisodes": "Snimi samo nove epizode",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Dani",
"HeaderActiveRecordings": "Aktivna snimanja",
"HeaderLatestRecordings": "Zadnje snimke",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Port Web priklju\u010dka:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/it.json b/MediaBrowser.Server.Implementations/Localization/Server/it.json
index 79be970d6..137a45965 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/it.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/it.json
@@ -1,16 +1,16 @@
{
"LabelExit": "Esci",
- "LabelVisitCommunity": "Visita Comunit\u00e0",
+ "LabelVisitCommunity": "Visita la Community",
"LabelGithub": "Github",
"LabelSwagger": "Swagger",
"LabelStandard": "Standard",
- "LabelApiDocumentation": "Documentazione Api",
- "LabelDeveloperResources": "Risorse programmatori",
+ "LabelApiDocumentation": "Documentazione sulle Api",
+ "LabelDeveloperResources": "Risorse per i programmatori",
"LabelBrowseLibrary": "Esplora la libreria",
"LabelConfigureServer": "Configura Emby",
"LabelOpenLibraryViewer": "Apri visualizzatore libreria",
"LabelRestartServer": "Riavvia Server",
- "LabelShowLogWindow": "Mostra Finestra log",
+ "LabelShowLogWindow": "Mostra finestra dei log",
"LabelPrevious": "Precedente",
"LabelFinish": "Finito",
"LabelNext": "Prossimo",
@@ -27,31 +27,33 @@
"WindowsServiceIntro1": "Emby Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.",
"WindowsServiceIntro2": "Se si utilizza il servizio di Windows, si ricorda che non pu\u00f2 essere eseguito allo stesso tempo con l'icona di sistema, quindi devi chiudere l'applicazione al fine di eseguire il servizio. Il servizio dovr\u00e0 anche essere configurato con privilegi amministrativi tramite il pannello di controllo. Si prega di notare che in questo momento il servizio non \u00e8 in grado di Autoaggiornarsi, quindi le nuove versioni richiedono l'interazione manuale",
"WizardCompleted": "That's all we need for now. Emby has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Server Dashboard<\/b>.",
- "LabelConfigureSettings": "Configura",
+ "LabelConfigureSettings": "Configura le impostazioni",
"LabelEnableVideoImageExtraction": "Abilita estrazione immagine video",
- "VideoImageExtractionHelp": "Per i video che sono sprovvisti di immagini, e per i quali non siamo riusciti a trovare immagini su Internet.Questo aggiunger\u00e0 del tempo addizionale alla scansione della tua libreria ma si tradurr\u00e0 in una presentazione pi\u00f9 piacevole.",
- "LabelEnableChapterImageExtractionForMovies": "Estrazione immagine capitolo estratto per i Film",
+ "VideoImageExtractionHelp": "Per i video che sono sprovvisti di immagini, e per i quali non siamo riusciti a trovare immagini su Internet. Questa opzione allungher\u00e0 il tempo di scansione della tua libreria ma si tradurr\u00e0 in una presentazione pi\u00f9 gradevole.",
+ "LabelEnableChapterImageExtractionForMovies": "Estrazione immagine del capitolo per i Film",
"LabelChapterImageExtractionForMoviesHelp": "L'estrazione delle immagini dai capitoli permetter\u00e0 ai client di avere un men\u00f9 grafico per la selezione delle scene. Il processo potrebbe essere lento, con uso intensivo della CPU e potrebbe richiedere diversi gigabyte di spazio. Viene avviato durante la notte, ad ogni modo \u00e8 configurabile nella sezione azioni pianificate. Non \u00e8 raccomandato l'avvio di questo processo durante le ore di massimo utilizzo.",
- "LabelEnableAutomaticPortMapping": "Abilita mappatura delle porte automatiche",
- "LabelEnableAutomaticPortMappingHelp": "UPnP consente la configurazione automatica del router per l'accesso remoto facile. Questo potrebbe non funzionare con alcuni modelli di router.",
- "HeaderTermsOfService": "Emby termini di servizio",
+ "LabelEnableAutomaticPortMapping": "Abilita mappatura automatica delle porte",
+ "LabelEnableAutomaticPortMappingHelp": "UPnP consente la configurazione automatica del router per facilitare l'accesso remoto. Questa opzione potrebbe non funzionare con alcuni modelli di router.",
+ "HeaderTermsOfService": "Termini di servizio di Emby",
"MessagePleaseAcceptTermsOfService": "Per favore accetta i termini di servizio e l'informativa sulla privacy prima di continuare.",
"OptionIAcceptTermsOfService": "Accetto i termini di servizio",
"ButtonPrivacyPolicy": "Informativa sulla privacy",
"ButtonTermsOfService": "Termini di Servizio",
- "HeaderDeveloperOptions": "Opzioni Sviluppatore",
- "OptionEnableWebClientResponseCache": "Abilita la cache del client web",
+ "HeaderDeveloperOptions": "Opzioni per il programmatore",
+ "OptionEnableWebClientResponseCache": "Abilita il caching delle risposte del client",
"OptionDisableForDevelopmentHelp": "Configura questi parametri per sviluppatori del client web",
"OptionEnableWebClientResourceMinification": "Abilita la minimizzazione delle risorse del client web",
- "LabelDashboardSourcePath": "Percorso sorgente client web",
+ "LabelDashboardSourcePath": "Percorso del codice sorgente del client web:",
"LabelDashboardSourcePathHelp": "se si sta eseguendo il server da una sorgente, specifica il percorso dell'interfaccia. Tutti i file per i client saranno presi da questo percorso",
"ButtonConvertMedia": "Converti media",
"ButtonOrganize": "Organizza",
"LinkedToEmbyConnect": "Collegato a Emby Connect",
- "HeaderSupporterBenefits": "Supporter Benefits",
- "HeaderAddUser": "Add User",
- "LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
+ "HeaderSupporterBenefits": "Benefici per il Supporter",
+ "HeaderAddUser": "Aggiungi utente",
+ "LabelAddConnectSupporterHelp": "Per aggiungere un utente non in lista, dovrai prima collegare il suo account a Emby Connect dalla pagina del suo profilo",
"LabelPinCode": "Codice Pin",
+ "OptionHideWatchedContentFromLatestMedia": "Nasconde i contenuti visti dagli Ultimi Media",
+ "HeaderSync": "Sincronizza",
"ButtonOk": "OK",
"ButtonCancel": "Annulla",
"ButtonExit": "Esci",
@@ -60,31 +62,31 @@
"HeaderAudio": "Audio",
"HeaderVideo": "Video",
"HeaderPaths": "Percorsi",
- "CategorySync": "Sinc.zza",
+ "CategorySync": "Sincronizza",
"TabPlaylist": "Playlist",
- "HeaderEasyPinCode": "Codice pin",
+ "HeaderEasyPinCode": "Codice pin semplificato",
"HeaderGrownupsOnly": "Solo adulti",
- "DividerOr": "- o -",
+ "DividerOr": "-- o --",
"HeaderInstalledServices": "Servizi installati",
"HeaderAvailableServices": "Servizi disponibili",
"MessageNoServicesInstalled": "Nessun servizio attualmente installato",
- "HeaderToAccessPleaseEnterEasyPinCode": "Per accedere per favore inserisci il tuo codice pin",
+ "HeaderToAccessPleaseEnterEasyPinCode": "Per accedere per favore inserisci il tuo codice pin semplificato",
"KidsModeAdultInstruction": "Clicca sull'icona del lucchetto nell'angolo in basso a destra per configurare o abbandonare la modalit\u00e0 bambini. Verr\u00e0 richiesto il tuo codice pin",
"ButtonConfigurePinCode": "Configura codice pin",
"HeaderAdultsReadHere": "Adulti leggete qui!",
- "RegisterWithPayPal": "Registra con PayPal",
+ "RegisterWithPayPal": "Registrati con PayPal",
"HeaderSyncRequiresSupporterMembership": "La sincronizzazione richiede un'iscrizione come supporter",
- "HeaderEnjoyDayTrial": "Goditi la tua prova gratuita di 14 giorni",
- "LabelSyncTempPath": "Percorso file temporanei",
- "LabelSyncTempPathHelp": "Specifica una cartella per la sincronizzazione. I file multimediali convertiti durante la sincronizzazione verranno collocati qui.",
+ "HeaderEnjoyDayTrial": "Goditi una prova gratuita per 14 giorni",
+ "LabelSyncTempPath": "Percorso file temporanei:",
+ "LabelSyncTempPathHelp": "Specifica una cartella per la sincronizzazione. I file multimediali convertiti durante la sincronizzazione verranno memorizzati qui.",
"LabelCustomCertificatePath": "Percorso certificati personalizzato:",
- "LabelCustomCertificatePathHelp": "Fornire un tuo file .pfx certificato SSL. Se omesso, il server creer\u00e0 un certificato auto-firmato.",
+ "LabelCustomCertificatePathHelp": "Fornisci il tuo file .pfx certificato SSL. Se omesso, il server creer\u00e0 un certificato auto-firmato.",
"TitleNotifications": "Notifiche",
"ButtonDonateWithPayPal": "Effettua una donazione con PayPal",
"OptionDetectArchiveFilesAsMedia": "Considera gli archivi come file multimediali",
"OptionDetectArchiveFilesAsMediaHelp": "se attivato, i file con estensione .rar e .zip saranno considerati come file multimediali.",
"LabelEnterConnectUserName": "Nome Utente o email:",
- "LabelEnterConnectUserNameHelp": "This is your Emby online account user name or password.",
+ "LabelEnterConnectUserNameHelp": "Questa \u00e8 la username o la password del tuo account online Emby",
"LabelEnableEnhancedMovies": "Abilita le visuali film migliorate",
"LabelEnableEnhancedMoviesHelp": "Quando abilitato, i film verranno mostrati come cartelle che includono i trailer, gli extra, il cast & crew, e altri contenuti correlati.",
"HeaderSyncJobInfo": "Attiv. di Sinc.",
@@ -100,8 +102,8 @@
"FolderTypeTvShows": "Tv",
"FolderTypeInherit": "ereditare",
"LabelContentType": "Tipo di contenuto:",
- "TitleScheduledTasks": "Compiti Pianificati",
- "HeaderSetupLibrary": "Configura la tua libreria",
+ "TitleScheduledTasks": "Task pianificati",
+ "HeaderSetupLibrary": "Configura la tua libreria di contenuti multimediali",
"ButtonAddMediaFolder": "Aggiungi cartella",
"LabelFolderType": "Tipo cartella",
"ReferToMediaLibraryWiki": "Fare riferimento alla wiki libreria multimediale.",
@@ -109,14 +111,14 @@
"LabelLanguage": "Lingua:",
"LabelTimeLimitHours": "Tempo limite (ore):",
"ButtonJoinTheDevelopmentTeam": "Unisciti al Team di Sviluppo",
- "HeaderPreferredMetadataLanguage": "Lingua dei metadati preferita:",
+ "HeaderPreferredMetadataLanguage": "Lingua preferita per i metadati:",
"LabelSaveLocalMetadata": "Salva immagini e metadati nelle cartelle multimediali",
- "LabelSaveLocalMetadataHelp": "Il salvataggio di immagini e dei metadati direttamente nelle cartelle multimediali verranno messe in un posto dove possono essere facilmente modificate.",
+ "LabelSaveLocalMetadataHelp": "Il salvataggio di immagini e metadati direttamente nelle cartelle multimediali consentir\u00e0 di tenerli in un posto dove possono essere facilmente modificati.",
"LabelDownloadInternetMetadata": "Scarica immagini e metadati da internet",
- "LabelDownloadInternetMetadataHelp": "Emby Server can download information about your media to enable rich presentations.",
+ "LabelDownloadInternetMetadataHelp": "Il Server Emby pu\u00f2 scaricare informazioni sui tuoi media per ottenere presentazioni pi\u00f9 complete",
"TabPreferences": "Preferenze",
"TabPassword": "Password",
- "TabLibraryAccess": "Accesso libreria",
+ "TabLibraryAccess": "Accesso alla libreria",
"TabAccess": "Accesso",
"TabImage": "Immagine",
"TabProfile": "Profilo",
@@ -124,24 +126,24 @@
"TabImages": "Immagini",
"TabNotifications": "Notifiche",
"TabCollectionTitles": "Titolo",
- "HeaderDeviceAccess": "Accesso dispositivo",
+ "HeaderDeviceAccess": "Accesso al dispositivo",
"OptionEnableAccessFromAllDevices": "Abilitare l'accesso da tutti i dispositivi",
"OptionEnableAccessToAllChannels": "Abilita l'accesso a tutti i canali",
"OptionEnableAccessToAllLibraries": "Abilita l'accesso a tutte le librerie",
"DeviceAccessHelp": "Questo vale solo per i dispositivi che possono essere identificati in modo univoco e non impedire l'accesso del browser. Filtraggio di accesso al dispositivo dell'utente impedir\u00e0 loro di usare nuovi dispositivi fino a quando non sono state approvate qui.",
"LabelDisplayMissingEpisodesWithinSeasons": "Visualizza gli episodi mancanti nelle stagioni",
"LabelUnairedMissingEpisodesWithinSeasons": "Visualizzare episodi mai andati in onda all'interno stagioni",
- "HeaderVideoPlaybackSettings": "Impostazioni di riproduzione video",
- "HeaderPlaybackSettings": "Impostazioni di riproduzione",
- "LabelAudioLanguagePreference": "Preferenze lingua audio:",
- "LabelSubtitleLanguagePreference": "Preferenze lingua dei sottotitoli:",
+ "HeaderVideoPlaybackSettings": "Impostazioni per la riproduzione di video",
+ "HeaderPlaybackSettings": "Impostazioni per la riproduzione",
+ "LabelAudioLanguagePreference": "Preferenza per la lingua dell'audio:",
+ "LabelSubtitleLanguagePreference": "Preferenza per la lingua dei sottotitoli:",
"OptionDefaultSubtitles": "Predefinito",
"OptionOnlyForcedSubtitles": "Solo i sottotitoli forzati",
"OptionAlwaysPlaySubtitles": "Visualizza sempre i sottotitoli",
"OptionNoSubtitles": "Nessun Sottotitolo",
"OptionDefaultSubtitlesHelp": "I sottotitoli corrispondenti alla lingua preferita saranno caricati quando l'audio \u00e8 in una lingua straniera.",
"OptionOnlyForcedSubtitlesHelp": "Solo i sottotitoli contrassegnati come forzati saranno caricati.",
- "OptionAlwaysPlaySubtitlesHelp": "I sottotitoli corrispondenti alla lingua preferita saranno caricati a prescindere dalla lingua audio.",
+ "OptionAlwaysPlaySubtitlesHelp": "I sottotitoli corrispondenti alla lingua preferita saranno caricati a prescindere dalla lingua dell'audio.",
"OptionNoSubtitlesHelp": "I sottotitoli non verranno caricati di default.",
"TabProfiles": "Profili",
"TabSecurity": "Sicurezza",
@@ -162,18 +164,19 @@
"LabelSelectUsers": "Seleziona Utenti:",
"ButtonUpload": "Carica",
"HeaderUploadNewImage": "Carica nuova immagine",
- "LabelDropImageHere": "Trascina l'immagine qui",
+ "LabelDropImageHere": "Rilasciare l'immagine qui",
"ImageUploadAspectRatioHelp": "1:1 Rapporto dimensioni raccomandato. Solo JPG\/PNG.",
"MessageNothingHere": "Niente qui.",
"MessagePleaseEnsureInternetMetadata": "Assicurarsi che il download dei metadati internet sia abilitato.",
"TabSuggested": "Suggeriti",
+ "TabSuggestions": "Suggerimenti",
"TabLatest": "Novit\u00e0",
"TabUpcoming": "In Arrivo",
- "TabShows": "Serie",
+ "TabShows": "Spettacoli",
"TabEpisodes": "Episodi",
"TabGenres": "Generi",
"TabPeople": "Attori",
- "TabNetworks": "Internet",
+ "TabNetworks": "Reti",
"HeaderUsers": "Utenti",
"HeaderFilters": "Filtri",
"ButtonFilter": "Filtro",
@@ -182,18 +185,18 @@
"OptionDislikes": "Brutti",
"OptionActors": "Attori",
"OptionGuestStars": "Personaggi Famosi",
- "OptionDirectors": "Registra",
- "OptionWriters": "Scrittore",
- "OptionProducers": "Produttore",
+ "OptionDirectors": "Registi",
+ "OptionWriters": "Sceneggiatori",
+ "OptionProducers": "Produttori",
"HeaderResume": "Riprendi",
- "HeaderNextUp": "Da vedere",
- "NoNextUpItemsMessage": "Trovato nessuno. Inizia a guardare i tuoi programmi!",
+ "HeaderNextUp": "Prossimo",
+ "NoNextUpItemsMessage": "Trovato niente. Inizia a guardare i tuoi programmi!",
"HeaderLatestEpisodes": "Ultimi Episodi Aggiunti",
"HeaderPersonTypes": "Tipo Persone:",
"TabSongs": "Canzoni",
"TabAlbums": "Album",
"TabArtists": "Artisti",
- "TabAlbumArtists": "Artisti Album",
+ "TabAlbumArtists": "Artisti degli album",
"TabMusicVideos": "Video Musicali",
"ButtonSort": "Ordina",
"HeaderSortBy": "Ordina per:",
@@ -207,7 +210,7 @@
"OptionPlayCount": "Visto N\u00b0",
"OptionDatePlayed": "Visto il",
"OptionDateAdded": "Aggiunto il",
- "OptionAlbumArtist": "Artista Album",
+ "OptionAlbumArtist": "Artista dell'album",
"OptionArtist": "Artista",
"OptionAlbum": "Album",
"OptionTrackName": "Nome Brano",
@@ -217,18 +220,18 @@
"OptionBudget": "Budget",
"OptionRevenue": "Recensione",
"OptionPoster": "Locandina",
- "OptionPosterCard": "scheda poster",
+ "OptionPosterCard": "Scheda locandina",
"OptionBackdrop": "Sfondo",
- "OptionTimeline": "Anno",
- "OptionThumb": "Sfondo",
+ "OptionTimeline": "Cronologia",
+ "OptionThumb": "Pollice",
"OptionThumbCard": "carta Thumb",
"OptionBanner": "Banner",
- "OptionCriticRating": "Voto critica",
+ "OptionCriticRating": "Voto della critica",
"OptionVideoBitrate": "Bitrate Video",
"OptionResumable": "Interrotti",
- "ScheduledTasksHelp": "Fare clic su una voce per cambiare la pianificazione.",
+ "ScheduledTasksHelp": "Fare clic su una voce per cambiare la sua pianificazione.",
"ScheduledTasksTitle": "Operazioni Pianificate",
- "TabMyPlugins": "Plugins Installati",
+ "TabMyPlugins": "Plugin installati",
"TabCatalog": "Catalogo",
"TitlePlugins": "Plugins",
"HeaderAutomaticUpdates": "Aggiornamenti Automatici",
@@ -286,17 +289,17 @@
"TitleSupport": "Supporto",
"TabLog": "Eventi",
"TabAbout": "Info",
- "TabSupporterKey": "Chiave finanziatore",
- "TabBecomeSupporter": "Diventa finanziatore",
- "ProjectHasCommunity": "Emby has a thriving community of users and contributors.",
- "CheckoutKnowledgeBase": "Check out our knowledge base to help you get the most out of Emby.",
- "SearchKnowledgeBase": "Cerca sulla guida online",
- "VisitTheCommunity": "Visita la nostra comunit\u00e0",
- "VisitProjectWebsite": "Visit the Emby Web Site",
- "VisitProjectWebsiteLong": "Visit the Emby Web site to catch the latest news and keep up with the developer blog.",
+ "TabSupporterKey": "Chiave del Supporter",
+ "TabBecomeSupporter": "Diventa un Supporter",
+ "ProjectHasCommunity": "Emby ha una ricca community di utilizzatori e collaboratori",
+ "CheckoutKnowledgeBase": "Scopri la nostra Knoledge Base per ottenere il massimo da Emby",
+ "SearchKnowledgeBase": "Cerca nella guida online",
+ "VisitTheCommunity": "Visita la nostra Community",
+ "VisitProjectWebsite": "Visita il sito di Emby",
+ "VisitProjectWebsiteLong": "Visita il sito web di Emby per tenerti aggiornato con le ultime novit\u00e0 e le notizie dal blog degli sviluppatori.",
"OptionHideUser": "Nascondi questo utente dalla schermata di Accesso",
"OptionHideUserFromLoginHelp": "Utile per account nascosti o amministratore. L'utente avr\u00e0 bisogno di accedere manualmente utilizzando la propria username e password",
- "OptionDisableUser": "Disabilita utente",
+ "OptionDisableUser": "Disabilita questo utente",
"OptionDisableUserHelp": "Se disabilitato, il server non sar\u00e0 disponibile per questo utente. La connessione corrente verr\u00e0 TERMINATA",
"HeaderAdvancedControl": "Controlli avanzati",
"LabelName": "Nome:",
@@ -304,12 +307,12 @@
"OptionAllowUserToManageServer": "Consenti a questo utente di accedere alla configurazione del SERVER",
"HeaderFeatureAccess": "Accesso alle funzionalit\u00e0",
"OptionAllowMediaPlayback": "Consentire la riproduzione multimediale",
- "OptionAllowBrowsingLiveTv": "Consenti accesso TV Live",
+ "OptionAllowBrowsingLiveTv": "Consenti accesso alla TV live",
"OptionAllowDeleteLibraryContent": "Consenti l'eliminazione dei media",
"OptionAllowManageLiveTv": "Consenti la gestione di registrazione Live TV",
"OptionAllowRemoteControlOthers": "Consenti controllo remoto di altri utenti",
"OptionAllowRemoteSharedDevices": "Consenti controllo remoto di dispositivi condivisi",
- "OptionAllowRemoteSharedDevicesHelp": "Dispositivi DLNA sono considerati condivisa fino a quando un utente inizia controllarlo.",
+ "OptionAllowRemoteSharedDevicesHelp": "Dispositivi DLNA sono considerati condivisi fino a quando un utente non inizia a controllarli.",
"HeaderRemoteControl": "telecomando",
"OptionMissingTmdbId": "Tmdb Id mancante",
"OptionIsHD": "HD",
@@ -321,7 +324,7 @@
"PismoMessage": "Dona per avere una licenza di Pismo",
"TangibleSoftwareMessage": "Utilizza Tangible Solutions Java\/C# con una licenza su donazione.",
"HeaderCredits": "Crediti",
- "PleaseSupportOtherProduces": "Per favore supporta gli altri prodotti 'GRATIS' che MB utilizza",
+ "PleaseSupportOtherProduces": "Per favore supporta gli altri prodotti gratuiti che utilizziamo",
"VersionNumber": "Versione {0}",
"TabPaths": "Percorsi",
"TabServer": "Server",
@@ -333,21 +336,21 @@
"OptionDev": "Dev (instabile)",
"LabelAllowServerAutoRestart": "Consenti al server di Riavviarsi automaticamente per applicare gli aggiornamenti",
"LabelAllowServerAutoRestartHelp": "Il server si Riavvier\u00e0 solamente quando nessun utente \u00e8 collegato",
- "LabelEnableDebugLogging": "Abilit\u00e0 registro di DEBUG",
+ "LabelEnableDebugLogging": "Attiva la registrazione degli eventi",
"LabelRunServerAtStartup": "Esegui il server all'avvio di windows",
"LabelRunServerAtStartupHelp": "Verr\u00e0 avviata l'icona della barra all'avvio di Windows. Per avviare il servizio di Windows, deselezionare questa ed eseguire il servizio dal pannello di controllo di Windows. Si prega di notare che non \u00e8 possibile eseguire entrambi allo stesso tempo, quindi sar\u00e0 necessario chiudere l'icona sulla barra prima di avviare il servizio.",
"ButtonSelectDirectory": "Seleziona cartella",
"LabelCustomPaths": "Specifica un percorso personalizzato.Lasciare vuoto per usare quello predefinito",
"LabelCachePath": "Percorso Cache:",
- "LabelCachePathHelp": "Questa cartella contiene la cache come files e immagini .",
+ "LabelCachePathHelp": "Specifica la cartella dove memorizzare i file di cache del server, come le immagini",
"LabelImagesByNamePath": "Percorso immagini per nome:",
"LabelImagesByNamePathHelp": "Specificare un percorso personalizzato per le immagini di attori, artisti, generi e case cinematografiche scaricate.",
- "LabelMetadataPath": "Percorso dei file METADATI:",
- "LabelMetadataPathHelp": "Specificare un percorso personalizzato per artwork e metadati scaricati, se non il si vuole salvare nelle cartelle multimediali.",
+ "LabelMetadataPath": "Percorso dei file con i metadati:",
+ "LabelMetadataPathHelp": "Specificare un percorso personalizzato per le immagini e i metadati scaricati, se non si desidera salvarli nelle cartelle multimediali.",
"LabelTranscodingTempPath": "Cartella temporanea per la trascodifica:",
"LabelTranscodingTempPathHelp": "Questa cartella contiene i file di lavoro utilizzati dal transcoder. Specificare un percorso personalizzato, oppure lasciare vuoto per utilizzare l'impostazione predefinita all'interno della cartella dei dati del server.",
"TabBasics": "Base",
- "TabTV": "Serie Tv",
+ "TabTV": "Serie TV",
"TabGames": "Giochi",
"TabMusic": "Musica",
"TabOthers": "Altri",
@@ -357,19 +360,19 @@
"OptionOtherVideos": "Altri Video",
"TitleMetadata": "Metadati",
"LabelAutomaticUpdates": "Abilita gli aggiornamenti automatici",
- "LabelAutomaticUpdatesTmdb": "Abilita gli aggiornamenti automatici per TheMovieDB.org",
- "LabelAutomaticUpdatesTvdb": "Abilita gli aggiornamenti automatici per TheTVDB.com",
+ "LabelAutomaticUpdatesTmdb": "Abilita gli aggiornamenti automatici da TheMovieDB.org",
+ "LabelAutomaticUpdatesTvdb": "Abilita gli aggiornamenti automatici da TheTVDB.com",
"LabelAutomaticUpdatesFanartHelp": "Se abilitato le nuove immagini verranno scaricate automaticamente da fanart.tv. Le immagini esistenti non verranno sovrascritte.",
"LabelAutomaticUpdatesTmdbHelp": "Se abilitato le nuove immagini verranno scaricate automaticamente da ThemovieDb.org. Le immagini esistenti non verranno sovrascritte.",
"LabelAutomaticUpdatesTvdbHelp": "Se abilitato le nuove immagini verranno scaricate automaticamente da TheTvDB.com. Le immagini esistenti non verranno sovrascritte.",
"LabelFanartApiKey": "Chiavi API personali",
- "LabelFanartApiKeyHelp": "I risultati di richieste per fanart senza una chiave API personale che sono state approvate pi\u00f9 di 7 giorni fa. Con una chiave API personale questo tempo scende a 48 ore, e se sei un membro VIP scender\u00e0 ulteriormente a circa 10 minuti.",
+ "LabelFanartApiKeyHelp": "Le richieste di fanart effettuate senza una chiave API personale restituiranno risultati approvati pi\u00f9 di 7 giorni fa. Con una chiave API personale questo tempo scende a 48 ore, e se sei un membro VIP questo tempo scender\u00e0 ulteriormente a circa 10 minuti.",
"ExtractChapterImagesHelp": "L'estrazione delle immagini dai capitoli permetter\u00e0 ai client di avere un men\u00f9 grafico per la selezione delle scene. Il processo potrebbe essere lento, con uso intensivo della CPU e potrebbe richiedere diversi gigabyte di spazio. Viene avviato quando vengono trovati nuovi video, e anche durante la notte, ad ogni modo \u00e8 configurabile nella sezione azioni pianificate. Non \u00e8 raccomandato l'avvio di questo processo durante le ore di massimo utilizzo.",
"LabelMetadataDownloadLanguage": "Lingua preferita per il download:",
"ButtonAutoScroll": "Scorrimento automatico",
"LabelImageSavingConvention": "Convenzione per il salvataggio di immagini:",
- "LabelImageSavingConventionHelp": "Emby recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
- "OptionImageSavingCompatible": "Compatible - Emby\/Kodi\/Plex",
+ "LabelImageSavingConventionHelp": "Emby riconosce le immagini fornite dalle principali applicazioni di gestione di media. Scegliere il formato del download \u00e8 utile se usi anche altri prodotti",
+ "OptionImageSavingCompatible": "Compatibile - Emby\/Kodi\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Accedi",
"TitleSignIn": "Accedi",
@@ -389,7 +392,7 @@
"TabMyLibrary": "Mia Libreria",
"ButtonCancelRecording": "Annulla la registrazione",
"HeaderPrePostPadding": "Pre\/Post Registrazione",
- "LabelPrePaddingMinutes": "Pre registrazione minuti",
+ "LabelPrePaddingMinutes": "Minuti di pre-registrazione:",
"OptionPrePaddingRequired": "Attiva pre registrazione",
"LabelPostPaddingMinutes": "Minuti post registrazione",
"OptionPostPaddingRequired": "Attiva post registrazione",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Registra su tutti i canali",
"OptionRecordAnytime": "Registra a qualsiasi ora",
"OptionRecordOnlyNewEpisodes": "Registra solo i nuovi episodi",
+ "HeaderRepeatingOptions": "Opzioni di ripetizione",
"HeaderDays": "Giorni",
"HeaderActiveRecordings": "Registrazioni Attive",
"HeaderLatestRecordings": "Ultime registrazioni",
@@ -417,11 +421,11 @@
"HeaderDetails": "Dettagli",
"TitleLiveTV": "Tv in diretta",
"LabelNumberOfGuideDays": "Numero di giorni per i quali scaricare i dati della guida:",
- "LabelNumberOfGuideDaysHelp": "Scaricando pi\u00f9 giorni si avr\u00e0 la possibilit\u00e0 di pianificare in anticipo pi\u00f9 programmi e vedere pi\u00f9 liste. 'Auto': MB sceglier\u00e0 automaticamente in base al numero di canali.",
+ "LabelNumberOfGuideDaysHelp": "Scaricando pi\u00f9 giorni si avr\u00e0 la possibilit\u00e0 di pianificare in anticipo pi\u00f9 programmi e vedere pi\u00f9 liste, ma il tempo di download si allungher\u00e0. 'Auto': MB sceglier\u00e0 automaticamente in base al numero di canali.",
"OptionAutomatic": "Automatico",
- "HeaderServices": "Services",
+ "HeaderServices": "Servizi",
"LiveTvPluginRequired": "E' richiesto il servizio LIVE TV per continuare.",
- "LiveTvPluginRequiredHelp": "Installa un servizio disponibile, come Next Pvr or ServerWMC.",
+ "LiveTvPluginRequiredHelp": "Installa un plugin tra quelli disponibili, come Next Pvr o ServerWMC.",
"LabelCustomizeOptionsPerMediaType": "Personalizza per il tipo di supporto:",
"OptionDownloadThumbImage": "Foto",
"OptionDownloadMenuImage": "Men\u00f9",
@@ -435,7 +439,7 @@
"HeaderFetchImages": "Identifica Immagini:",
"HeaderImageSettings": "Impostazioni Immagini",
"TabOther": "Altro",
- "LabelMaxBackdropsPerItem": "Massimo numero di sfondi per oggetto.",
+ "LabelMaxBackdropsPerItem": "Massimo numero di sfondi per oggetto:",
"LabelMaxScreenshotsPerItem": "Massimo numero di foto per oggetto:",
"LabelMinBackdropDownloadWidth": "Massima larghezza sfondo:",
"LabelMinScreenshotDownloadWidth": "Minima larghezza foto:",
@@ -443,21 +447,21 @@
"HeaderAddScheduledTaskTrigger": "Aggiungi operazione",
"ButtonAdd": "Aggiungi",
"LabelTriggerType": "Tipo Evento:",
- "OptionDaily": "Giornal.",
+ "OptionDaily": "Giornaliero",
"OptionWeekly": "Settimanale",
"OptionOnInterval": "Su intervallo",
"OptionOnAppStartup": "All'avvio",
- "OptionAfterSystemEvent": "Dopo un vento di sistema",
+ "OptionAfterSystemEvent": "Dopo un evento di sistema",
"LabelDay": "Giorno:",
"LabelTime": "Ora:",
"LabelEvent": "Evento:",
"OptionWakeFromSleep": "Risveglio:",
"LabelEveryXMinutes": "Tutti:",
- "HeaderTvTuners": "Schede Tv",
+ "HeaderTvTuners": "Sintonizzatori Tv",
"HeaderGallery": "Galleria",
"HeaderLatestGames": "Ultimi giochi",
- "HeaderRecentlyPlayedGames": "Ultimi giochi recenti",
- "TabGameSystems": "Sistema di Giocho",
+ "HeaderRecentlyPlayedGames": "Ultimi giochi eseguiti",
+ "TabGameSystems": "Sistemi di gioco",
"TitleMediaLibrary": "Libreria",
"TabFolders": "Cartelle",
"TabPathSubstitution": "Percorso da sostiuire",
@@ -509,31 +513,31 @@
"OptionMaxQualityTranscoding": "Massima qualit\u00e0",
"OptionEnableDebugTranscodingLogging": "Abilita la registrazione transcodifica di debug",
"OptionEnableDebugTranscodingLoggingHelp": "Questo creer\u00e0 file di log molto grandi ed \u00e8 consigliato solo se necessario per la risoluzione dei problemi.",
- "EditCollectionItemsHelp": "Aggiungi o rimuovi film, serie, album, libri o giochi e che vuoi raggruppare in questa collezione.",
- "HeaderAddTitles": "Aggiungi Titolo",
+ "EditCollectionItemsHelp": "Aggiungi o rimuovi film, serie, album, libri o giochi che desideri raggruppare in questa collezione.",
+ "HeaderAddTitles": "Aggiungi titoli",
"LabelEnableDlnaPlayTo": "Abilita DLNA su",
- "LabelEnableDlnaPlayToHelp": "Emby can detect devices within your network and offer the ability to remote control them.",
+ "LabelEnableDlnaPlayToHelp": "Emby pu\u00f2 individuare i dispositivi attivi in rete e offrire la possibilit\u00e0 di controllarli da remoto",
"LabelEnableDlnaDebugLogging": "Abilita il debug del DLNA",
"LabelEnableDlnaDebugLoggingHelp": "Questo creer\u00e0 file di log di notevoli dimensioni e deve essere abilitato solo per risolvere eventuali problemi",
"LabelEnableDlnaClientDiscoveryInterval": "Intervallo di ricerca dispositivi (secondi)",
- "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Emby.",
+ "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determina la durata in secondi tra le ricerche SSDP effettuate da Emby",
"HeaderCustomDlnaProfiles": "Profili personalizzati",
"HeaderSystemDlnaProfiles": "Profili di sistema",
"CustomDlnaProfilesHelp": "Crea un profilo personalizzato per un nuovo dispositivo o sovrascrivi quello di sistema",
"SystemDlnaProfilesHelp": "I profili di sistema sono in sola lettura. Le modifiche ad un profilo di sistema verranno salvate in un nuovo profilo personalizzato.",
- "TitleDashboard": "Dashboard",
+ "TitleDashboard": "Pannello di controllo",
"TabHome": "Home",
"TabInfo": "Info",
"HeaderLinks": "Links",
"HeaderSystemPaths": "Percorsi di sistema",
- "LinkCommunity": "Comunit\u00e0",
+ "LinkCommunity": "Community",
"LinkGithub": "Github",
"LinkApi": "API",
"LinkApiDocumentation": "Documentazione Api",
"LabelFriendlyServerName": "Nome condiviso del server:",
"LabelFriendlyServerNameHelp": "Questo nome \u00e8 usato per identificare il server sulla rete.Se lasciato vuoto verra usato il nome del pc",
"LabelPreferredDisplayLanguage": "Lingua preferita visualizzata",
- "LabelPreferredDisplayLanguageHelp": "Translating Emby is an ongoing project and is not yet complete.",
+ "LabelPreferredDisplayLanguageHelp": "La traduzione di Emby \u00e8 un'attivit\u00e0 in corso e non \u00e8 ancora conclusa",
"LabelReadHowYouCanContribute": "Leggi come puoi contribuire",
"HeaderNewCollection": "Nuova collezione",
"ButtonSubmit": "Invia",
@@ -541,20 +545,20 @@
"LabelCustomCss": "CSS Personalizzato",
"LabelCustomCssHelp": "Applica il tuo CSS personale all'interfaccia web",
"LabelLocalHttpServerPortNumber": "Porta HTTP locale",
- "LabelLocalHttpServerPortNumberHelp": "The tcp port number that Emby's http server should bind to.",
+ "LabelLocalHttpServerPortNumberHelp": "Numero di porta TCP da associare al server http di Emby",
"LabelPublicHttpPort": "Porta HTTP pubblica",
- "LabelPublicHttpPortHelp": "Il numero di porta pubblica dovrebbe essere mappato verso la porta HTTP locale.",
+ "LabelPublicHttpPortHelp": "Numero di porta pubblica che dovrebbe essere mappato sulla porta HTTP locale.",
"LabelPublicHttpsPort": "Numero porta HTTP pubblica",
- "LabelPublicHttpsPortHelp": "Il numero della porta HTTP pubblica dovrebbe essere mappato verso la porta HTTP locale.",
+ "LabelPublicHttpsPortHelp": "Numero della porta pubblica che dovrebbe essere mappato sulla porta HTTPS locale.",
"LabelEnableHttps": "Riporta HTTPS come indirizzo esterno",
- "LabelEnableHttpsHelp": "se abilitato, il server riporter\u00e0 un url HTTPS ai client come il proprio indirizzo esterno. Questo potrebbe non far funzionare i client che ancora non supportano l'HTTPS",
+ "LabelEnableHttpsHelp": "se abilitato, il server riporter\u00e0 un url HTTPS ai client come il proprio indirizzo esterno.",
"LabelHttpsPort": "Porta HTTPS locale",
- "LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
+ "LabelHttpsPortHelp": "Numero di porta TCP da associare al server https di Emby",
"LabelWebSocketPortNumber": "Numero porta web socket:",
- "LabelEnableAutomaticPortMap": "Abilita mappatura delle porte automatiche",
- "LabelEnableAutomaticPortMapHelp": "Tentativo di mappare automaticamente la porta pubblica alla porta locale tramite UPnP. Questo potrebbe non funzionare con alcuni modelli di router.",
+ "LabelEnableAutomaticPortMap": "Abilita mappatura automatica delle porte",
+ "LabelEnableAutomaticPortMapHelp": "Tenta di mappare automaticamente la porta pubblica sulla porta locale tramite UPnP. Questo potrebbe non funzionare con alcuni modelli di router.",
"LabelExternalDDNS": "Indirizzo WAN esterno",
- "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Emby apps will use it when connecting remotely. Leave empty for automatic detection.",
+ "LabelExternalDDNSHelp": "Se hai un DNS dinamico inserisci l'indirizzo qui. Le app di Emby lo utilizzeranno nelle connessioni remote. Lascia il campo vuoto per sfruttare la rilevazione automatica",
"TabResume": "Riprendi",
"TabWeather": "Tempo",
"TitleAppSettings": "Impostazioni delle app",
@@ -565,7 +569,7 @@
"LabelMaxResumePercentageHelp": "I film sono considerati visti se fermati dopo questo tempo",
"LabelMinResumeDurationHelp": "I film pi\u00f9 corti non saranno riprendibili",
"TitleAutoOrganize": "Organizza Automaticamente",
- "TabActivityLog": "Attivit\u00e0 Eventi",
+ "TabActivityLog": "Registrazione eventi",
"HeaderName": "Nome",
"HeaderDate": "Data",
"HeaderSource": "Sorgente",
@@ -579,13 +583,13 @@
"LabelSeries": "Serie:",
"LabelSeasonNumber": "Numero Stagione:",
"LabelEpisodeNumber": "Numero Episodio :",
- "LabelEndingEpisodeNumber": "Ultimo Episodio Numero:",
+ "LabelEndingEpisodeNumber": "Numero ultimo episodio:",
"LabelEndingEpisodeNumberHelp": "Richiesto solo se ci sono pi\u00f9 file per espisodio",
- "HeaderSupportTheTeam": "Support the Emby Team",
+ "HeaderSupportTheTeam": "Supporta il Team di Emby",
"LabelSupportAmount": "Ammontare (Dollari)",
- "HeaderSupportTheTeamHelp": "Aiutaci a continuare nello sviluppo di questo progetto tramite una donazione. una parte delle donazioni verranno impiegate per lo sviluppo di Plugins gratuiti.",
- "ButtonEnterSupporterKey": "Inserisci il numero di registrazione",
- "DonationNextStep": "Pe favore rientra ed inserisci la chiave di registrazione che hai ricevuto tramite mail.",
+ "HeaderSupportTheTeamHelp": "Aiutaci a continuare lo sviluppo di questo progetto tramite una donazione. Una parte delle donazioni verr\u00e0 impiegata per lo sviluppo di Plugins gratuiti.",
+ "ButtonEnterSupporterKey": "Inserisci il tuo codice Supporter",
+ "DonationNextStep": "Quando hai terminato, per favore rientra ed inserisci il codice Supporter che riceverai per email",
"AutoOrganizeHelp": "Organizzazione automatica monitorizza le cartelle dei file scaricati e li sposter\u00e0 automaticamente nelle tue cartelle dei media.",
"AutoOrganizeTvHelp": "L'organizzazione della TV aggiunger\u00e0 solo episodi nuovi alle serie esistenti. Non verranno create nuove cartelle delle serie.",
"OptionEnableEpisodeOrganization": "Abilita l'organizzazione dei nuovi episodi",
@@ -595,25 +599,25 @@
"LabelMinFileSizeForOrganize": "Dimensioni minime file (MB):",
"LabelMinFileSizeForOrganizeHelp": "I file al di sotto di questa dimensione verranno ignorati.",
"LabelSeasonFolderPattern": "Modello della cartella Stagione:",
- "LabelSeasonZeroFolderName": "Modello della cartella Stagione ZERO:",
+ "LabelSeasonZeroFolderName": "Nome della cartella Stagione Zero:",
"HeaderEpisodeFilePattern": "Modello del file Episodio:",
"LabelEpisodePattern": "Modello Episodio:",
"LabelMultiEpisodePattern": "Modello dei multi-file episodio:",
"HeaderSupportedPatterns": "Modelli supportati",
"HeaderTerm": "Termine",
"HeaderPattern": "Modello",
- "HeaderResult": "Resultato",
+ "HeaderResult": "Risultato",
"LabelDeleteEmptyFolders": "Elimina le cartelle vuote dopo l'organizzazione automatica",
"LabelDeleteEmptyFoldersHelp": "Attivare questa opzione per mantenere la directory di download pulita.",
"LabelDeleteLeftOverFiles": "Elimina i file rimasti con le seguenti estensioni:",
- "LabelDeleteLeftOverFilesHelp": "Separare con ; Per esempio:.. Nfo; txt",
- "OptionOverwriteExistingEpisodes": "Sovrascrivere episodi esistenti",
+ "LabelDeleteLeftOverFilesHelp": "Separare con ;. Per esempio: .nfo;.txt",
+ "OptionOverwriteExistingEpisodes": "Sovrascrive gli episodi esistenti",
"LabelTransferMethod": "Metodo di trasferimento",
"OptionCopy": "Copia",
"OptionMove": "Sposta",
"LabelTransferMethodHelp": "Copiare o spostare i file dalla cartella da monitorizzare",
"HeaderLatestNews": "Ultime Novit\u00e0",
- "HeaderHelpImproveProject": "Help Improve Emby",
+ "HeaderHelpImproveProject": "Aiuta a migliorare Emby",
"HeaderRunningTasks": "Operazioni in corso",
"HeaderActiveDevices": "Dispositivi Connessi",
"HeaderPendingInstallations": "installazioni in coda",
@@ -624,8 +628,8 @@
"ButtonUpdateNow": "Aggiorna Adesso",
"TabHosting": "Hosting",
"PleaseUpdateManually": "Per favore Arresta il server ed aggiorna manualmente",
- "NewServerVersionAvailable": "A new version of Emby Server is available!",
- "ServerUpToDate": "Emby Server is up to date",
+ "NewServerVersionAvailable": "E' disponibile una nuova versione del Server Emby!",
+ "ServerUpToDate": "Il Server Emby \u00e8 aggiornato",
"LabelComponentsUpdated": "I seguenti componenti sono stati installati o aggiornati:",
"MessagePleaseRestartServerToFinishUpdating": "Si prega di riavviare il server per completare l'applicazione degli aggiornamenti.",
"LabelDownMixAudioScale": "Boost audio durante il downmix:",
@@ -642,13 +646,13 @@
"LabelSupporterEmailAddress": "La mail che \u00e8 stata utilizzata per acquistare la chiave",
"ButtonRetrieveKey": "Recupera chiave",
"LabelSupporterKey": "Chiave (incollala dalla mail ricevuta)",
- "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Emby.",
+ "LabelSupporterKeyHelp": "Inserisci il tuo codice Supporter per iniziare a goderti ulteriori funzioni che la community ha sviluppato per Emby",
"MessageInvalidKey": "Chiave Sostenitore mancante o non valida.",
- "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be an Emby Supporter. Please donate and support the continued development of the core product. Thank you.",
+ "ErrorMessageInvalidKey": "Affinch\u00e8 un contenuto premium venga registrato, tu devi anche essere un Supporter di Emby. Per favore, fai una donazione e supporta il continuo sviluppo del prodotto principale. Grazie",
"HeaderDisplaySettings": "Configurazione Monitor",
"TabPlayTo": "Riproduci su",
"LabelEnableDlnaServer": "Abilita server DLNA",
- "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Emby content.",
+ "LabelEnableDlnaServerHelp": "Consente ai dispositivi UPnP nella tua rete di sfogliare i contenuti di Emby e riprodurli",
"LabelEnableBlastAliveMessages": "Invia segnale di presenza",
"LabelEnableBlastAliveMessagesHelp": "Attivare questa opzione se il server non viene rilevato in modo affidabile da altri dispositivi UPnP in rete.",
"LabelBlastMessageInterval": "Intervallo messaggi di presenza (secondi)",
@@ -676,13 +680,13 @@
"NotificationOptionVideoPlayback": "La riproduzione video \u00e8 iniziata",
"NotificationOptionAudioPlayback": "Riproduzione audio iniziata",
"NotificationOptionGamePlayback": "Gioco avviato",
- "NotificationOptionVideoPlaybackStopped": "Video Fermato",
+ "NotificationOptionVideoPlaybackStopped": "Riproduzione video interrotta",
"NotificationOptionAudioPlaybackStopped": "Audio Fermato",
"NotificationOptionGamePlaybackStopped": "Gioco Fermato",
"NotificationOptionTaskFailed": "Operazione pianificata fallita",
"NotificationOptionInstallationFailed": "Installazione fallita",
"NotificationOptionNewLibraryContent": "Nuovo contenuto aggiunto",
- "NotificationOptionNewLibraryContentMultiple": "Nuovi contenuti aggiunti",
+ "NotificationOptionNewLibraryContentMultiple": "Nuovi contenuti aggiunti (multipli)",
"NotificationOptionCameraImageUploaded": "Immagine fotocamera caricata",
"NotificationOptionUserLockedOut": "Utente bloccato",
"HeaderSendNotificationHelp": "Per impostazione predefinita, le notifiche vengono inviate alla casella della pagina principale. Sfoglia il catalogo plugin da installare opzioni di notifica aggiuntive.",
@@ -764,7 +768,7 @@
"LabelUserLibrary": "Libreria utente:",
"LabelUserLibraryHelp": "Selezionare la libreria utente da visualizzare sul dispositivo. Lasciare vuoto per ereditare l'impostazione predefinita.",
"OptionPlainStorageFolders": "Visualizzare tutte le cartelle come normali cartelle di archiviazione",
- "OptionPlainStorageFoldersHelp": "Se abilitato, tutte le cartelle sono rappresentati in DIDL come \"object.container.storageFolder\" invece che di tipo pi\u00f9 specifico, come \"object.container.person.musicArtist\".",
+ "OptionPlainStorageFoldersHelp": "Se abilitato, tutte le cartelle sono rappresentate in DIDL come \"object.container.storageFolder\" invece che di tipo pi\u00f9 specifico, come \"object.container.person.musicArtist\".",
"OptionPlainVideoItems": "Mostra tutti i video come normali file video",
"OptionPlainVideoItemsHelp": "Se attivato, tutti i video sono rappresentati in DIDL come \"object.item.videoItem\" invece che di tipo pi\u00f9 specifico, come \"object.item.videoItem.movie\".",
"LabelSupportedMediaTypes": "Tipi di media supportati:",
@@ -788,7 +792,7 @@
"LabelIconMaxHeight": "Altezza Icona massima:",
"LabelIconMaxHeightHelp": "Risoluzione massima delle icone inviate tramite upnp:icon.",
"LabelIdentificationFieldHelp": "Una stringa o espressione regex sensibile a maiuscole e minuscole.",
- "HeaderProfileServerSettingsHelp": "These values control how Emby Server will present itself to the device.",
+ "HeaderProfileServerSettingsHelp": "Questi valori controllano come il Server Emby si presenter\u00e0 ad un dispositivo.",
"LabelMaxBitrate": "Bitrate Massimo:",
"LabelMaxBitrateHelp": "Specificare un bitrate massimo in presenza di larghezza di banda limitata, o se il dispositivo impone il proprio limite.",
"LabelMaxStreamingBitrate": "Massimo Bitrate streaming",
@@ -829,7 +833,7 @@
"OptionEstimateContentLength": "Stimare la lunghezza contenuto durante la transcodifica",
"OptionReportByteRangeSeekingWhenTranscoding": "Segnala che il server supporta la ricerca di byte durante la transcodifica",
"OptionReportByteRangeSeekingWhenTranscodingHelp": "Questo \u00e8 necessario per alcuni dispositivi che non hanno l'avanzamento rapido che funziona bene.",
- "HeaderSubtitleDownloadingHelp": "When Emby scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
+ "HeaderSubtitleDownloadingHelp": "Quando Emby fa la scansione dei tuoi file video pu\u00f2 cercare i sottotitoli mancanti e scaricarli usando un provider come OpenSubtitles.org.",
"HeaderDownloadSubtitlesFor": "Scarica sottotitoli per:",
"MessageNoChapterProviders": "Installare un plugin provider capitoli come ChapterDb per attivare le opzioni capitolo aggiuntive.",
"LabelSkipIfGraphicalSubsPresent": "Salta se il video contiene gi\u00e0 i sottotitoli grafici",
@@ -839,7 +843,7 @@
"HeaderDownloadChaptersFor": "Scarica i nomi dei capitoli per:",
"LabelOpenSubtitlesUsername": "Nome utente Open Subtitles:",
"LabelOpenSubtitlesPassword": "Password Open Subtitles:",
- "HeaderChapterDownloadingHelp": "When Emby scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.",
+ "HeaderChapterDownloadingHelp": "Quando Emby esegue la scansione dei file video pu\u00f2 scaricare i nomi dei capitoli in modo semplice da internet utilizzando plugin di ricerca capitoli come ChapterDb.",
"LabelPlayDefaultAudioTrack": "Riprodurre la traccia audio di default indipendentemente dalla lingua",
"LabelSubtitlePlaybackMode": "Modalit\u00e0 Sottotitolo:",
"LabelDownloadLanguages": "Scarica lingue:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Pagina Iniziale Sezione 2:",
"LabelHomePageSection3": "Pagina Iniziale Sezione 3:",
"LabelHomePageSection4": "Pagina Iniziale Sezione 4:",
- "OptionMyViewsButtons": "Mie Viste (pulsanti)",
- "OptionMyViews": "Mie Viste",
- "OptionMyViewsSmall": "Mie Viste (piccola)",
+ "OptionMyMediaButtons": "I mei media (pulsanti)",
+ "OptionMyMedia": "I mei media",
+ "OptionMyMediaSmall": "I mei media (piccolo)",
"OptionResumablemedia": "Riprendi",
"OptionLatestMedia": "Ultimi media",
"OptionLatestChannelMedia": "Ultime voci del canale",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Predefinito",
"OptionCommunityMostWatchedSort": "Pi\u00f9 visti",
"TabNextUp": "Da vedere",
- "HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Goditi le caratteristiche aggiuntive",
+ "PlaceholderUsername": "Username",
+ "HeaderBecomeProjectSupporter": "Diventa un Supporter di Emby",
"MessageNoMovieSuggestionsAvailable": "Nessun suggerimento di film attualmente disponibile. Iniziare a guardare e valutare i vostri film, e poi tornare per i suggerimenti.",
"MessageNoCollectionsAvailable": "Le collezioni ti permettono di goderti raccolte personalizzate di Film, Serie TV, Album, Libri e Giochi. Clicca sul + per iniziare a creare le tue Collezioni",
"MessageNoPlaylistsAvailable": "Playlist ti permettere di mettere in coda gli elementi da riprodurre.Usa il tasto destro o tap e tieni premuto quindi seleziona elemento da aggiungere",
@@ -921,7 +925,7 @@
"LabelChannelDownloadAgeHelp": "Contenuti scaricati pi\u00f9 vecchi di questo limite sarnno cancellati. Rimarranno riproducibili via internet in streaming.",
"ChannelSettingsFormHelp": "Installare canali come Trailer e Vimeo nel catalogo plugin.",
"ButtonOptions": "Opzioni",
- "ViewTypePlaylists": "Playlists",
+ "ViewTypePlaylists": "Playlist",
"ViewTypeMovies": "Film",
"ViewTypeTvShows": "Serie Tv",
"ViewTypeGames": "Giochi",
@@ -971,7 +975,7 @@
"TabNfo": "Nfo",
"HeaderKodiMetadataHelp": "Emby includes native support for Nfo metadata files. To enable or disable Nfo metadata, use the Advanced tab to configure options for your media types.",
"LabelKodiMetadataUser": "Sincronizza i dati utente a nfo di per:",
- "LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Emby Server and Nfo files.",
+ "LabelKodiMetadataUserHelp": "Abilita questa opzione per mantenere i dati di orologio sincronizzati tra il Server Emby e i file NFO.",
"LabelKodiMetadataDateFormat": "Data di uscita Formato:",
"LabelKodiMetadataDateFormatHelp": "Tutte le date all'interno del nfo verranno letti e scritti utilizzando questo formato.",
"LabelKodiMetadataSaveImagePaths": "Salva percorsi delle immagini all'interno dei file NFO",
@@ -989,7 +993,7 @@
"TabLogs": "Logs",
"HeaderServerLogFiles": "File log del Server:",
"TabBranding": "Personalizza",
- "HeaderBrandingHelp": "Customize the appearance of Emby to fit the needs of your group or organization.",
+ "HeaderBrandingHelp": "Personalizza l'aspetto di Emby per soddisfare le esigenze del tuo gruppo o della tua organizzazione.",
"LabelLoginDisclaimer": "Avviso Login:",
"LabelLoginDisclaimerHelp": "Questo verr\u00e0 visualizzato nella parte inferiore della pagina di accesso.",
"LabelAutomaticallyDonate": "Donare automaticamente questo importo ogni mese",
@@ -999,13 +1003,13 @@
"TitleServer": "Server",
"LabelCache": "Cache:",
"LabelLogs": "Log:",
- "LabelMetadata": "Metadata:",
+ "LabelMetadata": "Metadati:",
"LabelImagesByName": "Immagini per nome:",
"LabelTranscodingTemporaryFiles": "Transcodifica file temporanei:",
"HeaderLatestMusic": "Musica Recente",
"HeaderBranding": "Personalizza",
"HeaderApiKeys": "Chiavi Api",
- "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Emby Server. Keys are issued by logging in with an Emby account, or by manually granting the application a key.",
+ "HeaderApiKeysHelp": "Le Applicazioni esterne devono avere una chiave API per comunicare con il Server Emby. Le chiavi sono emesse accedendo con un account Emby, o fornendo manualmente una chiave all'applicazione.",
"HeaderApiKey": "Chiave Api",
"HeaderApp": "App",
"HeaderDevice": "Dispositivo",
@@ -1015,8 +1019,8 @@
"HeaderNewApiKey": "Nuova Chiave Api",
"LabelAppName": "Nome app",
"LabelAppNameExample": "Esempio: Sickbeard, NzbDrone",
- "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Emby Server.",
- "HeaderHttpHeaders": "Http Headers",
+ "HeaderNewApiKeyHelp": "Concedere un permesso per applicazione al fine di comunicare con il Server Emby.",
+ "HeaderHttpHeaders": "Intestazioni Http",
"HeaderIdentificationHeader": "Identification Header",
"LabelValue": "valore:",
"LabelMatchType": "Match type:",
@@ -1119,7 +1123,7 @@
"UserDeletedWithName": "Utente {0} \u00e8 stato cancellato",
"MessageServerConfigurationUpdated": "Configurazione server aggioprnata",
"MessageNamedServerConfigurationUpdatedWithValue": "La sezione {0} \u00e8 stata aggiornata",
- "MessageApplicationUpdated": "Emby Server has been updated",
+ "MessageApplicationUpdated": "Il Server Emby \u00e8 stato aggiornato",
"AuthenticationSucceededWithUserName": "{0} Autenticati con successo",
"FailedLoginAttemptWithUserName": "Login fallito da {0}",
"UserDownloadingItemWithValues": "{0} sta scaricando {1}",
@@ -1140,14 +1144,14 @@
"ViewTypeLiveTvRecordingGroups": "Registrazioni",
"ViewTypeLiveTvChannels": "canali",
"LabelEasyPinCode": "Codice Pin",
- "EasyPasswordHelp": "Your easy pin code is used for offline access with supported Emby apps, and can also be used for easy in-network sign in.",
+ "EasyPasswordHelp": "Il codice pin facile viene utilizzato per l'accesso offline con le app Emby supportate, e pu\u00f2 essere utilizzato anche per una facile accesso in rete.",
"LabelInNetworkSignInWithEasyPassword": "Abilita l'accesso da rete locale tramite codice PIN.",
"LabelInNetworkSignInWithEasyPasswordHelp": "If enabled, you'll be able to use your easy pin code to sign in to Emby apps from inside your home network. Your regular password will only be needed away from home. If the pin code is left blank, you won't need a password within your home network.",
"HeaderPassword": "Password",
"HeaderLocalAccess": "Accesso locale",
"HeaderViewOrder": "Visualizza ordine",
"ButtonResetEasyPassword": "Resetta codice PIN",
- "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Emby apps",
+ "LabelSelectUserViewOrder": "Scegli l'ordine in cui le tue viste saranno mostrate all'interno della app di Emby",
"LabelMetadataRefreshMode": "Metadata (modo Aggiornamento)",
"LabelImageRefreshMode": "Immagine (modo Aggiornamento)",
"OptionDownloadMissingImages": "Immagini mancanti",
@@ -1164,7 +1168,7 @@
"LabelIfYouWishToContinueWithDeletion": "Se si desidera continuare, si prega di confermare inserendo il valore di:",
"ButtonIdentify": "Identifica",
"LabelAlbumArtist": "Artista Album",
- "LabelAlbumArtists": "Album artists:",
+ "LabelAlbumArtists": "Artisti:",
"LabelAlbum": "Album:",
"LabelCommunityRating": "Voto Comunit\u00e0:",
"LabelVoteCount": "Totale Voti:",
@@ -1249,10 +1253,10 @@
"OptionSaveMetadataAsHidden": "Salvare i metadati e le immagini come file nascosti",
"LabelExtractChaptersDuringLibraryScan": "Estrarre immagini capitolo durante la scansione biblioteca",
"LabelExtractChaptersDuringLibraryScanHelp": "Se abilitata, le immagini capitolo verranno estratti quando i video vengono importati durante la scansione della libreria. Se disabilitata verranno estratti durante le immagini dei capitoli programmati compito, permettendo la scansione biblioteca regolare per completare pi\u00f9 velocemente.",
- "LabelConnectGuestUserName": "Their Emby username or email address:",
- "LabelConnectUserName": "Emby username\/email:",
+ "LabelConnectGuestUserName": "Username di Emby o indirizzo email:",
+ "LabelConnectUserName": "Username\/email di Emby:",
"LabelConnectUserNameHelp": "Connect this user to an Emby account to enable easy sign-in access from any Emby app without having to know the server ip address.",
- "ButtonLearnMoreAboutEmbyConnect": "Learn more about Emby Connect",
+ "ButtonLearnMoreAboutEmbyConnect": "Scopri di pi\u00f9 su Emby Connect",
"LabelExternalPlayers": "Player esterni:",
"LabelExternalPlayersHelp": "Pulsanti di visualizzazione di riprodurre contenuti in lettori esterni. Questo \u00e8 disponibile solo su dispositivi che supportano schemi URL, generalmente Android e iOS. Con i giocatori esterni vi \u00e8 generalmente alcun supporto per il controllo remoto o ripresa.",
"HeaderSubtitleProfile": "Profilo sottotitolo",
@@ -1300,7 +1304,7 @@
"TitleDevices": "Dispositivi",
"TabCameraUpload": "Caricamenti Fotocamera",
"TabDevices": "Dispositivi",
- "HeaderCameraUploadHelp": "Automatically upload photos and videos taken from your mobile devices into Emby.",
+ "HeaderCameraUploadHelp": "Fa automaticamente l'upload su Emby delle foto e dei video residenti sul tuo telefonino",
"MessageNoDevicesSupportCameraUpload": "Al momento non si dispone di dispositivi che supportano il caricamento della fotocamera.",
"LabelCameraUploadPath": "Fotocamera percorso di upload:",
"LabelCameraUploadPathHelp": "Selezionare un percorso di caricamento personalizzato, se lo si desidera. Se non specificato verr\u00e0 utilizzata una cartella predefinita. Se si utilizza un percorso personalizzato che dovr\u00e0 anche essere aggiunti nella zona di installazione della libreria.",
@@ -1309,10 +1313,10 @@
"LabelCustomDeviceDisplayName": "Nome da visualizzare:",
"LabelCustomDeviceDisplayNameHelp": "Fornire un nome di visualizzazione personalizzato o lasciare vuoto per utilizzare il nome riportato dal dispositivo.",
"HeaderInviteUser": "Invita utente",
- "LabelConnectGuestUserNameHelp": "This is the username that your friend uses to sign in to the Emby website, or their email address.",
- "HeaderInviteUserHelp": "Sharing your media with friends is easier than ever before with Emby Connect.",
+ "LabelConnectGuestUserNameHelp": "Questo \u00e8 lo username che il tuo amico utilizza per accedere al sito web Emby, o il suo indirizzo email.",
+ "HeaderInviteUserHelp": "Condividere i tuo file multimediali con gli amici \u00e8 pi\u00f9 facile che mai con Emby Connect.",
"ButtonSendInvitation": "Invia Invito",
- "HeaderSignInWithConnect": "Sign in with Emby Connect",
+ "HeaderSignInWithConnect": "Accedi con Emby Connect",
"HeaderGuests": "ospiti",
"HeaderLocalUsers": "Utenti locale",
"HeaderPendingInvitations": "Inviti in sospeso",
@@ -1327,8 +1331,8 @@
"OptionEveryday": "Tutti i giorni",
"OptionWeekdays": "Feriali",
"OptionWeekends": "Il Weekend",
- "MessageProfileInfoSynced": "User profile information synced with Emby Connect.",
- "HeaderOptionalLinkEmbyAccount": "Optional: Link your Emby account",
+ "MessageProfileInfoSynced": "Informazioni sul profilo utente sincronizzate con Emby Connect.",
+ "HeaderOptionalLinkEmbyAccount": "Opzionale: collega il tuo account Emby",
"ButtonTrailerReel": "Trailer b.",
"HeaderTrailerReel": "Trailer b.",
"OptionPlayUnwatchedTrailersOnly": "Riproduci solo i trailer non visti",
@@ -1378,13 +1382,36 @@
"LabelTagFilterAllowModeHelp": "Se i tag permessi vengono utilizzati come parte di una struttura di cartelle profondamente nidificate, il contenuto che viene etichettato richieder\u00e0 cartelle principali di essere etichettato come bene.",
"HeaderThisUserIsCurrentlyDisabled": "Questo utente \u00e8 al momento disabilitato",
"MessageReenableUser": "Guarda in basso per ri-abilitare",
- "LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
- "OptionTVMovies": "TV Movies",
- "HeaderUpcomingMovies": "Upcoming Movies",
- "HeaderUpcomingPrograms": "Upcoming Programs",
+ "LabelEnableInternetMetadataForTvPrograms": "Fa il download da Internet dei metadati per:",
+ "OptionTVMovies": "Film TV",
+ "HeaderUpcomingMovies": "Film in arrivo",
+ "HeaderUpcomingSports": "Sport in arrivo",
+ "HeaderUpcomingPrograms": "Programmi in arrivo",
"ButtonMoreItems": "Pi\u00f9...",
- "LabelShowLibraryTileNames": "Show library tile names",
+ "LabelShowLibraryTileNames": "Mostra i nomi di file di libreria",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
- "OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottle": "Abilita il throttling",
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Velocit\u00e0 limite di upload (Mbps)",
+ "OptionAllowSyncTranscoding": "Abilita la sincronizzazione che necessita di transcodifica",
+ "HeaderPlayback": "Riproduzione",
+ "OptionAllowAudioPlaybackTranscoding": "Abilita la riproduzione di audio che necessita di transcodifica",
+ "OptionAllowVideoPlaybackTranscoding": "Abilita la riproduzione di video che necessita di transcodifica",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Gli utenti riceveranno messaggi esplicativi quando il contenuto non \u00e8 riproducibile a causa della policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Bitrate limite del client remoto (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "Limite della CPU:",
+ "LabelConversionCpuCoreLimitHelp": "Limiita il numero di CPU da utilizzare durante l'operazione di sincronizzazione.",
+ "OptionEnableFullSpeedConversion": "Abilita conversione a velocit\u00e0 piena",
+ "OptionEnableFullSpeedConversionHelp": "Per default, la sincronizzazione viene eseguita a bassa velocit\u00e0 per minimizzare il consumo di risorse",
+ "HeaderPlaylists": "Playlist",
+ "HeaderSelectDate": "Seleziona la data",
+ "HeaderWelcomeExclamation": "Benvenuto!",
+ "HeaderMyPreferences": "Le miei preferenze",
+ "ButtonMyPreferencesWelcomeYes": "Grazie, preferisco impostare le mie preferenze adesso",
+ "ButtonMyPreferencesWelcomeNo": "No grazie, provveder\u00f2 in seguito.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Desideri impostare le tue preferenze ora?",
+ "ToAccessPreferencesHelp": "Per accedere alle preferenze in un secondo tempo, fare clic sull'icona utente presente in alto a destra e seleziona Le Mie Preferenze."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/kk.json b/MediaBrowser.Server.Implementations/Localization/Server/kk.json
index 0f9ae2bed..6f939d79c 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/kk.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/kk.json
@@ -29,7 +29,7 @@
"WizardCompleted": "\u04d8\u0437\u0456\u0440\u0448\u0435 \u0431\u04b1\u043b \u0431\u0456\u0437\u0433\u0435 \u043a\u0435\u0440\u0435\u0433\u0456\u043d\u0456\u04a3 \u0431\u04d9\u0440\u0456 \u0431\u043e\u043b\u044b\u043f \u0442\u0430\u0431\u044b\u043b\u0430\u0434\u044b. Emby \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430\u04a3\u044b\u0437 \u0442\u0443\u0440\u0430\u043b\u044b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0436\u0438\u043d\u0430\u0439 \u0431\u0430\u0441\u0442\u0430\u0434\u044b. \u0415\u043d\u0434\u0456 \u043a\u0435\u0439\u0431\u0456\u0440 \u0431\u0456\u0437\u0434\u0456\u04a3 \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u044b\u043c\u044b\u0437\u0431\u0435\u043d \u0442\u0430\u043d\u044b\u0441\u044b\u04a3\u044b\u0437, \u0436\u04d9\u043d\u0435 \u043a\u0435\u0439\u0456\u043d <b>\u0414\u0430\u0439\u044b\u043d<\/b> \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u0433\u0456\u043d \u0431\u0430\u0441\u044b\u04a3\u044b\u0437, \u0441\u043e\u043d\u0434\u0430 <b>\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u0411\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b<\/b> \u049b\u0430\u0440\u0430\u0443\u0493\u0430 \u0448\u044b\u0493\u044b \u043a\u0435\u043b\u0435\u0434\u0456.",
"LabelConfigureSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u0442\u0435\u04a3\u0448\u0435\u0443",
"LabelEnableVideoImageExtraction": "\u0411\u0435\u0439\u043d\u0435 \u0441\u0443\u0440\u0435\u0442\u0456\u043d \u0448\u044b\u0493\u0430\u0440\u044b\u043f \u0430\u043b\u0443\u0434\u044b \u049b\u043e\u0441\u0443",
- "VideoImageExtractionHelp": "\u04d8\u043b\u0456 \u0434\u0435 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456 \u0436\u043e\u049b, \u0436\u04d9\u043d\u0435 \u043e\u043b\u0430\u0440 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435 \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0493\u0430\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440 \u04af\u0448\u0456\u043d. \u0411\u04b1\u043b \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430\u043d\u044b\u04a3 \u0431\u0430\u0441\u0442\u0430\u043f\u049b\u044b \u0441\u043a\u0430\u043d\u0435\u0440\u043b\u0435\u0443\u0456 \u04af\u0448\u0456\u043d \u049b\u043e\u0441\u044b\u043c\u0448\u0430 \u0443\u0430\u049b\u044b\u0442 \u04af\u0441\u0442\u0435\u0439\u0434\u0456, \u0431\u0456\u0440\u0430\u049b \u043d\u04d9\u0442\u0438\u0436\u0435\u0441\u0456\u043d\u0434\u0435 \u04b1\u043d\u0430\u043c\u0434\u044b\u043b\u0430\u0443 \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c \u0431\u043e\u043b\u0430\u0434\u044b.",
+ "VideoImageExtractionHelp": "\u04d8\u043b\u0456 \u0434\u0435 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456 \u0436\u043e\u049b, \u0436\u04d9\u043d\u0435 \u043e\u043b\u0430\u0440 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435 \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0493\u0430\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440 \u04af\u0448\u0456\u043d. \u0411\u04b1\u043b \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430\u043d\u044b\u04a3 \u0431\u0430\u0441\u0442\u0430\u043f\u049b\u044b \u0441\u043a\u0430\u043d\u0435\u0440\u043b\u0435\u0443\u0456 \u04af\u0448\u0456\u043d \u049b\u043e\u0441\u044b\u043c\u0448\u0430 \u0443\u0430\u049b\u044b\u0442 \u04af\u0441\u0442\u0435\u0439\u0434\u0456, \u0431\u0456\u0440\u0430\u049b \u043d\u04d9\u0442\u0438\u0436\u0435\u0441\u0456\u043d\u0434\u0435 \u04b1\u043d\u0430\u043c\u0434\u044b\u043b\u0430\u0443 \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c \u0431\u043e\u043b\u0430\u0434\u044b.",
"LabelEnableChapterImageExtractionForMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440 \u04af\u0448\u0456\u043d \u0441\u0430\u0445\u043d\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u0448\u044b\u0493\u0430\u0440\u044b\u043f \u0430\u043b\u0443\u0434\u044b \u049b\u043e\u0441\u0443",
"LabelChapterImageExtractionForMoviesHelp": "\u0421\u0430\u0445\u043d\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u0448\u044b\u0493\u0430\u0440\u044b\u043f \u0430\u043b\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440\u0433\u0435 \u0441\u0430\u0445\u043d\u0430 \u0431\u04e9\u043b\u0435\u043a\u0442\u0435\u0443\u0433\u0435 \u0430\u0440\u043d\u0430\u043b\u0493\u0430\u043d \u0441\u044b\u0437\u0431\u0430\u043b\u044b\u049b \u043c\u04d9\u0437\u0456\u0440\u043b\u0435\u0440\u0434\u0456 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0435\u0434\u0456. \u0411\u04b1\u043b \u043f\u0440\u043e\u0446\u0435\u0441 \u0431\u0430\u044f\u0443, \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0434\u044b \u0442\u043e\u0437\u0434\u044b\u0440\u0430\u0442\u044b\u043d \u0436\u04d9\u043d\u0435 \u0431\u0456\u0440\u0430\u0437 \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u043a\u0435\u04a3\u0456\u0441\u0442\u0456\u043a\u0442\u0456 \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0442\u0456\u043d \u0431\u043e\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d. \u0411\u04b1\u043b \u0442\u04af\u043d\u0433\u0456 \u0443\u0430\u049b\u044b\u0442\u044b\u043d\u0430 \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0439\u0434\u0456, \u0434\u0435\u0433\u0435\u043d\u043c\u0435\u043d \u0431\u04b1\u043b \u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0443\u0448\u044b \u0430\u0439\u043c\u0430\u0493\u044b\u043d\u0434\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0435\u0434\u0456. \u0411\u04b1\u043b \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043d\u044b \u049b\u0430\u0440\u0431\u0430\u043b\u0430\u0441 \u0441\u0430\u0493\u0430\u0442\u0442\u0430\u0440\u044b\u043d\u0434\u0430 \u043e\u0440\u044b\u043d\u0434\u0430\u0443 \u04b1\u0441\u044b\u043d\u044b\u043b\u043c\u0430\u0439\u0434\u044b.",
"LabelEnableAutomaticPortMapping": "\u041f\u043e\u0440\u0442 \u0430\u0432\u0442\u043e\u0441\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443\u044b\u043d \u049b\u043e\u0441\u0443",
@@ -52,6 +52,8 @@
"HeaderAddUser": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b \u04af\u0441\u0442\u0435\u0443",
"LabelAddConnectSupporterHelp": "\u0422\u0456\u0437\u0456\u043c\u0434\u0435 \u0436\u043e\u049b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b \u04af\u0441\u0442\u0435\u0443 \u04af\u0448\u0456\u043d, \u0430\u043b\u0434\u044b\u043c\u0435\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u044b\u049b \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u044b \u0431\u0435\u0442\u0456\u043d\u0435\u043d Emby Connect \u0430\u0440\u0430\u0441\u044b\u043d\u0434\u0430 \u043e\u043d\u044b\u04a3 \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0456\u0441\u0456\u043d \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u0440\u0443\u044b\u04a3\u044b\u0437 \u049b\u0430\u0436\u0435\u0442.",
"LabelPinCode": "PIN-\u043a\u043e\u0434:",
+ "OptionHideWatchedContentFromLatestMedia": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0435\u043d \u049b\u0430\u0440\u0430\u043b\u0493\u0430\u043d \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u0436\u0430\u0441\u044b\u0440\u0443",
+ "HeaderSync": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443",
"ButtonOk": "\u0416\u0430\u0440\u0430\u0439\u0434\u044b",
"ButtonCancel": "\u0411\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443",
"ButtonExit": "\u0428\u044b\u0493\u0443",
@@ -76,7 +78,7 @@
"HeaderSyncRequiresSupporterMembership": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u04af\u0448\u0456\u043d \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043b\u044b\u049b \u043c\u04af\u0448\u0435\u043b\u0456\u043a \u049b\u0430\u0436\u0435\u0442",
"HeaderEnjoyDayTrial": "\u0422\u0435\u0433\u0456\u043d \u0441\u044b\u043d\u0430\u0443\u0434\u044b 14 \u043a\u04af\u043d \u0442\u0430\u043c\u0430\u0448\u0430\u043b\u0430\u04a3\u044b\u0456\u0437",
"LabelSyncTempPath": "\u0423\u0430\u049b\u044b\u0442\u0448\u0430 \u0444\u0430\u0439\u043b \u0436\u043e\u043b\u044b:",
- "LabelSyncTempPathHelp": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u04b1\u043c\u044b\u0441 \u049b\u0430\u043b\u0442\u0430\u043d\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437. \u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0436\u0430\u0441\u0430\u043b\u0493\u0430\u043d \u0442\u04af\u0440\u043b\u0435\u043d\u0434\u0456\u0440\u0456\u043b\u0433\u0435\u043d \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u043e\u0441\u044b \u043e\u0440\u044b\u043d\u0434\u0430 \u0441\u0430\u049b\u0442\u0430\u043b\u0430\u0434\u044b.",
+ "LabelSyncTempPathHelp": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u04b1\u043c\u044b\u0441 \u049b\u0430\u043b\u0442\u0430\u043d\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437. \u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0456 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0436\u0430\u0441\u0430\u043b\u0493\u0430\u043d \u0442\u04af\u0440\u043b\u0435\u043d\u0434\u0456\u0440\u0456\u043b\u0433\u0435\u043d \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u043e\u0441\u044b \u043e\u0440\u044b\u043d\u0434\u0430 \u0441\u0430\u049b\u0442\u0430\u043b\u0430\u0434\u044b.",
"LabelCustomCertificatePath": "\u041a\u0443\u04d9\u043b\u0456\u043a \u0436\u043e\u043b\u044b:",
"LabelCustomCertificatePathHelp": "\u04e8\u0437 SSL-\u043a\u0443\u04d9\u043b\u0456\u0433\u0456\u04a3\u0456\u0437\u0434\u0456\u04a3 .pfx \u0444\u0430\u0439\u043b\u044b\u043d \u0436\u0435\u0442\u043a\u0456\u0437\u0456\u04a3\u0456\u0437. \u0415\u0433\u0435\u0440 \u0442\u04af\u0441\u0456\u0440\u0456\u043b\u0441\u0435, \u0441\u0435\u0440\u0432\u0435\u0440 \u043c\u0435\u043d\u0448\u0456\u043a \u049b\u043e\u043b\u0442\u0430\u04a3\u0431\u0430\u0441\u044b \u0431\u0430\u0440 \u043a\u0443\u04d9\u043b\u0456\u043a\u0442\u0456 \u0436\u0430\u0441\u0430\u0439\u0434\u044b.",
"TitleNotifications": "\u0425\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443\u043b\u0430\u0440",
@@ -112,14 +114,14 @@
"HeaderPreferredMetadataLanguage": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u0442\u0456\u043b\u0456\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:",
"LabelSaveLocalMetadata": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435\u043b\u0435\u0440 \u0431\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u0442\u0430\u0441\u044b\u0493\u044b\u0448 \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b \u0456\u0448\u0456\u043d\u0434\u0435 \u0441\u0430\u049b\u0442\u0430\u0443",
"LabelSaveLocalMetadataHelp": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435\u043b\u0435\u0440 \u0431\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u0442\u0430\u0441\u044b\u0493\u044b\u0448 \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b \u0456\u0448\u0456\u043d\u0434\u0435 \u0441\u0430\u049b\u0442\u0430\u043b\u0443\u044b \u043e\u043b\u0430\u0440\u0434\u044b \u0436\u0435\u04a3\u0456\u043b \u04e9\u04a3\u0434\u0435\u0439 \u0430\u043b\u0430\u0442\u044b\u043d \u043e\u0440\u044b\u043d\u0493\u0430 \u049b\u043e\u044f\u0434\u044b.",
- "LabelDownloadInternetMetadata": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435\u043b\u0435\u0440 \u0431\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443",
+ "LabelDownloadInternetMetadata": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435\u043b\u0435\u0440 \u0431\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443",
"LabelDownloadInternetMetadataHelp": "\u0422\u043e\u043b\u044b \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u043b\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u049b\u043e\u0441\u0443 \u04af\u0448\u0456\u043d Emby Server \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u0442\u0443\u0440\u0430\u043b\u044b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0436\u04af\u043a\u0442\u0435\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.",
"TabPreferences": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440",
"TabPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437",
"TabLibraryAccess": "\u0422\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430\u0493\u0430 \u049b\u0430\u0442\u044b\u043d\u0430\u0443",
"TabAccess": "\u049a\u0430\u0442\u044b\u043d\u0430\u0443",
"TabImage": "\u0421\u0443\u0440\u0435\u0442",
- "TabProfile": "\u041f\u0440\u043e\u0444\u0438\u043b\u044c",
+ "TabProfile": "\u041f\u0440\u043e\u0444\u0430\u0439\u043b",
"TabMetadata": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440",
"TabImages": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u0440",
"TabNotifications": "\u0425\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443\u043b\u0430\u0440",
@@ -143,7 +145,7 @@
"OptionOnlyForcedSubtitlesHelp": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u043c\u04d9\u0436\u0431\u04af\u0440\u043b\u0456 \u0434\u0435\u043f \u0431\u0435\u043b\u0433\u0456\u043b\u0435\u043d\u0433\u0435\u043d \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 \u0436\u04af\u043a\u0442\u0435\u043b\u0435\u0434\u0456.",
"OptionAlwaysPlaySubtitlesHelp": "\u0422\u0456\u043b \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456\u043d\u0435 \u0441\u04d9\u0439\u043a\u0435\u0441 \u043a\u0435\u043b\u0433\u0435\u043d \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 \u0434\u044b\u0431\u044b\u0441 \u0442\u0456\u043b\u0456\u043d\u0435 \u049b\u0430\u0442\u044b\u0441\u0441\u044b\u0437 \u0436\u04af\u043a\u0442\u0435\u043b\u0435\u0434\u0456.",
"OptionNoSubtitlesHelp": "\u04d8\u0434\u0435\u043f\u043a\u0456\u0434\u0435 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 \u0436\u04af\u043a\u0442\u0435\u043b\u043c\u0435\u0439\u0434\u0456.",
- "TabProfiles": "\u041f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0435\u0440",
+ "TabProfiles": "\u041f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\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",
"ButtonAddLocalUser": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b \u04af\u0441\u0442\u0435\u0443",
@@ -167,6 +169,7 @@
"MessageNothingHere": "\u041e\u0441\u044b\u043d\u0434\u0430 \u0435\u0448\u0442\u0435\u043c\u0435 \u0436\u043e\u049b.",
"MessagePleaseEnsureInternetMetadata": "\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0456 \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443\u044b \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u044b\u043d\u0430 \u043a\u04e9\u0437 \u0436\u0435\u0442\u043a\u0456\u0437\u0456\u04a3\u0456\u0437.",
"TabSuggested": "\u04b0\u0441\u044b\u043d\u044b\u043b\u0493\u0430\u043d",
+ "TabSuggestions": "\u04b0\u0441\u044b\u043d\u044b\u0441\u0442\u0430\u0440",
"TabLatest": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456",
"TabUpcoming": "\u041a\u04af\u0442\u0456\u043b\u0433\u0435\u043d",
"TabShows": "\u041a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c\u0434\u0435\u0440",
@@ -300,7 +303,7 @@
"OptionDisableUserHelp": "\u0415\u0433\u0435\u0440 \u0442\u044b\u0439\u044b\u043c \u0441\u0430\u043b\u044b\u043d\u0441\u0430, \u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u04b1\u043b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u0434\u0430\u043d \u0435\u0448\u049b\u0430\u043d\u0434\u0430\u0439 \u049b\u043e\u0441\u044b\u043b\u044b\u043c\u0493\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u043f\u0435\u0439\u0434\u0456. \u0411\u0430\u0440 \u049b\u043e\u0441\u044b\u043b\u044b\u043c\u0434\u0430\u0440 \u043a\u0435\u043d\u0435\u0442 \u04af\u0437\u0456\u043b\u0435\u0434\u0456.",
"HeaderAdvancedControl": "\u041a\u0435\u04a3\u0435\u0439\u0442\u0456\u043b\u0433\u0435\u043d \u0431\u0430\u0441\u049b\u0430\u0440\u0443",
"LabelName": "\u0410\u0442\u044b:",
- "ButtonHelp": "\u0410\u043d\u044b\u049b\u0442\u0430\u043c\u0430\u0493\u0430",
+ "ButtonHelp": "\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435\u0433\u0456 \u0430\u043d\u044b\u049b\u0442\u0430\u043c\u0430\u0493\u0430",
"OptionAllowUserToManageServer": "\u0411\u0443\u043b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u0493\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u0431\u0430\u0441\u049b\u0430\u0440\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
"HeaderFeatureAccess": "\u0415\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440\u0433\u0435 \u049b\u0430\u0442\u044b\u043d\u0430\u0443",
"OptionAllowMediaPlayback": "\u0422\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u043e\u0439\u043d\u0430\u0442\u0443\u0493\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
@@ -401,9 +404,10 @@
"ButtonRefresh": "\u0416\u0430\u04a3\u0493\u044b\u0440\u0442\u0443",
"ButtonAdvancedRefresh": "\u041a\u0435\u04a3\u0435\u0439\u0442\u0456\u043b\u0433\u0435\u043d \u0436\u0430\u04a3\u0493\u044b\u0440\u0442\u0443",
"OptionPriority": "\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442",
- "OptionRecordOnAllChannels": "\u0411\u0435\u0440\u0456\u043b\u0456\u043c\u0434\u0456 \u0431\u0430\u0440\u043b\u044b\u049b \u0430\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u0430\u043d \u0436\u0430\u0437\u044b\u043f \u0430\u043b\u0443",
- "OptionRecordAnytime": "\u0411\u0435\u0440\u0456\u043b\u0456\u043c\u0434\u0456 \u04d9\u0440 \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u0436\u0430\u0437\u044b\u043f \u0430\u043b\u0443",
+ "OptionRecordOnAllChannels": "\u0411\u0430\u0440\u043b\u044b\u049b \u0430\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u0430\u043d \u0436\u0430\u0437\u044b\u043f \u0430\u043b\u0443",
+ "OptionRecordAnytime": "\u04d8\u0440 \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u0436\u0430\u0437\u044b\u043f \u0430\u043b\u0443",
"OptionRecordOnlyNewEpisodes": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u0436\u0430\u04a3\u0430 \u0431\u04e9\u043b\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u0436\u0430\u0437\u044b\u043f \u0430\u043b\u0443",
+ "HeaderRepeatingOptions": "\u049a\u0430\u0439\u0442\u0430\u043b\u0430\u043c\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456",
"HeaderDays": "\u041a\u04af\u043d\u0434\u0435\u0440",
"HeaderActiveRecordings": "\u0411\u0435\u043b\u0441\u0435\u043d\u0434\u0456 \u0436\u0430\u0437\u0443\u043b\u0430\u0440",
"HeaderLatestRecordings": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u04a3\u0433\u0456 \u0436\u0430\u0437\u0431\u0430\u043b\u0430\u0440",
@@ -414,7 +418,7 @@
"ButtonDelete": "\u0416\u043e\u044e",
"ButtonRemove": "\u0410\u043b\u0430\u0441\u0442\u0430\u0443",
"OptionRecordSeries": "\u0422\u0435\u043b\u0435\u0445\u0438\u043a\u0430\u044f\u043d\u044b \u0436\u0430\u0437\u0443",
- "HeaderDetails": "\u041c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440",
+ "HeaderDetails": "\u0422\u043e\u043b\u044b\u049b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440",
"TitleLiveTV": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414",
"LabelNumberOfGuideDays": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u04af\u0448\u0456\u043d \u0410\u043d\u044b\u049b\u0442\u0430\u0493\u044b\u0448 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043d\u0434\u0435\u0433\u0456 \u043a\u04af\u043d \u0441\u0430\u043d\u044b:",
"LabelNumberOfGuideDaysHelp": "\u041a\u04e9\u0431\u0456\u0440\u0435\u043a \u043a\u04af\u043d\u0434\u0456 \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u0410\u043d\u044b\u049b\u0442\u0430\u0493\u044b\u0448 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043d\u0456\u04a3 \u049b\u04b1\u043d\u0434\u044b\u043b\u044b\u0493\u044b\u043d \u043a\u04e9\u0442\u0435\u0440\u0435\u0434\u0456 \u0434\u0435 \u0430\u043b\u0434\u044b\u043d-\u0430\u043b\u0430 \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0443 \u04af\u0448\u0456\u043d \u049b\u0430\u0431\u0456\u043b\u0435\u0442\u0456\u043d \u0436\u04d9\u043d\u0435 \u043a\u04e9\u0431\u0456\u0440\u0435\u043a \u0442\u0456\u0437\u0431\u0435\u043b\u0435\u0440 \u043a\u04e9\u0440\u0443\u0434\u0456 \u049b\u0430\u043c\u0442\u0430\u043c\u0430\u0441\u044b\u0437 \u0435\u0442\u0435\u0434\u0456, \u0431\u0456\u0440\u0430\u049b \u0431\u04b1\u043b \u0436\u04af\u043a\u0442\u0435\u0443 \u0443\u0430\u049b\u044b\u0442\u044b\u043d \u0434\u0430 \u0441\u043e\u0437\u0434\u044b\u0440\u0430\u0434\u044b. \u0410\u0432\u0442\u043e\u0442\u0430\u04a3\u0434\u0430\u0443 \u0430\u0440\u043d\u0430 \u0441\u0430\u043d\u044b\u043d\u0430 \u043d\u0435\u0433\u0456\u0437\u0434\u0435\u043b\u0456\u043d\u0435\u0434\u0456.",
@@ -517,10 +521,10 @@
"LabelEnableDlnaDebugLoggingHelp": "\u04e8\u0442\u0435 \u0430\u0443\u049b\u044b\u043c\u0434\u044b \u0436\u04b1\u0440\u043d\u0430\u043b \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u0436\u0430\u0441\u0430\u043b\u0430\u0434\u044b \u0436\u04d9\u043d\u0435 \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u0430\u049b\u0430\u0443\u043b\u044b\u049b\u0442\u0430\u0440\u0434\u044b \u0436\u043e\u044e \u04af\u0448\u0456\u043d \u049b\u0430\u0436\u0435\u0442 \u0431\u043e\u043b\u0493\u0430\u043d \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b.",
"LabelEnableDlnaClientDiscoveryInterval": "\u041a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440\u0434\u0456 \u0442\u0430\u0443\u044b\u043f \u0430\u0448\u0443 \u0430\u0440\u0430\u043b\u044b\u0493\u044b, \u0441:",
"LabelEnableDlnaClientDiscoveryIntervalHelp": "Emby \u043e\u0440\u044b\u043d\u0434\u0430\u0493\u0430\u043d SSDP \u0441\u0430\u0443\u0430\u043b \u0441\u0430\u043b\u0443 \u0430\u0440\u0430 \u04b1\u0437\u0430\u049b\u0442\u044b\u0493\u044b\u043d \u0441\u0435\u043a\u0443\u043d\u0434\u0442\u0430\u0440 \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u0439\u0434\u044b.",
- "HeaderCustomDlnaProfiles": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0435\u0440",
- "HeaderSystemDlnaProfiles": "\u0416\u04af\u0439\u0435\u043b\u0456\u043a \u043f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0435\u0440",
- "CustomDlnaProfilesHelp": "\u0416\u0430\u04a3\u0430 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b \u043c\u0430\u049b\u0441\u0430\u0442\u044b \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0456 \u0436\u0430\u0441\u0430\u0443 \u043d\u0435 \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u043f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0456 \u049b\u0430\u0439\u0442\u0430 \u0430\u043d\u044b\u049b\u0442\u0430\u0443.",
- "SystemDlnaProfilesHelp": "\u0416\u04af\u0439\u0435\u043b\u0456\u043a \u043f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0435\u0440 \u0442\u0435\u043a \u043e\u049b\u0443 \u04af\u0448\u0456\u043d. \u0416\u04af\u0439\u0435\u043b\u0456\u043a \u043f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0456\u04a3 \u04e9\u0437\u0433\u0435\u0440\u0456\u0441\u0442\u0435\u0440\u0456 \u0436\u0430\u04a3\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043f\u0440\u043e\u0444\u0438\u043b\u044c\u0433\u0435 \u0436\u0430\u0437\u044b\u043b\u0430\u0434\u044b.",
+ "HeaderCustomDlnaProfiles": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440",
+ "HeaderSystemDlnaProfiles": "\u0416\u04af\u0439\u0435\u043b\u0456\u043a \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440",
+ "CustomDlnaProfilesHelp": "\u0416\u0430\u04a3\u0430 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b \u043c\u0430\u049b\u0441\u0430\u0442\u044b \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u044b \u0436\u0430\u0441\u0430\u0443 \u043d\u0435 \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u044b \u049b\u0430\u0439\u0442\u0430 \u0430\u043d\u044b\u049b\u0442\u0430\u0443.",
+ "SystemDlnaProfilesHelp": "\u0416\u04af\u0439\u0435\u043b\u0456\u043a \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440 \u0442\u0435\u043a \u043e\u049b\u0443 \u04af\u0448\u0456\u043d. \u0416\u04af\u0439\u0435\u043b\u0456\u043a \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u044b\u04a3 \u04e9\u0437\u0433\u0435\u0440\u0456\u0441\u0442\u0435\u0440\u0456 \u0436\u0430\u04a3\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0493\u0430 \u0436\u0430\u0437\u044b\u043b\u0430\u0434\u044b.",
"TitleDashboard": "\u0411\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b",
"TabHome": "\u0411\u0430\u0441\u0442\u044b",
"TabInfo": "\u041f\u0440\u043e\u0444\u0430\u0439\u043b \u0442\u0443\u0440\u0430\u043b\u044b",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "\u0416\u0430\u0440\u0438\u044f https-\u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456:",
"LabelPublicHttpsPortHelp": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 https-\u043f\u043e\u0440\u0442\u044b\u043d\u0430 \u0441\u0430\u043b\u044b\u0441\u0442\u044b\u0440\u044b\u043b\u0443\u044b \u0442\u0438\u0456\u0441 \u0436\u0430\u0440\u0438\u044f \u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456.",
"LabelEnableHttps": "HTTPS \u0445\u0430\u0442\u0442\u0430\u043c\u0430\u0441\u044b \u0441\u044b\u0440\u0442\u049b\u044b \u043c\u0435\u043a\u0435\u043d\u0435\u0436\u0430\u0439 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0431\u0430\u044f\u043d\u0434\u0430\u0443",
- "LabelEnableHttpsHelp": "\u0415\u0433\u0435\u0440 \u049b\u043e\u0441\u044b\u043b\u0441\u0430, \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440 \u04af\u0448\u0456\u043d \u0441\u0435\u0440\u0432\u0435\u0440 https url \u0441\u044b\u0440\u0442\u049b\u044b \u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0431\u0430\u044f\u043d\u0434\u0430\u0439\u0434\u044b. \u0411\u04b1\u043b \u04d9\u043b\u0456 \u0434\u0435 https \u049b\u043e\u043b\u0434\u0430\u043c\u0430\u0439\u0442\u044b\u043d \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440\u0434\u0456\u04a3 \u0436\u04b1\u043c\u044b\u0441\u044b\u043d \u04af\u0437\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.",
+ "LabelEnableHttpsHelp": "\u0415\u0433\u0435\u0440 \u049b\u043e\u0441\u044b\u043b\u0441\u0430, \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440 \u04af\u0448\u0456\u043d \u0441\u0435\u0440\u0432\u0435\u0440 HTTPS URL \u0441\u044b\u0440\u0442\u049b\u044b \u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0431\u0430\u044f\u043d\u0434\u0430\u0439\u0434\u044b.",
"LabelHttpsPort": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 https-\u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456:",
"LabelHttpsPortHelp": "Emby HTTPS-\u0441\u0435\u0440\u0432\u0435\u0440\u0456 \u0431\u0430\u0439\u043b\u0430\u0441\u0442\u044b\u0440\u044b\u043b\u0443\u0493\u0430 \u0442\u0438\u0456\u0441\u0442\u0456 TCP-\u043f\u043e\u0440\u0442 \u043d\u04e9\u043c\u0456\u0440\u0456.",
"LabelWebSocketPortNumber": "\u0412\u0435\u0431-\u0441\u043e\u043a\u0435\u0442 \u043f\u043e\u0440\u0442\u044b\u043d\u044b\u04a3 \u043d\u04e9\u043c\u0456\u0440\u0456:",
@@ -654,7 +658,7 @@
"LabelBlastMessageInterval": "\u0411\u0435\u043b\u0441\u0435\u043d\u0434\u0456\u043b\u0456\u043a\u0442\u0456 \u0442\u0435\u043a\u0441\u0435\u0440\u0443 \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u0440 \u0430\u0440\u0430\u043b\u044b\u0493\u044b, \u0441",
"LabelBlastMessageIntervalHelp": "\u0421\u0435\u0440\u0432\u0435\u0440 \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456\u043b\u0456\u0433\u0456\u043d \u0442\u0435\u043a\u0441\u0435\u0440\u0443 \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u0440\u0434\u044b\u04a3 \u0430\u0440\u0430 \u04b1\u0437\u0430\u049b\u0442\u044b\u0493\u044b\u043d \u0441\u0435\u043a\u0443\u043d\u0434\u0442\u0430\u0440 \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u0439\u0434\u044b.",
"LabelDefaultUser": "\u04d8\u0434\u0435\u043f\u043a\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b:",
- "LabelDefaultUserHelp": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430 \u049b\u0430\u0439 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b\u04a3 \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430\u0441\u044b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0443\u0456 \u0442\u0438\u0456\u0441\u0442\u0456\u043b\u0456\u0433\u0456\u043d \u0430\u043d\u044b\u049b\u0442\u0430\u0439\u0434\u044b. \u041f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0435\u0440\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0493\u0430\u043d\u0434\u0430 \u0431\u04b1\u043b \u04d9\u0440 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b \u04af\u0448\u0456\u043d \u049b\u0430\u0439\u0442\u0430 \u0442\u0430\u0493\u0430\u0439\u044b\u043d\u0434\u0430\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.",
+ "LabelDefaultUserHelp": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430 \u049b\u0430\u0439 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b\u04a3 \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430\u0441\u044b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0443\u0456 \u0442\u0438\u0456\u0441\u0442\u0456\u043b\u0456\u0433\u0456\u043d \u0430\u043d\u044b\u049b\u0442\u0430\u0439\u0434\u044b. \u041f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u0434\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0493\u0430\u043d\u0434\u0430 \u0431\u04b1\u043b \u04d9\u0440 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b \u04af\u0448\u0456\u043d \u049b\u0430\u0439\u0442\u0430 \u0442\u0430\u0493\u0430\u0439\u044b\u043d\u0434\u0430\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.",
"TitleDlna": "DLNA",
"TitleChannels": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440",
"HeaderServerSettings": "\u0421\u0435\u0440\u0432\u0435\u0440 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456",
@@ -839,7 +843,7 @@
"HeaderDownloadChaptersFor": "\u041c\u044b\u043d\u0430\u0493\u0430\u043d \u0441\u0430\u0445\u043d\u0430\u043b\u0430\u0440 \u0430\u0442\u0430\u0443\u043b\u0430\u0440\u044b\u043d \u0436\u04af\u043a\u0442\u0435\u0443:",
"LabelOpenSubtitlesUsername": "Open Subtitles \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0430\u0442\u044b:",
"LabelOpenSubtitlesPassword": "Open Subtitles \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0456:",
- "HeaderChapterDownloadingHelp": "Emby \u0431\u0435\u0439\u043d\u0435\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u0434\u044b \u0441\u043a\u0430\u043d\u0435\u0440\u043b\u0435\u0433\u0435\u043d\u0434\u0435 \u0431\u04b1\u043b \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435\u043d ChapterDb \u0441\u0438\u044f\u049b\u0442\u044b \u0441\u0430\u0445\u043d\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440\u0456 \u0430\u0440\u049b\u044b\u043b\u044b \u043e\u04a3\u0430\u0439 \u0441\u0430\u0445\u043d\u0430 \u0442\u0430\u0443\u043b\u0430\u0440\u044b\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.",
+ "HeaderChapterDownloadingHelp": "Emby \u0431\u0435\u0439\u043d\u0435\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u0434\u044b \u0441\u043a\u0430\u043d\u0435\u0440\u043b\u0435\u0433\u0435\u043d\u0434\u0435 \u0431\u04b1\u043b \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435\u043d ChapterDb \u0441\u0438\u044f\u049b\u0442\u044b \u0441\u0430\u0445\u043d\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440\u0456 \u0430\u0440\u049b\u044b\u043b\u044b \u043e\u04a3\u0430\u0439 \u0441\u0430\u0445\u043d\u0430 \u0442\u0430\u0443\u043b\u0430\u0440\u044b\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.",
"LabelPlayDefaultAudioTrack": "\u0422\u0456\u043b\u0433\u0435 \u049b\u0430\u0442\u044b\u0441\u0441\u044b\u0437 \u04d9\u0434\u0435\u043f\u043a\u0456 \u0434\u044b\u0431\u044b\u0441 \u0436\u043e\u043b\u0448\u044b\u0493\u044b\u043d \u043e\u0439\u043d\u0430\u0442\u0443",
"LabelSubtitlePlaybackMode": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440 \u0440\u0435\u0436\u0456\u043c\u0456:",
"LabelDownloadLanguages": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0430\u0442\u044b\u043d \u0442\u0456\u043b\u0434\u0435\u0440:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "\u0411\u0430\u0441\u0442\u044b \u0431\u0435\u0442 2-\u0431\u04e9\u043b\u0456\u043c:",
"LabelHomePageSection3": "\u0411\u0430\u0441\u0442\u044b \u0431\u0435\u0442 3-\u0431\u04e9\u043b\u0456\u043c:",
"LabelHomePageSection4": "\u0411\u0430\u0441\u0442\u044b \u0431\u0435\u0442 4-\u0431\u04e9\u043b\u0456\u043c:",
- "OptionMyViewsButtons": "\u041c\u0435\u043d\u0456\u04a3 \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440\u0456\u043c (\u0442\u04af\u0439\u043c\u0435\u0448\u0456\u043a\u0442\u0435\u0440)",
- "OptionMyViews": "\u041c\u0435\u043d\u0456\u04a3 \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440\u0456\u043c",
- "OptionMyViewsSmall": "\u041c\u0435\u043d\u0456\u04a3 \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440\u0456\u043c (\u044b\u049b\u0448\u0430\u043c)",
+ "OptionMyMediaButtons": "\u041c\u0435\u043d\u0456\u04a3 \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043c (\u0442\u04af\u0439\u043c\u0435\u0448\u0456\u043a\u0442\u0435\u0440)",
+ "OptionMyMedia": "\u041c\u0435\u043d\u0456\u04a3 \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043c",
+ "OptionMyMediaSmall": "\u041c\u0435\u043d\u0456\u04a3 \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043c (\u044b\u049b\u0448\u0430\u043c)",
"OptionResumablemedia": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u043c\u0430\u043b\u044b",
"OptionLatestMedia": "\u0415\u04a3 \u043a\u0435\u0439\u043d\u0433\u0456 \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440",
"OptionLatestChannelMedia": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u044b\u04a3 \u0435\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0442\u0430\u0440\u043c\u0430\u049b\u0442\u0430\u0440\u044b",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "\u04d8\u0434\u0435\u043f\u043a\u0456",
"OptionCommunityMostWatchedSort": "\u0415\u04a3 \u043a\u04e9\u043f \u049b\u0430\u0440\u0430\u043b\u0493\u0430\u043d\u0434\u0430\u0440",
"TabNextUp": "\u041a\u0435\u0437\u0435\u043a\u0442\u0456",
+ "PlaceholderUsername": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0430\u0442\u044b",
"HeaderBecomeProjectSupporter": "Emby \u0436\u0430\u049b\u0442\u0430\u0443\u0448\u044b\u0441\u044b \u0431\u043e\u043b\u044b\u04a3\u044b\u0437",
- "TextEnjoyBonusFeatures": "\u0421\u044b\u0439\u0430\u049b\u044b \u0435\u0440\u0435\u043a\u0448\u0435\u043b\u0456\u043a\u0442\u0435\u0440\u0434\u0456 \u0442\u0430\u043c\u0430\u0448\u0430\u043b\u0430\u043d\u044b\u04a3\u044b\u0437",
"MessageNoMovieSuggestionsAvailable": "\u0415\u0448\u049b\u0430\u043d\u0434\u0430\u0439 \u0444\u0438\u043b\u044c\u043c \u04b1\u0441\u044b\u043d\u044b\u0441\u0442\u0430\u0440\u044b \u0430\u0493\u044b\u043c\u0434\u0430 \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0435\u043c\u0435\u0441. \u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440\u0434\u0456 \u049b\u0430\u0440\u0430\u0443\u0434\u044b \u0436\u04d9\u043d\u0435 \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u0434\u044b \u0431\u0430\u0441\u0442\u0430\u04a3\u044b\u0437, \u0441\u043e\u043d\u0434\u0430 \u0430\u0440\u043d\u0430\u043b\u0493\u0430\u043d \u04b1\u0441\u044b\u043d\u044b\u0442\u0430\u0440\u044b\u04a3\u044b\u0437\u0434\u044b \u043a\u04e9\u0440\u0443 \u04af\u0448\u0456\u043d \u049b\u0430\u0439\u0442\u0430 \u043a\u0435\u043b\u0456\u04a3\u0456\u0437.",
"MessageNoCollectionsAvailable": "\u0416\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u0430\u0440 \u0441\u0456\u0437\u0433\u0435 \u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440\u0434\u0456\u04a3, \u0422\u0435\u043b\u0435\u0445\u0438\u043a\u0430\u044f\u043b\u0430\u0440\u0434\u044b\u04a3, \u0410\u043b\u044c\u0431\u043e\u043c\u0434\u0430\u0440\u0434\u044b\u04a3, \u041a\u0456\u0442\u0430\u043f\u0442\u0430\u0440\u0434\u044b\u04a3, \u0436\u04d9\u043d\u0435 \u041e\u0439\u044b\u043d\u0434\u0430\u0440\u0434\u044b\u04a3 \u0434\u0435\u0440\u0431\u0435\u0441\u0442\u0435\u043d\u0434\u0456\u0440\u0456\u043b\u0433\u0435\u043d \u0442\u043e\u043f\u0442\u0430\u0443\u043b\u0430\u0440\u044b\u043c\u0435\u043d \u0442\u0430\u043c\u0430\u0448\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0435\u0434\u0456. \u0416\u0438\u044b\u043d\u0442\u044b\u049b\u0442\u0430\u0440 \u0436\u0430\u0441\u0430\u0443\u044b\u043d \u0431\u0430\u0441\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \"+\" \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u0433\u0456\u043d \u0431\u0430\u0441\u044b\u04a3\u044b\u0437.",
"MessageNoPlaylistsAvailable": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0434\u0435\u0440\u0456 \u0431\u0456\u0440 \u043a\u0435\u0437\u0434\u0435 \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u043c\u0430\u0437\u043c\u04b1\u043d \u0442\u0456\u0437\u0456\u043c\u0456\u043d \u0436\u0430\u0441\u0430\u0443\u0493\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0435\u0434\u0456. \u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0434\u0435\u0440\u0433\u0435 \u0442\u0430\u0440\u043c\u0430\u049b\u0442\u0430\u0440\u0434\u044b \u04af\u0441\u0442\u0435\u0443 \u04af\u0448\u0456\u043d, \u0442\u0456\u043d\u0442\u0443\u0456\u0440\u0434\u0456\u04a3 \u043e\u04a3 \u0436\u0430\u049b \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u0433\u0456\u043d \u0431\u0430\u0441\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0442\u04af\u0440\u0442\u0456\u043f \u0436\u04d9\u043d\u0435 \u04b1\u0441\u0442\u0430\u043f \u0442\u04b1\u0440\u044b\u04a3\u044b\u0437, \u0441\u043e\u043d\u0434\u0430 \u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0456\u043d\u0435 \u04af\u0441\u0442\u0435\u0443 \u0434\u0435\u0433\u0435\u043d\u0434\u0456 \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437.",
@@ -1378,13 +1382,36 @@
"LabelTagFilterAllowModeHelp": "\u0415\u0433\u0435\u0440 \u04b1\u0439\u0493\u0430\u0440\u044b\u043d\u0434\u044b \u0442\u0435\u0433\u0442\u0435\u0440 \u0442\u0435\u0440\u0435\u04a3 \u043a\u0456\u0440\u0456\u0441\u0442\u0456\u0440\u0456\u043b\u0433\u0435\u043d \u049b\u0430\u043b\u0442\u0430 \u049b\u04b1\u0440\u044b\u043b\u044b\u043c\u044b\u043d\u044b\u04a3 \u0431\u04e9\u043b\u0456\u0433\u0456 \u0431\u043e\u043b\u0441\u0430, \u043e\u043d\u0434\u0430 \u0442\u0435\u0433\u0442\u0435\u0440\u043c\u0435\u043d \u0431\u0435\u043b\u0433\u0456\u043b\u0435\u043d\u0433\u0435\u043d \u043c\u0430\u0437\u043c\u04b1\u043d\u0493\u0430, \u0441\u043e\u043d\u0434\u0430\u0439-\u0430\u049b \u0431\u0435\u043b\u0433\u0456\u043b\u0435\u043d\u0433\u0435\u043d \u0442\u0435\u043a\u0442\u0456\u043a \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440 \u0431\u043e\u043b\u0443\u044b \u0442\u0430\u043b\u0430\u043f \u0435\u0442\u0456\u043b\u0435\u0434\u0456.",
"HeaderThisUserIsCurrentlyDisabled": "\u041e\u0441\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u049b\u0430\u0437\u0456\u0440\u0433\u0456 \u043a\u0435\u0437\u0434\u0435 \u0430\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u0493\u0430\u043d",
"MessageReenableUser": "\u049a\u0430\u0439\u0442\u0430 \u049b\u043e\u0441\u0443 \u04af\u0448\u0456\u043d \u0442\u04e9\u043c\u0435\u043d\u0434\u0435 \u049b\u0430\u0440\u0430\u04a3\u044b\u0437",
- "LabelEnableInternetMetadataForTvPrograms": "\u041c\u044b\u043d\u0430\u0443 \u04af\u0448\u0456\u043d \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443",
+ "LabelEnableInternetMetadataForTvPrograms": "\u041c\u044b\u043d\u0430\u0443 \u04af\u0448\u0456\u043d \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0442\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443",
"OptionTVMovies": "\u0422\u0414-\u0444\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
"HeaderUpcomingMovies": "\u041a\u04af\u0442\u0456\u043b\u0433\u0435\u043d \u0444\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
+ "HeaderUpcomingSports": "\u041a\u04af\u0442\u0456\u043b\u0433\u0435\u043d \u0441\u043f\u043e\u0440\u0442",
"HeaderUpcomingPrograms": "\u041a\u04af\u0442\u0456\u043b\u0433\u0435\u043d \u0431\u0435\u0440\u043b\u0456\u043c\u0434\u0435\u0440",
"ButtonMoreItems": "\u041a\u04e9\u0431\u0456\u0440\u0435\u043a...",
"LabelShowLibraryTileNames": "\u0422\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430 \u0442\u0430\u049b\u0442\u0430\u0439\u0448\u0430\u043b\u0430\u0440\u044b\u043d\u044b\u04a3 \u0430\u0442\u0430\u0443\u043b\u0430\u0440\u044b\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443",
"LabelShowLibraryTileNamesHelp": "\u0411\u0430\u0441\u0442\u044b \u0431\u0435\u0442\u0442\u0435 \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430 \u0442\u0430\u049b\u0442\u0430\u0439\u0448\u0430\u043b\u0430\u0440\u044b \u0430\u0441\u0442\u044b\u043d\u0434\u0430 \u0436\u0430\u0437\u0443\u043b\u0430\u0440 \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u043b\u0435 \u043c\u0435 \u0435\u043a\u0435\u043d\u0456 \u0430\u043d\u044b\u049b\u0442\u0430\u043b\u0430\u0434\u044b.",
"OptionEnableTranscodingThrottle": "\u0420\u0435\u0442\u0442\u0435\u0443\u0434\u0456 \u049b\u043e\u0441\u0443",
- "OptionEnableTranscodingThrottleHelp": "\u041e\u0439\u043d\u0430\u0442\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u043e\u0440\u0442\u0430\u043b\u044b\u049b \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u044b\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u044b\u043d \u0430\u0437\u0430\u0439\u0442\u0443 \u04af\u0448\u0456\u043d \u0440\u0435\u0442\u0442\u0435\u0443 \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u043b\u0430\u0439\u044b\u049b\u0442\u0430\u0439\u0434\u044b."
+ "OptionEnableTranscodingThrottleHelp": "\u041e\u0439\u043d\u0430\u0442\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u043e\u0440\u0442\u0430\u043b\u044b\u049b \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u044b\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u044b\u043d \u0430\u0437\u0430\u0439\u0442\u0443 \u04af\u0448\u0456\u043d \u0440\u0435\u0442\u0442\u0435\u0443 \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u043b\u0430\u0439\u044b\u049b\u0442\u0430\u0439\u0434\u044b.",
+ "LabelUploadSpeedLimit": "\u0416\u04af\u043a\u0442\u0435\u043f \u0431\u0435\u0440\u0443 \u0436\u044b\u043b\u0434\u0430\u043c\u0434\u044b\u0493\u044b\u043d\u044b\u04a3 \u0448\u0435\u0433\u0456, \u041c\u0431\u0438\u0442\/\u0441",
+ "OptionAllowSyncTranscoding": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443\u0493\u0430 \u0442\u0430\u043b\u0430\u0431\u044b \u0431\u0430\u0440 \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
+ "HeaderPlayback": "\u0422\u0430\u0441\u044b\u0493\u044b\u0448\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u043e\u0439\u043d\u0430\u0442\u0443",
+ "OptionAllowAudioPlaybackTranscoding": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443\u0493\u0430 \u0442\u0430\u043b\u0430\u0431\u044b \u0431\u0430\u0440 \u0434\u044b\u0431\u044b\u0441 \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
+ "OptionAllowVideoPlaybackTranscoding": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443\u0493\u0430 \u0442\u0430\u043b\u0430\u0431\u044b \u0431\u0430\u0440 \u0431\u0435\u0439\u043d\u0435 \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
+ "OptionAllowMediaPlaybackTranscodingHelp": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440 \u04e9\u0437\u0434\u0435\u0440\u0456\u043d\u0456\u04a3 \u0441\u0430\u044f\u0441\u0430\u0442\u0442\u0430\u0440\u044b\u043d\u0430 \u043d\u0435\u0433\u0456\u0437\u0434\u0435\u043b\u0433\u0435\u043d \u043e\u0439\u043d\u0430\u0442\u044b\u043b\u043c\u0430\u0439\u0442\u044b\u043d \u043c\u0430\u0437\u043c\u04b1\u043d \u0431\u043e\u043b\u0493\u0430\u043d\u0434\u0430\u0493\u044b \u049b\u0430\u0442\u0435 \u0442\u0443\u0440\u0430\u043b\u044b \u043e\u04a3\u0430\u0439 \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u0440\u0434\u044b \u0430\u043b\u0430\u0434\u044b.",
+ "TabStreaming": "\u0410\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443",
+ "LabelRemoteClientBitrateLimit": "\u0410\u043b\u044b\u0441\u0442\u0430\u0493\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440 \u049b\u0430\u0440\u049b\u044b\u043d\u044b\u043d\u044b\u04a3 \u0448\u0435\u0433\u0456, \u041c\u0431\u0438\u0442\/\u0441",
+ "LabelRemoteClientBitrateLimitHelp": "\u041c\u0456\u043d\u0434\u0435\u0442\u0442\u0456 \u0435\u043c\u0435\u0441 \u0431\u0430\u0440\u043b\u044b\u049b \u0430\u043b\u044b\u0441\u0442\u0430\u0493\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440 \u04af\u0448\u0456\u043d \u049b\u0430\u0440\u049b\u044b\u043d \u0448\u0435\u0433\u0456. \u0411\u04b1\u043b \u049b\u043e\u0441\u044b\u043b\u044b\u043c\u044b\u04a3\u044b\u0437\u0434\u044b\u04a3 \u04e9\u04a3\u0434\u0435\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u043d\u0435 \u049b\u0430\u0440\u0430\u0493\u0430\u043d\u0434\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440\u0434\u0456\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b\u043b\u0430\u0443 \u049b\u0430\u0440\u049b\u044b\u043d \u0441\u0430\u0443\u0430\u043b\u0434\u0430\u0440\u044b\u043d\u0430 \u0442\u044b\u0439\u044b\u043c \u0441\u0430\u043b\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u044b \u0431\u043e\u043b\u044b\u043f \u0442\u0430\u0431\u044b\u043b\u0430\u0434\u044b.",
+ "LabelConversionCpuCoreLimit": "\u041f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043b\u044b\u049b \u04e9\u0437\u0435\u043a\u0442\u0435\u0440 \u0448\u0435\u0433\u0456:",
+ "LabelConversionCpuCoreLimitHelp": "\u04ae\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443\u043b\u0456\u043a \u0442\u04af\u0440\u043b\u0435\u043d\u0434\u0456\u0440\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u049b\u043e\u043b\u0434\u0430\u043d\u044b\u043b\u0430\u0442\u044b\u043d \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043b\u044b\u049b \u04e9\u0437\u0435\u043a\u0442\u0435\u0440\u0434\u0456\u04a3 \u0441\u0430\u043d\u044b\u043d \u0448\u0435\u043a\u0442\u0435\u0443.",
+ "OptionEnableFullSpeedConversion": "\u0422\u04af\u0440\u043b\u0435\u043d\u0434\u0456\u0440\u0443\u0434\u0456\u04a3 \u0442\u043e\u043b\u044b\u049b \u0436\u044b\u043b\u0434\u0430\u043c\u043b\u044b\u0493\u044b\u043d \u049b\u043e\u0441\u0443",
+ "OptionEnableFullSpeedConversionHelp": "\u0420\u0435\u0441\u0443\u0440\u0441\u0442\u0430\u0440 \u0442\u04b1\u0442\u044b\u043d\u0443\u0434\u044b \u0431\u0430\u0440\u044b\u043d\u0448\u0430 \u0430\u0437\u0430\u0439\u0442\u0443 \u04af\u0448\u0456\u043d \u04af\u043d\u0434\u0435\u0441\u0442\u0456\u0440\u0443\u043b\u0456\u043a \u0442\u04af\u0440\u043b\u0435\u043d\u0434\u0456\u0440\u0443 \u04d9\u0434\u0435\u043f\u043a\u0456\u0434\u0435 \u0442\u04e9\u043c\u0435\u043d \u0436\u044b\u043b\u0434\u0430\u043c\u0434\u044b\u049b\u043f\u0435\u043d \u043e\u0440\u044b\u043d\u0434\u0430\u043b\u0430\u0434\u044b.",
+ "HeaderPlaylists": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0434\u0435\u0440",
+ "HeaderSelectDate": "\u041a\u04af\u043d\u0434\u0456 \u0442\u0430\u04a3\u0434\u0430\u0443",
+ "HeaderWelcomeExclamation": "\u049a\u043e\u0448 \u043a\u0435\u043b\u0434\u0456\u04a3\u0456\u0437!",
+ "HeaderMyPreferences": "\u041c\u0435\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u043c",
+ "ButtonMyPreferencesWelcomeYes": "\u0418\u04d9, \u043c\u0435\u043d \u0435\u043d\u0434\u0456 \u043c\u0435\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u043c\u0434\u0456 \u043e\u0440\u043d\u0430\u0442\u0443\u044b\u043d \u049b\u0430\u043b\u0430\u0439\u043c\u044b\u043d.",
+ "ButtonMyPreferencesWelcomeNo": "\u0416\u043e\u049b, \u0440\u0430\u0445\u043c\u0435\u0442, \u043c\u0435\u043d \u043e\u043d\u044b \u043a\u0435\u0439\u0456\u043d\u0456\u0440\u0435\u043a \u0456\u0441\u0442\u0435\u0439\u043c\u0456\u043d.",
+ "MyPreferencesWelcomeMessage1": "\u0421\u0456\u0437 \u049b\u0430\u043b\u0430\u0439 \u0442\u0430\u043c\u0430\u0448\u0430\u043b\u0430\u0439\u0442\u044b\u043d\u044b\u043d \u043e\u0439\u043b\u0430\u0441\u0442\u044b\u0440\u044b\u043f \u0441\u0456\u0437\u0434\u0456\u04a3 \u0442\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430\u04a3\u044b\u0437\u0434\u044b \u043a\u04e9\u0440\u0441\u0435\u0442\u0442\u0456\u043c\u0456\u0437. \u0422\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u04a3\u0456\u0437\u0434\u0456 \u0440\u0435\u0442\u0442\u0435\u0443 \u0430\u0440\u049b\u044b\u043b\u044b \u043c\u0430\u0437\u043c\u04b1\u043d \u0431\u0435\u0437\u0435\u043d\u0434\u0456\u0440\u0443\u0456 \u043c\u0435\u043d \u0442\u043e\u043f\u0442\u0430\u0441\u0442\u044b\u0440\u0443\u044b \u043a\u0435\u0437 \u043a\u0435\u043b\u0433\u0435\u043d \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u04e9\u0437\u0433\u0435\u0440\u0442\u0456\u043b\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d. \u0421\u0456\u0437\u0434\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u04a3\u0456\u0437 \u0431\u0430\u0440\u043b\u044b\u049b Emby \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u044b\u043d\u0434\u0430 \u049b\u043e\u043b\u0434\u0430\u043d\u044b\u043b\u0430\u0434\u044b.",
+ "MyPreferencesWelcomeMessage2": "\u0421\u0456\u0437 \u0435\u043d\u0434\u0456 \u04e9\u0437 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u043d\u0456\u0437\u0434\u0456 \u043e\u0440\u043d\u0430\u0442\u0443\u044b\u043d \u049b\u0430\u043b\u0430\u0439\u0441\u044b\u0437 \u0431\u0430?",
+ "ToAccessPreferencesHelp": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u04a3\u0456\u0437\u0433\u0435 \u043a\u0435\u0439\u0456\u043d\u0456\u0440\u0435\u043a \u049b\u0430\u0442\u044b\u043d\u0430\u0443 \u04af\u0448\u0456\u043d, \u04af\u0441\u0442\u0456\u04a3\u0433\u0456 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u043c\u0435\u0441\u0456 \u043e\u04a3 \u0436\u0430\u0493\u044b\u043d\u0434\u0430\u0493\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0431\u0435\u043b\u0433\u0456\u0448\u0435\u0441\u0456\u043d \u0431\u0430\u0441\u044b\u04a3\u044b\u0437 \u0436\u04d9\u043d\u0435 \u041c\u0435\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u043c\u0434\u0456 \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ko.json b/MediaBrowser.Server.Implementations/Localization/Server/ko.json
index 36003bc3f..240d075b9 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ko.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ko.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nothing here.",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"TabSuggested": "Suggested",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Latest",
"TabUpcoming": "Upcoming",
"TabShows": "Shows",
@@ -401,9 +404,10 @@
"ButtonRefresh": "Refresh",
"ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnAllChannels": "Record on all channels",
+ "OptionRecordAnytime": "Record at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ms.json b/MediaBrowser.Server.Implementations/Localization/Server/ms.json
index 12081cc5a..705f9574f 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ms.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ms.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nothing here.",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"TabSuggested": "Suggested",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Latest",
"TabUpcoming": "Upcoming",
"TabShows": "Shows",
@@ -401,9 +404,10 @@
"ButtonRefresh": "Refresh",
"ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnAllChannels": "Record on all channels",
+ "OptionRecordAnytime": "Record at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/nb.json b/MediaBrowser.Server.Implementations/Localization/Server/nb.json
index cce3ec647..7af6fd415 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/nb.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/nb.json
@@ -15,7 +15,7 @@
"LabelFinish": "Ferdig",
"LabelNext": "Neste",
"LabelYoureDone": "Ferdig!",
- "WelcomeToProject": "Welcome to Emby!",
+ "WelcomeToProject": "Velkommen til Emby",
"ThisWizardWillGuideYou": "Denne wizarden vil guide deg gjennom server-konfigurasjonen. For \u00e5 begynne, vennligst velg spr\u00e5k.",
"TellUsAboutYourself": "Fortell om deg selv",
"ButtonQuickStartGuide": "Hurtigstartveiledning",
@@ -49,9 +49,11 @@
"ButtonOrganize": "Organiser",
"LinkedToEmbyConnect": "Linked to Emby Connect",
"HeaderSupporterBenefits": "Supporter Benefits",
- "HeaderAddUser": "Add User",
+ "HeaderAddUser": "Ny bruker",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
- "LabelPinCode": "Pin code:",
+ "LabelPinCode": "Pin kode:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Avbryt",
"ButtonExit": "Exit",
@@ -64,8 +66,8 @@
"TabPlaylist": "Playlist",
"HeaderEasyPinCode": "Enkel PIN-kode",
"HeaderGrownupsOnly": "Grown-ups Only!",
- "DividerOr": "-- or --",
- "HeaderInstalledServices": "Installed Services",
+ "DividerOr": "-- eller --",
+ "HeaderInstalledServices": "Installerte programtillegg",
"HeaderAvailableServices": "Available Services",
"MessageNoServicesInstalled": "No services are currently installed.",
"HeaderToAccessPleaseEnterEasyPinCode": "To access, please enter your easy pin code",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Ingeting her.",
"MessagePleaseEnsureInternetMetadata": "P\u00e5se at nedlasting av internet-metadata er sl\u00e5tt p\u00e5.",
"TabSuggested": "Forslag",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Siste",
"TabUpcoming": "Kommer",
"TabShows": "Show",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Ta opptak p\u00e5 alle kanaler",
"OptionRecordAnytime": "Ta opptak n\u00e5r som helst",
"OptionRecordOnlyNewEpisodes": "Ta opptak kun av nye episoder",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Dager",
"HeaderActiveRecordings": "Aktive opptak",
"HeaderLatestRecordings": "Siste opptak",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Hjemme side seksjon 2:",
"LabelHomePageSection3": "Hjemme side seksjon 3:",
"LabelHomePageSection4": "Hjemme side seksjon 4:",
- "OptionMyViewsButtons": "Mitt syn (knapper)",
- "OptionMyViews": "Mitt syn",
- "OptionMyViewsSmall": "Mitt Syn (liten)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Fortsette",
"OptionLatestMedia": "Siste media",
"OptionLatestChannelMedia": "Siste kanal elementer",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Standard",
"OptionCommunityMostWatchedSort": "Mest Sett",
"TabNextUp": "Neste",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "Ingen film forslag er forel\u00f8pig tilgjengelig. Start med \u00e5 se og ranger filmer. Kom deretter tilbake for \u00e5 f\u00e5 forslag p\u00e5 anbefalinger.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Spillelister tillater deg \u00e5 lage lister over innhold til \u00e5 spille etter hverandre p\u00e5 en gang. For \u00e5 legge til elementer i spillelister, h\u00f8yreklikk eller trykk og hold, og velg Legg til i spilleliste.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "Mer...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/nl.json b/MediaBrowser.Server.Implementations/Localization/Server/nl.json
index ded3ae100..5328b7aa3 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/nl.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/nl.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Gebruiker Toevoegen",
"LabelAddConnectSupporterHelp": "Om een \u200b\u200bgebruiker toe te voegen die niet in de lijst voorkomt, moet je eerst hun account koppelen aan Emby Connect uit hun gebruikersprofiel pagina.",
"LabelPinCode": "Pincode:",
+ "OptionHideWatchedContentFromLatestMedia": "Verberg bekeken inhoud van recent toegevoegd",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Annuleren",
"ButtonExit": "Afsluiten",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Lijst is leeg.",
"MessagePleaseEnsureInternetMetadata": "Zorg ervoor dat het downloaden van metadata van het internet is ingeschakeld.",
"TabSuggested": "Aanbevolen",
+ "TabSuggestions": "Suggesties",
"TabLatest": "Nieuw",
"TabUpcoming": "Binnenkort op TV",
"TabShows": "Series",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Programma van alle kanalen opnemen",
"OptionRecordAnytime": "Programma elke keer opnemen",
"OptionRecordOnlyNewEpisodes": "Alleen nieuwe afleveringen opnemen",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Dagen",
"HeaderActiveRecordings": "Actieve Opnames",
"HeaderLatestRecordings": "Nieuwe Opnames",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Startpagina sectie 2:",
"LabelHomePageSection3": "Startpagina sectie 3:",
"LabelHomePageSection4": "Startpagina sectie 4:",
- "OptionMyViewsButtons": "Mijn overzichten (knoppen)",
- "OptionMyViews": "Mijn overzichten",
- "OptionMyViewsSmall": "Mijn overzichten (klein)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Hervatten",
"OptionLatestMedia": "Nieuwste media",
"OptionLatestChannelMedia": "Nieuwste kanaal items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Standaard",
"OptionCommunityMostWatchedSort": "Meest bekeken",
"TabNextUp": "Volgend",
+ "PlaceholderUsername": "Gebruikersnaam",
"HeaderBecomeProjectSupporter": "Wordt Emby Supporter",
- "TextEnjoyBonusFeatures": "Geniet van Bonus Features",
"MessageNoMovieSuggestionsAvailable": "Er zijn momenteel geen film suggesties beschikbaar. Begin met het bekijken en waardeer uw films, kom daarna terug om uw aanbevelingen te bekijken.",
"MessageNoCollectionsAvailable": "Collecties maken het u mogelijk om Films, Series, Albums, Boeken en Games te groeperen. Klik op de + knop om Collecties aan te maken.",
"MessageNoPlaylistsAvailable": "Met afspeellijsten kunt u een lijst maken waarvan de items achter elkaar afgespeeld worden. Om een item toe te voegen klikt u met rechts of tik en houd het vast om het te selecteren, klik vervolgens op Toevoegen aan afspeellijst.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata voor:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Aankomende Films",
+ "HeaderUpcomingSports": "Sport binnenkort",
"HeaderUpcomingPrograms": "Aankomende Programma's",
"ButtonMoreItems": "Meer...",
"LabelShowLibraryTileNames": "Toon bibliotheek tegel namen",
"LabelShowLibraryTileNamesHelp": "Bepaalt of labels onder de bibliotheek tegels zullen worden weergegeven op de startpagina",
- "OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottle": "Throtteling inschakelen",
+ "OptionEnableTranscodingThrottleHelp": "Throtteling zal automatisch de snelheid van het transcoderen aanpassen om de cpu belasting laag te houden tijdens het afspelen.",
+ "LabelUploadSpeedLimit": "Upload limiet (mbps):",
+ "OptionAllowSyncTranscoding": "Sta synchronisatie toe die transcodering vereist",
+ "HeaderPlayback": "Media afspelen",
+ "OptionAllowAudioPlaybackTranscoding": "Sta het afspelen van audio wat transcoding vereist toe",
+ "OptionAllowVideoPlaybackTranscoding": "Sta het afspelen van video wat transcoding vereist toe",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Gebruikers zullen een bericht ontvangen als afspelen niet is toegestaan op basis van het beleid",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Client bitrate limiet (mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "Een optionele streaming bitrate limiet voor alle clients. Dit wordt gebruikt om te voorkomen dat clients een hogere bitrate aanvragen dan de internet connectie kan leveren.",
+ "LabelConversionCpuCoreLimit": "CPU core limiet:",
+ "LabelConversionCpuCoreLimitHelp": "Limiteer het aantal CPU cores wat gebruikt mag worden bij een omzetteing om te synchroniseren.",
+ "OptionEnableFullSpeedConversion": "Schakel hoge converteren op hoge snelheid in",
+ "OptionEnableFullSpeedConversionHelp": "Standaard wordt het converteren voor synchronisatie opdrachten op lage snelheid uitgevoerd zodat er weinig impact is op de server.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pl.json b/MediaBrowser.Server.Implementations/Localization/Server/pl.json
index ef441fccd..5a1d623c4 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/pl.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/pl.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Anuluj",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nic tutaj nie ma.",
"MessagePleaseEnsureInternetMetadata": "Upewnij si\u0119 \u017ce pobieranie metadanych z internetu jest w\u0142\u0105czone.",
"TabSuggested": "Sugerowane",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Ostatnie",
"TabUpcoming": "Upcoming",
"TabShows": "Seriale",
@@ -401,9 +404,10 @@
"ButtonRefresh": "Refresh",
"ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnAllChannels": "Record on all channels",
+ "OptionRecordAnytime": "Record at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json
index 20d7e32fa..1a93e7021 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Adicionar Usu\u00e1rio",
"LabelAddConnectSupporterHelp": "Para adicionar um usu\u00e1rio que n\u00e3o esteja listado, voc\u00ea precisar\u00e1 associar sua conta ao Emby Connect na sua p\u00e1gina de perfil.",
"LabelPinCode": "C\u00f3digo Pin:",
+ "OptionHideWatchedContentFromLatestMedia": "Ocultar conte\u00fado j\u00e1 assistido das m\u00eddias recentes",
+ "HeaderSync": "Sincroniza\u00e7\u00e3o",
"ButtonOk": "Ok",
"ButtonCancel": "Cancelar",
"ButtonExit": "Sair",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nada aqui.",
"MessagePleaseEnsureInternetMetadata": "Por favor, certifique-se que o download de metadados da internet est\u00e1 habilitado.",
"TabSuggested": "Sugeridos",
+ "TabSuggestions": "Sugest\u00f5es",
"TabLatest": "Recentes",
"TabUpcoming": "Por Estrear",
"TabShows": "S\u00e9ries",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Gravar programa em todos os canais",
"OptionRecordAnytime": "Gravar programa a qualquer hora",
"OptionRecordOnlyNewEpisodes": "Gravar apenas novos epis\u00f3dios",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Dias",
"HeaderActiveRecordings": "Grava\u00e7\u00f5es Ativas",
"HeaderLatestRecordings": "Grava\u00e7\u00f5es Recentes",
@@ -572,7 +576,7 @@
"HeaderDestination": "Destino",
"HeaderProgram": "Programa",
"HeaderClients": "Clientes",
- "LabelCompleted": "Completa",
+ "LabelCompleted": "Conclu\u00eddo",
"LabelFailed": "Falhou",
"LabelSkipped": "Ignorada",
"HeaderEpisodeOrganization": "Organiza\u00e7\u00e3o do Epis\u00f3dio",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Tela de in\u00edcio se\u00e7\u00e3o 2:",
"LabelHomePageSection3": "Tela de in\u00edcio se\u00e7\u00e3o 3:",
"LabelHomePageSection4": "Tela de in\u00edcio se\u00e7\u00e3o 4:",
- "OptionMyViewsButtons": "Minhas visualiza\u00e7\u00f5es (bot\u00f5es)",
- "OptionMyViews": "Minhas visualiza\u00e7\u00f5es",
- "OptionMyViewsSmall": "Minhas visualiza\u00e7\u00f5es (pequeno)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Retomar",
"OptionLatestMedia": "M\u00eddias recentes",
"OptionLatestChannelMedia": "Itens recentes de canal",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Padr\u00e3o",
"OptionCommunityMostWatchedSort": "Mais Assistidos",
"TabNextUp": "Pr\u00f3ximos",
+ "PlaceholderUsername": "Nome do usu\u00e1rio",
"HeaderBecomeProjectSupporter": "Torne-se um Colaborador do Emby",
- "TextEnjoyBonusFeatures": "Aproveite Funcionalidades Extras",
"MessageNoMovieSuggestionsAvailable": "N\u00e3o existem sugest\u00f5es de filmes dispon\u00edveis atualmente. Comece por assistir e avaliar seus filmes e, ent\u00e3o, volte para verificar suas recomenda\u00e7\u00f5es.",
"MessageNoCollectionsAvailable": "Cole\u00e7\u00f5es permitem que voc\u00ea aproveite grupos personalizados de Filmes, S\u00e9ries, \u00c1lbuns, Livros e Jogos. Clique no bot\u00e3o + para come\u00e7ar a criar Cole\u00e7\u00f5es.",
"MessageNoPlaylistsAvailable": "Listas de reprodu\u00e7\u00e3o permitem criar listas com conte\u00fado para reproduzir consecutivamente, de uma s\u00f3 vez. Para adicionar itens \u00e0s listas de reprodu\u00e7\u00e3o, clique com o bot\u00e3o direito ou toque a tela por alguns segundos, depois selecione Adicionar \u00e0 Lista de Reprodu\u00e7\u00e3o.",
@@ -1096,8 +1100,8 @@
"HeaderActivity": "Atividade",
"ScheduledTaskStartedWithName": "{0} iniciado",
"ScheduledTaskCancelledWithName": "{0} foi cancelado",
- "ScheduledTaskCompletedWithName": "{0} completa",
- "ScheduledTaskFailed": "Tarefa agendada completa",
+ "ScheduledTaskCompletedWithName": "{0} conclu\u00edda",
+ "ScheduledTaskFailed": "Tarefa agendada conclu\u00edda",
"PluginInstalledWithName": "{0} foi instalado",
"PluginUpdatedWithName": "{0} foi atualizado",
"PluginUninstalledWithName": "{0} foi desinstalado",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Fazer download dos metadados da internet para:",
"OptionTVMovies": "Filmes da TV",
"HeaderUpcomingMovies": "Filmes Por Estrear",
+ "HeaderUpcomingSports": "Esportes Por Estrear",
"HeaderUpcomingPrograms": "Programas Por Estrear",
"ButtonMoreItems": "Mais...",
"LabelShowLibraryTileNames": "Mostrar os nomes das tiles da biblioteca",
"LabelShowLibraryTileNamesHelp": "Determina se os t\u00edtulos ser\u00e3o exibidos embaixo das tiles da biblioteca na p\u00e1gina in\u00edcio",
"OptionEnableTranscodingThrottle": "Ativar controlador de fluxo",
- "OptionEnableTranscodingThrottleHelp": "O controlador de fluxo ajustar\u00e1 automaticamente a velocidade de transcodifica\u00e7\u00e3o para minimizar o uso da cpu no servidor durante a reprodu\u00e7\u00e3o"
+ "OptionEnableTranscodingThrottleHelp": "O controlador de fluxo ajustar\u00e1 automaticamente a velocidade de transcodifica\u00e7\u00e3o para minimizar o uso da cpu no servidor durante a reprodu\u00e7\u00e3o.",
+ "LabelUploadSpeedLimit": "Limite de velocidade de upload (mbps):",
+ "OptionAllowSyncTranscoding": "Permitir sincroniza\u00e7\u00e3o que necessite de transcodifica\u00e7\u00e3o",
+ "HeaderPlayback": "Reprodu\u00e7\u00e3o de M\u00eddia",
+ "OptionAllowAudioPlaybackTranscoding": "Permitir reprodu\u00e7\u00e3o de \u00e1udio que necessite de transcodifica\u00e7\u00e3o",
+ "OptionAllowVideoPlaybackTranscoding": "Permitir reprodu\u00e7\u00e3o de v\u00eddeo que necessite de transcodifica\u00e7\u00e3o",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Os usu\u00e1rios receber\u00e3o mensagens de erro amig\u00e1veis quando o conte\u00fado n\u00e3o for reproduz\u00edvel, baseado nas pol\u00edticas.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Limite de taxa de bits para o cliente remoto (mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "Um limite opcional da taxa de bits para todos os clientes remotos. Esta op\u00e7\u00e3o \u00e9 \u00fatil para evitar que os clientes demandem uma taxa de bits maior que a permitida pela sua conex\u00e3o.",
+ "LabelConversionCpuCoreLimit": "Limite de n\u00facleos da CPU:",
+ "LabelConversionCpuCoreLimitHelp": "Limite o n\u00famero de n\u00facleos da CPU que ser\u00e3o usados durante a convers\u00e3o na sincroniza\u00e7\u00e3o",
+ "OptionEnableFullSpeedConversion": "Ativar convers\u00e3o de alta velocidade",
+ "OptionEnableFullSpeedConversionHelp": "Por padr\u00e3o, a convers\u00e3o na sincroniza\u00e7\u00e3o \u00e9 executada em uma velocidade baixa para reduzir o consumo de recursos.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json
index dec7d35d2..4b4ec0e55 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json
@@ -4,8 +4,8 @@
"LabelGithub": "Github",
"LabelSwagger": "Swagger",
"LabelStandard": "Padr\u00e3o",
- "LabelApiDocumentation": "Api Documentation",
- "LabelDeveloperResources": "Developer Resources",
+ "LabelApiDocumentation": "Documenta\u00e7\u00e3o da API",
+ "LabelDeveloperResources": "Recursos do Programador",
"LabelBrowseLibrary": "Navegar pela Biblioteca",
"LabelConfigureServer": "Configurar o Emby",
"LabelOpenLibraryViewer": "Abrir Visualizador da Biblioteca",
@@ -18,7 +18,7 @@
"WelcomeToProject": "Bem-vindo ao Emby!",
"ThisWizardWillGuideYou": "Este assistente ir\u00e1 ajud\u00e1-lo durante o processo de configura\u00e7\u00e3o. Para come\u00e7ar, selecione o idioma.",
"TellUsAboutYourself": "Fale-nos sobre si",
- "ButtonQuickStartGuide": "Quick start guide",
+ "ButtonQuickStartGuide": "Guia r\u00e1pido",
"LabelYourFirstName": "O seu primeiro nome:",
"MoreUsersCanBeAddedLater": "\u00c9 poss\u00edvel adicionar utilizadores mais tarde no Painel Principal",
"UserProfilesIntro": "O Emby inclui suporte nativo de perfis de utilizadores, permitindo que cada utilizador tenha as suas configura\u00e7\u00f5es de visualiza\u00e7\u00e3o, estado da reprodu\u00e7\u00e3o e controlos parentais.",
@@ -46,12 +46,14 @@
"LabelDashboardSourcePath": "Caminho da fonte do cliente web:",
"LabelDashboardSourcePathHelp": "Se correr o servidor a partir do c\u00f3digo fonte, especifique o caminho da pasta dashboard-ui. Todos os ficheiros do cliente web ser\u00e3o usados a partir desta localiza\u00e7\u00e3o.",
"ButtonConvertMedia": "Convert media",
- "ButtonOrganize": "Organize",
- "LinkedToEmbyConnect": "Linked to Emby Connect",
- "HeaderSupporterBenefits": "Supporter Benefits",
+ "ButtonOrganize": "Organizar",
+ "LinkedToEmbyConnect": "Associado ao Emby Connect",
+ "HeaderSupporterBenefits": "Benef\u00edcios do Apoiante",
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Cancelar",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nada aqui.",
"MessagePleaseEnsureInternetMetadata": "Certifique-se que a transfer\u00eancia de metadados da internet est\u00e1 activa.",
"TabSuggested": "Sugest\u00f5es",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Mais recente",
"TabUpcoming": "Pr\u00f3ximos",
"TabShows": "S\u00e9ries",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Gravar programa em todos os canais",
"OptionRecordAnytime": "Gravar programa em qualquer altura",
"OptionRecordOnlyNewEpisodes": "Gravar apenas novos epis\u00f3dios",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Dias",
"HeaderActiveRecordings": "Grava\u00e7\u00f5es ativas",
"HeaderLatestRecordings": "\u00daltimas Grava\u00e7\u00f5es",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "N\u00famero da porta da Web socket:",
@@ -632,7 +636,7 @@
"LabelDownMixAudioScaleHelp": "Aumentar o \u00e1udio ao fazer downmix. Defina como 1 para preservar o volume original.",
"ButtonLinkKeys": "Transferir Chave",
"LabelOldSupporterKey": "Chave de apoiante antiga",
- "LabelNewSupporterKey": "Chave de apoiante nova",
+ "LabelNewSupporterKey": "Nova chave de apoiante",
"HeaderMultipleKeyLinking": "Transferir para Nova Chave",
"MultipleKeyLinkingHelp": "If you received a new supporter key, use this form to transfer the old key's registrations to your new one.",
"LabelCurrentEmailAddress": "Endere\u00e7o de email atual",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
- "HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
+ "PlaceholderUsername": "Username",
+ "HeaderBecomeProjectSupporter": "Torne-se um Apoiante do Emby",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -963,7 +967,7 @@
"LabelSelectFolderGroups": "Automatically group content from the following folders into views such as Movies, Music and TV:",
"LabelSelectFolderGroupsHelp": "Folders that are unchecked will be displayed by themselves in their own view.",
"OptionDisplayAdultContent": "Display adult content",
- "OptionLibraryFolders": "Media folders",
+ "OptionLibraryFolders": "Pastas multim\u00e9dia",
"TitleRemoteControl": "Remote Control",
"OptionLatestTvRecordings": "Latest recordings",
"LabelProtocolInfo": "Protocol info:",
@@ -1102,8 +1106,8 @@
"PluginUpdatedWithName": "{0} was updated",
"PluginUninstalledWithName": "{0} was uninstalled",
"ScheduledTaskFailedWithName": "{0} failed",
- "ItemAddedWithName": "{0} was added to the library",
- "ItemRemovedWithName": "{0} was removed from the library",
+ "ItemAddedWithName": "{0} foi adicionado \u00e0 biblioteca",
+ "ItemRemovedWithName": "{0} foi removido da biblioteca",
"DeviceOnlineWithName": "{0} is connected",
"UserOnlineFromDevice": "{0} is online from {1}",
"DeviceOfflineWithName": "{0} has disconnected",
@@ -1268,12 +1272,12 @@
"OptionHlsSegmentedSubtitles": "Hls segmented subtitles",
"LabelSubtitleFormatHelp": "Example: srt",
"ButtonLearnMore": "Learn more",
- "TabPlayback": "Playback",
+ "TabPlayback": "Reprodu\u00e7\u00e3o",
"HeaderLanguagePreferences": "Language Preferences",
- "TabCinemaMode": "Cinema Mode",
- "TitlePlayback": "Playback",
- "LabelEnableCinemaModeFor": "Enable cinema mode for:",
- "CinemaModeConfigurationHelp": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
+ "TabCinemaMode": "Modo Cinema",
+ "TitlePlayback": "Reprodu\u00e7\u00e3o",
+ "LabelEnableCinemaModeFor": "Ativar modo cinema para:",
+ "CinemaModeConfigurationHelp": "O modo cinema traz a experi\u00eancia do cinema para a sua sala, possibilitando reproduzir trailers e introdu\u00e7\u00f5es personalizadas antes da longa-metragem.",
"OptionTrailersFromMyMovies": "Include trailers from movies in my library",
"OptionUpcomingMoviesInTheaters": "Include trailers from new and upcoming movies",
"LabelLimitIntrosToUnwatchedContent": "Only use trailers from unwatched content",
@@ -1284,14 +1288,14 @@
"LabelCustomIntrosPath": "Custom intros path:",
"LabelCustomIntrosPathHelp": "A folder containing video files. A video will be randomly selected and played after trailers.",
"ValueSpecialEpisodeName": "Special - {0}",
- "LabelSelectInternetTrailersForCinemaMode": "Internet trailers:",
+ "LabelSelectInternetTrailersForCinemaMode": "Trailers da Internet:",
"OptionUpcomingDvdMovies": "Include trailers from new and upcoming movies on Dvd & Blu-ray",
"OptionUpcomingStreamingMovies": "Include trailers from new and upcoming movies on Netflix",
"LabelDisplayTrailersWithinMovieSuggestions": "Display trailers within movie suggestions",
"LabelDisplayTrailersWithinMovieSuggestionsHelp": "Requires installation of the Trailer channel.",
- "CinemaModeConfigurationHelp2": "Individual users will have the ability to disable cinema mode within their own preferences.",
- "LabelEnableCinemaMode": "Enable cinema mode",
- "HeaderCinemaMode": "Cinema Mode",
+ "CinemaModeConfigurationHelp2": "Os utilizadores poder\u00e3o desativar o modo cinema nas suas prefer\u00eancias.",
+ "LabelEnableCinemaMode": "Ativar modo cinema",
+ "HeaderCinemaMode": "Modo Cinema",
"LabelDateAddedBehavior": "Date added behavior for new content:",
"OptionDateAddedImportTime": "Use date scanned into the library",
"OptionDateAddedFileTime": "Use file creation date",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ru.json b/MediaBrowser.Server.Implementations/Localization/Server/ru.json
index 29c1b9d12..b437ac74f 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ru.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ru.json
@@ -16,7 +16,7 @@
"LabelNext": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435",
"LabelYoureDone": "\u0412\u044b \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438!",
"WelcomeToProject": "Emby \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u0430\u0441!",
- "ThisWizardWillGuideYou": "\u042d\u0442\u043e\u0442 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u043f\u0440\u043e\u0432\u0435\u0434\u0451\u0442 \u0432\u0430\u0441 \u0447\u0435\u0440\u0435\u0437 \u0432\u0441\u0435 \u0444\u0430\u0437\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u044f\u0437\u044b\u043a.",
+ "ThisWizardWillGuideYou": "\u042d\u0442\u043e\u0442 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u043f\u0440\u043e\u0432\u0435\u0434\u0451\u0442 \u0432\u0430\u0441 \u0447\u0435\u0440\u0435\u0437 \u0432\u0441\u0435 \u0444\u0430\u0437\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u044f\u0437\u044b\u043a.",
"TellUsAboutYourself": "\u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0438\u0442\u0435 \u043e \u0441\u0435\u0431\u0435",
"ButtonQuickStartGuide": "\u041a\u043e \u043a\u0440\u0430\u0442\u043a\u043e\u043c\u0443 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0443 \u043f\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0443",
"LabelYourFirstName": "\u0412\u0430\u0448\u0435 \u0438\u043c\u044f:",
@@ -29,9 +29,9 @@
"WizardCompleted": "\u042d\u0442\u043e \u043f\u043e\u043a\u0430 \u0432\u0441\u0451 \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e. Emby \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435. \u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043d\u0430\u0448\u0438\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438, \u0430 \u043f\u043e\u0442\u043e\u043c \u043d\u0430\u0436\u043c\u0438\u0442\u0435 <b>\u0413\u043e\u0442\u043e\u0432\u043e<\/b>, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <b>\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/b>.",
"LabelConfigureSettings": "\u041d\u0430\u0437\u043d\u0430\u0447\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b",
"LabelEnableVideoImageExtraction": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0430 \u0438\u0437 \u0432\u0438\u0434\u0435\u043e",
- "VideoImageExtractionHelp": "\u0414\u043b\u044f \u0432\u0438\u0434\u0435\u043e, \u0433\u0434\u0435 \u0435\u0449\u0451 \u200b\u200b\u043d\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432, \u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0435\u0449\u0451 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043a \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438, \u043d\u043e \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u0438.",
+ "VideoImageExtractionHelp": "\u0414\u043b\u044f \u0432\u0438\u0434\u0435\u043e, \u0433\u0434\u0435 \u0435\u0449\u0451 \u200b\u200b\u043d\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432, \u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043d\u0430\u0439\u0442\u0438 \u0432 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0435\u0449\u0451 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043a \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438, \u043d\u043e \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044e.",
"LabelEnableChapterImageExtractionForMovies": "\u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0442\u044c \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0441\u0446\u0435\u043d \u0434\u043b\u044f \u0444\u0438\u043b\u044c\u043c\u043e\u0432",
- "LabelChapterImageExtractionForMoviesHelp": "\u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0441\u0446\u0435\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043c\u0435\u043d\u044e \u0432\u044b\u0431\u043e\u0440\u0430 \u0441\u0446\u0435\u043d\u044b. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u043c, \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430. \u041e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u0447\u0430, \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u0430\u044f \u043d\u0430 \u043d\u043e\u0447\u044c, \u043e\u0434\u043d\u0430\u043a\u043e, \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447. \u041d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 \u0447\u0430\u0441\u044b \u043f\u0438\u043a.",
+ "LabelChapterImageExtractionForMoviesHelp": "\u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0441\u0446\u0435\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043c\u0435\u043d\u044e \u0432\u044b\u0431\u043e\u0440\u0430 \u0441\u0446\u0435\u043d\u044b. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u044b\u043c, \u043d\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0433\u0438\u0433\u0430\u0431\u0430\u0439\u0442 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430. \u041e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0432\u0438\u0434\u0435 \u0437\u0430\u0434\u0430\u0447\u0438, \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u0430\u044f \u043d\u0430 \u043d\u043e\u0447\u044c, \u043e\u0434\u043d\u0430\u043a\u043e, \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447. \u041d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 \u0447\u0430\u0441\u044b \u043f\u0438\u043a.",
"LabelEnableAutomaticPortMapping": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u0442\u043e\u0432",
"LabelEnableAutomaticPortMappingHelp": "UPnP \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u0430 \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u0438\u044f \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430.\u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432.",
"HeaderTermsOfService": "\u0423\u0441\u043b\u043e\u0432\u0438\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0443\u0441\u043b\u0443\u0433 Emby",
@@ -41,7 +41,7 @@
"ButtonTermsOfService": "\u041a \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0443\u0441\u043b\u0443\u0433",
"HeaderDeveloperOptions": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432",
"OptionEnableWebClientResponseCache": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432 \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0430",
- "OptionDisableForDevelopmentHelp": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0434\u0430\u043d\u043d\u043e\u0435, \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0432 \u0446\u0435\u043b\u044f\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0430.",
+ "OptionDisableForDevelopmentHelp": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0438\u0445, \u043f\u043e \u043c\u0435\u0440\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u0432 \u0446\u0435\u043b\u044f\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0430.",
"OptionEnableWebClientResourceMinification": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0430",
"LabelDashboardSourcePath": "\u041f\u0443\u0442\u044c \u043a \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0443 \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0430:",
"LabelDashboardSourcePathHelp": "\u0415\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0445 \u043a\u043e\u0434\u043e\u0432, \u0443\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 dashboard-ui. \u0412\u0441\u0435 \u0444\u0430\u0439\u043b\u044b \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u044d\u0442\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f.",
@@ -52,6 +52,8 @@
"HeaderAddUser": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f",
"LabelAddConnectSupporterHelp": "\u0427\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435\u0442 \u0432 \u0441\u043f\u0438\u0441\u043a\u0435, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u0435\u0433\u043e \u0443\u0447\u0451\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c \u0441 Emby Connect \u0441 \u0435\u0433\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.",
"LabelPinCode": "PIN-\u043a\u043e\u0434:",
+ "OptionHideWatchedContentFromLatestMedia": "\u0421\u043a\u0440\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0438\u0437 \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
+ "HeaderSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f",
"ButtonOk": "\u041e\u041a",
"ButtonCancel": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c",
"ButtonExit": "\u0412\u044b\u0439\u0442\u0438",
@@ -112,7 +114,7 @@
"HeaderPreferredMetadataLanguage": "\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u044f\u0437\u044b\u043a \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445:",
"LabelSaveLocalMetadata": "\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u043d\u0443\u0442\u0440\u044c \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043e\u043a",
"LabelSaveLocalMetadataHelp": "\u041f\u0440\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0439 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432\u043d\u0443\u0442\u0440\u044c \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043e\u043a, \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432 \u0442\u0430\u043a\u043e\u043c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0438, \u0433\u0434\u0435 \u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u0430\u0432\u0438\u0442\u044c.",
- "LabelDownloadInternetMetadata": "\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430",
+ "LabelDownloadInternetMetadata": "\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430",
"LabelDownloadInternetMetadataHelp": "\u0412 Emby Server \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0445 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0439.",
"TabPreferences": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438",
"TabPassword": "\u041f\u0430\u0440\u043e\u043b\u044c",
@@ -165,8 +167,9 @@
"LabelDropImageHere": "\u041f\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435 \u0440\u0438\u0441\u0443\u043d\u043e\u043a \u0441\u044e\u0434\u0430",
"ImageUploadAspectRatioHelp": "\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c\u043e\u0435 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0441\u0442\u043e\u0440\u043e\u043d - 1:1. \u0414\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e JPG\/PNG.",
"MessageNothingHere": "\u0417\u0434\u0435\u0441\u044c \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e.",
- "MessagePleaseEnsureInternetMetadata": "\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430.",
- "TabSuggested": "\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u0435",
+ "MessagePleaseEnsureInternetMetadata": "\u0423\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430.",
+ "TabSuggested": "\u041f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0435",
+ "TabSuggestions": "\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u043e\u0435",
"TabLatest": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435",
"TabUpcoming": "\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u043e\u0435",
"TabShows": "\u0422\u0412-\u0446\u0438\u043a\u043b\u044b",
@@ -185,8 +188,8 @@
"OptionDirectors": "\u0420\u0435\u0436\u0438\u0441\u0441\u0451\u0440\u044b",
"OptionWriters": "\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0441\u0442\u044b",
"OptionProducers": "\u041f\u0440\u043e\u0434\u044e\u0441\u0435\u0440\u044b",
- "HeaderResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u044b\u0435",
- "HeaderNextUp": "\u041e\u0447\u0435\u0440\u0435\u0434\u043d\u044b\u0435",
+ "HeaderResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u043e\u0435",
+ "HeaderNextUp": "\u041e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0435",
"NoNextUpItemsMessage": "\u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e. \u041d\u0430\u0447\u043d\u0438\u0442\u0435 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u0432\u043e\u0438 \u0422\u0412-\u0446\u0438\u043a\u043b\u044b!",
"HeaderLatestEpisodes": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b",
"HeaderPersonTypes": "\u0422\u0438\u043f\u044b \u043f\u0435\u0440\u0441\u043e\u043d:",
@@ -225,7 +228,7 @@
"OptionBanner": "\u0411\u0430\u043d\u043d\u0435\u0440",
"OptionCriticRating": "\u041e\u0446\u0435\u043d\u043a\u0430 \u043a\u0440\u0438\u0442\u0438\u043a\u043e\u0432",
"OptionVideoBitrate": "\u041f\u043e\u0442\u043e\u043a. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432\u0438\u0434\u0435\u043e",
- "OptionResumable": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u044b\u0435",
+ "OptionResumable": "\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435",
"ScheduledTasksHelp": "\u0429\u0451\u043b\u043a\u043d\u0438\u0442\u0435 \u043f\u043e \u0437\u0430\u0434\u0430\u0447\u0435, \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0451 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435.",
"ScheduledTasksTitle": "\u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a",
"TabMyPlugins": "\u041c\u043e\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u044b",
@@ -295,12 +298,12 @@
"VisitProjectWebsite": "\u041f\u043e\u0441\u0435\u0442\u0438\u0442\u044c \u0441\u0430\u0439\u0442 Emby",
"VisitProjectWebsiteLong": "\u041f\u043e\u0441\u0435\u0449\u0430\u0439\u0442\u0435 \u0441\u0430\u0439\u0442 Emby, \u0447\u0442\u043e\u0431\u044b \u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c\u0438 \u043d\u043e\u0432\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0431\u043b\u043e\u0433\u043e\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.",
"OptionHideUser": "\u0421\u043a\u0440\u044b\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441 \u044d\u043a\u0440\u0430\u043d\u043e\u0432 \u0432\u0445\u043e\u0434\u0430",
- "OptionHideUserFromLoginHelp": "\u041f\u043e\u043b\u0435\u0437\u043d\u043e \u043f\u0440\u0438 \u043b\u0438\u0447\u043d\u044b\u0445 \u0438\u043b\u0438 \u0441\u043a\u0440\u044b\u0442\u044b\u0445 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0441\u043a\u0438\u0445 \u0443\u0447\u0451\u0442\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043d\u0443\u0436\u043d\u043e \u0432\u043e\u0439\u0442\u0438 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0432\u0440\u0443\u0447\u043d\u0443\u044e, \u0432\u0432\u0435\u0434\u044f \u0441\u0432\u043e\u0451 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043f\u0430\u0440\u043e\u043b\u044c.",
+ "OptionHideUserFromLoginHelp": "\u0426\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e \u0434\u043b\u044f \u043b\u0438\u0447\u043d\u044b\u0445 \u0438\u043b\u0438 \u0441\u043a\u0440\u044b\u0442\u044b\u0445 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0441\u043a\u0438\u0445 \u0443\u0447\u0451\u0442\u043d\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0431\u0443\u0434\u0435\u0442 \u043d\u0443\u0436\u043d\u043e \u0432\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0432\u0440\u0443\u0447\u043d\u0443\u044e, \u0432\u0432\u043e\u0434\u044f \u0441\u0432\u043e\u0451 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438 \u043f\u0430\u0440\u043e\u043b\u044c.",
"OptionDisableUser": "\u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f",
"OptionDisableUserHelp": "\u041f\u0440\u0438 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438, \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442 \u043b\u044e\u0431\u044b\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0437\u043a\u043e \u043e\u0431\u043e\u0440\u0432\u0430\u043d\u044b.",
"HeaderAdvancedControl": "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435",
"LabelName": "\u0418\u043c\u044f (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435):",
- "ButtonHelp": "\u041a \u0441\u043f\u0440\u0430\u0432\u043a\u0435",
+ "ButtonHelp": "\u041a \u0441\u043f\u0440\u0430\u0432\u043a\u0435 \u0432 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435",
"OptionAllowUserToManageServer": "\u042d\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c",
"HeaderFeatureAccess": "\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438",
"OptionAllowMediaPlayback": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
@@ -345,7 +348,7 @@
"LabelMetadataPath": "\u041f\u0443\u0442\u044c \u043a \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c:",
"LabelMetadataPathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0439 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u0440\u0438 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u043d\u0435 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043e\u043a.",
"LabelTranscodingTempPath": "\u041f\u0443\u0442\u044c \u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0444\u0430\u0439\u043b\u0430\u043c \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438:",
- "LabelTranscodingTempPathHelp": "\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0447\u0438\u0435 \u0444\u0430\u0439\u043b\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435. \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u043e\u043b\u0435 \u043d\u0435\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0430\u043f\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.",
+ "LabelTranscodingTempPathHelp": "\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0447\u0438\u0435 \u0444\u0430\u0439\u043b\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435. \u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0438\u043b\u0438 \u043d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0430\u043f\u043a\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 data.",
"TabBasics": "\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435",
"TabTV": "\u0422\u0412",
"TabGames": "\u0418\u0433\u0440\u044b",
@@ -368,7 +371,7 @@
"LabelMetadataDownloadLanguage": "\u041f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u044f\u0437\u044b\u043a \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e:",
"ButtonAutoScroll": "\u041a \u0430\u0432\u0442\u043e\u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0435",
"LabelImageSavingConvention": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432:",
- "LabelImageSavingConventionHelp": "\u0412 Emby \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u044e\u0442\u0441\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0438\u0437 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0440\u0430\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043c\u0443\u043b\u044c\u0442\u0438\u043c\u0435\u0434\u0438\u0430. \u0412\u044b\u0431\u043e\u0440 \u0441\u0432\u043e\u0435\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u043e\u043b\u0435\u0437\u0435\u043d, \u0435\u0441\u043b\u0438 \u0432\u044b \u0442\u0430\u043a\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b.",
+ "LabelImageSavingConventionHelp": "\u0412 Emby \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u044e\u0442\u0441\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0438\u0437 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445. \u0412\u044b\u0431\u043e\u0440 \u0441\u0432\u043e\u0435\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u043c, \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0442\u0430\u043a\u0436\u0435 \u0438\u043d\u044b\u0445 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432.",
"OptionImageSavingCompatible": "\u0421\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 - Emby\/Kodi\/Plex",
"OptionImageSavingStandard": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 - MB2",
"ButtonSignIn": "\u0412\u043e\u0439\u0442\u0438",
@@ -401,9 +404,10 @@
"ButtonRefresh": "\u041f\u043e\u0434\u043d\u043e\u0432\u0438\u0442\u044c",
"ButtonAdvancedRefresh": "\u041f\u043e\u0434\u043d\u043e\u0432\u0438\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e",
"OptionPriority": "\u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442",
- "OptionRecordOnAllChannels": "\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0441\u043e \u0432\u0441\u0435\u0445 \u043a\u0430\u043d\u0430\u043b\u043e\u0432",
- "OptionRecordAnytime": "\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0443 \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f",
+ "OptionRecordOnAllChannels": "\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0441\u043e \u0432\u0441\u0435\u0445 \u043a\u0430\u043d\u0430\u043b\u043e\u0432",
+ "OptionRecordAnytime": "\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f",
"OptionRecordOnlyNewEpisodes": "\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b",
+ "HeaderRepeatingOptions": "\u041f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b",
"HeaderDays": "\u0414\u043d\u0438",
"HeaderActiveRecordings": "\u0410\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438",
"HeaderLatestRecordings": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0438",
@@ -414,7 +418,7 @@
"ButtonDelete": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c",
"ButtonRemove": "\u0418\u0437\u044a\u044f\u0442\u044c",
"OptionRecordSeries": "\u0417\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0435\u0440\u0438\u0430\u043b",
- "HeaderDetails": "\u0414\u0435\u0442\u0430\u043b\u0438",
+ "HeaderDetails": "\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0435 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
"TitleLiveTV": "\u0422\u0412-\u044d\u0444\u0438\u0440",
"LabelNumberOfGuideDays": "\u0427\u0438\u0441\u043b\u043e \u0434\u043d\u0435\u0439 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0433\u0438\u0434\u0430:",
"LabelNumberOfGuideDaysHelp": "\u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u0434\u043d\u0435\u0439, \u0442\u0435\u043c \u0446\u0435\u043d\u043d\u0435\u0435 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0433\u0438\u0434\u0430, \u0434\u0430\u0432\u0430\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0440\u0430\u043d\u043d\u0435\u0433\u043e \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0433\u043e \u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u043e\u0431\u044a\u0451\u043c\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0447, \u043d\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u043e\u0434\u043b\u044f\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443. \u041f\u0440\u0438 \u0440\u0435\u0436\u0438\u043c\u0435 \u00ab\u0410\u0432\u0442\u043e\u00bb \u0432\u044b\u0431\u043e\u0440 \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u0430\u043d\u0430\u043b\u043e\u0432.",
@@ -547,14 +551,14 @@
"LabelPublicHttpsPort": "\u041d\u043e\u043c\u0435\u0440 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0433\u043e HTTPS-\u043f\u043e\u0440\u0442\u0430:",
"LabelPublicHttpsPortHelp": "\u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u043c HTTPS-\u043f\u043e\u0440\u0442\u043e\u043c.",
"LabelEnableHttps": "\u041e\u0442\u0434\u0430\u0432\u0430\u0442\u044c HTTPS \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430",
- "LabelEnableHttpsHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0441\u0435\u0440\u0432\u0435\u0440 \u043e\u0442\u0434\u0430\u0451\u0442 HTTPS URL \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0435\u0433\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0449\u0451 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 HTTPS-\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b.",
+ "LabelEnableHttpsHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0441\u0435\u0440\u0432\u0435\u0440 \u043e\u0442\u0434\u0430\u0451\u0442 HTTPS URL \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0435\u0433\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430.",
"LabelHttpsPort": "\u041d\u043e\u043c\u0435\u0440 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e HTTPS-\u043f\u043e\u0440\u0442\u0430:",
"LabelHttpsPortHelp": "TCP-\u043f\u043e\u0440\u0442, \u043a\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 HTTPS-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 Emby.",
"LabelWebSocketPortNumber": "\u041d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0430 \u0432\u0435\u0431-\u0441\u043e\u043a\u0435\u0442\u0430:",
"LabelEnableAutomaticPortMap": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u0442\u043e\u0432",
"LabelEnableAutomaticPortMapHelp": "\u041f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u043f\u043e\u0440\u0442 \u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u0440\u0442\u043e\u043c \u0447\u0435\u0440\u0435\u0437 UPnP. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432.",
"LabelExternalDDNS": "\u0412\u043d\u0435\u0448\u043d\u0438\u0439 WAN-\u0430\u0434\u0440\u0435\u0441:",
- "LabelExternalDDNSHelp": "\u0415\u0441\u043b\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 DNS, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0435\u0433\u043e \u0437\u0434\u0435\u0441\u044c. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f Emby-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438. \u041e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u0443\u0441\u0442\u044b\u043c \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f.",
+ "LabelExternalDDNSHelp": "\u0415\u0441\u043b\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0439 DNS, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0435\u0433\u043e \u0437\u0434\u0435\u0441\u044c. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f Emby-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438. \u041d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f.",
"TabResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435",
"TabWeather": "\u041f\u043e\u0433\u043e\u0434\u0430",
"TitleAppSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f",
@@ -711,7 +715,7 @@
"ButtonPageUp": "\u041d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432\u0432\u0435\u0440\u0445",
"ButtonPageDown": "\u041d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432\u043d\u0438\u0437",
"PageAbbreviation": "\u0421\u0422\u0420",
- "ButtonHome": "\u041a \u0433\u043b\u0430\u0432\u043d\u043e\u043c\u0443",
+ "ButtonHome": "\u041a\u043e \u0433\u043b\u0430\u0432\u043d\u043e\u043c\u0443",
"ButtonSearch": "\u0412\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u043e\u0438\u0441\u043a",
"ButtonSettings": "\u041a \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c",
"ButtonTakeScreenshot": "\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043d\u0438\u043c\u043e\u043a \u044d\u043a\u0440\u0430\u043d\u0430",
@@ -762,7 +766,7 @@
"OptionProfileVideoAudio": "\u0412\u0438\u0434\u0435\u043e \u0410\u0443\u0434\u0438\u043e",
"OptionProfilePhoto": "\u0424\u043e\u0442\u043e",
"LabelUserLibrary": "\u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:",
- "LabelUserLibraryHelp": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u0447\u044c\u044e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0443 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435. \u041e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u043e\u043b\u0435 \u043d\u0435\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.",
+ "LabelUserLibraryHelp": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u0447\u044c\u044e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0443 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435. \u041d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.",
"OptionPlainStorageFolders": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0432\u0441\u0435 \u043f\u0430\u043f\u043a\u0438, \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u043f\u0430\u043f\u043a\u0438 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f",
"OptionPlainStorageFoldersHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0432\u0441\u0435 \u043f\u0430\u043f\u043a\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 DIDL \u043a\u0430\u043a \u00abobject.container.storageFolder\u00bb, \u0432\u043c\u0435\u0441\u0442\u043e \u0431\u043e\u043b\u0435\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u00abobject.container.person.musicArtist\u00bb.",
"OptionPlainVideoItems": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0432\u0441\u0435 \u0438\u043c\u0435\u044e\u0449\u0438\u0435\u0441\u044f \u0432\u0438\u0434\u0435\u043e, \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b",
@@ -839,7 +843,7 @@
"HeaderDownloadChaptersFor": "\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0439 \u0441\u0446\u0435\u043d \u0434\u043b\u044f:",
"LabelOpenSubtitlesUsername": "\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f Open Subtitles:",
"LabelOpenSubtitlesPassword": "\u041f\u0430\u0440\u043e\u043b\u044c Open Subtitles:",
- "HeaderChapterDownloadingHelp": "\u041f\u0440\u0438 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u043e\u0432 \u0432 Emby, \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0445 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0439 \u0441\u0446\u0435\u043d \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0441\u0446\u0435\u043d, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, ChapterDb.",
+ "HeaderChapterDownloadingHelp": "\u041f\u0440\u0438 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u043e\u0432 \u0432 Emby, \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0445 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0439 \u0441\u0446\u0435\u043d \u0438\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0441\u0446\u0435\u043d, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, ChapterDb.",
"LabelPlayDefaultAudioTrack": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443\u044e \u0430\u0443\u0434\u0438\u043e\u0434\u043e\u0440\u043e\u0436\u043a\u0443 \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u044f\u0437\u044b\u043a\u0430",
"LabelSubtitlePlaybackMode": "\u0420\u0435\u0436\u0438\u043c \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432:",
"LabelDownloadLanguages": "\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0435 \u044f\u0437\u044b\u043a\u0438:",
@@ -884,10 +888,10 @@
"LabelHomePageSection2": "\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 - \u0440\u0430\u0437\u0434\u0435\u043b 2:",
"LabelHomePageSection3": "\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 - \u0440\u0430\u0437\u0434\u0435\u043b 3:",
"LabelHomePageSection4": "\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 - \u0440\u0430\u0437\u0434\u0435\u043b 4:",
- "OptionMyViewsButtons": "\u041c\u043e\u0438 \u0430\u0441\u043f\u0435\u043a\u0442\u044b (\u043a\u043d\u043e\u043f\u043a\u0438)",
- "OptionMyViews": "\u041c\u043e\u0438 \u0430\u0441\u043f\u0435\u043a\u0442\u044b",
- "OptionMyViewsSmall": "\u041c\u043e\u0438 \u0430\u0441\u043f\u0435\u043a\u0442\u044b (\u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u043e)",
- "OptionResumablemedia": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u044b\u0435",
+ "OptionMyMediaButtons": "\u041c\u043e\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435 (\u043a\u043d\u043e\u043f\u043a\u0438)",
+ "OptionMyMedia": "\u041c\u043e\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435",
+ "OptionMyMediaSmall": "\u041c\u043e\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435 (\u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u043e)",
+ "OptionResumablemedia": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u043e\u0435",
"OptionLatestMedia": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435",
"OptionLatestChannelMedia": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0438\u0437 \u043a\u0430\u043d\u0430\u043b\u043e\u0432",
"HeaderLatestChannelItems": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0438\u0437 \u043a\u0430\u043d\u0430\u043b\u043e\u0432",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "\u0423\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u0435",
"OptionCommunityMostWatchedSort": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0435 \u0431\u043e\u043b\u044c\u0448\u0435",
"TabNextUp": "\u041e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0435",
+ "PlaceholderUsername": "\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f",
"HeaderBecomeProjectSupporter": "\u0421\u0442\u0430\u043d\u044c\u0442\u0435 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043e\u043c Emby",
- "TextEnjoyBonusFeatures": "\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u0431\u043e\u043d\u0443\u0441\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438",
"MessageNoMovieSuggestionsAvailable": "\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u044b\u0445 \u0444\u0438\u043b\u044c\u043c\u043e\u0432. \u041d\u0430\u0447\u043d\u0438\u0442\u0435 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438 \u043e\u0446\u0435\u043d\u0438\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u0444\u0438\u043b\u044c\u043c\u044b, \u0438 \u0442\u043e\u0433\u0434\u0430 \u0432\u0435\u0440\u043d\u0438\u0442\u0435\u0441\u044c \u043d\u0430\u0437\u0430\u0434, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438.",
"MessageNoCollectionsAvailable": "\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043d\u0434\u0438\u0432\u0438\u0434\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u0441\u043e\u0431\u0440\u0430\u043d\u0438\u044f\u043c\u0438 \u0444\u0438\u043b\u044c\u043c\u043e\u0432, \u0441\u0435\u0440\u0438\u0430\u043b\u043e\u0432, \u0430\u043b\u044c\u0431\u043e\u043c\u043e\u0432, \u043a\u043d\u0438\u0433 \u0438 \u0438\u0433\u0440. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \"+\", \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439.",
"MessageNoPlaylistsAvailable": "\u0421\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u043a\u043e\u0432 \u0438\u0437 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0440\u0430\u0437\u043e\u043c. \u0427\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432\u043e \u0441\u043f\u0438\u0441\u043a\u0438, \u0449\u0435\u043b\u043a\u043d\u0438\u0442\u0435 \u043f\u0440\u0430\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u043e\u0439 \u043c\u044b\u0448\u0438 \u0438\u043b\u0438 \u043a\u043e\u0441\u043d\u0438\u0442\u0435\u0441\u044c \u0438 \u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435, \u0437\u0430\u0442\u0435\u043c \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u00ab\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432\u043e \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f\u00bb.",
@@ -916,7 +920,7 @@
"LabelEnableChannelContentDownloadingFor": "\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043a\u0430\u043d\u0430\u043b\u0430 \u0434\u043b\u044f:",
"LabelEnableChannelContentDownloadingForHelp": "\u041d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u0430\u043d\u0430\u043b\u0430\u0445 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435, \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u044f\u044e\u0449\u0435\u0435 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440. \u0412\u043a\u043b\u044e\u0447\u0430\u0439\u0442\u0435 \u043f\u0440\u0438 \u0441\u0440\u0435\u0434\u0430\u0445 \u0441 \u043d\u0438\u0437\u043a\u043e\u0439 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u043a\u0430\u043d\u0430\u043b\u0430 \u0432 \u043d\u0435\u0440\u0430\u0431\u043e\u0447\u0435\u0435 \u0432\u0440\u0435\u043c\u044f. \u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u00ab\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u0430\u043d\u0430\u043b\u043e\u0432\u00bb.",
"LabelChannelDownloadPath": "\u041f\u0443\u0442\u044c \u0434\u043b\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u043a\u0430\u043d\u0430\u043b\u043e\u0432:",
- "LabelChannelDownloadPathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e, \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e. \u041e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u043e\u043b\u0435 \u043d\u0435\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044e\u044e \u043f\u0430\u043f\u043a\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.",
+ "LabelChannelDownloadPathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e, \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e. \u041d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044e\u044e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u0443\u044e \u043f\u0430\u043f\u043a\u0443 data.",
"LabelChannelDownloadAge": "\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437, \u0434\u043d\u0438:",
"LabelChannelDownloadAgeHelp": "\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0440\u0448\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u043e. \u041e\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u0435\u0442\u0441\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u044b\u043c \u043f\u043e \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u0438.",
"ChannelSettingsFormHelp": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043a\u0430\u043d\u0430\u043b\u044b (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: Trailers \u0438\u043b\u0438 Vimeo) \u0438\u0437 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432.",
@@ -937,14 +941,14 @@
"ViewTypeGameFavorites": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u043e\u0435",
"ViewTypeGameSystems": "\u0418\u0433\u0440\u043e\u0432\u044b\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b",
"ViewTypeGameGenres": "\u0416\u0430\u043d\u0440\u044b",
- "ViewTypeTvResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u044b\u0435",
- "ViewTypeTvNextUp": "\u041e\u0447\u0435\u0440\u0435\u0434\u043d\u044b\u0435",
+ "ViewTypeTvResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u043e\u0435",
+ "ViewTypeTvNextUp": "\u041e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0435",
"ViewTypeTvLatest": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435",
"ViewTypeTvShowSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u044b",
"ViewTypeTvGenres": "\u0416\u0430\u043d\u0440\u044b",
"ViewTypeTvFavoriteSeries": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0438\u0430\u043b\u044b",
"ViewTypeTvFavoriteEpisodes": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b",
- "ViewTypeMovieResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u044b\u0435",
+ "ViewTypeMovieResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u043e\u0435",
"ViewTypeMovieLatest": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435",
"ViewTypeMovieMovies": "\u0424\u0438\u043b\u044c\u043c\u044b",
"ViewTypeMovieCollections": "\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438",
@@ -970,7 +974,7 @@
"LabelProtocolInfoHelp": "\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043e\u0442\u043a\u043b\u0438\u043a\u0435 \u043d\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u044b GetProtocolInfo \u043e\u0442 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430.",
"TabNfo": "NFO-\u0444\u0430\u0439\u043b\u044b",
"HeaderKodiMetadataHelp": "\u0412 Emby \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 NFO-\u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445. \u0427\u0442\u043e\u0431\u044b \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0438\u043b\u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0442\u044c NFO-\u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u00ab\u0421\u043b\u0443\u0436\u0431\u044b\u00bb, \u0434\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u043f\u043e \u0442\u0438\u043f\u0430\u043c \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445.",
- "LabelKodiMetadataUser": "\u0421\u0438\u043d\u0445\u0440-\u0438\u044f NFO \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:",
+ "LabelKodiMetadataUser": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0441 NFO \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:",
"LabelKodiMetadataUserHelp": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u043e\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 Emby Server \u0438 NFO-\u0444\u0430\u0439\u043b\u0430\u043c\u0438.",
"LabelKodiMetadataDateFormat": "\u0424\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u0442\u044b \u0432\u044b\u043f\u0443\u0441\u043a\u0430:",
"LabelKodiMetadataDateFormatHelp": "\u0412\u0441\u0435 \u0434\u0430\u0442\u044b \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 NFO-\u0444\u0430\u0439\u043b\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430.",
@@ -1209,7 +1213,7 @@
"HeaderTags": "\u0422\u0435\u0433\u0438",
"HeaderMetadataSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
"LabelLockItemToPreventChanges": "\u0417\u0430\u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c \u0431\u0443\u0434\u0443\u0449\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f",
- "MessageLeaveEmptyToInherit": "\u041e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u043e\u043b\u0435 \u043d\u0435\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u0438\u043b\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.",
+ "MessageLeaveEmptyToInherit": "\u041d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u0438\u043b\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.",
"TabDonate": "\u041f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f",
"HeaderDonationType": "\u0422\u0438\u043f \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f:",
"OptionMakeOneTimeDonation": "\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435",
@@ -1246,7 +1250,7 @@
"HeaderXmlDocumentAttributes": "\u0410\u0442\u0440\u0438\u0431\u0443\u0442\u044b XML-\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430",
"HeaderXmlDocumentAttribute": "\u0410\u0442\u0440\u0438\u0431\u0443\u0442 XML-\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430",
"XmlDocumentAttributeListHelp": "\u0414\u0430\u043d\u043d\u044b\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u043a\u043e \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e XML-\u043e\u0442\u043a\u043b\u0438\u043a\u0430.",
- "OptionSaveMetadataAsHidden": "\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u043a\u0430\u043a \u0441\u043a\u0440\u044b\u0442\u044b\u0435 \u0444\u0430\u0439\u043b\u044b",
+ "OptionSaveMetadataAsHidden": "\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0441\u043a\u0440\u044b\u0442\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432",
"LabelExtractChaptersDuringLibraryScan": "\u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0442\u044c \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0441\u0446\u0435\u043d \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438",
"LabelExtractChaptersDuringLibraryScanHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0441\u0446\u0435\u043d \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u044b, \u043a\u043e\u0433\u0434\u0430 \u0432\u0438\u0434\u0435\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438. \u041f\u0440\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u044b \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u00ab\u0420\u0438\u0441\u0443\u043d\u043a\u0438 \u0441\u0446\u0435\u043d\u00bb, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044f \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u043c\u0443 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435.",
"LabelConnectGuestUserName": "\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f Emby \u0438\u043b\u0438 \u0430\u0434\u0440\u0435\u0441 \u044d-\u043f\u043e\u0447\u0442\u044b:",
@@ -1307,7 +1311,7 @@
"LabelCreateCameraUploadSubfolder": "\u0421\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043f\u0430\u043f\u043a\u0443 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430",
"LabelCreateCameraUploadSubfolderHelp": "\u041d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043f\u0430\u043f\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u0434\u043b\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u0438 \u0449\u0435\u043b\u0447\u043a\u0435 \u043d\u0430 \u043d\u0451\u043c \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \"\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\".",
"LabelCustomDeviceDisplayName": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435:",
- "LabelCustomDeviceDisplayNameHelp": "\u041f\u0440\u0438\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u043e\u043b\u0435 \u043d\u0435\u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u044f, \u0432\u044b\u0434\u0430\u043d\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c.",
+ "LabelCustomDeviceDisplayNameHelp": "\u041f\u0440\u0438\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u043e\u0435 \u0438\u043c\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0439\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043c\u044f, \u0432\u044b\u0434\u0430\u043d\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c.",
"HeaderInviteUser": "\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f",
"LabelConnectGuestUserNameHelp": "\u0418\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u044d-\u043f\u043e\u0447\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u0430\u0448 \u0434\u0440\u0443\u0433 \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u0430 \u043d\u0430 \u0432\u0435\u0431-\u0441\u0430\u0439\u0442 Emby.",
"HeaderInviteUserHelp": "\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u0430\u0448\u0438\u043c \u0434\u0440\u0443\u0437\u044c\u044f\u043c \u043e\u0431\u0449\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 Emby Connect.",
@@ -1378,13 +1382,36 @@
"LabelTagFilterAllowModeHelp": "\u0415\u0441\u043b\u0438 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u0442\u0435\u0433\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0447\u0430\u0441\u0442\u044c\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0433\u043b\u0443\u0431\u043e\u043a\u043e \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u043f\u0430\u043f\u043e\u043a, \u0442\u043e \u0434\u043b\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f, \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u0433\u0430\u043c\u0438, \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u043f\u0430\u043f\u043a\u0438 \u0431\u044b\u043b\u0438 \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u044b \u0442\u0430\u043a\u0436\u0435.",
"HeaderThisUserIsCurrentlyDisabled": "\u042d\u0442\u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d",
"MessageReenableUser": "\u0421\u043c. \u043d\u0438\u0436\u0435 \u0434\u043b\u044f \u0440\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438",
- "LabelEnableInternetMetadataForTvPrograms": "\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u0434\u043b\u044f:",
+ "LabelEnableInternetMetadataForTvPrograms": "\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430 \u0434\u043b\u044f:",
"OptionTVMovies": "\u0422\u0412 \u0444\u0438\u043b\u044c\u043c\u044b",
"HeaderUpcomingMovies": "\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435 \u0444\u0438\u043b\u044c\u043c\u044b",
+ "HeaderUpcomingSports": "\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435 \u0441\u043f\u043e\u0440\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438",
"HeaderUpcomingPrograms": "\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438",
"ButtonMoreItems": "\u0415\u0449\u0451...",
"LabelShowLibraryTileNames": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043f\u043b\u0438\u0442\u043e\u043a \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438",
"LabelShowLibraryTileNamesHelp": "\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f, \u0431\u0443\u0434\u0443\u0442 \u043b\u0438 \u043d\u0430\u0434\u043f\u0438\u0441\u0438 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u043f\u043e\u0434 \u043f\u043b\u0438\u0442\u043a\u0430\u043c\u0438 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435.",
"OptionEnableTranscodingThrottle": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0433\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435",
- "OptionEnableTranscodingThrottleHelp": "\u0420\u0435\u0433\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u0432\u0435\u0441\u0442\u0438 \u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f."
+ "OptionEnableTranscodingThrottleHelp": "\u0420\u0435\u0433\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f.",
+ "LabelUploadSpeedLimit": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u044f, \u041c\u0431\u0438\u0442\/\u0441",
+ "OptionAllowSyncTranscoding": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0443",
+ "HeaderPlayback": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
+ "OptionAllowAudioPlaybackTranscoding": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0430\u0443\u0434\u0438\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0443",
+ "OptionAllowVideoPlaybackTranscoding": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0443",
+ "OptionAllowMediaPlaybackTranscodingHelp": "\u041f\u0440\u0438 \u043d\u0435\u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 \u0438\u0445 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0430\u0445 \u0434\u0440\u0443\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445.",
+ "TabStreaming": "\u0422\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u044f",
+ "LabelRemoteClientBitrateLimit": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u041c\u0431\u0438\u0442\/\u0441",
+ "LabelRemoteClientBitrateLimitHelp": "\u041d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432. \u042d\u0442\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0446\u0435\u043b\u0435\u0441\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c\u0438 \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438, \u0447\u0435\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435.",
+ "LabelConversionCpuCoreLimit": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u043d\u044b\u0445 \u044f\u0434\u0435\u0440:",
+ "LabelConversionCpuCoreLimitHelp": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0438\u0441\u043b\u043e \u044f\u0434\u0435\u0440 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u044b \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438.",
+ "OptionEnableFullSpeedConversion": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0441\u043a\u043e\u0440\u043e\u0441\u0442\u043d\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435",
+ "OptionEnableFullSpeedConversionHelp": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043d\u0438\u0437\u043a\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438, \u0447\u0442\u043e\u0431\u044b \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432.",
+ "HeaderPlaylists": "\u0421\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
+ "HeaderSelectDate": "\u0412\u044b\u0431\u043e\u0440 \u0434\u0430\u0442\u044b",
+ "HeaderWelcomeExclamation": "\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u043c!",
+ "HeaderMyPreferences": "\u041c\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438",
+ "ButtonMyPreferencesWelcomeYes": "\u0414\u0430, \u044f \u0445\u043e\u0447\u0443 \u0442\u0435\u043f\u0435\u0440\u044c \u0437\u0430\u0434\u0430\u0442\u044c \u043c\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438.",
+ "ButtonMyPreferencesWelcomeNo": "\u041d\u0435\u0442, \u0441\u043f\u0430\u0441\u0438\u0431\u043e, \u044f \u0441\u0434\u0435\u043b\u0430\u044e \u044d\u0442\u043e \u043f\u043e\u0442\u043e\u043c.",
+ "MyPreferencesWelcomeMessage1": "\u0412\u0430\u0448\u0430 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u043d\u0430\u043c\u0438 \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043a\u0430\u043a \u043c\u044b \u0434\u0443\u043c\u0430\u0435\u043c, \u0447\u0442\u043e \u0432\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u044f\u0442\u043d\u043e. \u0412\u043d\u0435\u0448\u043d\u0438\u0439 \u0432\u0438\u0434 \u0438 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0430\u0448\u0438\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a. \u0412\u0430\u0448\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u043a\u043e \u0432\u0441\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c Emby.",
+ "MyPreferencesWelcomeMessage2": "\u0425\u043e\u0442\u0435\u043b\u0438 \u0431\u044b \u0432\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0435\u0439\u0447\u0430\u0441?",
+ "ToAccessPreferencesHelp": "\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0432\u0430\u0448\u0438\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c, \u0449\u0435\u043b\u043a\u043d\u0438\u0442\u0435 \u0437\u043d\u0430\u0447\u043e\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441\u043f\u0440\u0430\u0432\u0430 \u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u0438 \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u041c\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json
index 0cff99c5d..bfd23243a 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/server.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json
@@ -53,6 +53,7 @@
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
"OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonExit": "Exit",
@@ -168,6 +169,7 @@
"MessageNothingHere": "Nothing here.",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"TabSuggested": "Suggested",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Latest",
"TabUpcoming": "Upcoming",
"TabShows": "Shows",
@@ -402,9 +404,10 @@
"ButtonRefresh": "Refresh",
"ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnAllChannels": "Record on all channels",
+ "OptionRecordAnytime": "Record at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -550,7 +553,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -894,9 +897,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -912,8 +915,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -961,6 +964,7 @@
"ViewTypeMovieFavorites": "Favorites",
"ViewTypeMovieGenres": "Genres",
"ViewTypeMusicLatest": "Latest",
+ "ViewTypeMusicPlaylists": "Playlists",
"ViewTypeMusicAlbums": "Albums",
"ViewTypeMusicAlbumArtists": "Album Artists",
"HeaderOtherDisplaySettings": "Display Settings",
@@ -1398,10 +1402,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
}
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/sl_SI.json b/MediaBrowser.Server.Implementations/Localization/Server/sl_SI.json
index 86cb406b5..9232bafa5 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/sl_SI.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/sl_SI.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nothing here.",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"TabSuggested": "Suggested",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Latest",
"TabUpcoming": "Upcoming",
"TabShows": "Shows",
@@ -401,9 +404,10 @@
"ButtonRefresh": "Refresh",
"ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnAllChannels": "Record on all channels",
+ "OptionRecordAnytime": "Record at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/sv.json b/MediaBrowser.Server.Implementations/Localization/Server/sv.json
index 390ecb170..5147b08b3 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/sv.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/sv.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "OK",
"ButtonCancel": "Avbryt",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Ingenting h\u00e4r.",
"MessagePleaseEnsureInternetMetadata": "Var god se till att h\u00e4mtning av metadata via Internet \u00e4r aktiverad.",
"TabSuggested": "Rekommenderas",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Nytillkommet",
"TabUpcoming": "Kommande",
"TabShows": "Serier",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "Spela in fr\u00e5n alla kanaler",
"OptionRecordAnytime": "Spela in vid alla tidpunkter",
"OptionRecordOnlyNewEpisodes": "Spela bara in nya avsnitt",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Dagar",
"HeaderActiveRecordings": "P\u00e5g\u00e5ende inspelningar",
"HeaderLatestRecordings": "Senaste inspelningarna",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Webanslutningens portnummer:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Startsidans sektion 2:",
"LabelHomePageSection3": "Startsidans sektion 3:",
"LabelHomePageSection4": "Startsidans sektion 4:",
- "OptionMyViewsButtons": "Mina vyer (knappar)",
- "OptionMyViews": "Mina vyer",
- "OptionMyViewsSmall": "Mina vyer (liten)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "\u00c5teruppta",
"OptionLatestMedia": "Nytillkommet",
"OptionLatestChannelMedia": "Senaste objekten i Kanaler",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "F\u00f6rval",
"OptionCommunityMostWatchedSort": "Oftast visade",
"TabNextUp": "N\u00e4stkommande",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "Det finns inga filmf\u00f6rslag f\u00f6r tillf\u00e4llet. Efter att ha sett ett antal filmer kan du \u00e5terkomma hit f\u00f6r att se dina f\u00f6rslag.",
"MessageNoCollectionsAvailable": "Samlingar g\u00f6r det m\u00f6jligt att avnjuta personliga grupperingar av filmer, serier, Album, b\u00f6cker och spel. Klicka p\u00e5 knappen + f\u00f6r att b\u00f6rja skapa samlingar.",
"MessageNoPlaylistsAvailable": "Spellistor l\u00e5ter dig skapa listor med inneh\u00e5ll att spela upp i ordning. F\u00f6r att l\u00e4gga till objekt i spellistor, h\u00f6gerklicka eller tryck-och-h\u00e5ll och v\u00e4lj \"l\u00e4gg till i spellista\".",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "Mer...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/tr.json b/MediaBrowser.Server.Implementations/Localization/Server/tr.json
index 96b8db8fc..f79cf64c6 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/tr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/tr.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Tamam",
"ButtonCancel": "\u0130ptal",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nothing here.",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"TabSuggested": "\u00d6nerilen",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Son",
"TabUpcoming": "Gelecek",
"TabShows": "G\u00f6steriler",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "T\u00fcm kanallardaki program\u0131 kaydet",
"OptionRecordAnytime": "Program\u0131 herhangi bir zamanda kaydet",
"OptionRecordOnlyNewEpisodes": "Sadece yeni b\u00f6l\u00fcmleri kaydet",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "G\u00fcnler",
"HeaderActiveRecordings": "Aktif Kay\u0131tlar",
"HeaderLatestRecordings": "Ge\u00e7mi\u015f Kay\u0131tlar",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Anasayfa Secenek 2:",
"LabelHomePageSection3": "Anasayfa Secenek 3:",
"LabelHomePageSection4": "Anasayfa Secenek 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "En Son G\u00f6r\u00fcnt\u00fclemeler",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Sonraki hafta",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/uk.json b/MediaBrowser.Server.Implementations/Localization/Server/uk.json
index 1f6da0700..bb41b82ff 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/uk.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/uk.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Nothing here.",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"TabSuggested": "Suggested",
+ "TabSuggestions": "Suggestions",
"TabLatest": "Latest",
"TabUpcoming": "Upcoming",
"TabShows": "Shows",
@@ -401,9 +404,10 @@
"ButtonRefresh": "Refresh",
"ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnAllChannels": "Record on all channels",
+ "OptionRecordAnytime": "Record at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "\u041e\u0441\u0442\u0430\u043d\u043d\u0456 \u043c\u0435\u0434\u0456\u0430",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/vi.json b/MediaBrowser.Server.Implementations/Localization/Server/vi.json
index 8183e4601..b4df819e0 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/vi.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/vi.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "Ok",
"ButtonCancel": "Tho\u00e1t",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "Kh\u00f4ng c\u00f3 g\u00ec \u1edf \u0111\u00e2y.",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
"TabSuggested": "Suggested",
+ "TabSuggestions": "Suggestions",
"TabLatest": "M\u1edbi nh\u1ea5t",
"TabUpcoming": "S\u1eafp di\u1ec5n ra",
"TabShows": "Shows",
@@ -401,9 +404,10 @@
"ButtonRefresh": "Refresh",
"ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnAllChannels": "Record on all channels",
+ "OptionRecordAnytime": "Record at any time",
"OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "Days",
"HeaderActiveRecordings": "Active Recordings",
"HeaderLatestRecordings": "Latest Recordings",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web socket port number:",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json b/MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json
index b2c216960..27907b30b 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "\u786e\u5b9a",
"ButtonCancel": "\u53d6\u6d88",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "\u8fd9\u513f\u4ec0\u4e48\u90fd\u6ca1\u6709\u3002",
"MessagePleaseEnsureInternetMetadata": "\u8bf7\u786e\u4fdd\u5df2\u542f\u7528\u4ece\u4e92\u8054\u7f51\u4e0b\u8f7d\u5a92\u4f53\u8d44\u6599\u3002",
"TabSuggested": "\u5efa\u8bae",
+ "TabSuggestions": "Suggestions",
"TabLatest": "\u6700\u65b0",
"TabUpcoming": "\u5373\u5c06\u53d1\u5e03",
"TabShows": "\u8282\u76ee",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "\u5f55\u5236\u6240\u6709\u9891\u9053",
"OptionRecordAnytime": "\u5f55\u5236\u6240\u6709\u65f6\u6bb5",
"OptionRecordOnlyNewEpisodes": "\u53ea\u5f55\u5236\u65b0\u5267\u96c6",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "\u5929",
"HeaderActiveRecordings": "\u6b63\u5728\u5f55\u5236\u7684\u8282\u76ee",
"HeaderLatestRecordings": "\u6700\u65b0\u5f55\u5236\u7684\u8282\u76ee",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "Web Socket\u7aef\u53e3\u53f7\uff1a",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "\u9996\u9875\u7b2c2\u533a\uff1a",
"LabelHomePageSection3": "\u9996\u9875\u7b2c3\u533a\uff1a",
"LabelHomePageSection4": "\u9996\u9875\u7b2c4\u533a\uff1a",
- "OptionMyViewsButtons": "\u6211\u7684\u754c\u9762(\u6309\u94ae)",
- "OptionMyViews": "\u6211\u7684\u754c\u9762",
- "OptionMyViewsSmall": "\u6211\u7684\u754c\u9762 (\u5c0f)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "\u6062\u590d\u64ad\u653e",
"OptionLatestMedia": "\u6700\u65b0\u5a92\u4f53",
"OptionLatestChannelMedia": "\u6700\u65b0\u9891\u9053\u9879\u76ee",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "\u9ed8\u8ba4",
"OptionCommunityMostWatchedSort": "\u6700\u53d7\u77a9\u76ee",
"TabNextUp": "\u4e0b\u4e00\u4e2a",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "\u4eab\u53d7\u5956\u52b1\u529f\u80fd",
"MessageNoMovieSuggestionsAvailable": "\u6ca1\u6709\u53ef\u7528\u7684\u7535\u5f71\u5efa\u8bae\u3002\u5f00\u59cb\u89c2\u770b\u4f60\u7684\u7535\u5f71\u5e76\u8fdb\u884c\u8bc4\u5206\uff0c\u518d\u56de\u8fc7\u5934\u6765\u67e5\u770b\u4f60\u7684\u5efa\u8bae\u3002",
"MessageNoCollectionsAvailable": "\u5408\u96c6\u8ba9\u4f60\u4eab\u53d7\u7535\u5f71\uff0c\u7cfb\u5217\uff0c\u76f8\u518c\uff0c\u4e66\u7c4d\u548c\u6e38\u620f\u4e2a\u6027\u5316\u7684\u5206\u7ec4\u3002\u5355\u51fb\u201c+\u201d\u6309\u94ae\u5f00\u59cb\u521b\u5efa\u5408\u96c6\u3002",
"MessageNoPlaylistsAvailable": "\u64ad\u653e\u5217\u8868\u5141\u8bb8\u60a8\u521b\u5efa\u4e00\u4e2a\u5185\u5bb9\u5217\u8868\u6765\u8fde\u7eed\u64ad\u653e\u3002\u5c06\u9879\u76ee\u6dfb\u52a0\u5230\u64ad\u653e\u5217\u8868\uff0c\u53f3\u952e\u5355\u51fb\u6216\u70b9\u51fb\u5e76\u6309\u4f4f\uff0c\u7136\u540e\u9009\u62e9\u201c\u6dfb\u52a0\u5230\u64ad\u653e\u5217\u8868\u201d\u3002",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "\u66f4\u591a...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json
index d957eb2cd..82645d51e 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json
@@ -52,6 +52,8 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
+ "HeaderSync": "Sync",
"ButtonOk": "OK",
"ButtonCancel": "\u53d6\u6d88",
"ButtonExit": "Exit",
@@ -167,6 +169,7 @@
"MessageNothingHere": "\u9019\u88e1\u6c92\u6709\u4ec0\u9ebc\u3002",
"MessagePleaseEnsureInternetMetadata": "\u8acb\u78ba\u4fdd\u5df2\u555f\u7528\u5f9e\u4e92\u806f\u7db2\u4e0b\u8f09\u5a92\u9ad4\u8cc7\u6599\u3002",
"TabSuggested": "\u5efa\u8b70",
+ "TabSuggestions": "Suggestions",
"TabLatest": "\u6700\u65b0",
"TabUpcoming": "\u5373\u5c07\u767c\u5e03",
"TabShows": "\u7bc0\u76ee",
@@ -404,6 +407,7 @@
"OptionRecordOnAllChannels": "\u9304\u5f71\u6240\u4ee5\u983b\u5ea6\u7684\u7bc0\u76ee",
"OptionRecordAnytime": "\u9304\u5f71\u6240\u6709\u6642\u6bb5\u7684\u7bc0\u76ee",
"OptionRecordOnlyNewEpisodes": "\u53ea\u9304\u5f71\u6700\u65b0\u7684\u55ae\u5143",
+ "HeaderRepeatingOptions": "Repeating Options",
"HeaderDays": "\u9304\u5f71\u65e5",
"HeaderActiveRecordings": "\u6b63\u5728\u9304\u5f71\u7684\u7bc0\u76ee",
"HeaderLatestRecordings": "\u6700\u65b0\u9304\u5f71\u7684\u7bc0\u76ee",
@@ -547,7 +551,7 @@
"LabelPublicHttpsPort": "Public https port number:",
"LabelPublicHttpsPortHelp": "The public port number that should be mapped to the local https port.",
"LabelEnableHttps": "Report https as external address",
- "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address. This may break clients that do not yet support https.",
+ "LabelEnableHttpsHelp": "If enabled, the server will report an https url to clients as it's external address.",
"LabelHttpsPort": "Local https port number:",
"LabelHttpsPortHelp": "The tcp port number that Emby's https server should bind to.",
"LabelWebSocketPortNumber": "\u7db2\u7d61\u5957\u63a5\u7aef\u53e3\uff1a",
@@ -884,9 +888,9 @@
"LabelHomePageSection2": "Home page section 2:",
"LabelHomePageSection3": "Home page section 3:",
"LabelHomePageSection4": "Home page section 4:",
- "OptionMyViewsButtons": "My views (buttons)",
- "OptionMyViews": "My views",
- "OptionMyViewsSmall": "My views (small)",
+ "OptionMyMediaButtons": "My media (buttons)",
+ "OptionMyMedia": "My media",
+ "OptionMyMediaSmall": "My media (small)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -902,8 +906,8 @@
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
+ "PlaceholderUsername": "Username",
"HeaderBecomeProjectSupporter": "Become an Emby Supporter",
- "TextEnjoyBonusFeatures": "Enjoy Bonus Features",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
@@ -1381,10 +1385,33 @@
"LabelEnableInternetMetadataForTvPrograms": "Download internet metadata for:",
"OptionTVMovies": "TV Movies",
"HeaderUpcomingMovies": "Upcoming Movies",
+ "HeaderUpcomingSports": "Upcoming Sports",
"HeaderUpcomingPrograms": "Upcoming Programs",
"ButtonMoreItems": "More...",
"LabelShowLibraryTileNames": "Show library tile names",
"LabelShowLibraryTileNamesHelp": "Determines if labels will be displayed underneath library tiles on the home page",
"OptionEnableTranscodingThrottle": "Enable throttling",
- "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback."
+ "OptionEnableTranscodingThrottleHelp": "Throttling will automatically adjust transcoding speed in order to minimize server cpu utilization during playback.",
+ "LabelUploadSpeedLimit": "Upload speed limit (Mbps):",
+ "OptionAllowSyncTranscoding": "Allow syncing that requires transcoding",
+ "HeaderPlayback": "Media Playback",
+ "OptionAllowAudioPlaybackTranscoding": "Allow audio playback that requires transcoding",
+ "OptionAllowVideoPlaybackTranscoding": "Allow video playback that requires transcoding",
+ "OptionAllowMediaPlaybackTranscodingHelp": "Users will receive friendly messages when content is unplayable based on policy.",
+ "TabStreaming": "Streaming",
+ "LabelRemoteClientBitrateLimit": "Remote client bitrate limit (Mbps):",
+ "LabelRemoteClientBitrateLimitHelp": "An optional streaming bitrate limit for all remote clients. This is useful to prevent clients from requesting a higher bitrate than your connection can handle.",
+ "LabelConversionCpuCoreLimit": "CPU core limit:",
+ "LabelConversionCpuCoreLimitHelp": "Limit the number of CPU cores that will be used during sync conversion.",
+ "OptionEnableFullSpeedConversion": "Enable full speed conversion",
+ "OptionEnableFullSpeedConversionHelp": "By default, sync conversion is performed at a low speed to minimize resource consumption.",
+ "HeaderPlaylists": "Playlists",
+ "HeaderSelectDate": "Select Date",
+ "HeaderWelcomeExclamation": "Welcome!",
+ "HeaderMyPreferences": "My Preferences",
+ "ButtonMyPreferencesWelcomeYes": "Yes, I'd like to set my preferences now.",
+ "ButtonMyPreferencesWelcomeNo": "No thanks, I'll do it later.",
+ "MyPreferencesWelcomeMessage1": "We've presented your library in a way we think you'll enjoy. The appearance and grouping of content can be changed anytime by adjusting your preferences. Your preferences will apply to all Emby apps.",
+ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?",
+ "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index db2397d2f..a6e49ea8c 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -45,22 +45,22 @@
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
- <Reference Include="ImageMagickSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
- <SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\ImageMagickSharp.1.0.0.11\lib\net45\ImageMagickSharp.dll</HintPath>
- </Reference>
<Reference Include="MediaBrowser.Naming, Version=1.0.5509.27636, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MediaBrowser.Naming.1.0.0.32\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
</Reference>
- <Reference Include="Mono.Nat, Version=1.2.21.0, Culture=neutral, processorArchitecture=MSIL">
+ <Reference Include="Mono.Nat, Version=1.2.23.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Mono.Nat.1.2.21.0\lib\net40\Mono.Nat.dll</HintPath>
+ <HintPath>..\packages\Mono.Nat.1.2.23.0\lib\net40\Mono.Nat.dll</HintPath>
</Reference>
<Reference Include="MoreLinq, Version=1.1.17511.0, Culture=neutral, PublicKeyToken=384d532d7e88985d, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\morelinq.1.1.0\lib\net35\MoreLinq.dll</HintPath>
</Reference>
+ <Reference Include="Patterns.IO, Version=1.0.5580.36861, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\packages\Patterns.IO.1.0.0.3\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.IO.dll</HintPath>
+ </Reference>
<Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
<Private>True</Private>
@@ -68,9 +68,9 @@
<Reference Include="ServiceStack.Api.Swagger">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
</Reference>
- <Reference Include="SocketHttpListener, Version=1.0.5554.26260, Culture=neutral, processorArchitecture=MSIL">
+ <Reference Include="SocketHttpListener, Version=1.0.5581.23362, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\SocketHttpListener.1.0.0.3\lib\net45\SocketHttpListener.dll</HintPath>
+ <HintPath>..\packages\SocketHttpListener.1.0.0.4\lib\net45\SocketHttpListener.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@@ -129,10 +129,6 @@
<Compile Include="Devices\DeviceManager.cs" />
<Compile Include="Devices\DeviceRepository.cs" />
<Compile Include="Devices\CameraUploadsFolder.cs" />
- <Compile Include="Drawing\ImageHeader.cs" />
- <Compile Include="Drawing\PercentPlayedDrawer.cs" />
- <Compile Include="Drawing\PlayedIndicatorDrawer.cs" />
- <Compile Include="Drawing\UnplayedCountIndicator.cs" />
<Compile Include="Dto\DtoService.cs" />
<Compile Include="EntryPoints\ActivityLogEntryPoint.cs" />
<Compile Include="EntryPoints\AutomaticRestartEntryPoint.cs" />
@@ -174,13 +170,11 @@
<Compile Include="HttpServer\SocketSharp\SharpWebSocket.cs" />
<Compile Include="HttpServer\StreamWriter.cs" />
<Compile Include="HttpServer\SwaggerService.cs" />
- <Compile Include="Drawing\ImageProcessor.cs" />
<Compile Include="HttpServer\SocketSharp\Extensions.cs" />
<Compile Include="HttpServer\SocketSharp\RequestMono.cs" />
<Compile Include="HttpServer\SocketSharp\WebSocketSharpListener.cs" />
<Compile Include="HttpServer\SocketSharp\WebSocketSharpRequest.cs" />
<Compile Include="HttpServer\SocketSharp\WebSocketSharpResponse.cs" />
- <Compile Include="HttpServer\ThrottledStream.cs" />
<Compile Include="Intros\DefaultIntroProvider.cs" />
<Compile Include="IO\LibraryMonitor.cs" />
<Compile Include="Library\CoreResolutionIgnoreRule.cs" />
@@ -233,6 +227,7 @@
<Compile Include="Localization\LocalizationManager.cs" />
<Compile Include="Logging\PatternsLogger.cs" />
<Compile Include="MediaEncoder\EncodingManager.cs" />
+ <Compile Include="Sorting\StartDateComparer.cs" />
<Compile Include="Sync\SyncHelper.cs" />
<Compile Include="Sync\SyncJobOptions.cs" />
<Compile Include="UserViews\DynamicImageProvider.cs" />
@@ -251,8 +246,6 @@
<Compile Include="Persistence\SqliteShrinkMemoryTimer.cs" />
<Compile Include="Persistence\TypeMapper.cs" />
<Compile Include="Photos\BaseDynamicImageProvider.cs" />
- <Compile Include="Photos\DynamicImageHelpers.cs" />
- <Compile Include="UserViews\StripCollageBuilder.cs" />
<Compile Include="Playlists\ManualPlaylistsFolder.cs" />
<Compile Include="Photos\PhotoAlbumImageProvider.cs" />
<Compile Include="Playlists\PlaylistImageProvider.cs" />
@@ -431,9 +424,6 @@
<EmbeddedResource Include="Localization\JavaScript\uk.json" />
<EmbeddedResource Include="Localization\Server\bg_BG.json" />
<EmbeddedResource Include="Localization\Server\uk.json" />
- <EmbeddedResource Include="Drawing\fonts\webdings.ttf" />
- <EmbeddedResource Include="Drawing\fonts\robotoregular.ttf" />
- <EmbeddedResource Include="Drawing\fonts\MontserratLight.otf" />
<None Include="Localization\JavaScript\sl_SI.json" />
<EmbeddedResource Include="Localization\Server\sl_SI.json" />
<None Include="packages.config" />
diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
index 56557d6e1..6b99883a5 100644
--- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
+++ b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
@@ -151,8 +151,9 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
chapter.ImagePath = path;
changesMade = true;
}
- catch
+ catch (Exception ex)
{
+ _logger.ErrorException("Error extraching chapter images for {0}", ex, string.Join(",", inputPath));
success = false;
break;
}
diff --git a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs
index 5e02b2bac..1ff928cd5 100644
--- a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs
+++ b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs
@@ -95,7 +95,7 @@ namespace MediaBrowser.Server.Implementations.Notifications
var config = GetConfiguration();
return _userManager.Users
- .Where(i => config.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N"), i.Configuration))
+ .Where(i => config.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N"), i.Policy))
.Select(i => i.Id.ToString("N"));
}
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs
index e9d7f44ec..76c1274b2 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteMediaStreamsRepository.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Persistence;
+using System.Globalization;
+using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
@@ -40,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
// Add PixelFormat column
- createTableCommand += "(ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, PRIMARY KEY (ItemId, StreamIndex))";
+ createTableCommand += "(ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, KeyFrames TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";
string[] queries = {
@@ -61,6 +62,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
AddIsAnamorphicColumn();
AddIsCabacColumn();
AddRefFramesCommand();
+ AddKeyFramesCommand();
PrepareStatements();
@@ -160,6 +162,37 @@ namespace MediaBrowser.Server.Implementations.Persistence
_connection.RunQueries(new[] { builder.ToString() }, _logger);
}
+ private void AddKeyFramesCommand()
+ {
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = "PRAGMA table_info(mediastreams)";
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
+ {
+ while (reader.Read())
+ {
+ if (!reader.IsDBNull(1))
+ {
+ var name = reader.GetString(1);
+
+ if (string.Equals(name, "KeyFrames", StringComparison.OrdinalIgnoreCase))
+ {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ var builder = new StringBuilder();
+
+ builder.AppendLine("alter table mediastreams");
+ builder.AppendLine("add column KeyFrames TEXT NULL");
+
+ _connection.RunQueries(new[] { builder.ToString() }, _logger);
+ }
+
private void AddIsCabacColumn()
{
using (var cmd = _connection.CreateCommand())
@@ -249,6 +282,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
"BitDepth",
"IsAnamorphic",
"RefFrames",
+ "KeyFrames",
"IsCabac"
};
@@ -430,7 +464,12 @@ namespace MediaBrowser.Server.Implementations.Persistence
if (!reader.IsDBNull(25))
{
- item.IsCabac = reader.GetBoolean(25);
+ item.KeyFrames = reader.GetString(25).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => int.Parse(i, CultureInfo.InvariantCulture)).ToList();
+ }
+
+ if (!reader.IsDBNull(26))
+ {
+ item.IsCabac = reader.GetBoolean(26);
}
return item;
@@ -498,7 +537,15 @@ namespace MediaBrowser.Server.Implementations.Persistence
_saveStreamCommand.GetParameter(22).Value = stream.BitDepth;
_saveStreamCommand.GetParameter(23).Value = stream.IsAnamorphic;
_saveStreamCommand.GetParameter(24).Value = stream.RefFrames;
- _saveStreamCommand.GetParameter(25).Value = stream.IsCabac;
+ if (stream.KeyFrames != null)
+ {
+ _saveStreamCommand.GetParameter(25).Value = string.Join(",", stream.KeyFrames.Select(i => i.ToString(CultureInfo.InvariantCulture)).ToArray());
+ }
+ else
+ {
+ _saveStreamCommand.GetParameter(25).Value = null;
+ }
+ _saveStreamCommand.GetParameter(26).Value = stream.IsCabac;
_saveStreamCommand.Transaction = transaction;
_saveStreamCommand.ExecuteNonQuery();
diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs
index 1063fde53..4b7bfad3f 100644
--- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs
@@ -1,14 +1,14 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Playlists;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
-using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
@@ -22,12 +22,14 @@ namespace MediaBrowser.Server.Implementations.Photos
protected IFileSystem FileSystem { get; private set; }
protected IProviderManager ProviderManager { get; private set; }
protected IApplicationPaths ApplicationPaths { get; private set; }
+ protected IImageProcessor ImageProcessor { get; set; }
- protected BaseDynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths)
+ protected BaseDynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor)
{
ApplicationPaths = applicationPaths;
ProviderManager = providerManager;
FileSystem = fileSystem;
+ ImageProcessor = imageProcessor;
}
public virtual bool Supports(IHasImages item)
@@ -76,56 +78,23 @@ namespace MediaBrowser.Server.Implementations.Photos
string cacheKey,
CancellationToken cancellationToken)
{
- var stream = await CreateImageAsync(item, itemsWithImages, imageType, 0).ConfigureAwait(false);
+ var outputPath = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid() + ".png");
+ Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
+ var imageCreated = CreateImage(item, itemsWithImages, outputPath, imageType, 0);
- if (stream == null)
+ if (!imageCreated)
{
return ItemUpdateType.None;
}
- if (stream is MemoryStream)
- {
- using (stream)
- {
- stream.Position = 0;
-
- await ProviderManager.SaveImage(item, stream, "image/png", imageType, null, cacheKey, cancellationToken).ConfigureAwait(false);
- }
- }
- else
- {
- using (var ms = new MemoryStream())
- {
- await stream.CopyToAsync(ms).ConfigureAwait(false);
-
- ms.Position = 0;
-
- await ProviderManager.SaveImage(item, ms, "image/png", imageType, null, cacheKey, cancellationToken).ConfigureAwait(false);
- }
- }
+ await ProviderManager.SaveImage(item, outputPath, "image/png", imageType, null, cacheKey, cancellationToken).ConfigureAwait(false);
return ItemUpdateType.ImageUpdate;
}
- public async Task<DynamicImageResponse> GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken)
- {
- var items = await GetItemsWithImages(item).ConfigureAwait(false);
- var cacheKey = GetConfigurationCacheKey(items, item.Name);
-
- var result = await CreateImageAsync(item, items, type, 0).ConfigureAwait(false);
-
- return new DynamicImageResponse
- {
- HasImage = result != null,
- Stream = result,
- InternalCacheKey = cacheKey,
- Format = ImageFormat.Png
- };
- }
-
protected abstract Task<List<BaseItem>> GetItemsWithImages(IHasImages item);
- private const string Version = "5";
+ private const string Version = "29";
protected string GetConfigurationCacheKey(List<BaseItem> items, string itemName)
{
var parts = Version + "_" + (itemName ?? string.Empty) + "_" +
@@ -134,30 +103,47 @@ namespace MediaBrowser.Server.Implementations.Photos
return parts.GetMD5().ToString("N");
}
- protected Task<Stream> GetThumbCollage(List<BaseItem> items)
+ protected void CreateThumbCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath)
+ {
+ CreateCollage(primaryItem, items, outputPath, 960, 540, true, primaryItem.Name);
+ }
+
+ protected virtual IEnumerable<string> GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable<BaseItem> items)
{
- var files = items
+ return items
.Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb))
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .ToList();
+ .Where(i => !string.IsNullOrWhiteSpace(i));
+ }
- return DynamicImageHelpers.GetThumbCollage(files,
- FileSystem,
- 1600,
- 900,
- ApplicationPaths);
+ protected void CreatePosterCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath)
+ {
+ CreateCollage(primaryItem, items, outputPath, 600, 900, true, primaryItem.Name);
}
- protected Task<Stream> GetSquareCollage(List<BaseItem> items)
+ protected void CreateSquareCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath)
{
- var files = items
- .Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb))
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .ToList();
+ CreateCollage(primaryItem, items, outputPath, 800, 800, true, primaryItem.Name);
+ }
+
+ protected void CreateThumbCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height, bool drawText, string text)
+ {
+ CreateCollage(primaryItem, items, outputPath, width, height, drawText, text);
+ }
+
+ private void CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height, bool drawText, string text)
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
+
+ var options = new ImageCollageOptions
+ {
+ Height = height,
+ Width = width,
+ OutputPath = outputPath,
+ Text = drawText ? text : null,
+ InputPaths = GetStripCollageImagePaths(primaryItem, items).ToArray()
+ };
- return DynamicImageHelpers.GetSquareCollage(files,
- FileSystem,
- 800, ApplicationPaths);
+ ImageProcessor.CreateImageCollage(options);
}
public string Name
@@ -165,19 +151,38 @@ namespace MediaBrowser.Server.Implementations.Photos
get { return "Dynamic Image Provider"; }
}
- protected virtual async Task<Stream> CreateImageAsync(IHasImages item,
+ protected virtual bool CreateImage(IHasImages item,
List<BaseItem> itemsWithImages,
+ string outputPath,
ImageType imageType,
int imageIndex)
{
if (itemsWithImages.Count == 0)
{
- return null;
+ return false;
+ }
+
+ if (imageType == ImageType.Thumb)
+ {
+ CreateThumbCollage(item, itemsWithImages, outputPath);
+ return true;
+ }
+
+ if (imageType == ImageType.Primary)
+ {
+ if (item is PhotoAlbum || item is Playlist)
+ {
+ CreateSquareCollage(item, itemsWithImages, outputPath);
+ }
+ else
+ {
+ CreatePosterCollage(item, itemsWithImages, outputPath);
+ }
+
+ return true;
}
- return imageType == ImageType.Thumb ?
- await GetThumbCollage(itemsWithImages).ConfigureAwait(false) :
- await GetSquareCollage(itemsWithImages).ConfigureAwait(false);
+ throw new ArgumentException("Unexpected image type");
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
diff --git a/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs b/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs
deleted file mode 100644
index 7f8435097..000000000
--- a/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs
+++ /dev/null
@@ -1,132 +0,0 @@
-using ImageMagickSharp;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.IO;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Server.Implementations.Photos
-{
- public static class DynamicImageHelpers
- {
- public static async Task<Stream> GetThumbCollage(List<string> files,
- IFileSystem fileSystem,
- int width,
- int height, IApplicationPaths appPaths)
- {
- if (files.Any(string.IsNullOrWhiteSpace))
- {
- throw new ArgumentException("Empty file found in files list");
- }
-
- if (files.Count == 0)
- {
- return null;
- }
-
- if (files.Count < 3)
- {
- return await GetSingleImage(files, fileSystem).ConfigureAwait(false);
- }
-
- const int rows = 1;
- const int cols = 3;
-
- int cellWidth = 2 * (width / 3);
- int cellHeight = height;
- var index = 0;
-
- using (var wand = new MagickWand(width, height, new PixelWand(ColorName.None, 1)))
- {
- for (var row = 0; row < rows; row++)
- {
- for (var col = 0; col < cols; col++)
- {
- var x = col * (cellWidth / 2);
- var y = row * cellHeight;
-
- if (files.Count > index)
- {
- using (var innerWand = new MagickWand(files[index]))
- {
- innerWand.CurrentImage.ResizeImage(cellWidth, cellHeight);
- wand.CurrentImage.CompositeImage(innerWand, CompositeOperator.OverCompositeOp, x, y);
- }
- }
-
- index++;
- }
- }
-
- return GetStream(wand, appPaths);
- }
- }
-
- public static async Task<Stream> GetSquareCollage(List<string> files,
- IFileSystem fileSystem,
- int size, IApplicationPaths appPaths)
- {
- if (files.Any(string.IsNullOrWhiteSpace))
- {
- throw new ArgumentException("Empty file found in files list");
- }
-
- if (files.Count == 0)
- {
- return null;
- }
-
- if (files.Count < 4)
- {
- return await GetSingleImage(files, fileSystem).ConfigureAwait(false);
- }
-
- const int rows = 2;
- const int cols = 2;
-
- int singleSize = size / 2;
- var index = 0;
-
- using (var wand = new MagickWand(size, size, new PixelWand(ColorName.None, 1)))
- {
- for (var row = 0; row < rows; row++)
- {
- for (var col = 0; col < cols; col++)
- {
- var x = col * singleSize;
- var y = row * singleSize;
-
- using (var innerWand = new MagickWand(files[index]))
- {
- innerWand.CurrentImage.ResizeImage(singleSize, singleSize);
- wand.CurrentImage.CompositeImage(innerWand, CompositeOperator.OverCompositeOp, x, y);
- }
-
- index++;
- }
- }
-
- return GetStream(wand, appPaths);
- }
- }
-
- private static Task<Stream> GetSingleImage(List<string> files, IFileSystem fileSystem)
- {
- return Task.FromResult<Stream>(fileSystem.GetFileStream(files[0], FileMode.Open, FileAccess.Read, FileShare.Read));
- }
-
- internal static Stream GetStream(MagickWand image, IApplicationPaths appPaths)
- {
- var tempFile = Path.Combine(appPaths.TempDirectory, Guid.NewGuid().ToString("N") + ".png");
-
- Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
-
- image.CurrentImage.CompressionQuality = 100;
- image.SaveImage(tempFile);
-
- return File.OpenRead(tempFile);
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs
index 73d9183a5..eda4d8cc1 100644
--- a/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using System.Collections.Generic;
@@ -10,14 +11,14 @@ namespace MediaBrowser.Server.Implementations.Photos
{
public class PhotoAlbumImageProvider : BaseDynamicImageProvider<PhotoAlbum>
{
- public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths)
+ public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor)
{
}
protected override Task<List<BaseItem>> GetItemsWithImages(IHasImages item)
{
var photoAlbum = (PhotoAlbum)item;
- var items = GetFinalItems(photoAlbum.GetRecursiveChildren(i => i is Photo).ToList());
+ var items = GetFinalItems(photoAlbum.GetRecursiveChildren().ToList());
return Task.FromResult(items);
}
diff --git a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
index 980c3d14a..2f3a1dd0c 100644
--- a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
+++ b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
@@ -45,11 +45,11 @@ namespace MediaBrowser.Server.Implementations.Playlists
}
}
- public class PlaylistssDynamicFolder : IVirtualFolderCreator
+ public class PlaylistsDynamicFolder : IVirtualFolderCreator
{
private readonly IApplicationPaths _appPaths;
- public PlaylistssDynamicFolder(IApplicationPaths appPaths)
+ public PlaylistsDynamicFolder(IApplicationPaths appPaths)
{
_appPaths = appPaths;
}
diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs
index 81f9438b9..dcd9d21ea 100644
--- a/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
@@ -16,7 +17,7 @@ namespace MediaBrowser.Server.Implementations.Playlists
{
public class PlaylistImageProvider : BaseDynamicImageProvider<Playlist>
{
- public PlaylistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths)
+ public PlaylistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor)
{
}
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index 7f5033b98..112778ec8 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -305,12 +305,9 @@ namespace MediaBrowser.Server.Implementations.Session
}
}
- private async Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId)
+ private Task<MediaSourceInfo> GetMediaSource(IHasMediaSources item, string mediaSourceId)
{
- var sources = await _mediaSourceManager.GetPlayackMediaSources(item.Id.ToString("N"), false, CancellationToken.None)
- .ConfigureAwait(false);
-
- return sources.FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
+ return _mediaSourceManager.GetMediaSource(item, mediaSourceId, false);
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/Sorting/StartDateComparer.cs b/MediaBrowser.Server.Implementations/Sorting/StartDateComparer.cs
new file mode 100644
index 000000000..7e6f24ec1
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Sorting/StartDateComparer.cs
@@ -0,0 +1,47 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.Sorting;
+using MediaBrowser.Model.Querying;
+using System;
+
+namespace MediaBrowser.Server.Implementations.Sorting
+{
+ public class StartDateComparer : IBaseItemComparer
+ {
+ /// <summary>
+ /// Compares the specified x.
+ /// </summary>
+ /// <param name="x">The x.</param>
+ /// <param name="y">The y.</param>
+ /// <returns>System.Int32.</returns>
+ public int Compare(BaseItem x, BaseItem y)
+ {
+ return GetDate(x).CompareTo(GetDate(y));
+ }
+
+ /// <summary>
+ /// Gets the date.
+ /// </summary>
+ /// <param name="x">The x.</param>
+ /// <returns>DateTime.</returns>
+ private DateTime GetDate(BaseItem x)
+ {
+ var hasStartDate = x as LiveTvProgram;
+
+ if (hasStartDate != null)
+ {
+ return hasStartDate.StartDate;
+ }
+ return DateTime.MinValue;
+ }
+
+ /// <summary>
+ /// Gets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name
+ {
+ get { return ItemSortBy.StartDate; }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs
index 99d758233..7b1fa4dec 100644
--- a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs
+++ b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs
@@ -44,7 +44,7 @@ namespace MediaBrowser.Server.Implementations.Sync
public string Name
{
- get { return "App Sync"; }
+ get { return "Mobile Sync"; }
}
public IEnumerable<SyncTarget> GetAllSyncTargets()
diff --git a/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs b/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs
index 73400f834..f881a2055 100644
--- a/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs
+++ b/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs
@@ -195,17 +195,39 @@ namespace MediaBrowser.Server.Implementations.Sync
}
};
- var maxAudioChannels = supportsAc3 || supportsDca ? "5" : "2";
codecProfiles.Add(new CodecProfile
{
Type = CodecType.VideoAudio,
+ Codec = "ac3",
Conditions = new[]
{
new ProfileCondition
{
Condition = ProfileConditionType.LessThanEqual,
Property = ProfileConditionValue.AudioChannels,
- Value = maxAudioChannels,
+ Value = "5",
+ IsRequired = true
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.Equals,
+ Property = ProfileConditionValue.IsSecondaryAudio,
+ Value = "false",
+ IsRequired = false
+ }
+ }
+ });
+ codecProfiles.Add(new CodecProfile
+ {
+ Type = CodecType.VideoAudio,
+ Codec = "ac3",
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "2",
IsRequired = true
},
new ProfileCondition
diff --git a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs
index 26413c033..1a8b55a25 100644
--- a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs
+++ b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs
@@ -1,7 +1,8 @@
-using System.Globalization;
+using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Sync;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@@ -10,12 +11,14 @@ using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Sync;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using Patterns.IO;
namespace MediaBrowser.Server.Implementations.Sync
{
@@ -25,13 +28,18 @@ namespace MediaBrowser.Server.Implementations.Sync
private readonly IServerApplicationHost _appHost;
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
+ private readonly IConfigurationManager _config;
- public MediaSync(ILogger logger, ISyncManager syncManager, IServerApplicationHost appHost, IFileSystem fileSystem)
+ public const string PathSeparatorString = "/";
+ public const char PathSeparatorChar = '/';
+
+ public MediaSync(ILogger logger, ISyncManager syncManager, IServerApplicationHost appHost, IFileSystem fileSystem, IConfigurationManager config)
{
_logger = logger;
_syncManager = syncManager;
_appHost = appHost;
_fileSystem = fileSystem;
+ _config = config;
}
public async Task Sync(IServerSyncProvider provider,
@@ -67,7 +75,24 @@ namespace MediaBrowser.Server.Implementations.Sync
SyncTarget target,
CancellationToken cancellationToken)
{
- var jobItemIds = await dataProvider.GetSyncJobItemIds(target, serverId).ConfigureAwait(false);
+ var localItems = await dataProvider.GetLocalItems(target, serverId).ConfigureAwait(false);
+ var remoteFiles = await provider.GetFiles(new FileQuery(), target, cancellationToken).ConfigureAwait(false);
+ var remoteIds = remoteFiles.Items.Select(i => i.Id).ToList();
+
+ var jobItemIds = new List<string>();
+
+ foreach (var localItem in localItems)
+ {
+ // TODO: Remove this after a while
+ if (string.IsNullOrWhiteSpace(localItem.FileId))
+ {
+ jobItemIds.Add(localItem.SyncJobItemId);
+ }
+ else if (remoteIds.Contains(localItem.FileId, StringComparer.OrdinalIgnoreCase))
+ {
+ jobItemIds.Add(localItem.SyncJobItemId);
+ }
+ }
var result = await _syncManager.SyncData(new SyncDataRequest
{
@@ -152,12 +177,14 @@ namespace MediaBrowser.Server.Implementations.Sync
var transferSuccess = false;
Exception transferException = null;
+ var options = _config.GetSyncOptions();
+
try
{
var fileTransferProgress = new ActionableProgress<double>();
fileTransferProgress.RegisterAction(pct => progress.Report(pct * .92));
- var sendFileResult = await SendFile(provider, internalSyncJobItem.OutputPath, localItem.LocalPath, target, fileTransferProgress, cancellationToken).ConfigureAwait(false);
+ var sendFileResult = await SendFile(provider, internalSyncJobItem.OutputPath, localItem.LocalPath.Split(PathSeparatorChar), target, options, fileTransferProgress, cancellationToken).ConfigureAwait(false);
if (localItem.Item.MediaSources != null)
{
@@ -171,6 +198,8 @@ namespace MediaBrowser.Server.Implementations.Sync
}
}
+ localItem.FileId = sendFileResult.Id;
+
// Create db record
await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false);
@@ -179,7 +208,7 @@ namespace MediaBrowser.Server.Implementations.Sync
var mediaSource = localItem.Item.MediaSources.FirstOrDefault();
if (mediaSource != null)
{
- await SendSubtitles(localItem, mediaSource, provider, dataProvider, target, cancellationToken).ConfigureAwait(false);
+ await SendSubtitles(localItem, mediaSource, provider, dataProvider, target, options, cancellationToken).ConfigureAwait(false);
}
}
@@ -207,7 +236,7 @@ namespace MediaBrowser.Server.Implementations.Sync
}
}
- private async Task SendSubtitles(LocalItem localItem, MediaSourceInfo mediaSource, IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, CancellationToken cancellationToken)
+ private async Task SendSubtitles(LocalItem localItem, MediaSourceInfo mediaSource, IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, SyncOptions options, CancellationToken cancellationToken)
{
var failedSubtitles = new List<MediaStream>();
var requiresSave = false;
@@ -219,13 +248,13 @@ namespace MediaBrowser.Server.Implementations.Sync
try
{
var remotePath = GetRemoteSubtitlePath(localItem, mediaStream, provider, target);
- var sendFileResult = await SendFile(provider, mediaStream.Path, remotePath, target, new Progress<double>(), cancellationToken).ConfigureAwait(false);
+ var sendFileResult = await SendFile(provider, mediaStream.Path, remotePath, target, options, new Progress<double>(), cancellationToken).ConfigureAwait(false);
// This is the path that will be used when talking to the provider
- mediaStream.ExternalId = remotePath;
+ mediaStream.ExternalId = sendFileResult.Id;
// Keep track of all additional files for cleanup later.
- localItem.AdditionalFiles.Add(remotePath);
+ localItem.AdditionalFiles.Add(sendFileResult.Id);
// This is the public path clients will use
mediaStream.Path = sendFileResult.Path;
@@ -250,17 +279,15 @@ namespace MediaBrowser.Server.Implementations.Sync
}
}
- private string GetRemoteSubtitlePath(LocalItem item, MediaStream stream, IServerSyncProvider provider, SyncTarget target)
+ private string[] GetRemoteSubtitlePath(LocalItem item, MediaStream stream, IServerSyncProvider provider, SyncTarget target)
{
- var path = item.LocalPath;
-
var filename = GetSubtitleSaveFileName(item, stream.Language, stream.IsForced) + "." + stream.Codec.ToLower();
- var parentPath = provider.GetParentDirectoryPath(path, target);
-
- path = Path.Combine(parentPath, filename);
+ var pathParts = item.LocalPath.Split(PathSeparatorChar);
+ var list = pathParts.Take(pathParts.Length - 1).ToList();
+ list.Add(filename);
- return path;
+ return list.ToArray();
}
private string GetSubtitleSaveFileName(LocalItem item, string language, bool isForced)
@@ -294,12 +321,16 @@ namespace MediaBrowser.Server.Implementations.Sync
foreach (var localItem in localItems)
{
var files = localItem.AdditionalFiles.ToList();
- files.Insert(0, localItem.LocalPath);
+
+ // TODO: Remove this. Have to check it for now since this is a new property
+ if (!string.IsNullOrWhiteSpace(localItem.FileId))
+ {
+ files.Insert(0, localItem.FileId);
+ }
foreach (var file in files)
{
_logger.Debug("Removing {0} from {1}.", file, target.Name);
-
await provider.DeleteFile(file, target, cancellationToken).ConfigureAwait(false);
}
@@ -307,12 +338,19 @@ namespace MediaBrowser.Server.Implementations.Sync
}
}
- private async Task<SyncedFileInfo> SendFile(IServerSyncProvider provider, string inputPath, string remotePath, SyncTarget target, IProgress<double> progress, CancellationToken cancellationToken)
+ private async Task<SyncedFileInfo> SendFile(IServerSyncProvider provider, string inputPath, string[] pathParts, SyncTarget target, SyncOptions options, IProgress<double> progress, CancellationToken cancellationToken)
{
- _logger.Debug("Sending {0} to {1}. Remote path: {2}", inputPath, provider.Name, remotePath);
- using (var stream = _fileSystem.GetFileStream(inputPath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
+ _logger.Debug("Sending {0} to {1}. Remote path: {2}", inputPath, provider.Name, string.Join("/", pathParts));
+ using (var fileStream = _fileSystem.GetFileStream(inputPath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
{
- return await provider.SendFile(stream, remotePath, target, progress, cancellationToken).ConfigureAwait(false);
+ Stream stream = fileStream;
+
+ if (options.UploadSpeedLimitBytes > 0 && provider is IRemoteSyncProvider)
+ {
+ stream = new ThrottledStream(stream, options.UploadSpeedLimitBytes);
+ }
+
+ return await provider.SendFile(stream, pathParts, target, progress, cancellationToken).ConfigureAwait(false);
}
}
@@ -336,7 +374,7 @@ namespace MediaBrowser.Server.Implementations.Sync
var path = GetDirectoryPath(provider, job, syncedItem, libraryItem, serverName);
path.Add(GetLocalFileName(provider, libraryItem, originalFileName));
- var localPath = provider.GetFullPath(path, target);
+ var localPath = string.Join(PathSeparatorString, path.ToArray());
foreach (var mediaSource in libraryItem.MediaSources)
{
diff --git a/MediaBrowser.Server.Implementations/Sync/MultiProviderSync.cs b/MediaBrowser.Server.Implementations/Sync/MultiProviderSync.cs
index a8bc24c2a..6f09e96f0 100644
--- a/MediaBrowser.Server.Implementations/Sync/MultiProviderSync.cs
+++ b/MediaBrowser.Server.Implementations/Sync/MultiProviderSync.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Sync;
@@ -18,13 +19,15 @@ namespace MediaBrowser.Server.Implementations.Sync
private readonly IServerApplicationHost _appHost;
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
+ private readonly IConfigurationManager _config;
- public MultiProviderSync(SyncManager syncManager, IServerApplicationHost appHost, ILogger logger, IFileSystem fileSystem)
+ public MultiProviderSync(SyncManager syncManager, IServerApplicationHost appHost, ILogger logger, IFileSystem fileSystem, IConfigurationManager config)
{
_syncManager = syncManager;
_appHost = appHost;
_logger = logger;
_fileSystem = fileSystem;
+ _config = config;
}
public async Task Sync(IEnumerable<IServerSyncProvider> providers, IProgress<double> progress, CancellationToken cancellationToken)
@@ -56,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.Sync
var dataProvider = _syncManager.GetDataProvider(target.Item1, target.Item2);
- await new MediaSync(_logger, _syncManager, _appHost, _fileSystem)
+ await new MediaSync(_logger, _syncManager, _appHost, _fileSystem, _config)
.Sync(target.Item1, dataProvider, target.Item2, innerProgress, cancellationToken)
.ConfigureAwait(false);
diff --git a/MediaBrowser.Server.Implementations/Sync/ServerSyncScheduledTask.cs b/MediaBrowser.Server.Implementations/Sync/ServerSyncScheduledTask.cs
index 148602bd4..9477a23f1 100644
--- a/MediaBrowser.Server.Implementations/Sync/ServerSyncScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Sync/ServerSyncScheduledTask.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Sync;
@@ -17,13 +18,15 @@ namespace MediaBrowser.Server.Implementations.Sync
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
private readonly IServerApplicationHost _appHost;
+ private readonly IConfigurationManager _config;
- public ServerSyncScheduledTask(ISyncManager syncManager, ILogger logger, IFileSystem fileSystem, IServerApplicationHost appHost)
+ public ServerSyncScheduledTask(ISyncManager syncManager, ILogger logger, IFileSystem fileSystem, IServerApplicationHost appHost, IConfigurationManager config)
{
_syncManager = syncManager;
_logger = logger;
_fileSystem = fileSystem;
_appHost = appHost;
+ _config = config;
}
public string Name
@@ -46,7 +49,7 @@ namespace MediaBrowser.Server.Implementations.Sync
public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{
- return new MultiProviderSync((SyncManager)_syncManager, _appHost, _logger, _fileSystem)
+ return new MultiProviderSync((SyncManager)_syncManager, _appHost, _logger, _fileSystem, _config)
.Sync(ServerSyncProviders, progress, cancellationToken);
}
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
index 185c3464e..fd4092974 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
@@ -456,17 +456,18 @@ namespace MediaBrowser.Server.Implementations.Sync
jobItem.Progress = 0;
+ var syncOptions = _config.GetSyncOptions();
var user = _userManager.GetUserById(job.UserId);
var video = item as Video;
if (video != null)
{
- await Sync(jobItem, job, video, user, enableConversion, progress, cancellationToken).ConfigureAwait(false);
+ await Sync(jobItem, job, video, user, enableConversion, syncOptions, progress, cancellationToken).ConfigureAwait(false);
}
else if (item is Audio)
{
- await Sync(jobItem, job, (Audio)item, user, enableConversion, progress, cancellationToken).ConfigureAwait(false);
+ await Sync(jobItem, job, (Audio)item, user, enableConversion, syncOptions, progress, cancellationToken).ConfigureAwait(false);
}
else if (item is Photo)
@@ -480,7 +481,7 @@ namespace MediaBrowser.Server.Implementations.Sync
}
}
- private async Task Sync(SyncJobItem jobItem, SyncJob job, Video item, User user, bool enableConversion, IProgress<double> progress, CancellationToken cancellationToken)
+ private async Task Sync(SyncJobItem jobItem, SyncJob job, Video item, User user, bool enableConversion, SyncOptions syncOptions, IProgress<double> progress, CancellationToken cancellationToken)
{
var jobOptions = _syncManager.GetVideoOptions(jobItem, job);
var conversionOptions = new VideoOptions
@@ -493,7 +494,7 @@ namespace MediaBrowser.Server.Implementations.Sync
conversionOptions.ItemId = item.Id.ToString("N");
conversionOptions.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList();
- var streamInfo = new StreamBuilder().BuildVideoItem(conversionOptions);
+ var streamInfo = new StreamBuilder(_logger).BuildVideoItem(conversionOptions);
var mediaSource = streamInfo.MediaSource;
// No sense creating external subs if we're already burning one into the video
@@ -542,7 +543,9 @@ namespace MediaBrowser.Server.Implementations.Sync
jobItem.OutputPath = await _mediaEncoder.EncodeVideo(new EncodingJobOptions(streamInfo, conversionOptions.Profile)
{
- OutputDirectory = jobItem.TemporaryPath
+ OutputDirectory = jobItem.TemporaryPath,
+ CpuCoreLimit = syncOptions.TranscodingCpuCoreLimit,
+ ReadInputAtNativeFramerate = !syncOptions.EnableFullSpeedTranscoding
}, innerProgress, cancellationToken);
}
@@ -677,7 +680,7 @@ namespace MediaBrowser.Server.Implementations.Sync
private const int DatabaseProgressUpdateIntervalSeconds = 2;
- private async Task Sync(SyncJobItem jobItem, SyncJob job, Audio item, User user, bool enableConversion, IProgress<double> progress, CancellationToken cancellationToken)
+ private async Task Sync(SyncJobItem jobItem, SyncJob job, Audio item, User user, bool enableConversion, SyncOptions syncOptions, IProgress<double> progress, CancellationToken cancellationToken)
{
var jobOptions = _syncManager.GetAudioOptions(jobItem, job);
var conversionOptions = new AudioOptions
@@ -690,7 +693,7 @@ namespace MediaBrowser.Server.Implementations.Sync
conversionOptions.ItemId = item.Id.ToString("N");
conversionOptions.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList();
- var streamInfo = new StreamBuilder().BuildAudioItem(conversionOptions);
+ var streamInfo = new StreamBuilder(_logger).BuildAudioItem(conversionOptions);
var mediaSource = streamInfo.MediaSource;
jobItem.MediaSourceId = streamInfo.MediaSourceId;
@@ -725,7 +728,8 @@ namespace MediaBrowser.Server.Implementations.Sync
jobItem.OutputPath = await _mediaEncoder.EncodeAudio(new EncodingJobOptions(streamInfo, conversionOptions.Profile)
{
- OutputDirectory = jobItem.TemporaryPath
+ OutputDirectory = jobItem.TemporaryPath,
+ CpuCoreLimit = syncOptions.TranscodingCpuCoreLimit
}, innerProgress, cancellationToken);
}
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
index a39a2b1cd..6f0310e3c 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
@@ -512,12 +512,7 @@ namespace MediaBrowser.Server.Implementations.Sync
var video = item as Video;
if (video != null)
{
- if (video.VideoType == VideoType.Iso)
- {
- return false;
- }
-
- if (video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd || video.VideoType == VideoType.HdDvd)
+ if (video.VideoType == VideoType.Iso || video.VideoType == VideoType.BluRay || video.VideoType == VideoType.Dvd || video.VideoType == VideoType.HdDvd)
{
return false;
}
@@ -552,7 +547,7 @@ namespace MediaBrowser.Server.Implementations.Sync
}
}
- if (item is LiveTvChannel || item is IChannelItem || item is ILiveTvRecording)
+ if (item is LiveTvChannel || item is IChannelItem)
{
return false;
}
@@ -566,7 +561,7 @@ namespace MediaBrowser.Server.Implementations.Sync
return true;
}
- return item.LocationType == LocationType.FileSystem || item is Season || item is ILiveTvRecording;
+ return item.LocationType == LocationType.FileSystem || item is Season;
}
private string GetDefaultName(BaseItem item)
@@ -755,6 +750,9 @@ namespace MediaBrowser.Server.Implementations.Sync
foreach (var jobItem in jobItemResult.Items)
{
+ var requiresSaving = false;
+ var removeFromDevice = false;
+
if (request.LocalItemIds.Contains(jobItem.ItemId, StringComparer.OrdinalIgnoreCase))
{
var job = _repo.GetJob(jobItem.JobId);
@@ -764,13 +762,13 @@ namespace MediaBrowser.Server.Implementations.Sync
{
// Tell the device to remove it since it has been marked for removal
_logger.Debug("Adding ItemIdsToRemove {0} because IsMarkedForRemoval is set.", jobItem.ItemId);
- response.ItemIdsToRemove.Add(jobItem.ItemId);
+ removeFromDevice = true;
}
else if (user == null)
{
// Tell the device to remove it since the user is gone now
_logger.Debug("Adding ItemIdsToRemove {0} because the user is no longer valid.", jobItem.ItemId);
- response.ItemIdsToRemove.Add(jobItem.ItemId);
+ removeFromDevice = true;
}
else if (job.UnwatchedOnly)
{
@@ -782,23 +780,41 @@ namespace MediaBrowser.Server.Implementations.Sync
{
// Tell the device to remove it since it has been played
_logger.Debug("Adding ItemIdsToRemove {0} because it has been marked played.", jobItem.ItemId);
- response.ItemIdsToRemove.Add(jobItem.ItemId);
+ removeFromDevice = true;
}
}
else
{
// Tell the device to remove it since it's no longer available
_logger.Debug("Adding ItemIdsToRemove {0} because it is no longer available.", jobItem.ItemId);
- response.ItemIdsToRemove.Add(jobItem.ItemId);
+ removeFromDevice = true;
}
}
}
else
{
- _logger.Debug("Setting status to RemovedFromDevice for {0} because it is no longer on the device.", jobItem.ItemId);
-
// Content is no longer on the device
- jobItem.Status = SyncJobItemStatus.RemovedFromDevice;
+ if (jobItem.IsMarkedForRemoval)
+ {
+ jobItem.Status = SyncJobItemStatus.RemovedFromDevice;
+ }
+ else
+ {
+ _logger.Debug("Setting status to Queued for {0} because it is no longer on the device.", jobItem.ItemId);
+ jobItem.Status = SyncJobItemStatus.Queued;
+ }
+ requiresSaving = true;
+ }
+
+ if (removeFromDevice)
+ {
+ response.ItemIdsToRemove.Add(jobItem.ItemId);
+ jobItem.IsMarkedForRemoval = true;
+ requiresSaving = true;
+ }
+
+ if (requiresSaving)
+ {
await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
}
}
@@ -842,6 +858,9 @@ namespace MediaBrowser.Server.Implementations.Sync
foreach (var jobItem in jobItemResult.Items)
{
+ var requiresSaving = false;
+ var removeFromDevice = false;
+
if (request.SyncJobItemIds.Contains(jobItem.Id, StringComparer.OrdinalIgnoreCase))
{
var job = _repo.GetJob(jobItem.JobId);
@@ -851,13 +870,13 @@ namespace MediaBrowser.Server.Implementations.Sync
{
// Tell the device to remove it since it has been marked for removal
_logger.Debug("Adding ItemIdsToRemove {0} because IsMarkedForRemoval is set.", jobItem.Id);
- response.ItemIdsToRemove.Add(jobItem.Id);
+ removeFromDevice = true;
}
else if (user == null)
{
// Tell the device to remove it since the user is gone now
_logger.Debug("Adding ItemIdsToRemove {0} because the user is no longer valid.", jobItem.Id);
- response.ItemIdsToRemove.Add(jobItem.Id);
+ removeFromDevice = true;
}
else if (job.UnwatchedOnly)
{
@@ -869,23 +888,41 @@ namespace MediaBrowser.Server.Implementations.Sync
{
// Tell the device to remove it since it has been played
_logger.Debug("Adding ItemIdsToRemove {0} because it has been marked played.", jobItem.Id);
- response.ItemIdsToRemove.Add(jobItem.Id);
+ removeFromDevice = true;
}
}
else
{
// Tell the device to remove it since it's no longer available
_logger.Debug("Adding ItemIdsToRemove {0} because it is no longer available.", jobItem.Id);
- response.ItemIdsToRemove.Add(jobItem.Id);
+ removeFromDevice = true;
}
}
}
else
{
- _logger.Debug("Setting status to RemovedFromDevice for {0} because it is no longer on the device.", jobItem.Id);
-
// Content is no longer on the device
- jobItem.Status = SyncJobItemStatus.RemovedFromDevice;
+ if (jobItem.IsMarkedForRemoval)
+ {
+ jobItem.Status = SyncJobItemStatus.RemovedFromDevice;
+ }
+ else
+ {
+ _logger.Debug("Setting status to Queued for {0} because it is no longer on the device.", jobItem.Id);
+ jobItem.Status = SyncJobItemStatus.Queued;
+ }
+ requiresSaving = true;
+ }
+
+ if (removeFromDevice)
+ {
+ response.ItemIdsToRemove.Add(jobItem.Id);
+ jobItem.IsMarkedForRemoval = true;
+ requiresSaving = true;
+ }
+
+ if (requiresSaving)
+ {
await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
}
}
@@ -1168,13 +1205,18 @@ namespace MediaBrowser.Server.Implementations.Sync
public IEnumerable<SyncQualityOption> GetQualityOptions(string targetId)
{
+ return GetQualityOptions(targetId, null);
+ }
+
+ public IEnumerable<SyncQualityOption> GetQualityOptions(string targetId, User user)
+ {
foreach (var provider in _providers)
{
foreach (var target in GetSyncTargets(provider))
{
if (string.Equals(target.Id, targetId, StringComparison.OrdinalIgnoreCase))
{
- return GetQualityOptions(provider, target);
+ return GetQualityOptions(provider, target, user);
}
}
}
@@ -1182,12 +1224,19 @@ namespace MediaBrowser.Server.Implementations.Sync
return new List<SyncQualityOption>();
}
- private IEnumerable<SyncQualityOption> GetQualityOptions(ISyncProvider provider, SyncTarget target)
+ private IEnumerable<SyncQualityOption> GetQualityOptions(ISyncProvider provider, SyncTarget target, User user)
{
var hasQuality = provider as IHasSyncQuality;
if (hasQuality != null)
{
- return hasQuality.GetQualityOptions(target);
+ var options = hasQuality.GetQualityOptions(target);
+
+ if (user != null && !user.Policy.EnableSyncTranscoding)
+ {
+ options = options.Where(i => i.IsOriginalQuality);
+ }
+
+ return options;
}
// Default options for providers that don't override
@@ -1217,7 +1266,7 @@ namespace MediaBrowser.Server.Implementations.Sync
};
}
- public IEnumerable<SyncProfileOption> GetProfileOptions(string targetId)
+ public IEnumerable<SyncProfileOption> GetProfileOptions(string targetId, User user)
{
foreach (var provider in _providers)
{
@@ -1225,7 +1274,7 @@ namespace MediaBrowser.Server.Implementations.Sync
{
if (string.Equals(target.Id, targetId, StringComparison.OrdinalIgnoreCase))
{
- return GetProfileOptions(provider, target);
+ return GetProfileOptions(provider, target, user);
}
}
}
@@ -1233,7 +1282,12 @@ namespace MediaBrowser.Server.Implementations.Sync
return new List<SyncProfileOption>();
}
- private IEnumerable<SyncProfileOption> GetProfileOptions(ISyncProvider provider, SyncTarget target)
+ public IEnumerable<SyncProfileOption> GetProfileOptions(string targetId)
+ {
+ return GetProfileOptions(targetId, null);
+ }
+
+ private IEnumerable<SyncProfileOption> GetProfileOptions(ISyncProvider provider, SyncTarget target, User user)
{
var hasQuality = provider as IHasSyncQuality;
if (hasQuality != null)
@@ -1251,20 +1305,23 @@ namespace MediaBrowser.Server.Implementations.Sync
EnableQualityOptions = false
});
- list.Add(new SyncProfileOption
+ if (user == null || user.Policy.EnableSyncTranscoding)
{
- Name = "Baseline",
- Id = "baseline",
- Description = "Designed for compatibility with all devices, including web browsers. Targets H264/AAC video and MP3 audio."
- });
+ list.Add(new SyncProfileOption
+ {
+ Name = "Baseline",
+ Id = "baseline",
+ Description = "Designed for compatibility with all devices, including web browsers. Targets H264/AAC video and MP3 audio."
+ });
- list.Add(new SyncProfileOption
- {
- Name = "General",
- Id = "general",
- Description = "Designed for compatibility with Chromecast, Roku, Smart TV's, and other similar devices. Targets H264/AAC/AC3 video and MP3 audio.",
- IsDefault = true
- });
+ list.Add(new SyncProfileOption
+ {
+ Name = "General",
+ Id = "general",
+ Description = "Designed for compatibility with Chromecast, Roku, Smart TV's, and other similar devices. Targets H264/AAC/AC3 video and MP3 audio.",
+ IsDefault = true
+ });
+ }
return list;
}
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs b/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs
index 40d40d415..f7f320741 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs
@@ -109,8 +109,13 @@ namespace MediaBrowser.Server.Implementations.Sync
var dataProvider = _syncManager.GetDataProvider(provider, target);
var localItem = await dataProvider.Get(target, openKeys[2]).ConfigureAwait(false);
+ var fileId = localItem.FileId;
+ if (string.IsNullOrWhiteSpace(fileId))
+ {
+ }
+
var requiresDynamicAccess = (IHasDynamicAccess)provider;
- var dynamicInfo = await requiresDynamicAccess.GetSyncedFileInfo(localItem.LocalPath, target, cancellationToken).ConfigureAwait(false);
+ var dynamicInfo = await requiresDynamicAccess.GetSyncedFileInfo(fileId, target, cancellationToken).ConfigureAwait(false);
var mediaSource = localItem.Item.MediaSources.First();
mediaSource.LiveStreamId = Guid.NewGuid().ToString();
diff --git a/MediaBrowser.Server.Implementations/Sync/TargetDataProvider.cs b/MediaBrowser.Server.Implementations/Sync/TargetDataProvider.cs
index 3323ae148..dc95ee316 100644
--- a/MediaBrowser.Server.Implementations/Sync/TargetDataProvider.cs
+++ b/MediaBrowser.Server.Implementations/Sync/TargetDataProvider.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Sync;
@@ -12,6 +11,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using Patterns.IO;
namespace MediaBrowser.Server.Implementations.Sync
{
@@ -29,8 +29,6 @@ namespace MediaBrowser.Server.Implementations.Sync
private readonly IApplicationPaths _appPaths;
private readonly IServerApplicationHost _appHost;
- private readonly SemaphoreSlim _cacheFileLock = new SemaphoreSlim(1, 1);
-
public TargetDataProvider(IServerSyncProvider provider, SyncTarget target, IServerApplicationHost appHost, ILogger logger, IJsonSerializer json, IFileSystem fileSystem, IApplicationPaths appPaths)
{
_logger = logger;
@@ -42,7 +40,7 @@ namespace MediaBrowser.Server.Implementations.Sync
_appHost = appHost;
}
- private string GetRemotePath()
+ private string[] GetRemotePath()
{
var parts = new List<string>
{
@@ -52,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.Sync
parts = parts.Select(i => GetValidFilename(_provider, i)).ToList();
- return _provider.GetFullPath(parts, _target);
+ return parts.ToArray();
}
private string GetValidFilename(IServerSyncProvider provider, string filename)
@@ -65,22 +63,22 @@ namespace MediaBrowser.Server.Implementations.Sync
{
if (_items == null)
{
- try
+ _logger.Debug("Getting {0} from {1}", string.Join(MediaSync.PathSeparatorString, GetRemotePath().ToArray()), _provider.Name);
+
+ var fileResult = await _provider.GetFiles(new FileQuery
{
- var path = GetRemotePath();
+ FullPath = GetRemotePath().ToArray()
- _logger.Debug("Getting {0} from {1}", path, _provider.Name);
+ }, _target, cancellationToken).ConfigureAwait(false);
- using (var stream = await _provider.GetFile(path, _target, new Progress<double>(), cancellationToken))
+ if (fileResult.Items.Length > 0)
+ {
+ using (var stream = await _provider.GetFile(fileResult.Items[0].Id, _target, new Progress<double>(), cancellationToken))
{
_items = _json.DeserializeFromStream<List<LocalItem>>(stream);
}
}
- catch (FileNotFoundException)
- {
- _items = new List<LocalItem>();
- }
- catch (DirectoryNotFoundException)
+ else
{
_items = new List<LocalItem>();
}
@@ -133,14 +131,9 @@ namespace MediaBrowser.Server.Implementations.Sync
}
}
- public Task<List<string>> GetServerItemIds(SyncTarget target, string serverId)
- {
- return GetData(items => items.Where(i => string.Equals(i.ServerId, serverId, StringComparison.OrdinalIgnoreCase)).Select(i => i.ItemId).ToList());
- }
-
- public Task<List<string>> GetSyncJobItemIds(SyncTarget target, string serverId)
+ public Task<List<LocalItem>> GetLocalItems(SyncTarget target, string serverId)
{
- return GetData(items => items.Where(i => string.Equals(i.ServerId, serverId, StringComparison.OrdinalIgnoreCase)).Select(i => i.SyncJobItemId).Where(i => !string.IsNullOrWhiteSpace(i)).ToList());
+ return GetData(items => items.Where(i => string.Equals(i.ServerId, serverId, StringComparison.OrdinalIgnoreCase)).ToList());
}
public Task AddOrUpdate(SyncTarget target, LocalItem item)
diff --git a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs
index d6a94210c..47487bf4c 100644
--- a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
@@ -22,8 +23,8 @@ namespace MediaBrowser.Server.Implementations.UserViews
private readonly IUserManager _userManager;
private readonly ILibraryManager _libraryManager;
- public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IUserManager userManager, ILibraryManager libraryManager)
- : base(fileSystem, providerManager, applicationPaths)
+ public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, IUserManager userManager, ILibraryManager libraryManager)
+ : base(fileSystem, providerManager, applicationPaths, imageProcessor)
{
_userManager = userManager;
_libraryManager = libraryManager;
@@ -107,7 +108,7 @@ namespace MediaBrowser.Server.Implementations.UserViews
User = _userManager.GetUserById(view.UserId.Value),
CollapseBoxSetItems = false,
Recursive = recursive,
- ExcludeItemTypes = new[] { "UserView", "CollectionFolder" }
+ ExcludeItemTypes = new[] { "UserView", "CollectionFolder", "Playlist" }
}).ConfigureAwait(false);
@@ -202,6 +203,7 @@ namespace MediaBrowser.Server.Implementations.UserViews
SpecialFolder.MusicGenres,
SpecialFolder.MusicGenre,
SpecialFolder.MusicLatest,
+ SpecialFolder.MusicPlaylists,
SpecialFolder.MusicSongs,
SpecialFolder.MusicFavorites,
SpecialFolder.MusicFavoriteArtists,
@@ -238,26 +240,28 @@ namespace MediaBrowser.Server.Implementations.UserViews
return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty);
}
- protected override async Task<Stream> CreateImageAsync(IHasImages item, List<BaseItem> itemsWithImages, ImageType imageType, int imageIndex)
+ protected override bool CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPath, ImageType imageType, int imageIndex)
{
var view = (UserView)item;
if (imageType == ImageType.Primary && IsUsingCollectionStrip(view))
{
if (itemsWithImages.Count == 0 && !string.Equals(view.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
{
- return null;
+ return false;
}
- var stream = new StripCollageBuilder(ApplicationPaths).BuildThumbCollage(GetStripCollageImagePaths(itemsWithImages, view.ViewType), item.Name, 960, 540);
- return stream;
+ CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540, false, item.Name);
+ return true;
}
- return await base.CreateImageAsync(item, itemsWithImages, imageType, imageIndex);
+ return base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex);
}
- private IEnumerable<String> GetStripCollageImagePaths(IEnumerable<BaseItem> items, string viewType)
+ protected override IEnumerable<String> GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable<BaseItem> items)
{
- if (string.Equals(viewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
+ var userView = primaryItem as UserView;
+
+ if (userView != null && string.Equals(userView.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
{
var list = new List<string>();
for (int i = 1; i <= 8; i++)
@@ -267,9 +271,7 @@ namespace MediaBrowser.Server.Implementations.UserViews
return list;
}
- return items
- .Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb))
- .Where(i => !string.IsNullOrWhiteSpace(i));
+ return base.GetStripCollageImagePaths(primaryItem, items);
}
private string ExtractLiveTvResource(string name, IApplicationPaths paths)
diff --git a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs b/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs
deleted file mode 100644
index 0bf4d8e4a..000000000
--- a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs
+++ /dev/null
@@ -1,180 +0,0 @@
-using ImageMagickSharp;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Server.Implementations.Drawing;
-using MediaBrowser.Server.Implementations.Photos;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace MediaBrowser.Server.Implementations.UserViews
-{
- public class StripCollageBuilder
- {
- private readonly IApplicationPaths _appPaths;
-
- public StripCollageBuilder(IApplicationPaths appPaths)
- {
- _appPaths = appPaths;
- }
-
- public Stream BuildThumbCollage(IEnumerable<string> paths, string text, int width, int height)
- {
- using (var wand = BuildThumbCollageWand(paths, width, height))
- {
- return DynamicImageHelpers.GetStream(wand, _appPaths);
- }
- }
-
- private string[] ProjectPaths(IEnumerable<string> paths, int count)
- {
- var clone = paths.ToList();
- var list = new List<string>();
-
- while (list.Count < count)
- {
- foreach (var path in clone)
- {
- list.Add(path);
-
- if (list.Count >= count)
- {
- break;
- }
- }
- }
-
- return list.Take(count).ToArray();
- }
-
- private MagickWand BuildThumbCollageWandWithText(IEnumerable<string> paths, string text, int width, int height)
- {
- var inputPaths = ProjectPaths(paths, 8);
- using (var wandImages = new MagickWand(inputPaths))
- {
- var wand = new MagickWand(width, height);
- wand.OpenImage("gradient:#111111-#111111");
- using (var draw = new DrawingWand())
- {
- using (var fcolor = new PixelWand(ColorName.White))
- {
- draw.FillColor = fcolor;
- draw.Font = MontserratLightFont;
- draw.FontSize = 50;
- draw.FontWeight = FontWeightType.LightStyle;
- draw.TextAntialias = true;
- }
-
- var fontMetrics = wand.QueryFontMetrics(draw, text);
- var textContainerY = Convert.ToInt32(height * .165);
- wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, text);
-
- var iSlice = Convert.ToInt32(width * .1166666667);
- int iTrans = Convert.ToInt32(height * 0.2);
- int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296);
- var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
-
- foreach (var element in wandImages.ImageList)
- {
- int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
- element.Gravity = GravityType.CenterGravity;
- element.BackgroundColor = new PixelWand("none", 1);
- element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
- int ix = (int)Math.Abs((iWidth - iSlice) / 2);
- element.CropImage(iSlice, iHeight, ix, 0);
-
- element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
- }
-
- wandImages.SetFirstIterator();
- using (var wandList = wandImages.AppendImages())
- {
- wandList.CurrentImage.TrimImage(1);
- using (var mwr = wandList.CloneMagickWand())
- {
- mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
- mwr.CurrentImage.FlipImage();
-
- mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
- mwr.CurrentImage.ColorizeImage(ColorName.Black, ColorName.Grey70);
-
- using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
- {
- mwg.OpenImage("gradient:black-none");
- var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
- mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.DstInCompositeOp, 0, verticalSpacing);
-
- wandList.AddImage(mwr);
- int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
- wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * 0.26851851851851851851851851851852));
- }
- }
- }
- }
-
- return wand;
- }
- }
-
- private MagickWand BuildThumbCollageWand(IEnumerable<string> paths, int width, int height)
- {
- var inputPaths = ProjectPaths(paths, 8);
- using (var wandImages = new MagickWand(inputPaths))
- {
- var wand = new MagickWand(width, height);
- wand.OpenImage("gradient:#111111-#111111");
- using (var draw = new DrawingWand())
- {
- var iSlice = Convert.ToInt32(width * .1166666667);
- int iTrans = Convert.ToInt32(height * .25);
- int iHeight = Convert.ToInt32(height * .62);
- var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
-
- foreach (var element in wandImages.ImageList)
- {
- int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
- element.Gravity = GravityType.CenterGravity;
- element.BackgroundColor = ColorName.Black;
- element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
- int ix = (int)Math.Abs((iWidth - iSlice) / 2);
- element.CropImage(iSlice, iHeight, ix, 0);
-
- element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
- }
-
- wandImages.SetFirstIterator();
- using (var wandList = wandImages.AppendImages())
- {
- wandList.CurrentImage.TrimImage(1);
- using (var mwr = wandList.CloneMagickWand())
- {
- mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
- mwr.CurrentImage.FlipImage();
-
- mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
- mwr.CurrentImage.ColorizeImage(ColorName.Black, ColorName.Grey60);
-
- using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
- {
- mwg.OpenImage("gradient:black-none");
- var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
- mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing);
-
- wandList.AddImage(mwr);
- int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
- wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .085));
- }
- }
- }
- }
-
- return wand;
- }
- }
-
- private string MontserratLightFont
- {
- get { return PlayedIndicatorDrawer.ExtractFont("MontserratLight.otf", _appPaths); }
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index 438ccff92..f374cbea1 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="ImageMagickSharp" version="1.0.0.11" targetFramework="net45" />
<package id="MediaBrowser.Naming" version="1.0.0.32" targetFramework="net45" />
- <package id="Mono.Nat" version="1.2.21.0" targetFramework="net45" />
+ <package id="Mono.Nat" version="1.2.23.0" targetFramework="net45" />
<package id="morelinq" version="1.1.0" targetFramework="net45" />
+ <package id="Patterns.IO" version="1.0.0.3" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
- <package id="SocketHttpListener" version="1.0.0.3" targetFramework="net45" />
+ <package id="SocketHttpListener" version="1.0.0.4" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
index 911a55634..057996739 100644
--- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
+++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
@@ -1,4 +1,7 @@
-using MediaBrowser.Api;
+using Emby.Drawing;
+using Emby.Drawing.GDI;
+using Emby.Drawing.ImageMagick;
+using MediaBrowser.Api;
using MediaBrowser.Common;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Events;
@@ -63,7 +66,6 @@ using MediaBrowser.Server.Implementations.Collections;
using MediaBrowser.Server.Implementations.Configuration;
using MediaBrowser.Server.Implementations.Connect;
using MediaBrowser.Server.Implementations.Devices;
-using MediaBrowser.Server.Implementations.Drawing;
using MediaBrowser.Server.Implementations.Dto;
using MediaBrowser.Server.Implementations.EntryPoints;
using MediaBrowser.Server.Implementations.FileOrganization;
@@ -440,7 +442,7 @@ namespace MediaBrowser.Server.Startup.Common
var innerProgress = new ActionableProgress<double>();
innerProgress.RegisterAction(p => progress.Report((.75 * p) + 15));
- ImageProcessor = new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer);
+ ImageProcessor = new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, GetImageEncoder());
RegisterSingleInstance(ImageProcessor);
TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager);
@@ -544,6 +546,23 @@ namespace MediaBrowser.Server.Startup.Common
await ((UserManager)UserManager).Initialize().ConfigureAwait(false);
}
+ private IImageEncoder GetImageEncoder()
+ {
+ if (!_startupOptions.ContainsOption("-enablegdi"))
+ {
+ try
+ {
+ return new ImageMagickEncoder(LogManager.GetLogger("ImageMagick"), ApplicationPaths);
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error loading ImageMagick. Will revert to GDI.", ex);
+ }
+ }
+
+ return new GDIImageEncoder(FileSystemManager, LogManager.GetLogger("GDI"));
+ }
+
protected override INetworkManager CreateNetworkManager(ILogger logger)
{
return NativeApp.CreateNetworkManager(logger);
diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs
index cabb8dc83..4d2ed067b 100644
--- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs
+++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs
@@ -22,7 +22,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
var info = new FFMpegDownloadInfo();
// Windows builds: http://ffmpeg.zeranoe.com/builds/
- // Linux builds: http://ffmpeg.gusari.org/static/
+ // Linux builds: http://johnvansickle.com/ffmpeg/
// OS X builds: http://ffmpegmac.net/
// OS X x64: http://www.evermeet.cx/ffmpeg/
@@ -33,7 +33,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
case OperatingSystem.Linux:
info.ArchiveType = "7z";
- info.Version = "20150124";
+ info.Version = "20150331";
break;
case OperatingSystem.Osx:
@@ -54,7 +54,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
info.FFMpegFilename = "ffmpeg.exe";
info.FFProbeFilename = "ffprobe.exe";
- info.Version = "20150110";
+ info.Version = "20150331";
info.ArchiveType = "7z";
switch (environment.SystemArchitecture)
@@ -83,14 +83,14 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
case Architecture.X86_X64:
return new[]
{
- "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20150110-git-4df01d5-win64-static.7z",
- "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/windows/ffmpeg-20150110-git-4df01d5-win64-static.7z"
+ "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20150331-git-5cba529-win64-static.7z",
+ "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/windows/ffmpeg-20150331-git-5cba529-win64-static.7z"
};
case Architecture.X86:
return new[]
{
- "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20150110-git-4df01d5-win32-static.7z",
- "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/windows/ffmpeg-20150110-git-4df01d5-win32-static.7z"
+ "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20150331-git-5cba529-win32-static.7z",
+ "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/windows/ffmpeg-20150331-git-5cba529-win32-static.7z"
};
}
break;
@@ -119,12 +119,12 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
case Architecture.X86_X64:
return new[]
{
- "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/linux/ffmpeg-2.5.3-64bit-static.7z"
+ "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/linux/ffmpeg-2.6.1-64bit-static.7z"
};
case Architecture.X86:
return new[]
{
- "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/linux/ffmpeg-2.5.3-32bit-static.7z"
+ "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/linux/ffmpeg-2.6.1-32bit-static.7z"
};
}
break;
diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs
index d4cefdb10..fe7cd943a 100644
--- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs
+++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs
@@ -202,7 +202,14 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg
}
}
- throw new ApplicationException("Unable to download required components. Please try again later.");
+ if (downloadinfo.DownloadUrls.Length == 0)
+ {
+ throw new ApplicationException("ffmpeg unvailable. Please install it and start the server with two command line arguments: -ffmpeg \"{PATH}\" and -ffprobe \"{PATH}\"");
+ }
+ else
+ {
+ throw new ApplicationException("Unable to download required components. Please try again later.");
+ }
}
private void ExtractFFMpeg(FFMpegDownloadInfo downloadinfo, string tempFile, string targetFolder)
diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
index 38e07fde4..fb49692b5 100644
--- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
+++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
@@ -76,6 +76,10 @@
<Compile Include="UnhandledExceptionWriter.cs" />
</ItemGroup>
<ItemGroup>
+ <ProjectReference Include="..\Emby.Drawing\Emby.Drawing.csproj">
+ <Project>{08fff49b-f175-4807-a2b5-73b0ebd9f716}</Project>
+ <Name>Emby.Drawing</Name>
+ </ProjectReference>
<ProjectReference Include="..\MediaBrowser.Api\MediaBrowser.Api.csproj">
<Project>{4fd51ac5-2c16-4308-a993-c3a84f3b4582}</Project>
<Name>MediaBrowser.Api</Name>
diff --git a/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs b/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs
index be8ae2f81..49114b96f 100644
--- a/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs
+++ b/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs
@@ -44,7 +44,12 @@ namespace MediaBrowser.Server.Startup.Common.Migrations
{
if (string.Equals(options[i], "Media Browser Legacy Xml", StringComparison.OrdinalIgnoreCase))
{
- options[i] = "Media Browser Xml";
+ options[i] = "Emby Xml";
+ changed = true;
+ }
+ else if (string.Equals(options[i], "Media Browser Xml", StringComparison.OrdinalIgnoreCase))
+ {
+ options[i] = "Emby Xml";
changed = true;
}
}
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs
index e77af1c6b..6e8774eea 100644
--- a/MediaBrowser.ServerApplication/MainStartup.cs
+++ b/MediaBrowser.ServerApplication/MainStartup.cs
@@ -40,7 +40,6 @@ namespace MediaBrowser.ServerApplication
var applicationPath = currentProcess.MainModule.FileName;
- //Wand.SetMagickCoderModulePath(Path.Combine(Path.GetDirectoryName(applicationPath), "ImageMagickCoders", "x86"));
var appPaths = CreateApplicationPaths(applicationPath, _isRunningAsService);
var logManager = new NlogManager(appPaths.LogDirectoryPath, "server");
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index 2adb9fbbc..e118e25d1 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -62,7 +62,7 @@
<ItemGroup>
<Reference Include="ImageMagickSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\ImageMagickSharp.1.0.0.11\lib\net45\ImageMagickSharp.dll</HintPath>
+ <HintPath>..\packages\ImageMagickSharp.1.0.0.14\lib\net45\ImageMagickSharp.dll</HintPath>
</Reference>
<Reference Include="MediaBrowser.IsoMounter">
<HintPath>..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll</HintPath>
diff --git a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs
index 9db3bdb90..3c5ed6e54 100644
--- a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs
+++ b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs
@@ -166,6 +166,13 @@ namespace MediaBrowser.ServerApplication
contextMenuStrip1.Invoke(action);
}
+
+ notifyIcon1.DoubleClick += notifyIcon1_DoubleClick;
+ }
+
+ void notifyIcon1_DoubleClick(object sender, EventArgs e)
+ {
+ BrowserLauncher.OpenDashboard(_appHost, _logger);
}
private void LocalizeText()
diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config
index f429269b3..06379542e 100644
--- a/MediaBrowser.ServerApplication/packages.config
+++ b/MediaBrowser.ServerApplication/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="ImageMagickSharp" version="1.0.0.11" targetFramework="net45" />
+ <package id="ImageMagickSharp" version="1.0.0.14" targetFramework="net45" />
<package id="MediaBrowser.IsoMounting" version="3.0.69" targetFramework="net45" />
<package id="System.Data.SQLite.Core" version="1.0.94.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
index 8982b5739..90af13b57 100644
--- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs
+++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
@@ -451,7 +451,6 @@ namespace MediaBrowser.WebDashboard.Api
"moviegenres.js",
"moviecollections.js",
"movies.js",
- "movieslatest.js",
"moviepeople.js",
"moviesrecommended.js",
"moviestudios.js",
@@ -483,6 +482,7 @@ namespace MediaBrowser.WebDashboard.Api
"selectserver.js",
"serversecurity.js",
"songs.js",
+ "streamingsettings.js",
"supporterkeypage.js",
"supporterpage.js",
"syncactivity.js",
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index 2725d63ad..7abe2ded9 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -57,9 +57,9 @@
<Reference Include="ServiceStack.Interfaces">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
</Reference>
- <Reference Include="WebMarkupMin.Core, Version=0.9.11.0, Culture=neutral, PublicKeyToken=99472178d266584b, processorArchitecture=MSIL">
+ <Reference Include="WebMarkupMin.Core, Version=0.9.12.0, Culture=neutral, PublicKeyToken=99472178d266584b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\WebMarkupMin.Core.0.9.11\lib\net40\WebMarkupMin.Core.dll</HintPath>
+ <HintPath>..\packages\WebMarkupMin.Core.0.9.12\lib\net40\WebMarkupMin.Core.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -87,7 +87,9 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
- <Content Include="dashboard-ui\css\images\clients\androidtv-tile.png" />
+ <Content Include="dashboard-ui\css\images\clients\androidtv-tile.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\css\images\kids\bg.jpg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -148,6 +150,9 @@
<Content Include="dashboard-ui\scripts\selectserver.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\scripts\streamingsettings.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\scripts\syncjob.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -172,6 +177,9 @@
<Content Include="dashboard-ui\selectserver.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\streamingsettings.html">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\syncjob.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -556,9 +564,6 @@
<Content Include="dashboard-ui\metadatasubtitles.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\movieslatest.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\musicalbumartists.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -889,9 +894,6 @@
<Content Include="dashboard-ui\scripts\metadatasubtitles.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\movieslatest.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\scripts\musicalbumartists.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config
index aed67fb69..48f68789b 100644
--- a/MediaBrowser.WebDashboard/packages.config
+++ b/MediaBrowser.WebDashboard/packages.config
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MediaBrowser.ApiClient.Javascript" version="3.0.249" targetFramework="net45" />
- <package id="WebMarkupMin.Core" version="0.9.11" targetFramework="net45" />
+ <package id="WebMarkupMin.Core" version="0.9.12" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
index 5c4319d22..9cde958c4 100644
--- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
+++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
@@ -856,16 +856,6 @@ namespace MediaBrowser.XbmcMetadata.Savers
{
writer.WriteStartElement("collectionitem");
- if (!string.IsNullOrWhiteSpace(link.ItemName))
- {
- writer.WriteElementString("name", link.ItemName);
- }
-
- if (!string.IsNullOrWhiteSpace(link.ItemType))
- {
- writer.WriteElementString("type", link.ItemType);
- }
-
if (!string.IsNullOrWhiteSpace(link.Path))
{
writer.WriteElementString("path", link.Path);
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index 143a3da41..3fc5e3f33 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -61,6 +61,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Server.Mono",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Server.Startup.Common", "MediaBrowser.Server.Startup.Common\MediaBrowser.Server.Startup.Common.csproj", "{B90AB8F2-1BFF-4568-A3FD-2A338A435A75}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing", "Emby.Drawing\Emby.Drawing.csproj", "{08FFF49B-F175-4807-A2B5-73B0EBD9F716}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -516,6 +518,27 @@ Global
{B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|Win32.ActiveCfg = Release|Any CPU
{B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|x64.ActiveCfg = Release|Any CPU
{B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|x86.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|Any CPU.Build.0 = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|Mixed Platforms.Build.0 = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|Win32.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|x64.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|x86.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.Build.0 = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Win32.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|x64.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index d31071666..029e13b68 100644
--- a/Nuget/MediaBrowser.Common.Internal.nuspec
+++ b/Nuget/MediaBrowser.Common.Internal.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
- <version>3.0.612</version>
+ <version>3.0.619</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
<description>Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Emby 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.612" />
+ <dependency id="MediaBrowser.Common" version="3.0.619" />
<dependency id="NLog" version="3.2.0.0" />
<dependency id="SimpleInjector" version="2.7.0" />
</dependencies>
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index d4d7de019..f2c9f87fa 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
- <version>3.0.612</version>
+ <version>3.0.619</version>
<title>MediaBrowser.Common</title>
<authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners>
diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec
index de9c503b9..9d14d3a0b 100644
--- a/Nuget/MediaBrowser.Model.Signed.nuspec
+++ b/Nuget/MediaBrowser.Model.Signed.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Model.Signed</id>
- <version>3.0.612</version>
+ <version>3.0.619</version>
<title>MediaBrowser.Model - Signed Edition</title>
<authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners>
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index b0008f9d0..35163a659 100644
--- a/Nuget/MediaBrowser.Server.Core.nuspec
+++ b/Nuget/MediaBrowser.Server.Core.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
- <version>3.0.612</version>
+ <version>3.0.619</version>
<title>Media Browser.Server.Core</title>
<authors>Emby Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,8 @@
<description>Contains core components required to build plugins for Emby Server.</description>
<copyright>Copyright © Emby 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.612" />
+ <dependency id="MediaBrowser.Common" version="3.0.619" />
+ <dependency id="Patterns.IO" version="1.0.0.3" />
</dependencies>
</metadata>
<files>
diff --git a/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs b/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs
index 76096a541..5a190ab72 100644
--- a/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs
+++ b/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs
@@ -51,8 +51,10 @@ namespace XmlRpcHandler
XmlWriterSettings sett = new XmlWriterSettings();
sett.Indent = true;
+ var requestXmlPath = Path.Combine(Path.GetTempPath(), "request.xml");
+
sett.Encoding = Encoding.UTF8;
- FileStream str = new FileStream(Path.GetTempPath() + "\\request.xml", FileMode.Create, FileAccess.Write);
+ FileStream str = new FileStream(requestXmlPath, FileMode.Create, FileAccess.Write);
XmlWriter XMLwrt = XmlWriter.Create(str, sett);
// Let's write the methods
@@ -88,7 +90,7 @@ namespace XmlRpcHandler
XMLwrt.Flush();
XMLwrt.Close();
str.Close();
- string requestContent = File.ReadAllText(Path.GetTempPath() + "\\request.xml");
+ string requestContent = File.ReadAllText(requestXmlPath);
return Encoding.UTF8.GetBytes(requestContent);
}
/// <summary>
diff --git a/SharedVersion.cs b/SharedVersion.cs
index 8177f8cca..c2890cb34 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,4 +1,4 @@
using System.Reflection;
//[assembly: AssemblyVersion("3.0.*")]
-[assembly: AssemblyVersion("3.0.5572.0")]
+[assembly: AssemblyVersion("3.0.5582.0")]