aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author7illusions <z@7illusions.com>2014-08-30 19:06:58 +0200
committer7illusions <z@7illusions.com>2014-08-30 19:06:58 +0200
commit66ad1699e22029b605e17735e8d9450285d8748a (patch)
treeffc92c88d24850b2f82b6b3a8bdd904a2ccc77a5
parent34bc54263e886aae777a3537dc50a6535b51330a (diff)
parent9d36f518182bc075c19d78084870f5115fa62d1e (diff)
Merge pull request #1 from MediaBrowser/master
Update to latest
-rw-r--r--MediaBrowser.Api/ApiEntryPoint.cs82
-rw-r--r--MediaBrowser.Api/AppThemeService.cs4
-rw-r--r--MediaBrowser.Api/AuthorizationRequestFilterAttribute.cs190
-rw-r--r--MediaBrowser.Api/BaseApiService.cs57
-rw-r--r--MediaBrowser.Api/BrandingService.cs28
-rw-r--r--MediaBrowser.Api/ChannelService.cs31
-rw-r--r--MediaBrowser.Api/ConfigurationService.cs165
-rw-r--r--MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs671
-rw-r--r--MediaBrowser.Api/DefaultTheme/Models.cs83
-rw-r--r--MediaBrowser.Api/DisplayPreferencesService.cs4
-rw-r--r--MediaBrowser.Api/Dlna/DlnaServerService.cs17
-rw-r--r--MediaBrowser.Api/Dlna/DlnaService.cs2
-rw-r--r--MediaBrowser.Api/EnvironmentService.cs2
-rw-r--r--MediaBrowser.Api/GamesService.cs2
-rw-r--r--MediaBrowser.Api/Images/ImageByNameService.cs8
-rw-r--r--MediaBrowser.Api/Images/ImageService.cs142
-rw-r--r--MediaBrowser.Api/Images/ImageWriter.cs96
-rw-r--r--MediaBrowser.Api/Images/RemoteImageService.cs29
-rw-r--r--MediaBrowser.Api/ItemLookupService.cs31
-rw-r--r--MediaBrowser.Api/ItemRefreshService.cs25
-rw-r--r--MediaBrowser.Api/ItemUpdateService.cs23
-rw-r--r--MediaBrowser.Api/Library/ChapterService.cs2
-rw-r--r--MediaBrowser.Api/Library/FileOrganizationService.cs2
-rw-r--r--MediaBrowser.Api/Library/LibraryHelpers.cs2
-rw-r--r--MediaBrowser.Api/Library/LibraryService.cs36
-rw-r--r--MediaBrowser.Api/Library/LibraryStructureService.cs28
-rw-r--r--MediaBrowser.Api/LiveTv/LiveTvService.cs82
-rw-r--r--MediaBrowser.Api/LocalizationService.cs2
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj29
-rw-r--r--MediaBrowser.Api/Movies/CollectionService.cs15
-rw-r--r--MediaBrowser.Api/Movies/MoviesService.cs2
-rw-r--r--MediaBrowser.Api/Movies/TrailersService.cs2
-rw-r--r--MediaBrowser.Api/Music/AlbumsService.cs3
-rw-r--r--MediaBrowser.Api/Music/InstantMixService.cs38
-rw-r--r--MediaBrowser.Api/NotificationsService.cs2
-rw-r--r--MediaBrowser.Api/PackageReviewService.cs2
-rw-r--r--MediaBrowser.Api/PackageService.cs2
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs297
-rw-r--r--MediaBrowser.Api/Playback/BifService.cs186
-rw-r--r--MediaBrowser.Api/Playback/EndlessStreamCopy.cs32
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs152
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs474
-rw-r--r--MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs4
-rw-r--r--MediaBrowser.Api/Playback/Hls/VideoHlsService.cs23
-rw-r--r--MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs131
-rw-r--r--MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs40
-rw-r--r--MediaBrowser.Api/Playback/Progressive/VideoService.cs10
-rw-r--r--MediaBrowser.Api/Playback/StreamRequest.cs10
-rw-r--r--MediaBrowser.Api/Playback/StreamState.cs9
-rw-r--r--MediaBrowser.Api/PlaylistService.cs176
-rw-r--r--MediaBrowser.Api/PluginService.cs2
-rw-r--r--MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs2
-rw-r--r--MediaBrowser.Api/SearchService.cs10
-rw-r--r--MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs (renamed from MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs)2
-rw-r--r--MediaBrowser.Api/Session/SessionsService.cs (renamed from MediaBrowser.Api/SessionsService.cs)118
-rw-r--r--MediaBrowser.Api/SimilarItemsHelper.cs4
-rw-r--r--MediaBrowser.Api/Subtitles/SubtitleService.cs (renamed from MediaBrowser.Api/Library/SubtitleService.cs)147
-rw-r--r--MediaBrowser.Api/Sync/SyncService.cs104
-rw-r--r--MediaBrowser.Api/System/ActivityLogService.cs53
-rw-r--r--MediaBrowser.Api/System/ActivityLogWebSocketListener.cs67
-rw-r--r--MediaBrowser.Api/System/SystemInfoWebSocketListener.cs (renamed from MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs)2
-rw-r--r--MediaBrowser.Api/System/SystemService.cs205
-rw-r--r--MediaBrowser.Api/SystemService.cs90
-rw-r--r--MediaBrowser.Api/TvShowsService.cs2
-rw-r--r--MediaBrowser.Api/UserLibrary/ArtistsService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/GameGenresService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/GenresService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/ItemsService.cs4
-rw-r--r--MediaBrowser.Api/UserLibrary/MusicGenresService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/PersonsService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/PlaystateService.cs388
-rw-r--r--MediaBrowser.Api/UserLibrary/StudiosService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/UserLibraryService.cs521
-rw-r--r--MediaBrowser.Api/UserLibrary/YearsService.cs6
-rw-r--r--MediaBrowser.Api/UserService.cs190
-rw-r--r--MediaBrowser.Api/VideosService.cs18
-rw-r--r--MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs149
-rw-r--r--MediaBrowser.Common.Implementations/BaseApplicationHost.cs56
-rw-r--r--MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs103
-rw-r--r--MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs22
-rw-r--r--MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs15
-rw-r--r--MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj14
-rw-r--r--MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs87
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs1
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs2
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs2
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs2
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/SystemUpdateTask.cs2
-rw-r--r--MediaBrowser.Common.Implementations/Security/UsageReporter.cs5
-rw-r--r--MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs20
-rw-r--r--MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs15
-rw-r--r--MediaBrowser.Common.Implementations/Updates/InstallationManager.cs48
-rw-r--r--MediaBrowser.Common.Implementations/packages.config4
-rw-r--r--MediaBrowser.Common/Configuration/ConfigurationHelper.cs28
-rw-r--r--MediaBrowser.Common/Configuration/ConfigurationUpdateEventArgs.cs18
-rw-r--r--MediaBrowser.Common/Configuration/IConfigurationFactory.cs17
-rw-r--r--MediaBrowser.Common/Configuration/IConfigurationManager.cs48
-rw-r--r--MediaBrowser.Common/IO/IFileSystem.cs14
-rw-r--r--MediaBrowser.Common/MediaBrowser.Common.csproj7
-rw-r--r--MediaBrowser.Common/Net/HttpRequestOptions.cs1
-rw-r--r--MediaBrowser.Common/Net/INetworkManager.cs7
-rw-r--r--MediaBrowser.Common/Net/IServerManager.cs20
-rw-r--r--MediaBrowser.Common/Net/IWebSocket.cs14
-rw-r--r--MediaBrowser.Common/Net/IWebSocketConnection.cs5
-rw-r--r--MediaBrowser.Common/Net/IWebSocketServer.cs32
-rw-r--r--MediaBrowser.Common/Net/MimeTypes.cs22
-rw-r--r--MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs5
-rw-r--r--MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs9
-rw-r--r--MediaBrowser.Controller/Activity/IActivityManager.cs17
-rw-r--r--MediaBrowser.Controller/Activity/IActivityRepository.cs14
-rw-r--r--MediaBrowser.Controller/Channels/Channel.cs2
-rw-r--r--MediaBrowser.Controller/Channels/ChannelFolderItem.cs7
-rw-r--r--MediaBrowser.Controller/Channels/ChannelItemInfo.cs13
-rw-r--r--MediaBrowser.Controller/Channels/ChannelMediaInfo.cs2
-rw-r--r--MediaBrowser.Controller/Channels/IChannelFactory.cs5
-rw-r--r--MediaBrowser.Controller/Channels/IChannelManager.cs16
-rw-r--r--MediaBrowser.Controller/Chapters/IChapterManager.cs7
-rw-r--r--MediaBrowser.Controller/Collections/CollectionEvents.cs37
-rw-r--r--MediaBrowser.Controller/Collections/ICollectionManager.cs22
-rw-r--r--MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs13
-rw-r--r--MediaBrowser.Controller/Connect/IConnectManager.cs9
-rw-r--r--MediaBrowser.Controller/Drawing/IImageProcessor.cs7
-rw-r--r--MediaBrowser.Controller/Drawing/ImageExtensions.cs33
-rw-r--r--MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs30
-rw-r--r--MediaBrowser.Controller/Dto/IDtoService.cs26
-rw-r--r--MediaBrowser.Controller/Entities/Audio/Audio.cs65
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs52
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs19
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicGenre.cs7
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs103
-rw-r--r--MediaBrowser.Controller/Entities/BasePluginFolder.cs7
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs201
-rw-r--r--MediaBrowser.Controller/Entities/IHasImages.cs6
-rw-r--r--MediaBrowser.Controller/Entities/IHasMediaSources.cs6
-rw-r--r--MediaBrowser.Controller/Entities/IHasUserData.cs18
-rw-r--r--MediaBrowser.Controller/Entities/IThemeMedia.cs8
-rw-r--r--MediaBrowser.Controller/Entities/LinkedChild.cs18
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs38
-rw-r--r--MediaBrowser.Controller/Entities/Movies/Movie.cs3
-rw-r--r--MediaBrowser.Controller/Entities/Person.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Photo.cs56
-rw-r--r--MediaBrowser.Controller/Entities/PhotoAlbum.cs21
-rw-r--r--MediaBrowser.Controller/Entities/Studio.cs9
-rw-r--r--MediaBrowser.Controller/Entities/TV/Episode.cs25
-rw-r--r--MediaBrowser.Controller/Entities/TV/Season.cs15
-rw-r--r--MediaBrowser.Controller/Entities/TV/Series.cs24
-rw-r--r--MediaBrowser.Controller/Entities/User.cs1
-rw-r--r--MediaBrowser.Controller/Entities/UserRootFolder.cs6
-rw-r--r--MediaBrowser.Controller/Entities/UserView.cs72
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs16
-rw-r--r--MediaBrowser.Controller/IServerApplicationHost.cs12
-rw-r--r--MediaBrowser.Controller/Library/IUserDataManager.cs9
-rw-r--r--MediaBrowser.Controller/Library/IUserManager.cs17
-rw-r--r--MediaBrowser.Controller/Library/IUserViewManager.cs2
-rw-r--r--MediaBrowser.Controller/Library/TVUtils.cs131
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs17
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs4
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvChannel.cs4
-rw-r--r--MediaBrowser.Controller/LiveTv/RecordingGroup.cs22
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj36
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs28
-rw-r--r--MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs4
-rw-r--r--MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs6
-rw-r--r--MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs5
-rw-r--r--MediaBrowser.Controller/Net/AuthenticatedAttribute.cs41
-rw-r--r--MediaBrowser.Controller/Net/AuthorizationInfo.cs37
-rw-r--r--MediaBrowser.Controller/Net/IAuthService.cs9
-rw-r--r--MediaBrowser.Controller/Net/IAuthorizationContext.cs14
-rw-r--r--MediaBrowser.Controller/Net/IHasAuthorization.cs12
-rw-r--r--MediaBrowser.Controller/Net/IHasResultFactory.cs3
-rw-r--r--MediaBrowser.Controller/Net/IHasSession.cs12
-rw-r--r--MediaBrowser.Controller/Net/IHttpResultFactory.cs41
-rw-r--r--MediaBrowser.Controller/Net/IHttpServer.cs12
-rw-r--r--MediaBrowser.Controller/Net/IRestfulService.cs1
-rw-r--r--MediaBrowser.Controller/Net/ISessionContext.cs13
-rw-r--r--MediaBrowser.Controller/Net/LoggedAttribute.cs73
-rw-r--r--MediaBrowser.Controller/Net/StaticResultOptions.cs42
-rw-r--r--MediaBrowser.Controller/Notifications/INotificationsRepository.cs12
-rw-r--r--MediaBrowser.Controller/Playlists/IPlaylistManager.cs49
-rw-r--r--MediaBrowser.Controller/Playlists/Playlist.cs157
-rw-r--r--MediaBrowser.Controller/Providers/BaseItemXmlParser.cs61
-rw-r--r--MediaBrowser.Controller/Providers/IMetadataProvider.cs1
-rw-r--r--MediaBrowser.Controller/Providers/ItemIdentities.cs5
-rw-r--r--MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs52
-rw-r--r--MediaBrowser.Controller/Providers/NameParser.cs4
-rw-r--r--MediaBrowser.Controller/RelatedMedia/IRelatedMediaProvider.cs17
-rw-r--r--MediaBrowser.Controller/Resolvers/BaseVideoResolver.cs19
-rw-r--r--MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs56
-rw-r--r--MediaBrowser.Controller/Security/AuthenticationInfo.cs61
-rw-r--r--MediaBrowser.Controller/Security/AuthenticationInfoQuery.cs42
-rw-r--r--MediaBrowser.Controller/Security/IAuthenticationRepository.cs39
-rw-r--r--MediaBrowser.Controller/Session/AuthenticationRequest.cs14
-rw-r--r--MediaBrowser.Controller/Session/ISessionManager.cs61
-rw-r--r--MediaBrowser.Controller/Session/SessionInfo.cs4
-rw-r--r--MediaBrowser.Controller/Subtitles/ISubtitleManager.cs17
-rw-r--r--MediaBrowser.Controller/Subtitles/SubtitleDownloadEventArgs.cs27
-rw-r--r--MediaBrowser.Controller/Sync/ICloudSyncProvider.cs12
-rw-r--r--MediaBrowser.Controller/Sync/ISyncManager.cs55
-rw-r--r--MediaBrowser.Controller/Sync/ISyncProvider.cs28
-rw-r--r--MediaBrowser.Controller/Sync/ISyncRepository.cs58
-rw-r--r--MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs341
-rw-r--r--MediaBrowser.Dlna/ConfigurationExtension.cs29
-rw-r--r--MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs17
-rw-r--r--MediaBrowser.Dlna/ContentDirectory/ContentDirectoryBrowser.cs126
-rw-r--r--MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs281
-rw-r--r--MediaBrowser.Dlna/Didl/DidlBuilder.cs295
-rw-r--r--MediaBrowser.Dlna/Didl/Filter.cs (renamed from MediaBrowser.Model/Dlna/Filter.cs)8
-rw-r--r--MediaBrowser.Dlna/DlnaManager.cs7
-rw-r--r--MediaBrowser.Dlna/Eventing/EventSubscription.cs (renamed from MediaBrowser.Model/Dlna/EventSubscription.cs)2
-rw-r--r--MediaBrowser.Dlna/Images/logo120.jpgbin6745 -> 8879 bytes
-rw-r--r--MediaBrowser.Dlna/Images/logo120.pngbin4124 -> 13621 bytes
-rw-r--r--MediaBrowser.Dlna/Images/logo240.jpgbin0 -> 22073 bytes
-rw-r--r--MediaBrowser.Dlna/Images/logo240.pngbin0 -> 33252 bytes
-rw-r--r--MediaBrowser.Dlna/Images/logo48.jpgbin2484 -> 2997 bytes
-rw-r--r--MediaBrowser.Dlna/Images/logo48.pngbin1661 -> 3837 bytes
-rw-r--r--MediaBrowser.Dlna/Main/DlnaEntryPoint.cs53
-rw-r--r--MediaBrowser.Dlna/MediaBrowser.Dlna.csproj23
-rw-r--r--MediaBrowser.Dlna/PlayTo/Device.cs70
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlayToController.cs75
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlayToManager.cs304
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs5
-rw-r--r--MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs6
-rw-r--r--MediaBrowser.Dlna/PlayTo/TransportCommands.cs35
-rw-r--r--MediaBrowser.Dlna/PlayTo/UpnpContainer.cs1
-rw-r--r--MediaBrowser.Dlna/Profiles/AndroidProfile.cs178
-rw-r--r--MediaBrowser.Dlna/Profiles/DefaultProfile.cs14
-rw-r--r--MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs5
-rw-r--r--MediaBrowser.Dlna/Profiles/DirectTvProfile.cs117
-rw-r--r--MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs9
-rw-r--r--MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs16
-rw-r--r--MediaBrowser.Dlna/Profiles/Windows81Profile.cs22
-rw-r--r--MediaBrowser.Dlna/Profiles/WindowsPhoneProfile.cs15
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Android.xml71
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Default.xml18
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml18
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml61
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml20
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml18
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml18
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml22
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml23
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml20
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml20
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml20
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml20
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml20
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml20
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml20
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml20
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Windows 8 RT.xml70
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Windows Phone.xml82
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml20
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml18
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml18
-rw-r--r--MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs18
-rw-r--r--MediaBrowser.Dlna/Service/BaseControlHandler.cs26
-rw-r--r--MediaBrowser.Dlna/Ssdp/Datagram.cs2
-rw-r--r--MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs246
-rw-r--r--MediaBrowser.Dlna/Ssdp/DeviceDiscoveryInfo.cs21
-rw-r--r--MediaBrowser.Dlna/Ssdp/Extensions.cs (renamed from MediaBrowser.Dlna/PlayTo/Extensions.cs)2
-rw-r--r--MediaBrowser.Dlna/Ssdp/SsdpHandler.cs84
-rw-r--r--MediaBrowser.Dlna/Ssdp/SsdpMessageBuilder.cs23
-rw-r--r--MediaBrowser.Dlna/Ssdp/SsdpMessageEventArgs.cs2
-rw-r--r--MediaBrowser.LocalMetadata/BaseXmlProvider.cs (renamed from MediaBrowser.Providers/BaseXmlProvider.cs)6
-rw-r--r--MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs (renamed from MediaBrowser.Providers/Folders/CollectionFolderImageProvider.cs)16
-rw-r--r--MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs (renamed from MediaBrowser.Providers/TV/EpisodeLocalImageProvider.cs)23
-rw-r--r--MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs (renamed from MediaBrowser.Providers/Folders/ImagesByNameImageProvider.cs)11
-rw-r--r--MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs (renamed from MediaBrowser.Providers/All/InternalMetadataFolderImageProvider.cs)11
-rw-r--r--MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs (renamed from MediaBrowser.Providers/All/LocalImageProvider.cs)23
-rw-r--r--MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj116
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs (renamed from MediaBrowser.Providers/BoxSets/BoxSetXmlParser.cs)59
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs (renamed from MediaBrowser.Providers/TV/EpisodeXmlParser.cs)12
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/GameSystemXmlParser.cs (renamed from MediaBrowser.Providers/Games/GameSystemXmlParser.cs)10
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs (renamed from MediaBrowser.Providers/Games/GameXmlParser.cs)12
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs (renamed from MediaBrowser.Providers/Movies/MovieXmlParser.cs)10
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/MusicVideoXmlParser.cs (renamed from MediaBrowser.Providers/Music/MusicVideoXmlParser.cs)7
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs86
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/SeasonXmlParser.cs (renamed from MediaBrowser.Providers/TV/SeasonXmlParser.cs)6
-rw-r--r--MediaBrowser.LocalMetadata/Parsers/SeriesXmlParser.cs (renamed from MediaBrowser.Providers/TV/SeriesXmlParser.cs)8
-rw-r--r--MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs34
-rw-r--r--MediaBrowser.LocalMetadata/Providers/AdultVideoXmlProvider.cs (renamed from MediaBrowser.Providers/AdultVideos/AdultVideoXmlProvider.cs)12
-rw-r--r--MediaBrowser.LocalMetadata/Providers/AlbumXmlProvider.cs (renamed from MediaBrowser.Providers/Music/AlbumXmlProvider.cs)10
-rw-r--r--MediaBrowser.LocalMetadata/Providers/ArtistXmlProvider.cs (renamed from MediaBrowser.Providers/Music/ArtistXmlProvider.cs)8
-rw-r--r--MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs (renamed from MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs)3
-rw-r--r--MediaBrowser.LocalMetadata/Providers/ChannelXmlProvider.cs (renamed from MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs)8
-rw-r--r--MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs (renamed from MediaBrowser.Providers/TV/EpisodeXmlProvider.cs)22
-rw-r--r--MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs (renamed from MediaBrowser.Providers/Folders/FolderXmlProvider.cs)8
-rw-r--r--MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs (renamed from MediaBrowser.Providers/Games/GameSystemXmlProvider.cs)9
-rw-r--r--MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs (renamed from MediaBrowser.Providers/Games/GameXmlProvider.cs)11
-rw-r--r--MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs (renamed from MediaBrowser.Providers/Movies/MovieXmlProvider.cs)5
-rw-r--r--MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs (renamed from MediaBrowser.Providers/Music/MusicVideoXmlProvider.cs)11
-rw-r--r--MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs (renamed from MediaBrowser.Providers/People/PersonXmlProvider.cs)8
-rw-r--r--MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs31
-rw-r--r--MediaBrowser.LocalMetadata/Providers/SeasonXmlProvider.cs (renamed from MediaBrowser.Providers/TV/SeasonXmlProvider.cs)20
-rw-r--r--MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs (renamed from MediaBrowser.Providers/TV/SeriesXmlProvider.cs)20
-rw-r--r--MediaBrowser.LocalMetadata/Providers/TrailerXmlProvider.cs (renamed from MediaBrowser.Providers/Movies/TrailerXmlProvider.cs)3
-rw-r--r--MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs (renamed from MediaBrowser.Providers/Videos/VideoXmlProvider.cs)12
-rw-r--r--MediaBrowser.LocalMetadata/Savers/AlbumXmlSaver.cs (renamed from MediaBrowser.Providers/Savers/AlbumXmlSaver.cs)10
-rw-r--r--MediaBrowser.LocalMetadata/Savers/ArtistXmlSaver.cs (renamed from MediaBrowser.Providers/Savers/ArtistXmlSaver.cs)10
-rw-r--r--MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs (renamed from MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs)11
-rw-r--r--MediaBrowser.LocalMetadata/Savers/ChannelXmlSaver.cs (renamed from MediaBrowser.Providers/Savers/ChannelXmlSaver.cs)11
-rw-r--r--MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs (renamed from MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs)12
-rw-r--r--MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs (renamed from MediaBrowser.Providers/Savers/FolderXmlSaver.cs)7
-rw-r--r--MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs (renamed from MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs)8
-rw-r--r--MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs (renamed from MediaBrowser.Providers/Savers/GameXmlSaver.cs)10
-rw-r--r--MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs (renamed from MediaBrowser.Providers/Savers/MovieXmlSaver.cs)15
-rw-r--r--MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs (renamed from MediaBrowser.Providers/Savers/PersonXmlSaver.cs)10
-rw-r--r--MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs86
-rw-r--r--MediaBrowser.LocalMetadata/Savers/SeasonXmlSaver.cs (renamed from MediaBrowser.Providers/Savers/SeasonXmlSaver.cs)10
-rw-r--r--MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs (renamed from MediaBrowser.Providers/Savers/SeriesXmlSaver.cs)14
-rw-r--r--MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs (renamed from MediaBrowser.Providers/Savers/XmlSaverHelpers.cs)66
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs169
-rw-r--r--MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj8
-rw-r--r--MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs4
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/AssParser.cs71
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs27
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs400
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs149
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs59
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs13
-rw-r--r--MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj180
-rw-r--r--MediaBrowser.Model.Portable/app.config15
-rw-r--r--MediaBrowser.Model.Portable/packages.config6
-rw-r--r--MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj127
-rw-r--r--MediaBrowser.Model/Activity/ActivityLogEntry.cs62
-rw-r--r--MediaBrowser.Model/ApiClient/ApiClientExtensions.cs6
-rw-r--r--MediaBrowser.Model/ApiClient/IApiClient.cs273
-rw-r--r--MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs22
-rw-r--r--MediaBrowser.Model/Branding/BrandingOptions.cs12
-rw-r--r--MediaBrowser.Model/Channels/ChannelItemQuery.cs5
-rw-r--r--MediaBrowser.Model/Collections/CollectionCreationResult.cs8
-rw-r--r--MediaBrowser.Model/Configuration/ChannelOptions.cs21
-rw-r--r--MediaBrowser.Model/Configuration/ChapterOptions.cs23
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs188
-rw-r--r--MediaBrowser.Model/Configuration/SubtitlePlaybackMode.cs10
-rw-r--r--MediaBrowser.Model/Configuration/UserConfiguration.cs20
-rw-r--r--MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs24
-rw-r--r--MediaBrowser.Model/Dlna/AudioOptions.cs45
-rw-r--r--MediaBrowser.Model/Dlna/ConditionProcessor.cs29
-rw-r--r--MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs89
-rw-r--r--MediaBrowser.Model/Dlna/DeviceProfile.cs27
-rw-r--r--MediaBrowser.Model/Dlna/DlnaFlags.cs27
-rw-r--r--MediaBrowser.Model/Dlna/DlnaMaps.cs2
-rw-r--r--MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs20
-rw-r--r--MediaBrowser.Model/Dlna/SearchCriteria.cs42
-rw-r--r--MediaBrowser.Model/Dlna/SearchType.cs3
-rw-r--r--MediaBrowser.Model/Dlna/SortCriteria.cs8
-rw-r--r--MediaBrowser.Model/Dlna/StreamBuilder.cs181
-rw-r--r--MediaBrowser.Model/Dlna/StreamInfo.cs120
-rw-r--r--MediaBrowser.Model/Dlna/SubtitleProfile.cs17
-rw-r--r--MediaBrowser.Model/Dlna/TranscodingProfile.cs9
-rw-r--r--MediaBrowser.Model/Dlna/VideoOptions.cs6
-rw-r--r--MediaBrowser.Model/Drawing/ImageOrientation.cs15
-rw-r--r--MediaBrowser.Model/Dto/BaseItemDto.cs80
-rw-r--r--MediaBrowser.Model/Dto/BaseItemPerson.cs3
-rw-r--r--MediaBrowser.Model/Dto/ChapterInfoDto.cs6
-rw-r--r--MediaBrowser.Model/Dto/MediaSourceInfo.cs13
-rw-r--r--MediaBrowser.Model/Dto/StreamOptions.cs64
-rw-r--r--MediaBrowser.Model/Dto/StudioDto.cs9
-rw-r--r--MediaBrowser.Model/Dto/UserDto.cs5
-rw-r--r--MediaBrowser.Model/Dto/UserItemDataDto.cs17
-rw-r--r--MediaBrowser.Model/Dto/VideoStreamOptions.cs99
-rw-r--r--MediaBrowser.Model/Entities/CollectionType.cs8
-rw-r--r--MediaBrowser.Model/Entities/DisplayPreferences.cs3
-rw-r--r--MediaBrowser.Model/Entities/MediaStream.cs8
-rw-r--r--MediaBrowser.Model/Events/GenericEventArgs.cs16
-rw-r--r--MediaBrowser.Model/Extensions/IHasPropertyChangedEvent.cs8
-rw-r--r--MediaBrowser.Model/Extensions/ListHelper.cs28
-rw-r--r--MediaBrowser.Model/Extensions/StringHelper.cs35
-rw-r--r--MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs17
-rw-r--r--MediaBrowser.Model/FileOrganization/TvFileOrganizationOptions.cs (renamed from MediaBrowser.Model/Configuration/TvFileOrganizationOptions.cs)2
-rw-r--r--MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs3
-rw-r--r--MediaBrowser.Model/LiveTv/ChannelInfoDto.cs3
-rw-r--r--MediaBrowser.Model/LiveTv/LiveTvOptions.cs (renamed from MediaBrowser.Model/Configuration/LiveTvOptions.cs)2
-rw-r--r--MediaBrowser.Model/LiveTv/ProgramInfoDto.cs3
-rw-r--r--MediaBrowser.Model/LiveTv/RecordingGroupDto.cs3
-rw-r--r--MediaBrowser.Model/LiveTv/RecordingInfoDto.cs3
-rw-r--r--MediaBrowser.Model/Logging/ILogger.cs16
-rw-r--r--MediaBrowser.Model/MediaBrowser.Model.csproj45
-rw-r--r--MediaBrowser.Model/MediaInfo/SubtitleFormat.cs2
-rw-r--r--MediaBrowser.Model/Notifications/Notification.cs5
-rw-r--r--MediaBrowser.Model/Notifications/NotificationOption.cs (renamed from MediaBrowser.Model/Configuration/NotificationOption.cs)4
-rw-r--r--MediaBrowser.Model/Notifications/NotificationOptions.cs (renamed from MediaBrowser.Model/Configuration/NotificationOptions.cs)11
-rw-r--r--MediaBrowser.Model/Notifications/NotificationRequest.cs7
-rw-r--r--MediaBrowser.Model/Notifications/NotificationType.cs (renamed from MediaBrowser.Model/Configuration/NotificationType.cs)2
-rw-r--r--MediaBrowser.Model/Notifications/SendToUserType.cs (renamed from MediaBrowser.Model/Configuration/SendToUserType.cs)2
-rw-r--r--MediaBrowser.Model/Playlists/PlaylistCreationRequest.cs20
-rw-r--r--MediaBrowser.Model/Playlists/PlaylistCreationResult.cs8
-rw-r--r--MediaBrowser.Model/Playlists/PlaylistItemQuery.cs37
-rw-r--r--MediaBrowser.Model/Providers/SubtitleOptions.cs (renamed from MediaBrowser.Model/Configuration/SubtitleOptions.cs)3
-rw-r--r--MediaBrowser.Model/Querying/ItemFields.cs5
-rw-r--r--MediaBrowser.Model/Querying/LatestItemsQuery.cs54
-rw-r--r--MediaBrowser.Model/Serialization/IJsonSerializer.cs8
-rw-r--r--MediaBrowser.Model/Serialization/IXmlSerializer.cs7
-rw-r--r--MediaBrowser.Model/Session/GeneralCommand.cs5
-rw-r--r--MediaBrowser.Model/Session/SessionInfoDto.cs33
-rw-r--r--MediaBrowser.Model/Sync/SyncJob.cs94
-rw-r--r--MediaBrowser.Model/Sync/SyncJobCreationResult.cs8
-rw-r--r--MediaBrowser.Model/Sync/SyncJobItem.cs48
-rw-r--r--MediaBrowser.Model/Sync/SyncJobQuery.cs17
-rw-r--r--MediaBrowser.Model/Sync/SyncJobRequest.cs58
-rw-r--r--MediaBrowser.Model/Sync/SyncJobStatus.cs13
-rw-r--r--MediaBrowser.Model/Sync/SyncQuality.cs21
-rw-r--r--MediaBrowser.Model/Sync/SyncTarget.cs17
-rw-r--r--MediaBrowser.Model/System/LogFile.cs31
-rw-r--r--MediaBrowser.Model/System/SystemInfo.cs47
-rw-r--r--MediaBrowser.Model/Tasks/TaskResult.cs6
-rw-r--r--MediaBrowser.Model/Themes/AppTheme.cs5
-rw-r--r--MediaBrowser.Model/Updates/CheckForUpdateResult.cs7
-rw-r--r--MediaBrowser.Model/Updates/PackageVersionInfo.cs2
-rw-r--r--MediaBrowser.Model/Users/AuthenticationResult.cs12
-rw-r--r--MediaBrowser.Mono.sln20
-rw-r--r--MediaBrowser.Mono.userprefs2
-rw-r--r--MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs6
-rw-r--r--MediaBrowser.Providers/Channels/AudioChannelItemMetadataService.cs (renamed from MediaBrowser.Providers/GameGenres/AudioChannelItemMetadataService.cs)6
-rw-r--r--MediaBrowser.Providers/Channels/VideoChannelItemMetadataService.cs (renamed from MediaBrowser.Providers/GameGenres/VideoChannelItemMetadataService.cs)6
-rw-r--r--MediaBrowser.Providers/Chapters/ChapterManager.cs32
-rw-r--r--MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs9
-rw-r--r--MediaBrowser.Providers/Manager/ImageSaver.cs38
-rw-r--r--MediaBrowser.Providers/Manager/ItemImageProvider.cs5
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs95
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs30
-rw-r--r--MediaBrowser.Providers/Manager/ProviderUtils.cs2
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj74
-rw-r--r--MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs28
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs2
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs5
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs11
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs59
-rw-r--r--MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs19
-rw-r--r--MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs137
-rw-r--r--MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs2
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbProvider.cs18
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbSearch.cs17
-rw-r--r--MediaBrowser.Providers/Music/AlbumMetadataService.cs16
-rw-r--r--MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs8
-rw-r--r--MediaBrowser.Providers/Music/Extensions.cs10
-rw-r--r--MediaBrowser.Providers/Music/FanArtAlbumProvider.cs2
-rw-r--r--MediaBrowser.Providers/Music/FanArtArtistProvider.cs4
-rw-r--r--MediaBrowser.Providers/Music/LastFmImageProvider.cs164
-rw-r--r--MediaBrowser.Providers/Music/LastfmAlbumProvider.cs322
-rw-r--r--MediaBrowser.Providers/Music/LastfmArtistProvider.cs160
-rw-r--r--MediaBrowser.Providers/Music/LastfmHelper.cs76
-rw-r--r--MediaBrowser.Providers/Music/SoundtrackPostScanTask.cs32
-rw-r--r--MediaBrowser.Providers/Omdb/OmdbItemProvider.cs45
-rw-r--r--MediaBrowser.Providers/Photos/ExifReader.cs613
-rw-r--r--MediaBrowser.Providers/Photos/ExifTags.cs132
-rw-r--r--MediaBrowser.Providers/Photos/PhotoHelper.cs17
-rw-r--r--MediaBrowser.Providers/Photos/PhotoProvider.cs187
-rw-r--r--MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs53
-rw-r--r--MediaBrowser.Providers/Subtitles/ConfigurationExtension.cs29
-rw-r--r--MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs59
-rw-r--r--MediaBrowser.Providers/Subtitles/SubtitleManager.cs69
-rw-r--r--MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs347
-rw-r--r--MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs319
-rw-r--r--MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs55
-rw-r--r--MediaBrowser.Providers/TV/SeasonMetadataService.cs10
-rw-r--r--MediaBrowser.Providers/TV/TvExternalIds.cs23
-rw-r--r--MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs7
-rw-r--r--MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs16
-rw-r--r--MediaBrowser.Providers/TV/TvdbSeriesProvider.cs92
-rw-r--r--MediaBrowser.Providers/packages.config1
-rw-r--r--MediaBrowser.Server.Implementations/Activity/ActivityManager.cs40
-rw-r--r--MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs309
-rw-r--r--MediaBrowser.Server.Implementations/Branding/BrandingConfigurationFactory.cs21
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs29
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs48
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelManager.cs159
-rw-r--r--MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Collections/CollectionManager.cs76
-rw-r--r--MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs16
-rw-r--r--MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs55
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectData.cs17
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs125
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectManager.cs204
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ServerRegistrationResponse.cs18
-rw-r--r--MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs144
-rw-r--r--MediaBrowser.Server.Implementations/Dto/DtoService.cs256
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs569
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs55
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs55
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/Notifications/WebSocketNotifier.cs9
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs6
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs28
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs1
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs45
-rw-r--r--MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs8
-rw-r--r--MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs29
-rw-r--r--MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs9
-rw-r--r--MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs19
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs339
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs138
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs42
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs28
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs21
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs299
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs17
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs25
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs164
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs104
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/Security/SessionAuthProvider.cs35
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/Security/SessionContext.cs36
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SocketSharp/Extensions.cs28
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs918
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs165
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs278
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs402
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs144
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs13
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/ThrottledStream.cs389
-rw-r--r--MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs19
-rw-r--r--MediaBrowser.Server.Implementations/Library/LibraryManager.cs19
-rw-r--r--MediaBrowser.Server.Implementations/Library/MusicManager.cs14
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs135
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs21
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs12
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/LocalTrailerResolver.cs12
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs21
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs39
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs26
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/PlaylistResolver.cs38
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs35
-rw-r--r--MediaBrowser.Server.Implementations/Library/SearchEngine.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserDataManager.cs37
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserManager.cs129
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserViewManager.cs97
-rw-r--r--MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs103
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/CleanDatabaseScheduledTask.cs2
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs21
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs11
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs257
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json266
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json266
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json336
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/da.json266
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/de.json464
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/el.json266
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json280
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json266
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/es.json274
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/es_ES.json237
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json268
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json396
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/he.json266
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/it.json268
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json626
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json288
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json266
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json544
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json280
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json433
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json318
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json266
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json340
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json260
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json433
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json266
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json266
-rw-r--r--MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ar.json364
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ca.json364
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/cs.json566
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/da.json356
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/de.json718
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/el.json364
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/en_GB.json372
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/en_US.json364
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/es.json352
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/es_ES.json872
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/es_MX.json414
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/fr.json458
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/he.json342
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/it.json394
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/kk.json484
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ko.json1098
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ms.json364
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/nb.json1500
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/nl.json466
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/pl.json1098
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json422
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json352
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ru.json704
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/server.json1947
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/sv.json334
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/tr.json1098
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/vi.json362
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json352
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj73
-rw-r--r--MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs14
-rw-r--r--MediaBrowser.Server.Implementations/Notifications/NotificationConfigurationFactory.cs21
-rw-r--r--MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs25
-rw-r--r--MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs66
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs22
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs71
-rw-r--r--MediaBrowser.Server.Implementations/Playlists/PlaylistImageEnhancer.cs292
-rw-r--r--MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs234
-rw-r--r--MediaBrowser.Server.Implementations/Security/AuthenticationException.cs16
-rw-r--r--MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs348
-rw-r--r--MediaBrowser.Server.Implementations/Security/EncryptionManager.cs21
-rw-r--r--MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs75
-rw-r--r--MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs54
-rw-r--r--MediaBrowser.Server.Implementations/Session/HttpSessionController.cs6
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionManager.cs239
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs19
-rw-r--r--MediaBrowser.Server.Implementations/Session/WebSocketController.cs51
-rw-r--r--MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs33
-rw-r--r--MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs26
-rw-r--r--MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs35
-rw-r--r--MediaBrowser.Server.Implementations/Sync/MockSyncProvider.cs33
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncManager.cs237
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncRepository.cs471
-rw-r--r--MediaBrowser.Server.Implementations/Udp/UdpServer.cs119
-rw-r--r--MediaBrowser.Server.Implementations/WebSocket/AlchemyServer.cs165
-rw-r--r--MediaBrowser.Server.Implementations/WebSocket/AlchemyWebSocket.cs134
-rw-r--r--MediaBrowser.Server.Implementations/packages.config3
-rw-r--r--MediaBrowser.Server.Mono/Imazen.WebP.config5
-rw-r--r--MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj23
-rw-r--r--MediaBrowser.Server.Mono/Native/NativeApp.cs18
-rw-r--r--MediaBrowser.Server.Mono/Native/ServerAuthorization.cs2
-rw-r--r--MediaBrowser.Server.Mono/Networking/NetworkManager.cs6
-rw-r--r--MediaBrowser.Server.Mono/Program.cs4
-rw-r--r--MediaBrowser.ServerApplication/ApplicationHost.cs368
-rw-r--r--MediaBrowser.ServerApplication/EntryPoints/WanAddressEntryPoint.cs55
-rw-r--r--MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs49
-rw-r--r--MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs19
-rw-r--r--MediaBrowser.ServerApplication/MainStartup.cs23
-rw-r--r--MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj17
-rw-r--r--MediaBrowser.ServerApplication/Native/BrowserLauncher.cs14
-rw-r--r--MediaBrowser.ServerApplication/Native/NativeApp.cs27
-rw-r--r--MediaBrowser.ServerApplication/Native/RegisterServer.bat6
-rw-r--r--MediaBrowser.ServerApplication/Native/ServerAuthorization.cs8
-rw-r--r--MediaBrowser.ServerApplication/Networking/NetworkManager.cs12
-rw-r--r--MediaBrowser.ServerApplication/ServerNotifyIcon.cs15
-rw-r--r--MediaBrowser.ServerApplication/packages.config4
-rw-r--r--MediaBrowser.Tests/MediaBrowser.Tests.csproj5
-rw-r--r--MediaBrowser.Tests/MediaEncoding/Subtitles/SsaParserTests.cs2
-rw-r--r--MediaBrowser.Tests/Providers/MovieDbProviderTests.cs6
-rw-r--r--MediaBrowser.Tests/Resolvers/MovieResolverTests.cs2
-rw-r--r--MediaBrowser.Tests/Resolvers/MusicResolverTests.cs30
-rw-r--r--MediaBrowser.Tests/Resolvers/TvUtilTests.cs17
-rw-r--r--MediaBrowser.WebDashboard/Api/DashboardService.cs54
-rw-r--r--MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj534
-rw-r--r--MediaBrowser.XbmcMetadata/Configuration/NfoOptions.cs29
-rw-r--r--MediaBrowser.XbmcMetadata/EntryPoint.cs110
-rw-r--r--MediaBrowser.XbmcMetadata/Images/XbmcImageSaver.cs (renamed from MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs)4
-rw-r--r--MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj92
-rw-r--r--MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs991
-rw-r--r--MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs211
-rw-r--r--MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs97
-rw-r--r--MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs45
-rw-r--r--MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs93
-rw-r--r--MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs34
-rw-r--r--MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs34
-rw-r--r--MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs34
-rw-r--r--MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs89
-rw-r--r--MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs55
-rw-r--r--MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs44
-rw-r--r--MediaBrowser.XbmcMetadata/Providers/MovieNfoProvider.cs45
-rw-r--r--MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs35
-rw-r--r--MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs34
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs101
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs94
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs1008
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs122
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs113
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs64
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs113
-rw-r--r--MediaBrowser.sln306
-rw-r--r--Nuget/MediaBrowser.Common.Internal.nuspec8
-rw-r--r--Nuget/MediaBrowser.Common.nuspec10
-rw-r--r--Nuget/MediaBrowser.Model.Signed.nuspec23
-rw-r--r--Nuget/MediaBrowser.Server.Core.nuspec4
-rw-r--r--OpenSubtitlesHandler/OpenSubtitlesHandler.csproj3
-rw-r--r--README.md8
678 files changed, 47382 insertions, 13438 deletions
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs
index 3e9a0926b..c51d9e7c0 100644
--- a/MediaBrowser.Api/ApiEntryPoint.cs
+++ b/MediaBrowser.Api/ApiEntryPoint.cs
@@ -37,11 +37,14 @@ namespace MediaBrowser.Api
private readonly ISessionManager _sessionManager;
+ public readonly SemaphoreSlim TranscodingStartLock = new SemaphoreSlim(1, 1);
+
/// <summary>
/// Initializes a new instance of the <see cref="ApiEntryPoint" /> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="appPaths">The application paths.</param>
+ /// <param name="sessionManager">The session manager.</param>
public ApiEntryPoint(ILogger logger, IServerApplicationPaths appPaths, ISessionManager sessionManager)
{
Logger = logger;
@@ -99,7 +102,7 @@ namespace MediaBrowser.Api
{
var jobCount = _activeTranscodingJobs.Count;
- Parallel.ForEach(_activeTranscodingJobs.ToList(), j => KillTranscodingJob(j, true));
+ Parallel.ForEach(_activeTranscodingJobs.ToList(), j => KillTranscodingJob(j, path => true));
// Try to allow for some time to kill the ffmpeg processes and delete the partial stream files
if (jobCount > 0)
@@ -119,14 +122,12 @@ namespace MediaBrowser.Api
/// <param name="path">The path.</param>
/// <param name="type">The type.</param>
/// <param name="process">The process.</param>
- /// <param name="startTimeTicks">The start time ticks.</param>
/// <param name="deviceId">The device id.</param>
/// <param name="state">The state.</param>
/// <param name="cancellationTokenSource">The cancellation token source.</param>
public void OnTranscodeBeginning(string path,
TranscodingJobType type,
Process process,
- long? startTimeTicks,
string deviceId,
StreamState state,
CancellationTokenSource cancellationTokenSource)
@@ -139,7 +140,6 @@ namespace MediaBrowser.Api
Path = path,
Process = process,
ActiveRequestCount = 1,
- StartTimeTicks = startTimeTicks,
DeviceId = deviceId,
CancellationTokenSource = cancellationTokenSource
});
@@ -215,9 +215,14 @@ namespace MediaBrowser.Api
/// <returns><c>true</c> if [has active transcoding job] [the specified path]; otherwise, <c>false</c>.</returns>
public bool HasActiveTranscodingJob(string path, TranscodingJobType type)
{
+ return GetTranscodingJob(path, type) != null;
+ }
+
+ public TranscodingJob GetTranscodingJob(string path, TranscodingJobType type)
+ {
lock (_activeTranscodingJobs)
{
- return _activeTranscodingJobs.Any(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));
+ return _activeTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase));
}
}
@@ -290,34 +295,70 @@ namespace MediaBrowser.Api
{
var job = (TranscodingJob)state;
- KillTranscodingJob(job, true);
+ KillTranscodingJob(job, path => true);
}
/// <summary>
/// Kills the single transcoding job.
/// </summary>
/// <param name="deviceId">The device id.</param>
- /// <param name="deleteFiles">if set to <c>true</c> [delete files].</param>
+ /// <param name="deleteFiles">The delete files.</param>
+ /// <param name="acquireLock">if set to <c>true</c> [acquire lock].</param>
+ /// <returns>Task.</returns>
+ /// <exception cref="ArgumentNullException">deviceId</exception>
/// <exception cref="System.ArgumentNullException">sourcePath</exception>
- internal void KillTranscodingJobs(string deviceId, bool deleteFiles)
+ internal Task KillTranscodingJobs(string deviceId, Func<string, bool> deleteFiles, bool acquireLock)
{
if (string.IsNullOrEmpty(deviceId))
{
throw new ArgumentNullException("deviceId");
}
+ return KillTranscodingJobs(j => string.Equals(deviceId, j.DeviceId, StringComparison.OrdinalIgnoreCase), deleteFiles, acquireLock);
+ }
+
+ /// <summary>
+ /// Kills the transcoding jobs.
+ /// </summary>
+ /// <param name="killJob">The kill job.</param>
+ /// <param name="deleteFiles">The delete files.</param>
+ /// <param name="acquireLock">if set to <c>true</c> [acquire lock].</param>
+ /// <returns>Task.</returns>
+ /// <exception cref="System.ArgumentNullException">deviceId</exception>
+ internal async Task KillTranscodingJobs(Func<TranscodingJob,bool> killJob, Func<string, bool> deleteFiles, bool acquireLock)
+ {
var jobs = new List<TranscodingJob>();
lock (_activeTranscodingJobs)
{
// This is really only needed for HLS.
// Progressive streams can stop on their own reliably
- jobs.AddRange(_activeTranscodingJobs.Where(i => string.Equals(deviceId, i.DeviceId, StringComparison.OrdinalIgnoreCase)));
+ jobs.AddRange(_activeTranscodingJobs.Where(killJob));
+ }
+
+ if (jobs.Count == 0)
+ {
+ return;
+ }
+
+ if (acquireLock)
+ {
+ await TranscodingStartLock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
}
- foreach (var job in jobs)
+ try
+ {
+ foreach (var job in jobs)
+ {
+ KillTranscodingJob(job, deleteFiles);
+ }
+ }
+ finally
{
- KillTranscodingJob(job, deleteFiles);
+ if (acquireLock)
+ {
+ TranscodingStartLock.Release();
+ }
}
}
@@ -325,8 +366,8 @@ namespace MediaBrowser.Api
/// Kills the transcoding job.
/// </summary>
/// <param name="job">The job.</param>
- /// <param name="deleteFiles">if set to <c>true</c> [delete files].</param>
- private void KillTranscodingJob(TranscodingJob job, bool deleteFiles)
+ /// <param name="delete">The delete.</param>
+ private void KillTranscodingJob(TranscodingJob job, Func<string, bool> delete)
{
lock (_activeTranscodingJobs)
{
@@ -378,7 +419,7 @@ namespace MediaBrowser.Api
}
}
- if (deleteFiles)
+ if (delete(job.Path))
{
DeletePartialStreamFiles(job.Path, job.Type, 0, 1500);
}
@@ -386,7 +427,7 @@ namespace MediaBrowser.Api
private async void DeletePartialStreamFiles(string path, TranscodingJobType jobType, int retryCount, int delayMs)
{
- if (retryCount >= 8)
+ if (retryCount >= 10)
{
return;
}
@@ -440,6 +481,8 @@ namespace MediaBrowser.Api
.Where(f => f.IndexOf(name, StringComparison.OrdinalIgnoreCase) != -1)
.ToList();
+ Exception e = null;
+
foreach (var file in filesToDelete)
{
try
@@ -449,9 +492,15 @@ namespace MediaBrowser.Api
}
catch (IOException ex)
{
+ e = ex;
Logger.ErrorException("Error deleting HLS file {0}", ex, file);
}
}
+
+ if (e != null)
+ {
+ throw e;
+ }
}
}
@@ -486,12 +535,13 @@ namespace MediaBrowser.Api
/// <value>The kill timer.</value>
public Timer KillTimer { get; set; }
- public long? StartTimeTicks { get; set; }
public string DeviceId { get; set; }
public CancellationTokenSource CancellationTokenSource { get; set; }
public object ProcessLock = new object();
+
+ public bool HasExited { get; set; }
}
/// <summary>
diff --git a/MediaBrowser.Api/AppThemeService.cs b/MediaBrowser.Api/AppThemeService.cs
index 4d8eed7dd..87084e415 100644
--- a/MediaBrowser.Api/AppThemeService.cs
+++ b/MediaBrowser.Api/AppThemeService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Themes;
using MediaBrowser.Model.Themes;
using ServiceStack;
@@ -47,6 +48,7 @@ namespace MediaBrowser.Api
{
}
+ [Authenticated]
public class AppThemeService : BaseApiService
{
private readonly IAppThemeManager _themeManager;
@@ -92,7 +94,7 @@ namespace MediaBrowser.Api
var contentType = MimeTypes.GetMimeType(info.Path);
- return ToCachedResult(cacheGuid, info.DateModified, cacheDuration, () => _fileSystem.GetFileStream(info.Path, FileMode.Open, FileAccess.Read, FileShare.Read), contentType);
+ return ResultFactory.GetCachedResult(Request, cacheGuid, null, cacheDuration, () => _fileSystem.GetFileStream(info.Path, FileMode.Open, FileAccess.Read, FileShare.Read), contentType);
}
}
}
diff --git a/MediaBrowser.Api/AuthorizationRequestFilterAttribute.cs b/MediaBrowser.Api/AuthorizationRequestFilterAttribute.cs
deleted file mode 100644
index 6c56083cb..000000000
--- a/MediaBrowser.Api/AuthorizationRequestFilterAttribute.cs
+++ /dev/null
@@ -1,190 +0,0 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Logging;
-using ServiceStack.Web;
-using System;
-using System.Collections.Generic;
-
-namespace MediaBrowser.Api
-{
- public class AuthorizationRequestFilterAttribute : Attribute, IHasRequestFilter
- {
- //This property will be resolved by the IoC container
- /// <summary>
- /// Gets or sets the user manager.
- /// </summary>
- /// <value>The user manager.</value>
- public IUserManager UserManager { get; set; }
-
- public ISessionManager SessionManager { get; set; }
-
- /// <summary>
- /// Gets or sets the logger.
- /// </summary>
- /// <value>The logger.</value>
- public ILogger Logger { get; set; }
-
- /// <summary>
- /// The request filter is executed before the service.
- /// </summary>
- /// <param name="request">The http request wrapper</param>
- /// <param name="response">The http response wrapper</param>
- /// <param name="requestDto">The request DTO</param>
- public void RequestFilter(IRequest request, IResponse response, object requestDto)
- {
- //This code is executed before the service
- var auth = GetAuthorizationDictionary(request);
-
- if (auth != null)
- {
- User user = null;
-
- if (auth.ContainsKey("UserId"))
- {
- var userId = auth["UserId"];
-
- if (!string.IsNullOrEmpty(userId))
- {
- user = UserManager.GetUserById(new Guid(userId));
- }
- }
-
- string deviceId;
- string device;
- string client;
- string version;
-
- auth.TryGetValue("DeviceId", out deviceId);
- auth.TryGetValue("Device", out device);
- auth.TryGetValue("Client", out client);
- auth.TryGetValue("Version", out version);
-
- if (!string.IsNullOrEmpty(client) && !string.IsNullOrEmpty(deviceId) && !string.IsNullOrEmpty(device) && !string.IsNullOrEmpty(version))
- {
- var remoteEndPoint = request.RemoteIp;
-
- SessionManager.LogSessionActivity(client, version, deviceId, device, remoteEndPoint, user);
- }
- }
- }
-
- /// <summary>
- /// Gets the auth.
- /// </summary>
- /// <param name="httpReq">The HTTP req.</param>
- /// <returns>Dictionary{System.StringSystem.String}.</returns>
- private static Dictionary<string, string> GetAuthorizationDictionary(IRequest httpReq)
- {
- var auth = httpReq.Headers["Authorization"];
-
- return GetAuthorization(auth);
- }
-
- public static User GetCurrentUser(IRequest httpReq, IUserManager userManager)
- {
- var info = GetAuthorization(httpReq);
-
- return string.IsNullOrEmpty(info.UserId) ? null :
- userManager.GetUserById(new Guid(info.UserId));
- }
-
- /// <summary>
- /// Gets the authorization.
- /// </summary>
- /// <param name="httpReq">The HTTP req.</param>
- /// <returns>Dictionary{System.StringSystem.String}.</returns>
- public static AuthorizationInfo GetAuthorization(IRequest httpReq)
- {
- var auth = GetAuthorizationDictionary(httpReq);
-
- string userId = null;
- string deviceId = null;
- string device = null;
- string client = null;
- string version = null;
-
- if (auth != null)
- {
- auth.TryGetValue("UserId", out userId);
- auth.TryGetValue("DeviceId", out deviceId);
- auth.TryGetValue("Device", out device);
- auth.TryGetValue("Client", out client);
- auth.TryGetValue("Version", out version);
- }
-
- return new AuthorizationInfo
- {
- Client = client,
- Device = device,
- DeviceId = deviceId,
- UserId = userId,
- Version = version
- };
- }
-
- /// <summary>
- /// Gets the authorization.
- /// </summary>
- /// <param name="authorizationHeader">The authorization header.</param>
- /// <returns>Dictionary{System.StringSystem.String}.</returns>
- private static Dictionary<string, string> GetAuthorization(string authorizationHeader)
- {
- if (authorizationHeader == null) return null;
-
- var parts = authorizationHeader.Split(' ');
-
- // There should be at least to parts
- if (parts.Length < 2) return null;
-
- // It has to be a digest request
- if (!string.Equals(parts[0], "MediaBrowser", StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
-
- // Remove uptil the first space
- authorizationHeader = authorizationHeader.Substring(authorizationHeader.IndexOf(' '));
- parts = authorizationHeader.Split(',');
-
- var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-
- foreach (var item in parts)
- {
- var param = item.Trim().Split(new[] { '=' }, 2);
- result.Add(param[0], param[1].Trim(new[] { '"' }));
- }
-
- return result;
- }
-
- /// <summary>
- /// A new shallow copy of this filter is used on every request.
- /// </summary>
- /// <returns>IHasRequestFilter.</returns>
- public IHasRequestFilter Copy()
- {
- return this;
- }
-
- /// <summary>
- /// Order in which Request Filters are executed.
- /// &lt;0 Executed before global request filters
- /// &gt;0 Executed after global request filters
- /// </summary>
- /// <value>The priority.</value>
- public int Priority
- {
- get { return 0; }
- }
- }
-
- public class AuthorizationInfo
- {
- public string UserId;
- public string DeviceId;
- public string Device;
- public string Client;
- public string Version;
- }
-}
diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index ca5b8b63a..1af7054d9 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -14,8 +14,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class BaseApiService
/// </summary>
- [AuthorizationRequestFilter]
- public class BaseApiService : IHasResultFactory, IRestfulService
+ public class BaseApiService : IHasResultFactory, IRestfulService, IHasSession
{
/// <summary>
/// Gets or sets the logger.
@@ -35,6 +34,8 @@ namespace MediaBrowser.Api
/// <value>The request context.</value>
public IRequest Request { get; set; }
+ public ISessionContext SessionContext { get; set; }
+
public string GetHeader(string name)
{
return Request.Headers[name];
@@ -82,33 +83,18 @@ namespace MediaBrowser.Api
/// <summary>
/// Gets the session.
/// </summary>
- /// <param name="sessionManager">The session manager.</param>
/// <returns>SessionInfo.</returns>
- protected SessionInfo GetSession(ISessionManager sessionManager)
+ /// <exception cref="System.ArgumentException">Session not found.</exception>
+ protected SessionInfo GetSession()
{
- var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
+ var session = SessionContext.GetSession(Request);
- return sessionManager.Sessions.First(i => string.Equals(i.DeviceId, auth.DeviceId) &&
- string.Equals(i.Client, auth.Client) &&
- string.Equals(i.ApplicationVersion, auth.Version));
- }
+ if (session == null)
+ {
+ throw new ArgumentException("Session not found.");
+ }
- /// <summary>
- /// To the cached result.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="cacheKey">The cache key.</param>
- /// <param name="lastDateModified">The last date modified.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- /// <param name="factoryFn">The factory fn.</param>
- /// <param name="contentType">Type of the content.</param>
- /// <param name="responseHeaders">The response headers.</param>
- /// <returns>System.Object.</returns>
- /// <exception cref="System.ArgumentNullException">cacheKey</exception>
- protected object ToCachedResult<T>(Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, string contentType, IDictionary<string,string> responseHeaders = null)
- where T : class
- {
- return ResultFactory.GetCachedResult(Request, cacheKey, lastDateModified, cacheDuration, factoryFn, contentType, responseHeaders);
+ return session;
}
/// <summary>
@@ -121,7 +107,7 @@ namespace MediaBrowser.Api
return ResultFactory.GetStaticFileResult(Request, path);
}
- private readonly char[] _dashReplaceChars = new[] { '?', '/' };
+ private readonly char[] _dashReplaceChars = { '?', '/' };
private const char SlugChar = '-';
protected MusicArtist GetArtist(string name, ILibraryManager libraryManager)
@@ -154,7 +140,7 @@ namespace MediaBrowser.Api
return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager));
}
- protected IList<BaseItem> GetAllLibraryItems(Guid? userId, IUserManager userManager, ILibraryManager libraryManager, string parentId = null)
+ protected IEnumerable<BaseItem> GetAllLibraryItems(Guid? userId, IUserManager userManager, ILibraryManager libraryManager, string parentId = null)
{
if (!string.IsNullOrEmpty(parentId))
{
@@ -164,7 +150,12 @@ namespace MediaBrowser.Api
{
var user = userManager.GetUserById(userId.Value);
- return folder.GetRecursiveChildren(user).ToList();
+ if (user == null)
+ {
+ throw new ArgumentException("User not found");
+ }
+
+ return folder.GetRecursiveChildren(user);
}
return folder.GetRecursiveChildren();
@@ -173,7 +164,12 @@ namespace MediaBrowser.Api
{
var user = userManager.GetUserById(userId.Value);
- return userManager.GetUserById(userId.Value).RootFolder.GetRecursiveChildren(user, null);
+ if (user == null)
+ {
+ throw new ArgumentException("User not found");
+ }
+
+ return userManager.GetUserById(userId.Value).RootFolder.GetRecursiveChildren(user);
}
return libraryManager.RootFolder.GetRecursiveChildren();
@@ -234,7 +230,8 @@ namespace MediaBrowser.Api
return name;
}
- return libraryManager.RootFolder.GetRecursiveChildren(i => i is Game)
+ return libraryManager.RootFolder.GetRecursiveChildren()
+ .OfType<Game>()
.SelectMany(i => i.Genres)
.Distinct(StringComparer.OrdinalIgnoreCase)
.FirstOrDefault(i =>
diff --git a/MediaBrowser.Api/BrandingService.cs b/MediaBrowser.Api/BrandingService.cs
new file mode 100644
index 000000000..4b49b411a
--- /dev/null
+++ b/MediaBrowser.Api/BrandingService.cs
@@ -0,0 +1,28 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Branding;
+using ServiceStack;
+
+namespace MediaBrowser.Api
+{
+ [Route("/Branding/Configuration", "GET", Summary = "Gets branding configuration")]
+ public class GetBrandingOptions : IReturn<BrandingOptions>
+ {
+ }
+
+ public class BrandingService : BaseApiService
+ {
+ private readonly IConfigurationManager _config;
+
+ public BrandingService(IConfigurationManager config)
+ {
+ _config = config;
+ }
+
+ public object Get(GetBrandingOptions request)
+ {
+ var result = _config.GetConfiguration<BrandingOptions>("branding");
+
+ return ToOptimizedResult(result);
+ }
+ }
+}
diff --git a/MediaBrowser.Api/ChannelService.cs b/MediaBrowser.Api/ChannelService.cs
index d71db929f..2dfa0918d 100644
--- a/MediaBrowser.Api/ChannelService.cs
+++ b/MediaBrowser.Api/ChannelService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@@ -8,6 +9,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
+using System.Threading.Tasks;
namespace MediaBrowser.Api
{
@@ -172,7 +174,8 @@ namespace MediaBrowser.Api
[ApiMember(Name = "UserId", Description = "Optional attach user data.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string UserId { get; set; }
}
-
+
+ [Authenticated]
public class ChannelService : BaseApiService
{
private readonly IChannelManager _channelManager;
@@ -196,14 +199,14 @@ namespace MediaBrowser.Api
return ToOptimizedResult(result);
}
- public object Get(GetChannelFolder request)
+ public async Task<object> Get(GetChannelFolder request)
{
- return ToOptimizedResult(_channelManager.GetChannelFolder(request.UserId, CancellationToken.None).Result);
+ return ToOptimizedResult(await _channelManager.GetChannelFolder(request.UserId, CancellationToken.None).ConfigureAwait(false));
}
-
- public object Get(GetChannels request)
+
+ public async Task<object> Get(GetChannels request)
{
- var result = _channelManager.GetChannels(new ChannelQuery
+ var result = await _channelManager.GetChannels(new ChannelQuery
{
Limit = request.Limit,
StartIndex = request.StartIndex,
@@ -211,14 +214,14 @@ namespace MediaBrowser.Api
SupportsLatestItems = request.SupportsLatestItems,
IsFavorite = request.IsFavorite
- }, CancellationToken.None).Result;
+ }, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedResult(result);
}
- public object Get(GetChannelItems request)
+ public async Task<object> Get(GetChannelItems request)
{
- var result = _channelManager.GetChannelItems(new ChannelItemQuery
+ var result = await _channelManager.GetChannelItems(new ChannelItemQuery
{
Limit = request.Limit,
StartIndex = request.StartIndex,
@@ -228,16 +231,16 @@ namespace MediaBrowser.Api
SortOrder = request.SortOrder,
SortBy = (request.SortBy ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToArray(),
Filters = request.GetFilters().ToArray(),
- Fields = request.GetItemFields().ToList()
+ Fields = request.GetItemFields().ToArray()
- }, CancellationToken.None).Result;
+ }, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedResult(result);
}
- public object Get(GetLatestChannelItems request)
+ public async Task<object> Get(GetLatestChannelItems request)
{
- var result = _channelManager.GetLatestChannelItems(new AllChannelMediaQuery
+ var result = await _channelManager.GetLatestChannelItems(new AllChannelMediaQuery
{
Limit = request.Limit,
StartIndex = request.StartIndex,
@@ -246,7 +249,7 @@ namespace MediaBrowser.Api
Filters = request.GetFilters().ToArray(),
Fields = request.GetItemFields().ToList()
- }, CancellationToken.None).Result;
+ }, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedResult(result);
}
diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs
index b3191cd4b..7b6e5ed19 100644
--- a/MediaBrowser.Api/ConfigurationService.cs
+++ b/MediaBrowser.Api/ConfigurationService.cs
@@ -1,15 +1,17 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Serialization;
using ServiceStack;
+using ServiceStack.Text.Controller;
+using ServiceStack.Web;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
namespace MediaBrowser.Api
@@ -18,35 +20,58 @@ namespace MediaBrowser.Api
/// Class GetConfiguration
/// </summary>
[Route("/System/Configuration", "GET", Summary = "Gets application configuration")]
+ [Authenticated]
public class GetConfiguration : IReturn<ServerConfiguration>
{
}
+ [Route("/System/Configuration/{Key}", "GET", Summary = "Gets a named configuration")]
+ [Authenticated]
+ public class GetNamedConfiguration
+ {
+ [ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Key { get; set; }
+ }
+
/// <summary>
/// Class UpdateConfiguration
/// </summary>
[Route("/System/Configuration", "POST", Summary = "Updates application configuration")]
+ [Authenticated]
public class UpdateConfiguration : ServerConfiguration, IReturnVoid
{
}
+ [Route("/System/Configuration/{Key}", "POST", Summary = "Updates named configuration")]
+ [Authenticated]
+ public class UpdateNamedConfiguration : IReturnVoid, IRequiresRequestStream
+ {
+ [ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Key { get; set; }
+
+ public Stream RequestStream { get; set; }
+ }
+
[Route("/System/Configuration/MetadataOptions/Default", "GET", Summary = "Gets a default MetadataOptions object")]
+ [Authenticated]
public class GetDefaultMetadataOptions : IReturn<MetadataOptions>
{
}
[Route("/System/Configuration/MetadataPlugins", "GET", Summary = "Gets all available metadata plugins")]
+ [Authenticated]
public class GetMetadataPlugins : IReturn<List<MetadataPluginSummary>>
{
}
- [Route("/System/Configuration/VideoImageExtraction", "POST", Summary = "Updates image extraction for all types")]
- public class UpdateVideoImageExtraction : IReturnVoid
+ [Route("/System/Configuration/MetadataPlugins/Autoset", "POST")]
+ [Authenticated]
+ public class AutoSetMetadataOptions : IReturnVoid
{
- public bool Enabled { get; set; }
+
}
public class ConfigurationService : BaseApiService
@@ -63,13 +88,15 @@ namespace MediaBrowser.Api
private readonly IFileSystem _fileSystem;
private readonly IProviderManager _providerManager;
+ private readonly ILibraryManager _libraryManager;
- public ConfigurationService(IJsonSerializer jsonSerializer, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IProviderManager providerManager)
+ public ConfigurationService(IJsonSerializer jsonSerializer, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IProviderManager providerManager, ILibraryManager libraryManager)
{
_jsonSerializer = jsonSerializer;
_configurationManager = configurationManager;
_fileSystem = fileSystem;
_providerManager = providerManager;
+ _libraryManager = libraryManager;
}
/// <summary>
@@ -88,95 +115,93 @@ namespace MediaBrowser.Api
return ToOptimizedResultUsingCache(cacheKey, dateModified, null, () => _configurationManager.Configuration);
}
- /// <summary>
- /// Posts the specified configuraiton.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(UpdateConfiguration request)
+ public object Get(GetNamedConfiguration request)
{
- // Silly, but we need to serialize and deserialize or the XmlSerializer will write the xml with an element name of UpdateConfiguration
+ var result = _configurationManager.GetConfiguration(request.Key);
- var json = _jsonSerializer.SerializeToString(request);
-
- var config = _jsonSerializer.DeserializeFromString<ServerConfiguration>(json);
-
- _configurationManager.ReplaceConfiguration(config);
+ return ToOptimizedResult(result);
}
- public object Get(GetDefaultMetadataOptions request)
- {
- return ToOptimizedSerializedResultUsingCache(new MetadataOptions());
- }
+ const string XbmcMetadata = "Xbmc Nfo";
+ const string MediaBrowserMetadata = "Media Browser Xml";
- public object Get(GetMetadataPlugins request)
+ public void Post(AutoSetMetadataOptions request)
{
- return ToOptimizedSerializedResultUsingCache(_providerManager.GetAllMetadataPlugins().ToList());
- }
+ var service = AutoDetectMetadataService();
- /// <summary>
- /// This is a temporary method used until image settings get broken out.
- /// </summary>
- /// <param name="request"></param>
- public void Post(UpdateVideoImageExtraction request)
- {
- var config = _configurationManager.Configuration;
+ Logger.Info("Setting preferred metadata format to " + service);
- EnableImageExtractionForType(typeof(Movie), config, request.Enabled);
- EnableImageExtractionForType(typeof(Episode), config, request.Enabled);
- EnableImageExtractionForType(typeof(AdultVideo), config, request.Enabled);
- EnableImageExtractionForType(typeof(MusicVideo), config, request.Enabled);
- EnableImageExtractionForType(typeof(Video), config, request.Enabled);
- EnableImageExtractionForType(typeof(Trailer), config, request.Enabled);
+ var serviceToDisable = string.Equals(service, XbmcMetadata) ?
+ MediaBrowserMetadata :
+ XbmcMetadata;
+ _configurationManager.DisableMetadataService(serviceToDisable);
_configurationManager.SaveConfiguration();
}
- private void EnableImageExtractionForType(Type type, ServerConfiguration config, bool enabled)
+ private string AutoDetectMetadataService()
{
- var options = GetMetadataOptions(type, config);
-
- const string imageProviderName = "Screen Grabber";
-
- var contains = options.DisabledImageFetchers.Contains(imageProviderName, StringComparer.OrdinalIgnoreCase);
-
- if (!enabled && !contains)
+ try
{
- var list = options.DisabledImageFetchers.ToList();
-
- list.Add(imageProviderName);
+ var paths = _libraryManager.GetDefaultVirtualFolders()
+ .SelectMany(i => i.Locations)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .Select(i => new DirectoryInfo(i))
+ .ToList();
+
+ if (paths.SelectMany(i => i.EnumerateFiles("*.xml", SearchOption.AllDirectories))
+ .Any())
+ {
+ return XbmcMetadata;
+ }
- options.DisabledImageFetchers = list.ToArray();
+ if (paths.SelectMany(i => i.EnumerateFiles("*.xml", SearchOption.AllDirectories))
+ .Any(i => string.Equals(i.Name, "series.xml", StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, "movie.xml", StringComparison.OrdinalIgnoreCase)))
+ {
+ return MediaBrowserMetadata;
+ }
}
- else if (enabled && contains)
+ catch (Exception)
{
- var list = options.DisabledImageFetchers.ToList();
-
- list.Remove(imageProviderName);
-
- options.DisabledImageFetchers = list.ToArray();
+
}
+
+ return XbmcMetadata;
}
- private MetadataOptions GetMetadataOptions(Type type, ServerConfiguration config)
+ /// <summary>
+ /// Posts the specified configuraiton.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ public void Post(UpdateConfiguration request)
{
- var options = config.MetadataOptions
- .FirstOrDefault(i => string.Equals(i.ItemType, type.Name, StringComparison.OrdinalIgnoreCase));
+ // Silly, but we need to serialize and deserialize or the XmlSerializer will write the xml with an element name of UpdateConfiguration
+ var json = _jsonSerializer.SerializeToString(request);
- if (options == null)
- {
- var list = config.MetadataOptions.ToList();
+ var config = _jsonSerializer.DeserializeFromString<ServerConfiguration>(json);
- options = new MetadataOptions
- {
- ItemType = type.Name
- };
+ _configurationManager.ReplaceConfiguration(config);
+ }
- list.Add(options);
+ public void Post(UpdateNamedConfiguration request)
+ {
+ var pathInfo = PathInfo.Parse(Request.PathInfo);
+ var key = pathInfo.GetArgumentValue<string>(2);
- config.MetadataOptions = list.ToArray();
- }
+ var configurationType = _configurationManager.GetConfigurationType(key);
+ var configuration = _jsonSerializer.DeserializeFromStream(request.RequestStream, configurationType);
+
+ _configurationManager.SaveConfiguration(key, configuration);
+ }
+
+ public object Get(GetDefaultMetadataOptions request)
+ {
+ return ToOptimizedSerializedResultUsingCache(new MetadataOptions());
+ }
- return options;
+ public object Get(GetMetadataPlugins request)
+ {
+ return ToOptimizedSerializedResultUsingCache(_providerManager.GetAllMetadataPlugins().ToList());
}
}
}
diff --git a/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs b/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs
deleted file mode 100644
index 6acecd342..000000000
--- a/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs
+++ /dev/null
@@ -1,671 +0,0 @@
-using MediaBrowser.Controller.Drawing;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Querying;
-using ServiceStack;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace MediaBrowser.Api.DefaultTheme
-{
- [Route("/MBT/DefaultTheme/Games", "GET")]
- public class GetGamesView : IReturn<GamesView>
- {
- [ApiMember(Name = "UserId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "RecentlyPlayedGamesLimit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int RecentlyPlayedGamesLimit { get; set; }
-
- public string ParentId { get; set; }
- }
-
- [Route("/MBT/DefaultTheme/TV", "GET")]
- public class GetTvView : IReturn<TvView>
- {
- [ApiMember(Name = "UserId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "ComedyGenre", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string ComedyGenre { get; set; }
-
- [ApiMember(Name = "RomanceGenre", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string RomanceGenre { get; set; }
-
- [ApiMember(Name = "TopCommunityRating", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public double TopCommunityRating { get; set; }
-
- [ApiMember(Name = "NextUpEpisodeLimit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int NextUpEpisodeLimit { get; set; }
-
- [ApiMember(Name = "ResumableEpisodeLimit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int ResumableEpisodeLimit { get; set; }
-
- [ApiMember(Name = "LatestEpisodeLimit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int LatestEpisodeLimit { get; set; }
-
- public string ParentId { get; set; }
- }
-
- [Route("/MBT/DefaultTheme/Movies", "GET")]
- public class GetMovieView : IReturn<MoviesView>
- {
- [ApiMember(Name = "UserId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "FamilyGenre", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string FamilyGenre { get; set; }
-
- [ApiMember(Name = "ComedyGenre", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string ComedyGenre { get; set; }
-
- [ApiMember(Name = "RomanceGenre", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string RomanceGenre { get; set; }
-
- [ApiMember(Name = "LatestMoviesLimit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int LatestMoviesLimit { get; set; }
-
- [ApiMember(Name = "LatestTrailersLimit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int LatestTrailersLimit { get; set; }
-
- public string ParentId { get; set; }
- }
-
- [Route("/MBT/DefaultTheme/Favorites", "GET")]
- public class GetFavoritesView : IReturn<FavoritesView>
- {
- [ApiMember(Name = "UserId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
- }
-
- public class DefaultThemeService : BaseApiService
- {
- private readonly IUserManager _userManager;
- private readonly IDtoService _dtoService;
- private readonly ILogger _logger;
- private readonly ILibraryManager _libraryManager;
- private readonly IUserDataManager _userDataManager;
-
- private readonly IImageProcessor _imageProcessor;
- private readonly IItemRepository _itemRepo;
-
- public DefaultThemeService(IUserManager userManager, IDtoService dtoService, ILogger logger, ILibraryManager libraryManager, IImageProcessor imageProcessor, IUserDataManager userDataManager, IItemRepository itemRepo)
- {
- _userManager = userManager;
- _dtoService = dtoService;
- _logger = logger;
- _libraryManager = libraryManager;
- _imageProcessor = imageProcessor;
- _userDataManager = userDataManager;
- _itemRepo = itemRepo;
- }
-
- public object Get(GetFavoritesView request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var allItems = user.RootFolder.GetRecursiveChildren(user)
- .ToList();
-
- var allFavoriteItems = allItems.Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite)
- .ToList();
-
- var itemsWithImages = allFavoriteItems.Where(i => !string.IsNullOrEmpty(i.PrimaryImagePath))
- .ToList();
-
- var itemsWithBackdrops = allFavoriteItems.Where(i => i.GetImages(ImageType.Backdrop).Any())
- .ToList();
-
- var view = new FavoritesView();
-
- var fields = new List<ItemFields>();
-
- view.BackdropItems = FilterItemsForBackdropDisplay(itemsWithBackdrops)
- .Randomize("backdrop")
- .Take(10)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- var spotlightItems = itemsWithBackdrops.Randomize("spotlight")
- .Take(10)
- .ToList();
-
- view.SpotlightItems = spotlightItems
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- fields.Add(ItemFields.PrimaryImageAspectRatio);
-
- view.Albums = itemsWithImages
- .OfType<MusicAlbum>()
- .Randomize()
- .Take(4)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.Books = itemsWithImages
- .OfType<Book>()
- .Randomize()
- .Take(6)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.Episodes = itemsWithImages
- .OfType<Episode>()
- .Randomize()
- .Take(6)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.Games = itemsWithImages
- .OfType<Game>()
- .Randomize()
- .Take(6)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.Movies = itemsWithImages
- .OfType<Movie>()
- .Randomize()
- .Take(6)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.Series = itemsWithImages
- .OfType<Series>()
- .Randomize()
- .Take(6)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.Songs = itemsWithImages
- .OfType<Audio>()
- .Randomize()
- .Take(4)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.MiniSpotlights = itemsWithBackdrops
- .Except(spotlightItems)
- .Randomize()
- .Take(5)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- var artists = allItems.OfType<Audio>()
- .SelectMany(i => i.AllArtists)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .Randomize()
- .Select(i =>
- {
- try
- {
- return _libraryManager.GetArtist(i);
- }
- catch
- {
- return null;
- }
- })
- .Where(i => i != null && _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite)
- .Take(4)
- .ToList();
-
- view.Artists = artists
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- return ToOptimizedSerializedResultUsingCache(view);
- }
-
- public object Get(GetGamesView request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var items = GetAllLibraryItems(user.Id, _userManager, _libraryManager, request.ParentId).Where(i => i is Game || i is GameSystem)
- .ToList();
-
- var gamesWithImages = items.OfType<Game>().Where(i => !string.IsNullOrEmpty(i.PrimaryImagePath)).ToList();
-
- var itemsWithBackdrops = FilterItemsForBackdropDisplay(items.Where(i => i.GetImages(ImageType.Backdrop).Any())).ToList();
-
- var gamesWithBackdrops = itemsWithBackdrops.OfType<Game>().ToList();
-
- var view = new GamesView();
-
- var fields = new List<ItemFields>();
-
- view.GameSystems = items
- .OfType<GameSystem>()
- .OrderBy(i => i.SortName)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- var currentUserId = user.Id;
- view.RecentlyPlayedGames = gamesWithImages
- .OrderByDescending(i => _userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).LastPlayedDate ?? DateTime.MinValue)
- .Take(request.RecentlyPlayedGamesLimit)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.BackdropItems = gamesWithBackdrops
- .OrderBy(i => Guid.NewGuid())
- .Take(10)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.SpotlightItems = gamesWithBackdrops
- .OrderBy(i => Guid.NewGuid())
- .Take(10)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.MultiPlayerItems = gamesWithImages
- .Where(i => i.PlayersSupported.HasValue && i.PlayersSupported.Value > 1)
- .Randomize()
- .Select(i => GetItemStub(i, ImageType.Primary))
- .Where(i => i != null)
- .Take(1)
- .ToList();
-
- return ToOptimizedSerializedResultUsingCache(view);
- }
-
- public object Get(GetTvView request)
- {
- var romanceGenres = request.RomanceGenre.Split(',').ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
- var comedyGenres = request.ComedyGenre.Split(',').ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
-
- var user = _userManager.GetUserById(request.UserId);
-
- var series = GetAllLibraryItems(user.Id, _userManager, _libraryManager, request.ParentId)
- .OfType<Series>()
- .ToList();
-
- var seriesWithBackdrops = series.Where(i => i.GetImages(ImageType.Backdrop).Any()).ToList();
-
- var view = new TvView();
-
- var fields = new List<ItemFields>();
-
- var seriesWithBestBackdrops = FilterItemsForBackdropDisplay(seriesWithBackdrops).ToList();
-
- view.BackdropItems = seriesWithBestBackdrops
- .OrderBy(i => Guid.NewGuid())
- .Take(10)
- .AsParallel()
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.ShowsItems = series
- .Where(i => i.GetImages(ImageType.Backdrop).Any())
- .Randomize("all")
- .Select(i => GetItemStub(i, ImageType.Backdrop))
- .Where(i => i != null)
- .Take(1)
- .ToList();
-
- view.RomanceItems = seriesWithBackdrops
- .Where(i => i.Genres.Any(romanceGenres.ContainsKey))
- .Randomize("romance")
- .Select(i => GetItemStub(i, ImageType.Backdrop))
- .Where(i => i != null)
- .Take(1)
- .ToList();
-
- view.ComedyItems = seriesWithBackdrops
- .Where(i => i.Genres.Any(comedyGenres.ContainsKey))
- .Randomize("comedy")
- .Select(i => GetItemStub(i, ImageType.Backdrop))
- .Where(i => i != null)
- .Take(1)
- .ToList();
-
- var spotlightSeries = seriesWithBestBackdrops
- .Where(i => i.CommunityRating.HasValue && i.CommunityRating >= 8.5)
- .ToList();
-
- if (spotlightSeries.Count < 20)
- {
- spotlightSeries = seriesWithBestBackdrops;
- }
-
- spotlightSeries = spotlightSeries
- .OrderBy(i => Guid.NewGuid())
- .Take(10)
- .ToList();
-
- view.SpotlightItems = spotlightSeries
- .AsParallel()
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- var miniSpotlightItems = seriesWithBackdrops
- .Except(spotlightSeries.OfType<Series>())
- .Where(i => i.CommunityRating.HasValue && i.CommunityRating >= 8)
- .ToList();
-
- if (miniSpotlightItems.Count < 15)
- {
- miniSpotlightItems = seriesWithBackdrops;
- }
-
- view.MiniSpotlights = miniSpotlightItems
- .Randomize("minispotlight")
- .Take(5)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- var nextUpEpisodes = new TvShowsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService)
- .GetNextUpEpisodes(new GetNextUpEpisodes { UserId = user.Id }, series)
- .ToList();
-
- fields.Add(ItemFields.PrimaryImageAspectRatio);
-
- view.NextUpEpisodes = nextUpEpisodes
- .Take(request.NextUpEpisodeLimit)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.SeriesIdsInProgress = nextUpEpisodes.Select(i => i.Series.Id.ToString("N")).ToList();
-
- // Avoid implicitly captured closure
- var currentUser1 = user;
-
- var ownedEpisodes = series
- .SelectMany(i => i.GetRecursiveChildren(currentUser1, j => j.LocationType != LocationType.Virtual))
- .OfType<Episode>()
- .ToList();
-
- // Avoid implicitly captured closure
- var currentUser = user;
-
- view.LatestEpisodes = ownedEpisodes
- .OrderByDescending(i => i.DateCreated)
- .Where(i => !_userDataManager.GetUserData(currentUser.Id, i.GetUserDataKey()).Played)
- .Take(request.LatestEpisodeLimit)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.ResumableEpisodes = ownedEpisodes
- .Where(i => _userDataManager.GetUserData(currentUser.Id, i.GetUserDataKey()).PlaybackPositionTicks > 0)
- .OrderByDescending(i => _userDataManager.GetUserData(currentUser.Id, i.GetUserDataKey()).LastPlayedDate ?? DateTime.MinValue)
- .Take(request.ResumableEpisodeLimit)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- return ToOptimizedSerializedResultUsingCache(view);
- }
-
- public object Get(GetMovieView request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var items = GetAllLibraryItems(user.Id, _userManager, _libraryManager, request.ParentId)
- .Where(i => i is Movie || i is Trailer || i is BoxSet)
- .ToList();
-
- var view = new MoviesView();
-
- var movies = items.OfType<Movie>()
- .ToList();
-
- var trailers = items.OfType<Trailer>()
- .ToList();
-
- var hdMovies = movies.Where(i => i.IsHD).ToList();
-
- var familyGenres = request.FamilyGenre.Split(',').ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
-
- var familyMovies = movies.Where(i => i.Genres.Any(familyGenres.ContainsKey)).ToList();
-
- view.HDMoviePercentage = 100 * hdMovies.Count;
- view.HDMoviePercentage /= movies.Count;
-
- view.FamilyMoviePercentage = 100 * familyMovies.Count;
- view.FamilyMoviePercentage /= movies.Count;
-
- var moviesWithBackdrops = movies
- .Where(i => i.GetImages(ImageType.Backdrop).Any())
- .ToList();
-
- var fields = new List<ItemFields>();
-
- var itemsWithTopBackdrops = FilterItemsForBackdropDisplay(moviesWithBackdrops).ToList();
-
- view.BackdropItems = itemsWithTopBackdrops
- .OrderBy(i => Guid.NewGuid())
- .Take(10)
- .AsParallel()
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.MovieItems = moviesWithBackdrops
- .Randomize("all")
- .Select(i => GetItemStub(i, ImageType.Backdrop))
- .Where(i => i != null)
- .Take(1)
- .ToList();
-
- view.TrailerItems = trailers
- .Where(i => !string.IsNullOrEmpty(i.PrimaryImagePath))
- .Randomize()
- .Select(i => GetItemStub(i, ImageType.Primary))
- .Where(i => i != null)
- .Take(1)
- .ToList();
-
- view.BoxSetItems = items
- .OfType<BoxSet>()
- .Where(i => i.GetImages(ImageType.Backdrop).Any())
- .Randomize()
- .Select(i => GetItemStub(i, ImageType.Backdrop))
- .Where(i => i != null)
- .Take(1)
- .ToList();
-
- view.ThreeDItems = moviesWithBackdrops
- .Where(i => i.Is3D)
- .Randomize("3d")
- .Select(i => GetItemStub(i, ImageType.Backdrop))
- .Where(i => i != null)
- .Take(1)
- .ToList();
-
- var romanceGenres = request.RomanceGenre.Split(',').ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
- var comedyGenres = request.ComedyGenre.Split(',').ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
-
- view.RomanceItems = moviesWithBackdrops
- .Where(i => i.Genres.Any(romanceGenres.ContainsKey))
- .Randomize("romance")
- .Select(i => GetItemStub(i, ImageType.Backdrop))
- .Where(i => i != null)
- .Take(1)
- .ToList();
-
- view.ComedyItems = moviesWithBackdrops
- .Where(i => i.Genres.Any(comedyGenres.ContainsKey))
- .Randomize("comedy")
- .Select(i => GetItemStub(i, ImageType.Backdrop))
- .Where(i => i != null)
- .Take(1)
- .ToList();
-
- view.HDItems = hdMovies
- .Where(i => i.GetImages(ImageType.Backdrop).Any())
- .Randomize("hd")
- .Select(i => GetItemStub(i, ImageType.Backdrop))
- .Where(i => i != null)
- .Take(1)
- .ToList();
-
- view.FamilyMovies = familyMovies
- .Where(i => i.GetImages(ImageType.Backdrop).Any())
- .Randomize("family")
- .Select(i => GetItemStub(i, ImageType.Backdrop))
- .Where(i => i != null)
- .Take(1)
- .ToList();
-
- var currentUserId = user.Id;
- var spotlightItems = itemsWithTopBackdrops
- .Where(i => i.CommunityRating.HasValue && i.CommunityRating >= 8)
- .Where(i => !_userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).Played)
- .ToList();
-
- if (spotlightItems.Count < 20)
- {
- spotlightItems = itemsWithTopBackdrops;
- }
-
- spotlightItems = spotlightItems
- .OrderBy(i => Guid.NewGuid())
- .Take(10)
- .ToList();
-
- view.SpotlightItems = spotlightItems
- .AsParallel()
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- var miniSpotlightItems = moviesWithBackdrops
- .Except(spotlightItems)
- .Where(i => i.CommunityRating.HasValue && i.CommunityRating >= 7.5)
- .ToList();
-
- if (miniSpotlightItems.Count < 15)
- {
- miniSpotlightItems = itemsWithTopBackdrops;
- }
-
- miniSpotlightItems = miniSpotlightItems
- .Randomize("minispotlight")
- .ToList();
-
- // Avoid implicitly captured closure
- miniSpotlightItems.InsertRange(0, moviesWithBackdrops
- .Where(i => _userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).PlaybackPositionTicks > 0)
- .OrderByDescending(i => _userDataManager.GetUserData(currentUserId, i.GetUserDataKey()).LastPlayedDate ?? DateTime.MaxValue)
- .Take(3));
-
- view.MiniSpotlights = miniSpotlightItems
- .Take(3)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- // Avoid implicitly captured closure
- var currentUserId1 = user.Id;
-
- view.LatestMovies = movies
- .OrderByDescending(i => i.DateCreated)
- .Where(i => !_userDataManager.GetUserData(currentUserId1, i.GetUserDataKey()).Played)
- .Take(request.LatestMoviesLimit)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- view.LatestTrailers = trailers
- .OrderByDescending(i => i.DateCreated)
- .Where(i => !_userDataManager.GetUserData(currentUserId1, i.GetUserDataKey()).Played)
- .Take(request.LatestTrailersLimit)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
- .ToList();
-
- return ToOptimizedSerializedResultUsingCache(view);
- }
-
- private IEnumerable<BaseItem> FilterItemsForBackdropDisplay(IEnumerable<BaseItem> items)
- {
- var tuples = items
- .Select(i => new Tuple<BaseItem, double>(i, GetResolution(i, ImageType.Backdrop, 0)))
- .Where(i => i.Item2 > 0)
- .ToList();
-
- var topItems = tuples
- .Where(i => i.Item2 >= 1920)
- .ToList();
-
- if (topItems.Count >= 10)
- {
- return topItems.Select(i => i.Item1);
- }
-
- return tuples.Select(i => i.Item1);
- }
-
- private double GetResolution(BaseItem item, ImageType type, int index)
- {
- try
- {
- var info = item.GetImageInfo(type, index);
-
- var size = _imageProcessor.GetImageSize(info.Path, info.DateModified);
-
- return size.Width;
- }
- catch
- {
- return 0;
- }
- }
-
- private ItemStub GetItemStub(BaseItem item, ImageType imageType)
- {
- var stub = new ItemStub
- {
- Id = _dtoService.GetDtoId(item),
- Name = item.Name,
- ImageType = imageType
- };
-
- try
- {
- var tag = _imageProcessor.GetImageCacheTag(item, imageType);
-
- if (tag != null)
- {
- stub.ImageTag = tag;
- }
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error getting image tag for {0}", ex, item.Path);
- return null;
- }
-
- return stub;
- }
- }
-
- static class RandomExtension
- {
- public static IEnumerable<T> Randomize<T>(this IEnumerable<T> sequence, string type = "none")
- where T : BaseItem
- {
- var hour = DateTime.Now.Hour + DateTime.Now.Day + 2;
-
- var typeCode = type.GetHashCode();
-
- return sequence.OrderBy(i =>
- {
- var val = i.Id.GetHashCode() + i.Genres.Count + i.People.Count + (i.ProductionYear ?? 0) + i.DateCreated.Minute + i.DateModified.Minute + typeCode;
-
- return val % hour;
- });
- }
-
- public static IEnumerable<string> Randomize(this IEnumerable<string> sequence)
- {
- var hour = DateTime.Now.Hour + 2;
-
- return sequence.OrderBy(i => i.GetHashCode() % hour);
- }
- }
-}
diff --git a/MediaBrowser.Api/DefaultTheme/Models.cs b/MediaBrowser.Api/DefaultTheme/Models.cs
deleted file mode 100644
index 6cc7af499..000000000
--- a/MediaBrowser.Api/DefaultTheme/Models.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using System;
-using System.Collections.Generic;
-
-namespace MediaBrowser.Api.DefaultTheme
-{
- public class ItemStub
- {
- public string Name { get; set; }
- public string Id { get; set; }
- public string ImageTag { get; set; }
- public ImageType ImageType { get; set; }
- }
-
- public class MoviesView : BaseView
- {
- public List<ItemStub> MovieItems { get; set; }
-
- public List<ItemStub> BoxSetItems { get; set; }
- public List<ItemStub> TrailerItems { get; set; }
- public List<ItemStub> HDItems { get; set; }
- public List<ItemStub> ThreeDItems { get; set; }
-
- public List<ItemStub> FamilyMovies { get; set; }
-
- public List<ItemStub> RomanceItems { get; set; }
- public List<ItemStub> ComedyItems { get; set; }
-
- public double FamilyMoviePercentage { get; set; }
-
- public double HDMoviePercentage { get; set; }
-
- public List<BaseItemDto> LatestTrailers { get; set; }
- public List<BaseItemDto> LatestMovies { get; set; }
- }
-
- public class TvView : BaseView
- {
- public List<ItemStub> ShowsItems { get; set; }
-
- public List<ItemStub> RomanceItems { get; set; }
- public List<ItemStub> ComedyItems { get; set; }
-
- public List<string> SeriesIdsInProgress { get; set; }
-
- public List<BaseItemDto> LatestEpisodes { get; set; }
- public List<BaseItemDto> NextUpEpisodes { get; set; }
- public List<BaseItemDto> ResumableEpisodes { get; set; }
- }
-
- public class ItemByNameInfo
- {
- public string Name { get; set; }
- public int ItemCount { get; set; }
- }
-
- public class GamesView : BaseView
- {
- public List<ItemStub> MultiPlayerItems { get; set; }
- public List<BaseItemDto> GameSystems { get; set; }
- public List<BaseItemDto> RecentlyPlayedGames { get; set; }
- }
-
- public class BaseView
- {
- public List<BaseItemDto> BackdropItems { get; set; }
- public List<BaseItemDto> SpotlightItems { get; set; }
- public List<BaseItemDto> MiniSpotlights { get; set; }
- }
-
- public class FavoritesView : BaseView
- {
- public List<BaseItemDto> Movies { get; set; }
- public List<BaseItemDto> Series { get; set; }
- public List<BaseItemDto> Episodes { get; set; }
- public List<BaseItemDto> Games { get; set; }
- public List<BaseItemDto> Books { get; set; }
- public List<BaseItemDto> Albums { get; set; }
- public List<BaseItemDto> Songs { get; set; }
- public List<BaseItemDto> Artists { get; set; }
- }
-}
diff --git a/MediaBrowser.Api/DisplayPreferencesService.cs b/MediaBrowser.Api/DisplayPreferencesService.cs
index 206f5bf7b..9f3a6134e 100644
--- a/MediaBrowser.Api/DisplayPreferencesService.cs
+++ b/MediaBrowser.Api/DisplayPreferencesService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Serialization;
using ServiceStack;
@@ -48,6 +49,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class DisplayPreferencesService
/// </summary>
+ [Authenticated]
public class DisplayPreferencesService : BaseApiService
{
/// <summary>
diff --git a/MediaBrowser.Api/Dlna/DlnaServerService.cs b/MediaBrowser.Api/Dlna/DlnaServerService.cs
index 28de8ee17..c6066f064 100644
--- a/MediaBrowser.Api/Dlna/DlnaServerService.cs
+++ b/MediaBrowser.Api/Dlna/DlnaServerService.cs
@@ -1,4 +1,6 @@
-using MediaBrowser.Controller.Dlna;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Dlna;
+using MediaBrowser.Model.Configuration;
using ServiceStack;
using ServiceStack.Text.Controller;
using ServiceStack.Web;
@@ -76,11 +78,14 @@ namespace MediaBrowser.Api.Dlna
private readonly IContentDirectory _contentDirectory;
private readonly IConnectionManager _connectionManager;
- public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager)
+ private readonly IConfigurationManager _config;
+
+ public DlnaServerService(IDlnaManager dlnaManager, IContentDirectory contentDirectory, IConnectionManager connectionManager, IConfigurationManager config)
{
_dlnaManager = dlnaManager;
_contentDirectory = contentDirectory;
_connectionManager = connectionManager;
+ _config = config;
}
public object Get(GetDescriptionXml request)
@@ -104,16 +109,16 @@ namespace MediaBrowser.Api.Dlna
return ResultFactory.GetResult(xml, "text/xml");
}
- public object Post(ProcessContentDirectoryControlRequest request)
+ public async Task<object> Post(ProcessContentDirectoryControlRequest request)
{
- var response = PostAsync(request.RequestStream, _contentDirectory).Result;
+ var response = await PostAsync(request.RequestStream, _contentDirectory).ConfigureAwait(false);
return ResultFactory.GetResult(response.Xml, "text/xml");
}
- public object Post(ProcessConnectionManagerControlRequest request)
+ public async Task<object> Post(ProcessConnectionManagerControlRequest request)
{
- var response = PostAsync(request.RequestStream, _connectionManager).Result;
+ var response = await PostAsync(request.RequestStream, _connectionManager).ConfigureAwait(false);
return ResultFactory.GetResult(response.Xml, "text/xml");
}
diff --git a/MediaBrowser.Api/Dlna/DlnaService.cs b/MediaBrowser.Api/Dlna/DlnaService.cs
index 9e6ca3aea..fec6d698a 100644
--- a/MediaBrowser.Api/Dlna/DlnaService.cs
+++ b/MediaBrowser.Api/Dlna/DlnaService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Dlna;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dlna;
using ServiceStack;
using System.Collections.Generic;
@@ -42,6 +43,7 @@ namespace MediaBrowser.Api.Dlna
{
}
+ [Authenticated]
public class DlnaService : BaseApiService
{
private readonly IDlnaManager _dlnaManager;
diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs
index 56f71fc00..590deff5a 100644
--- a/MediaBrowser.Api/EnvironmentService.cs
+++ b/MediaBrowser.Api/EnvironmentService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using ServiceStack;
@@ -86,6 +87,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class EnvironmentService
/// </summary>
+ [Authenticated]
public class EnvironmentService : BaseApiService
{
const char UncSeparator = '\\';
diff --git a/MediaBrowser.Api/GamesService.cs b/MediaBrowser.Api/GamesService.cs
index ff2771ce1..9aba2b065 100644
--- a/MediaBrowser.Api/GamesService.cs
+++ b/MediaBrowser.Api/GamesService.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using ServiceStack;
@@ -51,6 +52,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class GamesService
/// </summary>
+ [Authenticated]
public class GamesService : BaseApiService
{
/// <summary>
diff --git a/MediaBrowser.Api/Images/ImageByNameService.cs b/MediaBrowser.Api/Images/ImageByNameService.cs
index d40762964..99d2f144b 100644
--- a/MediaBrowser.Api/Images/ImageByNameService.cs
+++ b/MediaBrowser.Api/Images/ImageByNameService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
@@ -100,13 +101,16 @@ namespace MediaBrowser.Api.Images
/// </summary>
private readonly IServerApplicationPaths _appPaths;
+ private readonly IFileSystem _fileSystem;
+
/// <summary>
/// Initializes a new instance of the <see cref="ImageByNameService" /> class.
/// </summary>
/// <param name="appPaths">The app paths.</param>
- public ImageByNameService(IServerApplicationPaths appPaths)
+ public ImageByNameService(IServerApplicationPaths appPaths, IFileSystem fileSystem)
{
_appPaths = appPaths;
+ _fileSystem = fileSystem;
}
public object Get(GetMediaInfoImages request)
@@ -133,7 +137,7 @@ namespace MediaBrowser.Api.Images
.Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.Ordinal))
.Select(i => new ImageByNameInfo
{
- Name = Path.GetFileNameWithoutExtension(i.FullName),
+ Name = _fileSystem.GetFileNameWithoutExtension(i),
FileLength = i.Length,
// For themeable images, use the Theme property
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs
index 4f8c348bb..2213a5af1 100644
--- a/MediaBrowser.Api/Images/ImageService.cs
+++ b/MediaBrowser.Api/Images/ImageService.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Drawing;
@@ -13,7 +14,6 @@ using ServiceStack.Text.Controller;
using ServiceStack.Web;
using System;
using System.Collections.Generic;
-using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
@@ -26,6 +26,7 @@ namespace MediaBrowser.Api.Images
/// </summary>
[Route("/Items/{Id}/Images", "GET")]
[Api(Description = "Gets information about an item's images")]
+ [Authenticated]
public class GetItemImageInfos : IReturn<List<ImageInfo>>
{
/// <summary>
@@ -38,6 +39,8 @@ namespace MediaBrowser.Api.Images
[Route("/Items/{Id}/Images/{Type}", "GET")]
[Route("/Items/{Id}/Images/{Type}/{Index}", "GET")]
+ [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}", "GET")]
+ [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}", "HEAD")]
[Api(Description = "Gets an item image")]
public class GetItemImage : ImageRequest
{
@@ -47,8 +50,6 @@ namespace MediaBrowser.Api.Images
/// <value>The id.</value>
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
-
- public string Params { get; set; }
}
/// <summary>
@@ -56,6 +57,7 @@ namespace MediaBrowser.Api.Images
/// </summary>
[Route("/Items/{Id}/Images/{Type}/{Index}/Index", "POST")]
[Api(Description = "Updates the index for an item image")]
+ [Authenticated]
public class UpdateItemImageIndex : IReturnVoid
{
/// <summary>
@@ -137,6 +139,7 @@ namespace MediaBrowser.Api.Images
[Route("/Items/{Id}/Images/{Type}", "DELETE")]
[Route("/Items/{Id}/Images/{Type}/{Index}", "DELETE")]
[Api(Description = "Deletes an item image")]
+ [Authenticated]
public class DeleteItemImage : DeleteImageRequest, IReturnVoid
{
/// <summary>
@@ -153,6 +156,7 @@ namespace MediaBrowser.Api.Images
[Route("/Users/{Id}/Images/{Type}", "DELETE")]
[Route("/Users/{Id}/Images/{Type}/{Index}", "DELETE")]
[Api(Description = "Deletes a user image")]
+ [Authenticated]
public class DeleteUserImage : DeleteImageRequest, IReturnVoid
{
/// <summary>
@@ -169,6 +173,7 @@ namespace MediaBrowser.Api.Images
[Route("/Users/{Id}/Images/{Type}", "POST")]
[Route("/Users/{Id}/Images/{Type}/{Index}", "POST")]
[Api(Description = "Posts a user image")]
+ [Authenticated]
public class PostUserImage : DeleteImageRequest, IRequiresRequestStream, IReturnVoid
{
/// <summary>
@@ -191,6 +196,7 @@ namespace MediaBrowser.Api.Images
[Route("/Items/{Id}/Images/{Type}", "POST")]
[Route("/Items/{Id}/Images/{Type}/{Index}", "POST")]
[Api(Description = "Posts an item image")]
+ [Authenticated]
public class PostItemImage : DeleteImageRequest, IRequiresRequestStream, IReturnVoid
{
/// <summary>
@@ -355,49 +361,25 @@ namespace MediaBrowser.Api.Images
/// <returns>System.Object.</returns>
public object Get(GetItemImage request)
{
- var item = string.IsNullOrEmpty(request.Id) ?
+ var item = string.IsNullOrEmpty(request.Id) ?
_libraryManager.RootFolder :
_libraryManager.GetItemById(request.Id);
- if (!string.IsNullOrEmpty(request.Params))
- {
- ParseOptions(request, request.Params);
- }
-
- return GetImage(request, item);
+ return GetImage(request, item, false);
}
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- private void ParseOptions(ImageRequest request, string options)
+ /// <summary>
+ /// Gets the specified request.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ /// <returns>System.Object.</returns>
+ public object Head(GetItemImage request)
{
- var vals = options.Split(';');
-
- for (var i = 0; i < vals.Length; i++)
- {
- var val = vals[i];
-
- if (string.IsNullOrWhiteSpace(val))
- {
- continue;
- }
+ var item = string.IsNullOrEmpty(request.Id) ?
+ _libraryManager.RootFolder :
+ _libraryManager.GetItemById(request.Id);
- if (i == 0)
- {
- request.Tag = val;
- }
- else if (i == 1)
- {
- request.Format = (ImageOutputFormat)Enum.Parse(typeof(ImageOutputFormat), val, true);
- }
- else if (i == 2)
- {
- request.MaxWidth = int.Parse(val, _usCulture);
- }
- else if (i == 3)
- {
- request.MaxHeight = int.Parse(val, _usCulture);
- }
- }
+ return GetImage(request, item, true);
}
/// <summary>
@@ -409,7 +391,7 @@ namespace MediaBrowser.Api.Images
{
var item = _userManager.Users.First(i => i.Id == request.Id);
- return GetImage(request, item);
+ return GetImage(request, item, false);
}
public object Get(GetItemByNameImage request)
@@ -419,7 +401,7 @@ namespace MediaBrowser.Api.Images
var item = GetItemByName(request.Name, type, _libraryManager);
- return GetImage(request, item);
+ return GetImage(request, item, false);
}
/// <summary>
@@ -516,10 +498,10 @@ namespace MediaBrowser.Api.Images
/// </summary>
/// <param name="request">The request.</param>
/// <param name="item">The item.</param>
+ /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
/// <returns>System.Object.</returns>
- /// <exception cref="ResourceNotFoundException">
- /// </exception>
- public object GetImage(ImageRequest request, IHasImages item)
+ /// <exception cref="ResourceNotFoundException"></exception>
+ public object GetImage(ImageRequest request, IHasImages item, bool isHeadRequest)
{
var imageInfo = GetImageInfo(request, item);
@@ -528,9 +510,6 @@ namespace MediaBrowser.Api.Images
throw new ResourceNotFoundException(string.Format("{0} does not have an image of type {1}", item.Name, request.Type));
}
- // See if we can avoid a file system lookup by looking for the file in ResolveArgs
- var originalFileImageDateModified = imageInfo.DateModified;
-
var supportedImageEnhancers = request.EnableImageEnhancers ? _imageProcessor.ImageEnhancers.Where(i =>
{
try
@@ -557,25 +536,68 @@ namespace MediaBrowser.Api.Images
cacheDuration = TimeSpan.FromDays(365);
}
- // Avoid implicitly captured closure
- var currentItem = item;
- var currentRequest = request;
-
var responseHeaders = new Dictionary<string, string>
{
{"transferMode.dlna.org", "Interactive"},
{"realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*"}
};
- return ToCachedResult(cacheGuid, originalFileImageDateModified, cacheDuration, () => new ImageWriter
+ return GetImageResult(item,
+ request,
+ imageInfo,
+ supportedImageEnhancers,
+ contentType,
+ cacheDuration,
+ responseHeaders,
+ isHeadRequest)
+ .Result;
+ }
+
+ private async Task<object> GetImageResult(IHasImages item,
+ ImageRequest request,
+ ItemImageInfo image,
+ List<IImageEnhancer> enhancers,
+ string contentType,
+ TimeSpan? cacheDuration,
+ IDictionary<string, string> headers,
+ bool isHeadRequest)
+ {
+ var cropwhitespace = request.Type == ImageType.Logo || request.Type == ImageType.Art;
+
+ if (request.CropWhitespace.HasValue)
{
- Item = currentItem,
- Request = currentRequest,
- Enhancers = supportedImageEnhancers,
- Image = imageInfo,
- ImageProcessor = _imageProcessor
+ cropwhitespace = request.CropWhitespace.Value;
+ }
+
+ var options = new ImageProcessingOptions
+ {
+ CropWhiteSpace = cropwhitespace,
+ Enhancers = enhancers,
+ Height = request.Height,
+ ImageIndex = request.Index ?? 0,
+ Image = image,
+ Item = item,
+ MaxHeight = request.MaxHeight,
+ MaxWidth = request.MaxWidth,
+ Quality = request.Quality,
+ Width = request.Width,
+ OutputFormat = request.Format,
+ AddPlayedIndicator = request.AddPlayedIndicator,
+ PercentPlayed = request.PercentPlayed,
+ UnplayedCount = request.UnplayedCount,
+ BackgroundColor = request.BackgroundColor
+ };
- }, contentType, responseHeaders);
+ var file = await _imageProcessor.ProcessImage(options).ConfigureAwait(false);
+
+ return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
+ {
+ CacheDuration = cacheDuration,
+ ResponseHeaders = headers,
+ ContentType = contentType,
+ IsHeadRequest = isHeadRequest,
+ Path = file
+ });
}
private string GetMimeType(ImageOutputFormat format, string path)
@@ -596,6 +618,10 @@ namespace MediaBrowser.Api.Images
{
return Common.Net.MimeTypes.GetMimeType("i.png");
}
+ if (format == ImageOutputFormat.Webp)
+ {
+ return Common.Net.MimeTypes.GetMimeType("i.webp");
+ }
return Common.Net.MimeTypes.GetMimeType(path);
}
diff --git a/MediaBrowser.Api/Images/ImageWriter.cs b/MediaBrowser.Api/Images/ImageWriter.cs
deleted file mode 100644
index b6638d9df..000000000
--- a/MediaBrowser.Api/Images/ImageWriter.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-using MediaBrowser.Controller.Drawing;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using ServiceStack.Web;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Api.Images
-{
- /// <summary>
- /// Class ImageWriter
- /// </summary>
- public class ImageWriter : IStreamWriter, IHasOptions
- {
- public List<IImageEnhancer> Enhancers;
-
- /// <summary>
- /// Gets or sets the request.
- /// </summary>
- /// <value>The request.</value>
- public ImageRequest Request { get; set; }
- /// <summary>
- /// Gets or sets the item.
- /// </summary>
- /// <value>The item.</value>
- public IHasImages Item { get; set; }
- /// <summary>
- /// The original image date modified
- /// </summary>
- public ItemImageInfo Image;
-
- public IImageProcessor ImageProcessor { get; set; }
-
- /// <summary>
- /// The _options
- /// </summary>
- private readonly IDictionary<string, string> _options = new Dictionary<string, string>();
- /// <summary>
- /// Gets the options.
- /// </summary>
- /// <value>The options.</value>
- public IDictionary<string, string> Options
- {
- get { return _options; }
- }
-
- /// <summary>
- /// Writes to.
- /// </summary>
- /// <param name="responseStream">The response stream.</param>
- public void WriteTo(Stream responseStream)
- {
- var task = WriteToAsync(responseStream);
-
- Task.WaitAll(task);
- }
-
- /// <summary>
- /// Writes to async.
- /// </summary>
- /// <param name="responseStream">The response stream.</param>
- /// <returns>Task.</returns>
- private Task WriteToAsync(Stream responseStream)
- {
- var cropwhitespace = Request.Type == ImageType.Logo || Request.Type == ImageType.Art;
-
- if (Request.CropWhitespace.HasValue)
- {
- cropwhitespace = Request.CropWhitespace.Value;
- }
-
- var options = new ImageProcessingOptions
- {
- CropWhiteSpace = cropwhitespace,
- Enhancers = Enhancers,
- Height = Request.Height,
- ImageIndex = Request.Index ?? 0,
- Image = Image,
- Item = Item,
- MaxHeight = Request.MaxHeight,
- MaxWidth = Request.MaxWidth,
- Quality = Request.Quality,
- Width = Request.Width,
- OutputFormat = Request.Format,
- AddPlayedIndicator = Request.AddPlayedIndicator,
- PercentPlayed = Request.PercentPlayed,
- UnplayedCount = Request.UnplayedCount,
- BackgroundColor = Request.BackgroundColor
- };
-
- return ImageProcessor.ProcessImage(options, responseStream);
- }
- }
-}
diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs
index c76506357..235f18296 100644
--- a/MediaBrowser.Api/Images/RemoteImageService.cs
+++ b/MediaBrowser.Api/Images/RemoteImageService.cs
@@ -199,35 +199,33 @@ namespace MediaBrowser.Api.Images
return _providerManager.GetRemoteImageProviderInfo(item).ToList();
}
- public object Get(GetRemoteImages request)
+ public async Task<object> Get(GetRemoteImages request)
{
var item = _libraryManager.GetItemById(request.Id);
- var result = GetRemoteImageResult(item, request);
-
- return ToOptimizedSerializedResultUsingCache(result);
+ return await GetRemoteImageResult(item, request).ConfigureAwait(false);
}
- public object Get(GetItemByNameRemoteImages request)
+ public async Task<object> Get(GetItemByNameRemoteImages request)
{
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0);
var item = GetItemByName(request.Name, type, _libraryManager);
- return GetRemoteImageResult(item, request);
+ return await GetRemoteImageResult(item, request).ConfigureAwait(false);
}
- private RemoteImageResult GetRemoteImageResult(BaseItem item, BaseRemoteImageRequest request)
+ private async Task<RemoteImageResult> GetRemoteImageResult(BaseItem item, BaseRemoteImageRequest request)
{
- var images = _providerManager.GetAvailableRemoteImages(item, new RemoteImageQuery
+ var images = await _providerManager.GetAvailableRemoteImages(item, new RemoteImageQuery
{
ProviderName = request.ProviderName,
IncludeAllLanguages = request.IncludeAllLanguages,
IncludeDisabledProviders = true,
ImageType = request.Type
- }, CancellationToken.None).Result;
+ }, CancellationToken.None).ConfigureAwait(false);
var imagesList = images.ToList();
@@ -308,17 +306,10 @@ namespace MediaBrowser.Api.Images
/// <returns>System.Object.</returns>
public object Get(GetRemoteImage request)
{
- var task = GetRemoteImage(request);
-
- return task.Result;
+ return GetAsync(request).Result;
}
- /// <summary>
- /// Gets the remote image.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>Task{System.Object}.</returns>
- private async Task<object> GetRemoteImage(GetRemoteImage request)
+ public async Task<object> GetAsync(GetRemoteImage request)
{
var urlHash = request.ImageUrl.GetMD5();
var pointerCachePath = GetFullCachePath(urlHash.ToString());
@@ -356,7 +347,7 @@ namespace MediaBrowser.Api.Images
return ToStaticFileResult(contentPath);
}
-
+
/// <summary>
/// Downloads the image.
/// </summary>
diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs
index e68aa73f6..2ce7997a1 100644
--- a/MediaBrowser.Api/ItemLookupService.cs
+++ b/MediaBrowser.Api/ItemLookupService.cs
@@ -6,6 +6,7 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
@@ -21,6 +22,7 @@ namespace MediaBrowser.Api
{
[Route("/Items/{Id}/ExternalIdInfos", "GET")]
[Api(Description = "Gets external id infos for an item")]
+ [Authenticated]
public class GetExternalIdInfos : IReturn<List<ExternalIdInfo>>
{
/// <summary>
@@ -33,54 +35,63 @@ namespace MediaBrowser.Api
[Route("/Items/RemoteSearch/Movie", "POST")]
[Api(Description = "Gets external id infos for an item")]
+ [Authenticated]
public class GetMovieRemoteSearchResults : RemoteSearchQuery<MovieInfo>, IReturn<List<RemoteSearchResult>>
{
}
[Route("/Items/RemoteSearch/Trailer", "POST")]
[Api(Description = "Gets external id infos for an item")]
+ [Authenticated]
public class GetTrailerRemoteSearchResults : RemoteSearchQuery<TrailerInfo>, IReturn<List<RemoteSearchResult>>
{
}
[Route("/Items/RemoteSearch/AdultVideo", "POST")]
[Api(Description = "Gets external id infos for an item")]
+ [Authenticated]
public class GetAdultVideoRemoteSearchResults : RemoteSearchQuery<ItemLookupInfo>, IReturn<List<RemoteSearchResult>>
{
}
[Route("/Items/RemoteSearch/Series", "POST")]
[Api(Description = "Gets external id infos for an item")]
+ [Authenticated]
public class GetSeriesRemoteSearchResults : RemoteSearchQuery<SeriesInfo>, IReturn<List<RemoteSearchResult>>
{
}
[Route("/Items/RemoteSearch/Game", "POST")]
[Api(Description = "Gets external id infos for an item")]
+ [Authenticated]
public class GetGameRemoteSearchResults : RemoteSearchQuery<GameInfo>, IReturn<List<RemoteSearchResult>>
{
}
[Route("/Items/RemoteSearch/BoxSet", "POST")]
[Api(Description = "Gets external id infos for an item")]
+ [Authenticated]
public class GetBoxSetRemoteSearchResults : RemoteSearchQuery<BoxSetInfo>, IReturn<List<RemoteSearchResult>>
{
}
[Route("/Items/RemoteSearch/MusicArtist", "POST")]
[Api(Description = "Gets external id infos for an item")]
+ [Authenticated]
public class GetMusicArtistRemoteSearchResults : RemoteSearchQuery<ArtistInfo>, IReturn<List<RemoteSearchResult>>
{
}
[Route("/Items/RemoteSearch/MusicAlbum", "POST")]
[Api(Description = "Gets external id infos for an item")]
+ [Authenticated]
public class GetMusicAlbumRemoteSearchResults : RemoteSearchQuery<AlbumInfo>, IReturn<List<RemoteSearchResult>>
{
}
[Route("/Items/RemoteSearch/Person", "POST")]
[Api(Description = "Gets external id infos for an item")]
+ [Authenticated]
public class GetPersonRemoteSearchResults : RemoteSearchQuery<PersonLookupInfo>, IReturn<List<RemoteSearchResult>>
{
}
@@ -98,6 +109,7 @@ namespace MediaBrowser.Api
[Route("/Items/RemoteSearch/Apply/{Id}", "POST")]
[Api(Description = "Applies search criteria to an item and refreshes metadata")]
+ [Authenticated]
public class ApplySearchCriteria : RemoteSearchResult, IReturnVoid
{
[ApiMember(Name = "Id", Description = "The item id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -212,16 +224,23 @@ namespace MediaBrowser.Api
}
}
- var task = item.RefreshMetadata(new MetadataRefreshOptions
+ var service = new ItemRefreshService(_libraryManager)
{
+ Logger = Logger,
+ Request = Request,
+ ResultFactory = ResultFactory,
+ SessionContext = SessionContext
+ };
+
+ service.Post(new RefreshItem
+ {
+ Id = request.Id,
MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
ImageRefreshMode = ImageRefreshMode.FullRefresh,
ReplaceAllMetadata = true,
- ReplaceAllImages = true
-
- }, CancellationToken.None);
-
- Task.WaitAll(task);
+ ReplaceAllImages = true,
+ Recursive = true
+ });
}
/// <summary>
diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs
index 0094282c8..768e9a4a8 100644
--- a/MediaBrowser.Api/ItemRefreshService.cs
+++ b/MediaBrowser.Api/ItemRefreshService.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers;
using ServiceStack;
using System;
@@ -12,10 +13,16 @@ namespace MediaBrowser.Api
{
public class BaseRefreshRequest : IReturnVoid
{
- [ApiMember(Name = "Forced", Description = "Indicates if a normal or forced refresh should occur.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
- public bool Forced { get; set; }
+ [ApiMember(Name = "MetadataRefreshMode", Description = "Specifies the metadata refresh mode", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
+ public MetadataRefreshMode MetadataRefreshMode { get; set; }
- [ApiMember(Name = "ReplaceAllImages", Description = "Determines if images should be replaced during the refresh.", IsRequired = true, DataType = "boolean", ParameterType = "query", Verb = "POST")]
+ [ApiMember(Name = "ImageRefreshMode", Description = "Specifies the image refresh mode", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
+ public ImageRefreshMode ImageRefreshMode { get; set; }
+
+ [ApiMember(Name = "ReplaceAllMetadata", Description = "Determines if metadata should be replaced. Only applicable if mode is FullRefresh", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
+ public bool ReplaceAllMetadata { get; set; }
+
+ [ApiMember(Name = "ReplaceAllImages", Description = "Determines if images should be replaced. Only applicable if mode is FullRefresh", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
public bool ReplaceAllImages { get; set; }
}
@@ -30,6 +37,7 @@ namespace MediaBrowser.Api
public string Id { get; set; }
}
+ [Authenticated]
public class ItemRefreshService : BaseApiService
{
private readonly ILibraryManager _libraryManager;
@@ -91,7 +99,7 @@ namespace MediaBrowser.Api
private async Task RefreshItem(RefreshItem request, BaseItem item)
{
var options = GetRefreshOptions(request);
-
+
try
{
await item.RefreshMetadata(options, CancellationToken.None).ConfigureAwait(false);
@@ -146,10 +154,11 @@ namespace MediaBrowser.Api
{
return new MetadataRefreshOptions
{
- MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
- ImageRefreshMode = ImageRefreshMode.FullRefresh,
- ReplaceAllMetadata = request.Forced,
- ReplaceAllImages = request.ReplaceAllImages
+ MetadataRefreshMode = request.MetadataRefreshMode,
+ ImageRefreshMode = request.ImageRefreshMode,
+ ReplaceAllImages = request.ReplaceAllImages,
+ ReplaceAllMetadata = request.ReplaceAllMetadata,
+ ForceSave = true
};
}
}
diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs
index 4feba82b0..1fa1a5509 100644
--- a/MediaBrowser.Api/ItemUpdateService.cs
+++ b/MediaBrowser.Api/ItemUpdateService.cs
@@ -1,11 +1,12 @@
-using System.Collections.Generic;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dto;
using ServiceStack;
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -19,6 +20,7 @@ namespace MediaBrowser.Api
public string ItemId { get; set; }
}
+ [Authenticated]
public class ItemUpdateService : BaseApiService
{
private readonly ILibraryManager _libraryManager;
@@ -63,6 +65,11 @@ namespace MediaBrowser.Api
}
}
+ private DateTime NormalizeDateTime(DateTime val)
+ {
+ return DateTime.SpecifyKind(val, DateTimeKind.Utc);
+ }
+
private void UpdateItem(BaseItemDto request, BaseItem item)
{
item.Name = request.Name;
@@ -108,6 +115,12 @@ namespace MediaBrowser.Api
hasTags.Tags = request.Tags;
}
+ var hasTaglines = item as IHasTaglines;
+ if (hasTaglines != null)
+ {
+ hasTaglines.Taglines = request.Taglines;
+ }
+
var hasShortOverview = item as IHasShortOverview;
if (hasShortOverview != null)
{
@@ -132,11 +145,11 @@ namespace MediaBrowser.Api
if (request.DateCreated.HasValue)
{
- item.DateCreated = request.DateCreated.Value.ToUniversalTime();
+ item.DateCreated = NormalizeDateTime(request.DateCreated.Value);
}
- item.EndDate = request.EndDate.HasValue ? request.EndDate.Value.ToUniversalTime() : (DateTime?)null;
- item.PremiereDate = request.PremiereDate.HasValue ? request.PremiereDate.Value.ToUniversalTime() : (DateTime?)null;
+ item.EndDate = request.EndDate.HasValue ? NormalizeDateTime(request.EndDate.Value) : (DateTime?)null;
+ item.PremiereDate = request.PremiereDate.HasValue ? NormalizeDateTime(request.PremiereDate.Value) : (DateTime?)null;
item.ProductionYear = request.ProductionYear;
item.OfficialRating = request.OfficialRating;
item.CustomRating = request.CustomRating;
diff --git a/MediaBrowser.Api/Library/ChapterService.cs b/MediaBrowser.Api/Library/ChapterService.cs
index 72ffa3fca..6b8dd18f1 100644
--- a/MediaBrowser.Api/Library/ChapterService.cs
+++ b/MediaBrowser.Api/Library/ChapterService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Chapters;
+using MediaBrowser.Controller.Net;
using ServiceStack;
using System.Linq;
@@ -9,6 +10,7 @@ namespace MediaBrowser.Api.Library
{
}
+ [Authenticated]
public class ChapterService : BaseApiService
{
private readonly IChapterManager _chapterManager;
diff --git a/MediaBrowser.Api/Library/FileOrganizationService.cs b/MediaBrowser.Api/Library/FileOrganizationService.cs
index 01531a7ae..adf6a522b 100644
--- a/MediaBrowser.Api/Library/FileOrganizationService.cs
+++ b/MediaBrowser.Api/Library/FileOrganizationService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.FileOrganization;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.FileOrganization;
using MediaBrowser.Model.Querying;
using ServiceStack;
@@ -78,6 +79,7 @@ namespace MediaBrowser.Api.Library
public bool RememberCorrection { get; set; }
}
+ [Authenticated]
public class FileOrganizationService : BaseApiService
{
private readonly IFileOrganizationService _iFileOrganizationService;
diff --git a/MediaBrowser.Api/Library/LibraryHelpers.cs b/MediaBrowser.Api/Library/LibraryHelpers.cs
index be9f00a61..e21dc4a73 100644
--- a/MediaBrowser.Api/Library/LibraryHelpers.cs
+++ b/MediaBrowser.Api/Library/LibraryHelpers.cs
@@ -65,7 +65,7 @@ namespace MediaBrowser.Api.Library
var rootFolderPath = appPaths.DefaultUserViewsPath;
var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName);
- var shortcutFilename = Path.GetFileNameWithoutExtension(path);
+ var shortcutFilename = fileSystem.GetFileNameWithoutExtension(path);
var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension);
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index 802df5cca..34b930a6a 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto;
@@ -210,20 +211,23 @@ namespace MediaBrowser.Api.Library
[Api(Description = "Gets all user media folders.")]
public class GetMediaFolders : IReturn<ItemsResult>
{
-
+ [ApiMember(Name = "IsHidden", Description = "Optional. Filter by folders that are marked hidden, or not.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
+ public bool? IsHidden { get; set; }
}
+ [Route("/Library/Series/Added", "POST")]
[Route("/Library/Series/Updated", "POST")]
[Api(Description = "Reports that new episodes of a series have been added by an external source")]
public class PostUpdatedSeries : IReturnVoid
{
- [ApiMember(Name = "TvdbId", Description = "Tvdb Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ [ApiMember(Name = "TvdbId", Description = "Tvdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
public string TvdbId { get; set; }
}
/// <summary>
/// Class LibraryService
/// </summary>
+ [Authenticated]
public class LibraryService : BaseApiService
{
/// <summary>
@@ -258,6 +262,13 @@ namespace MediaBrowser.Api.Library
{
var items = _libraryManager.GetUserRootFolder().Children.OrderBy(i => i.SortName).ToList();
+ if (request.IsHidden.HasValue)
+ {
+ var val = request.IsHidden.Value;
+
+ items = items.Where(i => i.IsHidden == val).ToList();
+ }
+
// Get everything
var fields = Enum.GetNames(typeof(ItemFields))
.Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
@@ -273,6 +284,11 @@ namespace MediaBrowser.Api.Library
return ToOptimizedResult(result);
}
+ public void Post(PostUpdatedSeries request)
+ {
+ Task.Run(() => _libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None));
+ }
+
public object Get(GetFile request)
{
var item = _libraryManager.GetItemById(request.Id);
@@ -452,23 +468,11 @@ namespace MediaBrowser.Api.Library
/// <param name="request">The request.</param>
public void Delete(DeleteItem request)
{
- var task = DeleteItem(request);
-
- Task.WaitAll(task);
- }
-
- private Task DeleteItem(DeleteItem request)
- {
var item = _libraryManager.GetItemById(request.Id);
- var session = GetSession(_sessionManager);
+ var task = _libraryManager.DeleteItem(item);
- if (!session.UserId.HasValue || !_userManager.GetUserById(session.UserId.Value).Configuration.EnableContentDeletion)
- {
- throw new UnauthorizedAccessException("This operation requires a logged in user with delete access.");
- }
-
- return _libraryManager.DeleteItem(item);
+ Task.WaitAll(task);
}
/// <summary>
diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs
index 947da29fe..c3ef58768 100644
--- a/MediaBrowser.Api/Library/LibraryStructureService.cs
+++ b/MediaBrowser.Api/Library/LibraryStructureService.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using ServiceStack;
@@ -130,36 +131,11 @@ namespace MediaBrowser.Api.Library
/// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
public bool RefreshLibrary { get; set; }
}
-
- [Route("/Library/Downloaded", "POST")]
- public class ReportContentDownloaded : IReturnVoid
- {
- [ApiMember(Name = "Path", Description = "The path being downloaded to.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Path { get; set; }
-
- [ApiMember(Name = "ImageUrl", Description = "Optional thumbnail image url of the content.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ImageUrl { get; set; }
-
- [ApiMember(Name = "Name", Description = "The name of the content.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Name { get; set; }
- }
-
- [Route("/Library/Downloading", "POST")]
- public class ReportContentDownloading : IReturnVoid
- {
- [ApiMember(Name = "Path", Description = "The path being downloaded to.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Path { get; set; }
-
- [ApiMember(Name = "ImageUrl", Description = "Optional thumbnail image url of the content.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ImageUrl { get; set; }
-
- [ApiMember(Name = "Name", Description = "The name of the content.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Name { get; set; }
- }
/// <summary>
/// Class LibraryStructureService
/// </summary>
+ [Authenticated]
public class LibraryStructureService : BaseApiService
{
/// <summary>
diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
index 6973a233a..35420c936 100644
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;
@@ -267,6 +268,7 @@ namespace MediaBrowser.Api.LiveTv
public string UserId { get; set; }
}
+ [Authenticated]
public class LiveTvService : BaseApiService
{
private readonly ILiveTvManager _liveTvManager;
@@ -280,7 +282,7 @@ namespace MediaBrowser.Api.LiveTv
private void AssertUserCanManageLiveTv()
{
- var user = AuthorizationRequestFilterAttribute.GetCurrentUser(Request, _userManager);
+ var user = SessionContext.GetUser(Request);
if (user == null)
{
@@ -293,16 +295,16 @@ namespace MediaBrowser.Api.LiveTv
}
}
- public object Get(GetLiveTvInfo request)
+ public async Task<object> Get(GetLiveTvInfo request)
{
- var info = _liveTvManager.GetLiveTvInfo(CancellationToken.None).Result;
+ var info = await _liveTvManager.GetLiveTvInfo(CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(info);
}
- public object Get(GetChannels request)
+ public async Task<object> Get(GetChannels request)
{
- var result = _liveTvManager.GetChannels(new LiveTvChannelQuery
+ var result = await _liveTvManager.GetChannels(new LiveTvChannelQuery
{
ChannelType = request.Type,
UserId = request.UserId,
@@ -312,26 +314,26 @@ namespace MediaBrowser.Api.LiveTv
IsLiked = request.IsLiked,
IsDisliked = request.IsDisliked
- }, CancellationToken.None).Result;
+ }, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
- public object Get(GetChannel request)
+ public async Task<object> Get(GetChannel request)
{
var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(new Guid(request.UserId));
- var result = _liveTvManager.GetChannel(request.Id, CancellationToken.None, user).Result;
+ var result = await _liveTvManager.GetChannel(request.Id, CancellationToken.None, user).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
- public object Get(GetLiveTvFolder request)
+ public async Task<object> Get(GetLiveTvFolder request)
{
- return ToOptimizedResult(_liveTvManager.GetLiveTvFolder(request.UserId, CancellationToken.None).Result);
+ return ToOptimizedResult(await _liveTvManager.GetLiveTvFolder(request.UserId, CancellationToken.None).ConfigureAwait(false));
}
- public object Get(GetPrograms request)
+ public async Task<object> Get(GetPrograms request)
{
var query = new ProgramQuery
{
@@ -359,12 +361,12 @@ namespace MediaBrowser.Api.LiveTv
query.MaxEndDate = DateTime.Parse(request.MaxEndDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
}
- var result = _liveTvManager.GetPrograms(query, CancellationToken.None).Result;
+ var result = await _liveTvManager.GetPrograms(query, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
- public object Get(GetRecommendedPrograms request)
+ public async Task<object> Get(GetRecommendedPrograms request)
{
var query = new RecommendedProgramQuery
{
@@ -374,7 +376,7 @@ namespace MediaBrowser.Api.LiveTv
HasAired = request.HasAired
};
- var result = _liveTvManager.GetRecommendedPrograms(query, CancellationToken.None).Result;
+ var result = await _liveTvManager.GetRecommendedPrograms(query, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
@@ -384,9 +386,9 @@ namespace MediaBrowser.Api.LiveTv
return Get(request);
}
- public object Get(GetRecordings request)
+ public async Task<object> Get(GetRecordings request)
{
- var result = _liveTvManager.GetRecordings(new RecordingQuery
+ var result = await _liveTvManager.GetRecordings(new RecordingQuery
{
ChannelId = request.ChannelId,
UserId = request.UserId,
@@ -397,35 +399,35 @@ namespace MediaBrowser.Api.LiveTv
SeriesTimerId = request.SeriesTimerId,
IsInProgress = request.IsInProgress
- }, CancellationToken.None).Result;
+ }, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
- public object Get(GetRecording request)
+ public async Task<object> Get(GetRecording request)
{
var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(new Guid(request.UserId));
- var result = _liveTvManager.GetRecording(request.Id, CancellationToken.None, user).Result;
+ var result = await _liveTvManager.GetRecording(request.Id, CancellationToken.None, user).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
- public object Get(GetTimer request)
+ public async Task<object> Get(GetTimer request)
{
- var result = _liveTvManager.GetTimer(request.Id, CancellationToken.None).Result;
+ var result = await _liveTvManager.GetTimer(request.Id, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
- public object Get(GetTimers request)
+ public async Task<object> Get(GetTimers request)
{
- var result = _liveTvManager.GetTimers(new TimerQuery
+ var result = await _liveTvManager.GetTimers(new TimerQuery
{
ChannelId = request.ChannelId,
SeriesTimerId = request.SeriesTimerId
- }, CancellationToken.None).Result;
+ }, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
@@ -457,21 +459,21 @@ namespace MediaBrowser.Api.LiveTv
Task.WaitAll(task);
}
- public object Get(GetSeriesTimers request)
+ public async Task<object> Get(GetSeriesTimers request)
{
- var result = _liveTvManager.GetSeriesTimers(new SeriesTimerQuery
+ var result = await _liveTvManager.GetSeriesTimers(new SeriesTimerQuery
{
SortOrder = request.SortOrder,
SortBy = request.SortBy
- }, CancellationToken.None).Result;
+ }, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
- public object Get(GetSeriesTimer request)
+ public async Task<object> Get(GetSeriesTimer request)
{
- var result = _liveTvManager.GetSeriesTimer(request.Id, CancellationToken.None).Result;
+ var result = await _liveTvManager.GetSeriesTimer(request.Id, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
@@ -494,27 +496,27 @@ namespace MediaBrowser.Api.LiveTv
Task.WaitAll(task);
}
- public object Get(GetDefaultTimer request)
+ public async Task<object> Get(GetDefaultTimer request)
{
if (string.IsNullOrEmpty(request.ProgramId))
{
- var result = _liveTvManager.GetNewTimerDefaults(CancellationToken.None).Result;
+ var result = await _liveTvManager.GetNewTimerDefaults(CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
else
{
- var result = _liveTvManager.GetNewTimerDefaults(request.ProgramId, CancellationToken.None).Result;
+ var result = await _liveTvManager.GetNewTimerDefaults(request.ProgramId, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
}
- public object Get(GetProgram request)
+ public async Task<object> Get(GetProgram request)
{
var user = string.IsNullOrEmpty(request.UserId) ? null : _userManager.GetUserById(new Guid(request.UserId));
- var result = _liveTvManager.GetProgram(request.Id, CancellationToken.None, user).Result;
+ var result = await _liveTvManager.GetProgram(request.Id, CancellationToken.None, user).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
@@ -537,23 +539,23 @@ namespace MediaBrowser.Api.LiveTv
Task.WaitAll(task);
}
- public object Get(GetRecordingGroups request)
+ public async Task<object> Get(GetRecordingGroups request)
{
- var result = _liveTvManager.GetRecordingGroups(new RecordingGroupQuery
+ var result = await _liveTvManager.GetRecordingGroups(new RecordingGroupQuery
{
UserId = request.UserId
- }, CancellationToken.None).Result;
+ }, CancellationToken.None).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
- public object Get(GetRecordingGroup request)
+ public async Task<object> Get(GetRecordingGroup request)
{
- var result = _liveTvManager.GetRecordingGroups(new RecordingGroupQuery
+ var result = await _liveTvManager.GetRecordingGroups(new RecordingGroupQuery
{
- }, CancellationToken.None).Result;
+ }, CancellationToken.None).ConfigureAwait(false);
var group = result.Items.FirstOrDefault(i => string.Equals(i.Id, request.Id, StringComparison.OrdinalIgnoreCase));
diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs
index d3c47dfa1..5696d8df7 100644
--- a/MediaBrowser.Api/LocalizationService.cs
+++ b/MediaBrowser.Api/LocalizationService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Localization;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using ServiceStack;
@@ -42,6 +43,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class CulturesService
/// </summary>
+ [Authenticated]
public class LocalizationService : BaseApiService
{
/// <summary>
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 1e9ff9199..5cb9ebb1b 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -49,6 +49,9 @@
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
@@ -65,27 +68,25 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
+ <Compile Include="BrandingService.cs" />
<Compile Include="ChannelService.cs" />
<Compile Include="Dlna\DlnaServerService.cs" />
<Compile Include="Dlna\DlnaService.cs" />
<Compile Include="Library\ChapterService.cs" />
- <Compile Include="Library\SubtitleService.cs" />
+ <Compile Include="PlaylistService.cs" />
+ <Compile Include="Subtitles\SubtitleService.cs" />
<Compile Include="Movies\CollectionService.cs" />
<Compile Include="Music\AlbumsService.cs" />
<Compile Include="AppThemeService.cs" />
<Compile Include="BaseApiService.cs" />
<Compile Include="ConfigurationService.cs" />
- <Compile Include="DefaultTheme\DefaultThemeService.cs" />
- <Compile Include="DefaultTheme\Models.cs" />
<Compile Include="DisplayPreferencesService.cs" />
<Compile Include="EnvironmentService.cs" />
- <Compile Include="AuthorizationRequestFilterAttribute.cs" />
<Compile Include="GamesService.cs" />
<Compile Include="IHasItemFields.cs" />
<Compile Include="Images\ImageByNameService.cs" />
<Compile Include="Images\ImageRequest.cs" />
<Compile Include="Images\ImageService.cs" />
- <Compile Include="Images\ImageWriter.cs" />
<Compile Include="Music\InstantMixService.cs" />
<Compile Include="ItemLookupService.cs" />
<Compile Include="ItemRefreshService.cs" />
@@ -101,7 +102,7 @@
<Compile Include="NotificationsService.cs" />
<Compile Include="PackageReviewService.cs" />
<Compile Include="PackageService.cs" />
- <Compile Include="Playback\EndlessStreamCopy.cs" />
+ <Compile Include="Playback\BifService.cs" />
<Compile Include="Playback\Hls\BaseHlsService.cs" />
<Compile Include="Playback\Hls\DynamicHlsService.cs" />
<Compile Include="Playback\Hls\HlsSegmentService.cs" />
@@ -120,9 +121,12 @@
<Compile Include="ScheduledTasks\ScheduledTasksWebSocketListener.cs" />
<Compile Include="ApiEntryPoint.cs" />
<Compile Include="SearchService.cs" />
- <Compile Include="SessionsService.cs" />
+ <Compile Include="Session\SessionsService.cs" />
<Compile Include="SimilarItemsHelper.cs" />
- <Compile Include="SystemService.cs" />
+ <Compile Include="Sync\SyncService.cs" />
+ <Compile Include="System\ActivityLogService.cs" />
+ <Compile Include="System\ActivityLogWebSocketListener.cs" />
+ <Compile Include="System\SystemService.cs" />
<Compile Include="Movies\TrailersService.cs" />
<Compile Include="TvShowsService.cs" />
<Compile Include="UserLibrary\ArtistsService.cs" />
@@ -133,15 +137,15 @@
<Compile Include="UserLibrary\ItemsService.cs" />
<Compile Include="UserLibrary\MusicGenresService.cs" />
<Compile Include="UserLibrary\PersonsService.cs" />
+ <Compile Include="UserLibrary\PlaystateService.cs" />
<Compile Include="UserLibrary\StudiosService.cs" />
<Compile Include="UserLibrary\UserLibraryService.cs" />
<Compile Include="UserLibrary\YearsService.cs" />
<Compile Include="UserService.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="VideosService.cs" />
- <Compile Include="WebSocket\LogFileWebSocketListener.cs" />
- <Compile Include="WebSocket\SessionInfoWebSocketListener.cs" />
- <Compile Include="WebSocket\SystemInfoWebSocketListener.cs" />
+ <Compile Include="Session\SessionInfoWebSocketListener.cs" />
+ <Compile Include="System\SystemInfoWebSocketListener.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
@@ -160,13 +164,12 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
- <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
- <Import Project="$(SolutionDir)\.nuget\nuget.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.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">
diff --git a/MediaBrowser.Api/Movies/CollectionService.cs b/MediaBrowser.Api/Movies/CollectionService.cs
index b9e3888fd..346c085f8 100644
--- a/MediaBrowser.Api/Movies/CollectionService.cs
+++ b/MediaBrowser.Api/Movies/CollectionService.cs
@@ -1,5 +1,7 @@
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Model.Collections;
using MediaBrowser.Model.Querying;
using ServiceStack;
using System;
@@ -45,6 +47,7 @@ namespace MediaBrowser.Api.Movies
public Guid Id { get; set; }
}
+ [Authenticated]
public class CollectionService : BaseApiService
{
private readonly ICollectionManager _collectionManager;
@@ -56,17 +59,16 @@ namespace MediaBrowser.Api.Movies
_dtoService = dtoService;
}
- public object Post(CreateCollection request)
+ public async Task<object> Post(CreateCollection request)
{
- var task = _collectionManager.CreateCollection(new CollectionCreationOptions
+ var item = await _collectionManager.CreateCollection(new CollectionCreationOptions
{
IsLocked = request.IsLocked,
Name = request.Name,
ParentId = request.ParentId,
ItemIdList = (request.Ids ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => new Guid(i)).ToList()
- });
- var item = task.Result;
+ }).ConfigureAwait(false);
var dto = _dtoService.GetBaseItemDto(item, new List<ItemFields>());
@@ -90,9 +92,4 @@ namespace MediaBrowser.Api.Movies
Task.WaitAll(task);
}
}
-
- public class CollectionCreationResult
- {
- public string Id { get; set; }
- }
}
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
index db02ed428..f0bf22c5e 100644
--- a/MediaBrowser.Api/Movies/MoviesService.cs
+++ b/MediaBrowser.Api/Movies/MoviesService.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@@ -64,6 +65,7 @@ namespace MediaBrowser.Api.Movies
/// <summary>
/// Class MoviesService
/// </summary>
+ [Authenticated]
public class MoviesService : BaseApiService
{
/// <summary>
diff --git a/MediaBrowser.Api/Movies/TrailersService.cs b/MediaBrowser.Api/Movies/TrailersService.cs
index 05e6a9577..b0ee6b6d5 100644
--- a/MediaBrowser.Api/Movies/TrailersService.cs
+++ b/MediaBrowser.Api/Movies/TrailersService.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using ServiceStack;
@@ -18,6 +19,7 @@ namespace MediaBrowser.Api.Movies
/// <summary>
/// Class TrailersService
/// </summary>
+ [Authenticated]
public class TrailersService : BaseApiService
{
/// <summary>
diff --git a/MediaBrowser.Api/Music/AlbumsService.cs b/MediaBrowser.Api/Music/AlbumsService.cs
index 0732c951a..34a933dee 100644
--- a/MediaBrowser.Api/Music/AlbumsService.cs
+++ b/MediaBrowser.Api/Music/AlbumsService.cs
@@ -2,10 +2,10 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using ServiceStack;
using System;
-using System.Collections.Generic;
using System.Linq;
namespace MediaBrowser.Api.Music
@@ -15,6 +15,7 @@ namespace MediaBrowser.Api.Music
{
}
+ [Authenticated]
public class AlbumsService : BaseApiService
{
/// <summary>
diff --git a/MediaBrowser.Api/Music/InstantMixService.cs b/MediaBrowser.Api/Music/InstantMixService.cs
index f50c87f47..f34242242 100644
--- a/MediaBrowser.Api/Music/InstantMixService.cs
+++ b/MediaBrowser.Api/Music/InstantMixService.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Querying;
using ServiceStack;
using System.Collections.Generic;
@@ -33,6 +34,21 @@ namespace MediaBrowser.Api.Music
public string Name { get; set; }
}
+ [Route("/Artists/InstantMix", "GET", Summary = "Creates an instant playlist based on a given artist")]
+ public class GetInstantMixFromArtistId : BaseGetSimilarItems
+ {
+ [ApiMember(Name = "Id", Description = "The artist Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string Id { get; set; }
+ }
+
+ [Route("/MusicGenres/InstantMix", "GET", Summary = "Creates an instant playlist based on a music genre")]
+ public class GetInstantMixFromMusicGenreId : BaseGetSimilarItems
+ {
+ [ApiMember(Name = "Id", Description = "The genre Id", IsRequired = true, DataType = "string", ParameterType = "querypath", Verb = "GET")]
+ public string Id { get; set; }
+ }
+
+ [Authenticated]
public class InstantMixService : BaseApiService
{
private readonly IUserManager _userManager;
@@ -49,6 +65,28 @@ namespace MediaBrowser.Api.Music
_libraryManager = libraryManager;
}
+ public object Get(GetInstantMixFromArtistId request)
+ {
+ var item = (MusicArtist)_libraryManager.GetItemById(request.Id);
+
+ var user = _userManager.GetUserById(request.UserId.Value);
+
+ var items = _musicManager.GetInstantMixFromArtist(item.Name, user);
+
+ return GetResult(items, user, request);
+ }
+
+ public object Get(GetInstantMixFromMusicGenreId request)
+ {
+ var item = (MusicGenre)_libraryManager.GetItemById(request.Id);
+
+ var user = _userManager.GetUserById(request.UserId.Value);
+
+ var items = _musicManager.GetInstantMixFromGenres(new[] { item.Name }, user);
+
+ return GetResult(items, user, request);
+ }
+
public object Get(GetInstantMixFromSong request)
{
var item = (Audio)_libraryManager.GetItemById(request.Id);
diff --git a/MediaBrowser.Api/NotificationsService.cs b/MediaBrowser.Api/NotificationsService.cs
index 28edb61dd..51a080106 100644
--- a/MediaBrowser.Api/NotificationsService.cs
+++ b/MediaBrowser.Api/NotificationsService.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Model.Notifications;
using ServiceStack;
@@ -82,6 +83,7 @@ namespace MediaBrowser.Api
public string Ids { get; set; }
}
+ [Authenticated]
public class NotificationsService : BaseApiService
{
private readonly INotificationsRepository _notificationsRepo;
diff --git a/MediaBrowser.Api/PackageReviewService.cs b/MediaBrowser.Api/PackageReviewService.cs
index 94ff1b62e..112a2c5ce 100644
--- a/MediaBrowser.Api/PackageReviewService.cs
+++ b/MediaBrowser.Api/PackageReviewService.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Constants;
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Serialization;
using ServiceStack;
@@ -96,6 +97,7 @@ namespace MediaBrowser.Api
}
+ [Authenticated]
public class PackageReviewService : BaseApiService
{
private readonly IHttpClient _httpClient;
diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs
index b54b05fcf..84b42baa3 100644
--- a/MediaBrowser.Api/PackageService.cs
+++ b/MediaBrowser.Api/PackageService.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Updates;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Updates;
using ServiceStack;
using System;
@@ -121,6 +122,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class PackageService
/// </summary>
+ [Authenticated]
public class PackageService : BaseApiService
{
private readonly IInstallationManager _installationManager;
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index c016f67ab..31a81de73 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -13,7 +13,6 @@ using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Library;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.MediaInfo;
using System;
@@ -123,7 +122,11 @@ namespace MediaBrowser.Api.Playback
var outputFileExtension = GetOutputFileExtension(state);
- return Path.Combine(folder, GetCommandLineArguments("dummy\\dummy", state, false).GetMD5() + (outputFileExtension ?? string.Empty).ToLower());
+ var data = GetCommandLineArguments("dummy\\dummy", state, false);
+
+ data += "-" + (state.Request.DeviceId ?? string.Empty);
+
+ return Path.Combine(folder, data.GetMD5().ToString("N") + (outputFileExtension ?? string.Empty).ToLower());
}
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
@@ -138,14 +141,9 @@ namespace MediaBrowser.Api.Playback
{
var time = request.StartTimeTicks;
- if (time.HasValue)
+ if (time.HasValue && time.Value > 0)
{
- var seconds = TimeSpan.FromTicks(time.Value).TotalSeconds;
-
- if (seconds > 0)
- {
- return string.Format("-ss {0}", seconds.ToString(UsCulture));
- }
+ return string.Format("-ss {0}", MediaEncoder.GetTimeParameter(time.Value));
}
return string.Empty;
@@ -319,7 +317,7 @@ namespace MediaBrowser.Api.Playback
switch (qualitySetting)
{
case EncodingQuality.HighSpeed:
- param = "-preset ultrafast";
+ param = "-preset superfast";
break;
case EncodingQuality.HighQuality:
param = "-preset superfast";
@@ -350,16 +348,16 @@ namespace MediaBrowser.Api.Playback
var profileScore = 0;
string crf;
+ var qmin = "0";
+ var qmax = "50";
switch (qualitySetting)
{
case EncodingQuality.HighSpeed:
- crf = "12";
- profileScore = 2;
+ crf = "10";
break;
case EncodingQuality.HighQuality:
- crf = "8";
- profileScore = 1;
+ crf = "6";
break;
case EncodingQuality.MaxQuality:
crf = "4";
@@ -371,14 +369,17 @@ namespace MediaBrowser.Api.Playback
if (isVc1)
{
profileScore++;
- // Max of 2
- profileScore = Math.Min(profileScore, 2);
}
+ // Max of 2
+ profileScore = Math.Min(profileScore, 2);
+
// http://www.webmproject.org/docs/encoder-parameters/
- param = string.Format("-speed 16 -quality good -profile:v {0} -slices 8 -crf {1}",
+ param = string.Format("-speed 16 -quality good -profile:v {0} -slices 8 -crf {1} -qmin {2} -qmax {3}",
profileScore.ToString(UsCulture),
- crf);
+ crf,
+ qmin,
+ qmax);
}
else if (string.Equals(videoCodec, "mpeg4", StringComparison.OrdinalIgnoreCase))
@@ -469,11 +470,11 @@ namespace MediaBrowser.Api.Playback
/// </summary>
/// <param name="state">The state.</param>
/// <param name="outputVideoCodec">The output video codec.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
+ /// <param name="allowTimeStampCopy">if set to <c>true</c> [allow time stamp copy].</param>
/// <returns>System.String.</returns>
protected string GetOutputSizeParam(StreamState state,
string outputVideoCodec,
- CancellationToken cancellationToken)
+ bool allowTimeStampCopy = true)
{
// http://sonnati.wordpress.com/2012/10/19/ffmpeg-the-swiss-army-knife-of-internet-streaming-part-vi/
@@ -562,11 +563,14 @@ namespace MediaBrowser.Api.Playback
if (state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream)
{
- var subParam = GetTextSubtitleParam(state, cancellationToken);
+ var subParam = GetTextSubtitleParam(state);
filters.Add(subParam);
- output += " -copyts";
+ if (allowTimeStampCopy)
+ {
+ output += " -copyts";
+ }
}
if (filters.Count > 0)
@@ -581,12 +585,10 @@ namespace MediaBrowser.Api.Playback
/// Gets the text subtitle param.
/// </summary>
/// <param name="state">The state.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>System.String.</returns>
- protected string GetTextSubtitleParam(StreamState state,
- CancellationToken cancellationToken)
+ protected string GetTextSubtitleParam(StreamState state)
{
- var seconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds;
+ var seconds = Math.Round(TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds);
if (state.SubtitleStream.IsExternal)
{
@@ -604,17 +606,17 @@ namespace MediaBrowser.Api.Playback
}
}
- // TODO: Perhaps also use original_size=1920x800
+ // TODO: Perhaps also use original_size=1920x800 ??
return string.Format("subtitles=filename='{0}'{1},setpts=PTS -{2}/TB",
subtitlePath.Replace('\\', '/').Replace(":/", "\\:/"),
charsetParam,
- Math.Round(seconds).ToString(UsCulture));
+ seconds.ToString(UsCulture));
}
return string.Format("subtitles='{0}:si={1}',setpts=PTS -{2}/TB",
state.MediaPath.Replace('\\', '/').Replace(":/", "\\:/"),
state.InternalSubtitleStreamOffset.ToString(UsCulture),
- Math.Round(seconds).ToString(UsCulture));
+ seconds.ToString(UsCulture));
}
/// <summary>
@@ -623,7 +625,7 @@ namespace MediaBrowser.Api.Playback
/// <param name="state">The state.</param>
/// <param name="outputVideoCodec">The output video codec.</param>
/// <returns>System.String.</returns>
- protected string GetInternalGraphicalSubtitleParam(StreamState state, string outputVideoCodec)
+ protected string GetGraphicalSubtitleParam(StreamState state, string outputVideoCodec)
{
var outputSizeParam = string.Empty;
@@ -632,7 +634,7 @@ namespace MediaBrowser.Api.Playback
// Add resolution params, if specified
if (request.Width.HasValue || request.Height.HasValue || request.MaxHeight.HasValue || request.MaxWidth.HasValue)
{
- outputSizeParam = GetOutputSizeParam(state, outputVideoCodec, CancellationToken.None).TrimEnd('"');
+ outputSizeParam = GetOutputSizeParam(state, outputVideoCodec).TrimEnd('"');
outputSizeParam = "," + outputSizeParam.Substring(outputSizeParam.IndexOf("scale", StringComparison.OrdinalIgnoreCase));
}
@@ -772,6 +774,11 @@ namespace MediaBrowser.Api.Playback
return "copy";
}
+ protected virtual bool SupportsThrottling
+ {
+ get { return false; }
+ }
+
/// <summary>
/// Gets the input argument.
/// </summary>
@@ -779,6 +786,19 @@ namespace MediaBrowser.Api.Playback
/// <returns>System.String.</returns>
protected string GetInputArgument(StreamState state)
{
+ if (state.InputProtocol == MediaProtocol.File &&
+ state.RunTimeTicks.HasValue &&
+ state.VideoType == VideoType.VideoFile &&
+ !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
+ {
+ if (state.RunTimeTicks.Value >= TimeSpan.FromMinutes(5).Ticks && state.IsInputVideo)
+ {
+ var url = "http://localhost:" + ServerConfigurationManager.Configuration.HttpServerPortNumber.ToString(UsCulture) + "/mediabrowser/videos/" + state.Request.Id + "/stream?static=true&Throttle=true&mediaSourceId=" + state.Request.MediaSourceId;
+
+ return string.Format("\"{0}\"", url);
+ }
+ }
+
var protocol = state.InputProtocol;
var inputPath = new[] { state.MediaPath };
@@ -794,6 +814,81 @@ namespace MediaBrowser.Api.Playback
return MediaEncoder.GetInputArgument(inputPath, protocol);
}
+ private async Task AcquireResources(StreamState state, CancellationTokenSource cancellationTokenSource)
+ {
+ if (state.VideoType == VideoType.Iso && state.IsoType.HasValue && IsoManager.CanMount(state.MediaPath))
+ {
+ state.IsoMount = await IsoManager.Mount(state.MediaPath, cancellationTokenSource.Token).ConfigureAwait(false);
+ }
+
+ if (string.IsNullOrEmpty(state.MediaPath))
+ {
+ var checkCodecs = false;
+
+ if (string.Equals(state.ItemType, typeof(LiveTvChannel).Name))
+ {
+ var streamInfo = await LiveTvManager.GetChannelStream(state.Request.Id, cancellationTokenSource.Token).ConfigureAwait(false);
+
+ state.LiveTvStreamId = streamInfo.Id;
+
+ if (!string.IsNullOrEmpty(streamInfo.Path))
+ {
+ state.MediaPath = streamInfo.Path;
+ state.InputProtocol = MediaProtocol.File;
+
+ await Task.Delay(1500, cancellationTokenSource.Token).ConfigureAwait(false);
+ }
+ else if (!string.IsNullOrEmpty(streamInfo.Url))
+ {
+ state.MediaPath = streamInfo.Url;
+ state.InputProtocol = MediaProtocol.Http;
+ }
+
+ AttachMediaStreamInfo(state, streamInfo.MediaStreams, state.VideoRequest, state.RequestedUrl);
+ checkCodecs = true;
+ }
+
+ else if (string.Equals(state.ItemType, typeof(LiveTvVideoRecording).Name) ||
+ string.Equals(state.ItemType, typeof(LiveTvAudioRecording).Name))
+ {
+ var streamInfo = await LiveTvManager.GetRecordingStream(state.Request.Id, cancellationTokenSource.Token).ConfigureAwait(false);
+
+ state.LiveTvStreamId = streamInfo.Id;
+
+ if (!string.IsNullOrEmpty(streamInfo.Path))
+ {
+ state.MediaPath = streamInfo.Path;
+ state.InputProtocol = MediaProtocol.File;
+
+ await Task.Delay(1500, cancellationTokenSource.Token).ConfigureAwait(false);
+ }
+ else if (!string.IsNullOrEmpty(streamInfo.Url))
+ {
+ state.MediaPath = streamInfo.Url;
+ state.InputProtocol = MediaProtocol.Http;
+ }
+
+ AttachMediaStreamInfo(state, streamInfo.MediaStreams, state.VideoRequest, state.RequestedUrl);
+ checkCodecs = true;
+ }
+
+ var videoRequest = state.VideoRequest;
+
+ if (videoRequest != null && checkCodecs)
+ {
+ if (state.VideoStream != null && CanStreamCopyVideo(videoRequest, state.VideoStream))
+ {
+ state.OutputVideoCodec = "copy";
+ }
+
+ if (state.AudioStream != null && CanStreamCopyAudio(videoRequest, state.AudioStream, state.SupportedAudioCodecs))
+ {
+ state.OutputAudioCodec = "copy";
+ }
+ }
+ }
+ }
+
/// <summary>
/// Starts the FFMPEG.
/// </summary>
@@ -811,10 +906,7 @@ namespace MediaBrowser.Api.Playback
Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
- if (state.VideoType == VideoType.Iso && state.IsoType.HasValue && IsoManager.CanMount(state.MediaPath))
- {
- state.IsoMount = await IsoManager.Mount(state.MediaPath, cancellationTokenSource.Token).ConfigureAwait(false);
- }
+ await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false);
var commandLineArgs = GetCommandLineArguments(outputPath, state, true);
@@ -849,7 +941,6 @@ namespace MediaBrowser.Api.Playback
ApiEntryPoint.Instance.OnTranscodeBeginning(outputPath,
TranscodingJobType,
process,
- state.Request.StartTimeTicks,
state.Request.DeviceId,
state,
cancellationTokenSource);
@@ -866,7 +957,7 @@ namespace MediaBrowser.Api.Playback
var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(commandLineLogMessage + Environment.NewLine + Environment.NewLine);
await state.LogFileStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationTokenSource.Token).ConfigureAwait(false);
- process.Exited += (sender, args) => OnFfMpegProcessExited(process, state);
+ process.Exited += (sender, args) => OnFfMpegProcessExited(process, state, outputPath);
try
{
@@ -892,18 +983,6 @@ namespace MediaBrowser.Api.Playback
{
await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false);
}
-
- // Allow a small amount of time to buffer a little
- if (state.IsInputVideo)
- {
- await Task.Delay(500, cancellationTokenSource.Token).ConfigureAwait(false);
- }
-
- // This is arbitrary, but add a little buffer time when internet streaming
- if (state.InputProtocol != MediaProtocol.File)
- {
- await Task.Delay(3000, cancellationTokenSource.Token).ConfigureAwait(false);
- }
}
private async void StartStreamingLog(StreamState state, Stream source, Stream target)
@@ -1061,7 +1140,8 @@ namespace MediaBrowser.Api.Playback
// Make sure we don't request a bitrate higher than the source
var currentBitrate = audioStream == null ? request.AudioBitRate.Value : audioStream.BitRate ?? request.AudioBitRate.Value;
- return Math.Min(currentBitrate, request.AudioBitRate.Value);
+ return request.AudioBitRate.Value;
+ //return Math.Min(currentBitrate, request.AudioBitRate.Value);
}
return null;
@@ -1091,8 +1171,16 @@ namespace MediaBrowser.Api.Playback
/// </summary>
/// <param name="process">The process.</param>
/// <param name="state">The state.</param>
- private void OnFfMpegProcessExited(Process process, StreamState state)
+ /// <param name="outputPath">The output path.</param>
+ private void OnFfMpegProcessExited(Process process, StreamState state, string outputPath)
{
+ var job = ApiEntryPoint.Instance.GetTranscodingJob(outputPath, TranscodingJobType);
+
+ if (job != null)
+ {
+ job.HasExited = true;
+ }
+
Logger.Debug("Disposing stream resources");
state.Dispose();
@@ -1126,13 +1214,13 @@ namespace MediaBrowser.Api.Playback
return state.VideoRequest.Framerate.Value;
}
- var maxrate = state.VideoRequest.MaxFramerate ?? 23.97602;
+ var maxrate = state.VideoRequest.MaxFramerate;
- if (state.VideoStream != null)
+ if (maxrate.HasValue && state.VideoStream != null)
{
var contentRate = state.VideoStream.AverageFrameRate ?? state.VideoStream.RealFrameRate;
- if (contentRate.HasValue && contentRate.Value > maxrate)
+ if (contentRate.HasValue && contentRate.Value > maxrate.Value)
{
return maxrate;
}
@@ -1330,8 +1418,6 @@ namespace MediaBrowser.Api.Playback
ParseParams(request);
}
- var user = AuthorizationRequestFilterAttribute.GetCurrentUser(Request, UserManager);
-
var url = Request.PathInfo;
if (string.IsNullOrEmpty(request.AudioCodec))
@@ -1353,13 +1439,10 @@ namespace MediaBrowser.Api.Playback
var item = LibraryManager.GetItemById(request.Id);
- if (user != null && item.GetPlayAccess(user) != PlayAccess.Full)
- {
- throw new ArgumentException(string.Format("{0} is not allowed to play media.", user.Name));
- }
-
List<MediaStream> mediaStreams = null;
+ state.ItemType = item.GetType().Name;
+
if (item is ILiveTvRecording)
{
var recording = await LiveTvManager.GetInternalRecording(request.Id, cancellationToken).ConfigureAwait(false);
@@ -1376,16 +1459,8 @@ namespace MediaBrowser.Api.Playback
mediaStreams = source.MediaStreams;
- if (string.IsNullOrWhiteSpace(path) && string.IsNullOrWhiteSpace(mediaUrl))
- {
- var streamInfo = await LiveTvManager.GetRecordingStream(request.Id, cancellationToken).ConfigureAwait(false);
-
- state.LiveTvStreamId = streamInfo.Id;
- mediaStreams = streamInfo.MediaStreams;
-
- path = streamInfo.Path;
- mediaUrl = streamInfo.Url;
- }
+ // Just to prevent this from being null and causing other methods to fail
+ state.MediaPath = string.Empty;
if (!string.IsNullOrEmpty(path))
{
@@ -1397,17 +1472,20 @@ namespace MediaBrowser.Api.Playback
state.MediaPath = mediaUrl;
state.InputProtocol = MediaProtocol.Http;
}
-
- state.RunTimeTicks = recording.RunTimeTicks;
+ else
+ {
+ // No media info, so this is probably needed
+ state.DeInterlace = true;
+ }
if (recording.RecordingInfo.Status == RecordingStatus.InProgress)
{
- await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
+ state.ReadInputAtNativeFramerate = true;
}
- state.ReadInputAtNativeFramerate = recording.RecordingInfo.Status == RecordingStatus.InProgress;
+ state.RunTimeTicks = recording.RunTimeTicks;
+
state.OutputAudioSync = "1000";
- state.DeInterlace = true;
state.InputVideoSync = "-1";
state.InputAudioSync = "1";
state.InputContainer = recording.Container;
@@ -1418,40 +1496,27 @@ namespace MediaBrowser.Api.Playback
state.VideoType = VideoType.VideoFile;
state.IsInputVideo = string.Equals(channel.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
-
- var streamInfo = await LiveTvManager.GetChannelStream(request.Id, cancellationToken).ConfigureAwait(false);
-
- state.LiveTvStreamId = streamInfo.Id;
- mediaStreams = streamInfo.MediaStreams;
-
- if (!string.IsNullOrEmpty(streamInfo.Path))
- {
- state.MediaPath = streamInfo.Path;
- state.InputProtocol = MediaProtocol.File;
-
- await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
- }
- else if (!string.IsNullOrEmpty(streamInfo.Url))
- {
- state.MediaPath = streamInfo.Url;
- state.InputProtocol = MediaProtocol.Http;
- }
+ mediaStreams = new List<MediaStream>();
state.ReadInputAtNativeFramerate = true;
state.OutputAudioSync = "1000";
state.DeInterlace = true;
state.InputVideoSync = "-1";
state.InputAudioSync = "1";
+
+ // Just to prevent this from being null and causing other methods to fail
+ state.MediaPath = string.Empty;
}
else if (item is IChannelMediaItem)
{
- var source = await GetChannelMediaInfo(request.Id, request.MediaSourceId, cancellationToken).ConfigureAwait(false);
+ var mediaSource = await GetChannelMediaInfo(request.Id, request.MediaSourceId, cancellationToken).ConfigureAwait(false);
state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
- state.InputProtocol = source.Protocol;
- state.MediaPath = source.Path;
+ state.InputProtocol = mediaSource.Protocol;
+ state.MediaPath = mediaSource.Path;
state.RunTimeTicks = item.RunTimeTicks;
- state.RemoteHttpHeaders = source.RequiredHttpHeaders;
- mediaStreams = source.MediaStreams;
+ state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders;
+ state.InputBitrate = mediaSource.Bitrate;
+ mediaStreams = mediaSource.MediaStreams;
}
else
{
@@ -1465,6 +1530,7 @@ namespace MediaBrowser.Api.Playback
state.MediaPath = mediaSource.Path;
state.InputProtocol = mediaSource.Protocol;
state.InputContainer = mediaSource.Container;
+ state.InputBitrate = mediaSource.Bitrate;
if (item is Video)
{
@@ -1488,16 +1554,23 @@ namespace MediaBrowser.Api.Playback
state.RunTimeTicks = mediaSource.RunTimeTicks;
}
- if (string.Equals(state.InputContainer, "wtv", StringComparison.OrdinalIgnoreCase))
+ // If it's a wtv and we don't have media info, we will probably need to deinterlace
+ if (string.Equals(state.InputContainer, "wtv", StringComparison.OrdinalIgnoreCase) &&
+ mediaStreams.Count == 0)
{
state.DeInterlace = true;
}
+ if (state.InputProtocol == MediaProtocol.Rtmp)
+ {
+ state.ReadInputAtNativeFramerate = true;
+ }
+
var videoRequest = request as VideoStreamRequest;
AttachMediaStreamInfo(state, mediaStreams, videoRequest, url);
- state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 10;
+ state.SegmentLength = state.ReadInputAtNativeFramerate ? 5 : 7;
state.HlsListSize = state.ReadInputAtNativeFramerate ? 100 : 1440;
var container = Path.GetExtension(state.RequestedUrl);
@@ -1574,6 +1647,8 @@ namespace MediaBrowser.Api.Playback
{
state.AudioStream = GetMediaStream(mediaStreams, null, MediaStreamType.Audio, true);
}
+
+ state.AllMediaStreams = mediaStreams;
}
private async Task<MediaSourceInfo> GetChannelMediaInfo(string id,
@@ -1609,7 +1684,10 @@ namespace MediaBrowser.Api.Playback
// Can't stream copy if we're burning in subtitles
if (request.SubtitleStreamIndex.HasValue)
{
- return false;
+ if (request.SubtitleMethod == SubtitleDeliveryMethod.Encode)
+ {
+ return false;
+ }
}
// Source and target codecs must match
@@ -1886,7 +1964,8 @@ namespace MediaBrowser.Api.Playback
state.TargetPacketLength,
state.TranscodeSeekInfo,
state.IsTargetAnamorphic
- );
+
+ ).FirstOrDefault() ?? string.Empty;
}
foreach (var item in responseHeaders)
@@ -1911,12 +1990,6 @@ namespace MediaBrowser.Api.Playback
/// <param name="videoRequest">The video request.</param>
private void EnforceResolutionLimit(StreamState state, VideoStreamRequest videoRequest)
{
- // If enabled, allow whatever the client asks for
- if (ServerConfigurationManager.Configuration.AllowVideoUpscaling)
- {
- return;
- }
-
// Switch the incoming params to be ceilings rather than fixed values
videoRequest.MaxWidth = videoRequest.MaxWidth ?? videoRequest.Width;
videoRequest.MaxHeight = videoRequest.MaxHeight ?? videoRequest.Height;
@@ -1925,7 +1998,7 @@ namespace MediaBrowser.Api.Playback
videoRequest.Height = null;
}
- protected string GetInputModifier(StreamState state)
+ protected string GetInputModifier(StreamState state, bool genPts = true)
{
var inputModifier = string.Empty;
@@ -1945,9 +2018,9 @@ namespace MediaBrowser.Api.Playback
inputModifier += " " + GetFastSeekCommandLineParameter(state.Request);
inputModifier = inputModifier.Trim();
- if (state.VideoRequest != null)
+ if (state.VideoRequest != null && genPts)
{
- inputModifier += " -fflags genpts";
+ inputModifier += " -fflags +genpts";
}
if (!string.IsNullOrEmpty(state.InputAudioSync))
diff --git a/MediaBrowser.Api/Playback/BifService.cs b/MediaBrowser.Api/Playback/BifService.cs
new file mode 100644
index 000000000..057d81441
--- /dev/null
+++ b/MediaBrowser.Api/Playback/BifService.cs
@@ -0,0 +1,186 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.MediaEncoding;
+using ServiceStack;
+using System;
+using System.Collections.Concurrent;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Api.Playback
+{
+ [Route("/Videos/{Id}/index.bif", "GET")]
+ public class GetBifFile
+ {
+ [ApiMember(Name = "MediaSourceId", Description = "The media version id, if playing an alternate version", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string MediaSourceId { get; set; }
+
+ [ApiMember(Name = "MaxWidth", Description = "Optional. The maximum horizontal resolution of the encoded video.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? MaxWidth { get; set; }
+
+ [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Id { get; set; }
+ }
+
+ public class BifService : BaseApiService
+ {
+ private readonly IServerApplicationPaths _appPaths;
+ private readonly ILibraryManager _libraryManager;
+ private readonly IMediaEncoder _mediaEncoder;
+ private readonly IFileSystem _fileSystem;
+
+ public BifService(IServerApplicationPaths appPaths, ILibraryManager libraryManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem)
+ {
+ _appPaths = appPaths;
+ _libraryManager = libraryManager;
+ _mediaEncoder = mediaEncoder;
+ _fileSystem = fileSystem;
+ }
+
+ public object Get(GetBifFile request)
+ {
+ return ToStaticFileResult(GetBifFile(request).Result);
+ }
+
+ private async Task<string> GetBifFile(GetBifFile request)
+ {
+ var widthVal = request.MaxWidth.HasValue ? request.MaxWidth.Value.ToString(CultureInfo.InvariantCulture) : string.Empty;
+
+ var item = _libraryManager.GetItemById(request.Id);
+ var mediaSources = ((IHasMediaSources)item).GetMediaSources(false).ToList();
+ var mediaSource = mediaSources.FirstOrDefault(i => string.Equals(i.Id, request.MediaSourceId)) ?? mediaSources.First();
+
+ var path = Path.Combine(_appPaths.ImageCachePath, "bif", request.Id, request.MediaSourceId, widthVal, "index.bif");
+
+ if (File.Exists(path))
+ {
+ return path;
+ }
+
+ var protocol = mediaSource.Protocol;
+
+ var inputPath = MediaEncoderHelpers.GetInputArgument(mediaSource.Path, protocol, null, mediaSource.PlayableStreamFileNames);
+
+ var semaphore = GetLock(path);
+
+ await semaphore.WaitAsync().ConfigureAwait(false);
+
+ try
+ {
+ if (File.Exists(path))
+ {
+ return path;
+ }
+
+ await _mediaEncoder.ExtractVideoImagesOnInterval(inputPath, protocol, mediaSource.Video3DFormat,
+ TimeSpan.FromSeconds(10), Path.GetDirectoryName(path), "img_", request.MaxWidth, CancellationToken.None)
+ .ConfigureAwait(false);
+
+ var images = new DirectoryInfo(Path.GetDirectoryName(path))
+ .EnumerateFiles()
+ .Where(img => string.Equals(img.Extension, ".jpg", StringComparison.Ordinal))
+ .OrderBy(i => i.FullName)
+ .ToList();
+
+ using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ {
+ var magicNumber = new byte[] { 0x89, 0x42, 0x49, 0x46, 0x0d, 0x0a, 0x1a, 0x0a };
+ await fs.WriteAsync(magicNumber, 0, magicNumber.Length);
+
+ // version
+ var bytes = GetBytes(0);
+ await fs.WriteAsync(bytes, 0, bytes.Length);
+
+ // image count
+ bytes = GetBytes(images.Count);
+ await fs.WriteAsync(bytes, 0, bytes.Length);
+
+ // interval in ms
+ bytes = GetBytes(10000);
+ await fs.WriteAsync(bytes, 0, bytes.Length);
+
+ // reserved
+ for (var i = 20; i <= 63; i++)
+ {
+ bytes = new byte[] { 0x00 };
+ await fs.WriteAsync(bytes, 0, bytes.Length);
+ }
+
+ // write the bif index
+ var index = 0;
+ long imageOffset = 64 + (8 * images.Count) + 8;
+
+ foreach (var img in images)
+ {
+ bytes = GetBytes(index);
+ await fs.WriteAsync(bytes, 0, bytes.Length);
+
+ bytes = GetBytes(imageOffset);
+ await fs.WriteAsync(bytes, 0, bytes.Length);
+
+ imageOffset += img.Length;
+
+ index++;
+ }
+
+ bytes = new byte[] { 0xff, 0xff, 0xff, 0xff };
+ await fs.WriteAsync(bytes, 0, bytes.Length);
+
+ bytes = GetBytes(imageOffset);
+ await fs.WriteAsync(bytes, 0, bytes.Length);
+
+ // write the images
+ foreach (var img in images)
+ {
+ using (var imgStream = _fileSystem.GetFileStream(img.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
+ {
+ await imgStream.CopyToAsync(fs).ConfigureAwait(false);
+ }
+ }
+ }
+
+ return path;
+ }
+ finally
+ {
+ semaphore.Release();
+ }
+ }
+
+ private byte[] GetBytes(int value)
+ {
+ byte[] bytes = BitConverter.GetBytes(value);
+ if (BitConverter.IsLittleEndian)
+ Array.Reverse(bytes);
+ return bytes;
+ }
+
+ private byte[] GetBytes(long value)
+ {
+ var intVal = Convert.ToInt32(value);
+ return GetBytes(intVal);
+
+ //byte[] bytes = BitConverter.GetBytes(value);
+ //if (BitConverter.IsLittleEndian)
+ // Array.Reverse(bytes);
+ //return bytes;
+ }
+
+ private static readonly ConcurrentDictionary<string, SemaphoreSlim> SemaphoreLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
+
+ /// <summary>
+ /// Gets the lock.
+ /// </summary>
+ /// <param name="filename">The filename.</param>
+ /// <returns>System.Object.</returns>
+ private static SemaphoreSlim GetLock(string filename)
+ {
+ return SemaphoreLocks.GetOrAdd(filename, key => new SemaphoreSlim(1, 1));
+ }
+ }
+}
diff --git a/MediaBrowser.Api/Playback/EndlessStreamCopy.cs b/MediaBrowser.Api/Playback/EndlessStreamCopy.cs
deleted file mode 100644
index 40586261f..000000000
--- a/MediaBrowser.Api/Playback/EndlessStreamCopy.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Api.Playback
-{
- public class EndlessStreamCopy
- {
- public async Task CopyStream(Stream source, Stream target, CancellationToken cancellationToken)
- {
- long position = 0;
-
- while (!cancellationToken.IsCancellationRequested)
- {
- await source.CopyToAsync(target, 81920, cancellationToken).ConfigureAwait(false);
-
- var fsPosition = source.Position;
-
- var bytesRead = fsPosition - position;
-
- //Logger.Debug("Streamed {0} bytes from file {1}", bytesRead, path);
-
- if (bytesRead == 0)
- {
- await Task.Delay(100, cancellationToken).ConfigureAwait(false);
- }
-
- position = fsPosition;
- }
- }
- }
-}
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 39163a103..bd17dc0b2 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -1,14 +1,11 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
-using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
-using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.IO;
using System;
@@ -25,7 +22,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// </summary>
public abstract class BaseHlsService : BaseStreamingService
{
- protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder)
+ protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder)
+ : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder)
{
}
@@ -62,29 +60,33 @@ namespace MediaBrowser.Api.Playback.Hls
/// Processes the request.
/// </summary>
/// <param name="request">The request.</param>
+ /// <param name="isLive">if set to <c>true</c> [is live].</param>
/// <returns>System.Object.</returns>
- protected object ProcessRequest(StreamRequest request)
+ protected object ProcessRequest(StreamRequest request, bool isLive)
{
- return ProcessRequestAsync(request).Result;
+ return ProcessRequestAsync(request, isLive).Result;
}
- private static readonly SemaphoreSlim FfmpegStartLock = new SemaphoreSlim(1, 1);
/// <summary>
/// Processes the request async.
/// </summary>
/// <param name="request">The request.</param>
+ /// <param name="isLive">if set to <c>true</c> [is live].</param>
/// <returns>Task{System.Object}.</returns>
- /// <exception cref="ArgumentException">
- /// A video bitrate is required
+ /// <exception cref="ArgumentException">A video bitrate is required
/// or
- /// An audio bitrate is required
- /// </exception>
- private async Task<object> ProcessRequestAsync(StreamRequest request)
+ /// An audio bitrate is required</exception>
+ private async Task<object> ProcessRequestAsync(StreamRequest request, bool isLive)
{
var cancellationTokenSource = new CancellationTokenSource();
var state = await GetState(request, cancellationTokenSource.Token).ConfigureAwait(false);
+ if (isLive)
+ {
+ state.Request.StartTimeTicks = null;
+ }
+
var playlist = state.OutputFilePath;
if (File.Exists(playlist))
@@ -93,7 +95,7 @@ namespace MediaBrowser.Api.Playback.Hls
}
else
{
- await FfmpegStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
+ await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
try
{
if (File.Exists(playlist))
@@ -113,18 +115,34 @@ namespace MediaBrowser.Api.Playback.Hls
throw;
}
- await WaitForMinimumSegmentCount(playlist, GetSegmentWait(), cancellationTokenSource.Token).ConfigureAwait(false);
+ var waitCount = isLive ? 1 : GetSegmentWait();
+ await WaitForMinimumSegmentCount(playlist, waitCount, cancellationTokenSource.Token).ConfigureAwait(false);
}
}
finally
{
- FfmpegStartLock.Release();
+ ApiEntryPoint.Instance.TranscodingStartLock.Release();
+ }
+ }
+
+ if (isLive)
+ {
+ //var file = request.PlaylistId + Path.GetExtension(Request.PathInfo);
+
+ //file = Path.Combine(ServerConfigurationManager.ApplicationPaths.TranscodingTempPath, file);
+
+ try
+ {
+ return ResultFactory.GetStaticFileResult(Request, playlist, FileShare.ReadWrite);
+ }
+ finally
+ {
+ ApiEntryPoint.Instance.OnTranscodeEndRequest(playlist, TranscodingJobType.Hls);
}
}
- int audioBitrate;
- int videoBitrate;
- GetPlaylistBitrates(state, out audioBitrate, out videoBitrate);
+ var audioBitrate = state.OutputAudioBitrate ?? 0;
+ var videoBitrate = state.OutputVideoBitrate ?? 0;
var appendBaselineStream = false;
var baselineStreamBitrate = 64000;
@@ -165,37 +183,6 @@ namespace MediaBrowser.Api.Playback.Hls
return minimumSegmentCount;
}
- /// <summary>
- /// Gets the playlist bitrates.
- /// </summary>
- /// <param name="state">The state.</param>
- /// <param name="audioBitrate">The audio bitrate.</param>
- /// <param name="videoBitrate">The video bitrate.</param>
- protected void GetPlaylistBitrates(StreamState state, out int audioBitrate, out int videoBitrate)
- {
- var audioBitrateParam = state.OutputAudioBitrate;
- var videoBitrateParam = state.OutputVideoBitrate;
-
- if (!audioBitrateParam.HasValue)
- {
- if (state.AudioStream != null)
- {
- audioBitrateParam = state.AudioStream.BitRate;
- }
- }
-
- if (!videoBitrateParam.HasValue)
- {
- if (state.VideoStream != null)
- {
- videoBitrateParam = state.VideoStream.BitRate;
- }
- }
-
- audioBitrate = audioBitrateParam ?? 0;
- videoBitrate = videoBitrateParam ?? 0;
- }
-
private string GetMasterPlaylistFileText(string firstPlaylist, int bitrate, bool includeBaselineStream, int baselineStreamBitrate)
{
var builder = new StringBuilder();
@@ -223,50 +210,38 @@ namespace MediaBrowser.Api.Playback.Hls
protected async Task WaitForMinimumSegmentCount(string playlist, int segmentCount, CancellationToken cancellationToken)
{
+ Logger.Debug("Waiting for {0} segments in {1}", segmentCount, playlist);
+
while (true)
{
- cancellationToken.ThrowIfCancellationRequested();
-
- string fileText;
-
// 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 reader = new StreamReader(fileStream))
{
- fileText = await reader.ReadToEndAsync().ConfigureAwait(false);
- }
- }
+ var count = 0;
- if (CountStringOccurrences(fileText, "#EXTINF:") >= segmentCount)
- {
- break;
+ while (!reader.EndOfStream)
+ {
+ var line = await reader.ReadLineAsync().ConfigureAwait(false);
+
+ if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ count++;
+ if (count >= segmentCount)
+ {
+ Logger.Debug("Finished waiting for {0} segments in {1}", segmentCount, playlist);
+ return;
+ }
+ }
+ }
+ await Task.Delay(100, cancellationToken).ConfigureAwait(false);
+ }
}
-
- await Task.Delay(25, cancellationToken).ConfigureAwait(false);
}
}
/// <summary>
- /// Count occurrences of strings.
- /// </summary>
- /// <param name="text">The text.</param>
- /// <param name="pattern">The pattern.</param>
- /// <returns>System.Int32.</returns>
- private static int CountStringOccurrences(string text, string pattern)
- {
- // Loop through all instances of the string 'text'.
- var count = 0;
- var i = 0;
- while ((i = text.IndexOf(pattern, i, StringComparison.OrdinalIgnoreCase)) != -1)
- {
- i += pattern.Length;
- count++;
- }
- return count;
- }
-
- /// <summary>
/// Gets the command line arguments.
/// </summary>
/// <param name="outputPath">The output path.</param>
@@ -276,10 +251,10 @@ namespace MediaBrowser.Api.Playback.Hls
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
{
var hlsVideoRequest = state.VideoRequest as GetHlsVideoStream;
-
+
var itsOffsetMs = hlsVideoRequest == null
? 0
- : ((GetHlsVideoStream)state.VideoRequest).TimeStampOffsetMs;
+ : hlsVideoRequest.TimeStampOffsetMs;
var itsOffset = itsOffsetMs == 0 ? string.Empty : string.Format("-itsoffset {0} ", TimeSpan.FromMilliseconds(itsOffsetMs).TotalSeconds.ToString(UsCulture));
@@ -290,7 +265,15 @@ namespace MediaBrowser.Api.Playback.Hls
// If isEncoding is true we're actually starting ffmpeg
var startNumberParam = isEncoding ? GetStartNumber(state).ToString(UsCulture) : "0";
- var args = string.Format("{0} {1} -i {2} -map_metadata -1 -threads {3} {4} {5} -sc_threshold 0 {6} -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"",
+ var baseUrlParam = string.Empty;
+
+ if (state.Request is GetLiveHlsStream)
+ {
+ baseUrlParam = string.Format(" -hls_base_url \"{0}/\"",
+ "hls/" + Path.GetFileNameWithoutExtension(outputPath));
+ }
+
+ var args = string.Format("{0} {1} -i {2} -map_metadata -1 -threads {3} {4} {5} -sc_threshold 0 {6} -hls_time {7} -start_number {8} -hls_list_size {9}{10} -y \"{11}\"",
itsOffset,
inputModifier,
GetInputArgument(state),
@@ -301,6 +284,7 @@ namespace MediaBrowser.Api.Playback.Hls
state.SegmentLength.ToString(UsCulture),
startNumberParam,
state.HlsListSize.ToString(UsCulture),
+ baseUrlParam,
outputPath
).Trim();
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 352cbf365..134c28524 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -1,45 +1,46 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
+using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Api.Playback.Hls
{
- [Route("/Videos/{Id}/master.m3u8", "GET")]
- [Api(Description = "Gets a video stream using HTTP live streaming.")]
+ /// <summary>
+ /// Options is needed for chromecast. Threw Head in there since it's related
+ /// </summary>
+ [Route("/Videos/{Id}/master.m3u8", "GET", Summary = "Gets a video stream using HTTP live streaming.")]
+ [Route("/Videos/{Id}/master.m3u8", "HEAD", Summary = "Gets a video stream using HTTP live streaming.")]
public class GetMasterHlsVideoStream : VideoStreamRequest
{
- [ApiMember(Name = "BaselineStreamAudioBitRate", Description = "Optional. Specify the audio bitrate for the baseline stream.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? BaselineStreamAudioBitRate { get; set; }
+ public bool EnableAdaptiveBitrateStreaming { get; set; }
- [ApiMember(Name = "AppendBaselineStream", Description = "Optional. Whether or not to include a baseline audio-only stream in the master playlist.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool AppendBaselineStream { get; set; }
+ public GetMasterHlsVideoStream()
+ {
+ EnableAdaptiveBitrateStreaming = true;
+ }
}
- [Route("/Videos/{Id}/main.m3u8", "GET")]
- [Api(Description = "Gets a video stream using HTTP live streaming.")]
+ [Route("/Videos/{Id}/main.m3u8", "GET", Summary = "Gets a video stream using HTTP live streaming.")]
public class GetMainHlsVideoStream : VideoStreamRequest
{
}
- [Route("/Videos/{Id}/baseline.m3u8", "GET")]
- [Api(Description = "Gets a video stream using HTTP live streaming.")]
- public class GetBaselineHlsVideoStream : VideoStreamRequest
- {
- }
-
/// <summary>
/// Class GetHlsVideoSegment
/// </summary>
@@ -58,34 +59,48 @@ namespace MediaBrowser.Api.Playback.Hls
public class DynamicHlsService : BaseHlsService
{
- public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder)
+ public DynamicHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder)
+ : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder)
{
}
public object Get(GetMasterHlsVideoStream request)
{
- var result = GetAsync(request).Result;
+ var result = GetAsync(request, "GET").Result;
return result;
}
- public object Get(GetDynamicHlsVideoSegment request)
+ public object Head(GetMasterHlsVideoStream request)
{
- if (string.Equals("baseline", request.PlaylistId, StringComparison.OrdinalIgnoreCase))
- {
- return GetDynamicSegment(request, false).Result;
- }
+ var result = GetAsync(request, "HEAD").Result;
- return GetDynamicSegment(request, true).Result;
+ return result;
}
- private static readonly SemaphoreSlim FfmpegStartLock = new SemaphoreSlim(1, 1);
- private async Task<object> GetDynamicSegment(GetDynamicHlsVideoSegment request, bool isMain)
+ public object Get(GetMainHlsVideoStream request)
{
+ var result = GetPlaylistAsync(request, "main").Result;
+
+ return result;
+ }
+
+ public object Get(GetDynamicHlsVideoSegment request)
+ {
+ return GetDynamicSegment(request, request.SegmentId).Result;
+ }
+
+ private async Task<object> GetDynamicSegment(VideoStreamRequest request, string segmentId)
+ {
+ if ((request.StartTimeTicks ?? 0) > 0)
+ {
+ throw new ArgumentException("StartTimeTicks is not allowed.");
+ }
+
var cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;
- var index = int.Parse(request.SegmentId, NumberStyles.Integer, UsCulture);
+ var index = int.Parse(segmentId, NumberStyles.Integer, UsCulture);
var state = await GetState(request, cancellationToken).ConfigureAwait(false);
@@ -96,25 +111,35 @@ namespace MediaBrowser.Api.Playback.Hls
if (File.Exists(segmentPath))
{
ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType.Hls);
- return GetSegementResult(segmentPath);
+ return await GetSegmentResult(playlistPath, segmentPath, index, cancellationToken).ConfigureAwait(false);
}
- await FfmpegStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
+ await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
try
{
if (File.Exists(segmentPath))
{
ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlistPath, TranscodingJobType.Hls);
- return GetSegementResult(segmentPath);
+ return await GetSegmentResult(playlistPath, segmentPath, index, cancellationToken).ConfigureAwait(false);
}
else
{
- if (index == 0)
+ var currentTranscodingIndex = GetCurrentTranscodingIndex(playlistPath);
+
+ if (currentTranscodingIndex == null || index < currentTranscodingIndex.Value || (index - currentTranscodingIndex.Value) > 4)
{
// If the playlist doesn't already exist, startup ffmpeg
try
{
- ApiEntryPoint.Instance.KillTranscodingJobs(state.Request.DeviceId, false);
+ await ApiEntryPoint.Instance.KillTranscodingJobs(j => j.Type == TranscodingJobType.Hls && string.Equals(j.DeviceId, request.DeviceId, StringComparison.OrdinalIgnoreCase), p => !string.Equals(p, playlistPath, StringComparison.OrdinalIgnoreCase), false).ConfigureAwait(false);
+
+ if (currentTranscodingIndex.HasValue)
+ {
+ DeleteLastFile(playlistPath, 0);
+ }
+
+ var startSeconds = index * state.SegmentLength;
+ request.StartTimeTicks = TimeSpan.FromSeconds(startSeconds).Ticks;
await StartFfMpeg(state, playlistPath, cancellationTokenSource).ConfigureAwait(false);
}
@@ -124,13 +149,13 @@ namespace MediaBrowser.Api.Playback.Hls
throw;
}
- await WaitForMinimumSegmentCount(playlistPath, 2, cancellationTokenSource.Token).ConfigureAwait(false);
+ await WaitForMinimumSegmentCount(playlistPath, 1, cancellationTokenSource.Token).ConfigureAwait(false);
}
}
}
finally
{
- FfmpegStartLock.Release();
+ ApiEntryPoint.Instance.TranscodingStartLock.Release();
}
Logger.Info("waiting for {0}", segmentPath);
@@ -140,14 +165,88 @@ namespace MediaBrowser.Api.Playback.Hls
}
Logger.Info("returning {0}", segmentPath);
- return GetSegementResult(segmentPath);
+ return await GetSegmentResult(playlistPath, segmentPath, index, cancellationToken).ConfigureAwait(false);
+ }
+
+ public int? GetCurrentTranscodingIndex(string playlist)
+ {
+ var file = GetLastTranscodingFile(playlist, FileSystem);
+
+ if (file == null)
+ {
+ return null;
+ }
+
+ var playlistFilename = Path.GetFileNameWithoutExtension(playlist);
+
+ var indexString = Path.GetFileNameWithoutExtension(file.Name).Substring(playlistFilename.Length);
+
+ return int.Parse(indexString, NumberStyles.Integer, UsCulture);
+ }
+
+ private void DeleteLastFile(string path, int retryCount)
+ {
+ if (retryCount >= 5)
+ {
+ return;
+ }
+
+ var file = GetLastTranscodingFile(path, FileSystem);
+
+ if (file != null)
+ {
+ try
+ {
+ File.Delete(file.FullName);
+ }
+ catch (IOException ex)
+ {
+ Logger.ErrorException("Error deleting partial stream file(s) {0}", ex, file.FullName);
+
+ Thread.Sleep(100);
+ DeleteLastFile(path, retryCount + 1);
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error deleting partial stream file(s) {0}", ex, file.FullName);
+ }
+ }
+ }
+
+ private static FileInfo GetLastTranscodingFile(string playlist, IFileSystem fileSystem)
+ {
+ var folder = Path.GetDirectoryName(playlist);
+
+ try
+ {
+ return new DirectoryInfo(folder)
+ .EnumerateFiles("*", SearchOption.TopDirectoryOnly)
+ .Where(i => string.Equals(i.Extension, ".ts", StringComparison.OrdinalIgnoreCase))
+ .OrderByDescending(fileSystem.GetLastWriteTimeUtc)
+ .FirstOrDefault();
+ }
+ catch (DirectoryNotFoundException)
+ {
+ return null;
+ }
}
protected override int GetStartNumber(StreamState state)
{
- var request = (GetDynamicHlsVideoSegment) state.Request;
+ return GetStartNumber(state.VideoRequest);
+ }
+
+ private int GetStartNumber(VideoStreamRequest request)
+ {
+ var segmentId = "0";
+
+ var segmentRequest = request as GetDynamicHlsVideoSegment;
+ if (segmentRequest != null)
+ {
+ segmentId = segmentRequest.SegmentId;
+ }
- return int.Parse(request.SegmentId, NumberStyles.Integer, UsCulture);
+ return int.Parse(segmentId, NumberStyles.Integer, UsCulture);
}
private string GetSegmentPath(string playlist, int index)
@@ -159,75 +258,262 @@ namespace MediaBrowser.Api.Playback.Hls
return Path.Combine(folder, filename + index.ToString(UsCulture) + ".ts");
}
- private object GetSegementResult(string path)
+ private async Task<object> GetSegmentResult(string playlistPath, string segmentPath, int segmentIndex, CancellationToken cancellationToken)
+ {
+ // If all transcoding has completed, just return immediately
+ if (!IsTranscoding(playlistPath))
+ {
+ return ResultFactory.GetStaticFileResult(Request, segmentPath, FileShare.ReadWrite);
+ }
+
+ var segmentFilename = Path.GetFileName(segmentPath);
+
+ using (var fileStream = FileSystem.GetFileStream(playlistPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
+ {
+ using (var reader = new StreamReader(fileStream))
+ {
+ var text = await reader.ReadToEndAsync().ConfigureAwait(false);
+
+ // If it appears in the playlist, it's done
+ if (text.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ return ResultFactory.GetStaticFileResult(Request, segmentPath, FileShare.ReadWrite);
+ }
+ }
+ }
+
+ // if a different file is encoding, it's done
+ //var currentTranscodingIndex = GetCurrentTranscodingIndex(playlistPath);
+ //if (currentTranscodingIndex > segmentIndex)
+ //{
+ // return ResultFactory.GetStaticFileResult(Request, segmentPath, FileShare.ReadWrite);
+ //}
+
+ // Wait for the file to stop being written to, then stream it
+ var length = new FileInfo(segmentPath).Length;
+ var eofCount = 0;
+
+ while (eofCount < 10)
+ {
+ var info = new FileInfo(segmentPath);
+
+ if (!info.Exists)
+ {
+ break;
+ }
+
+ var newLength = info.Length;
+
+ if (newLength == length)
+ {
+ eofCount++;
+ }
+ else
+ {
+ eofCount = 0;
+ }
+
+ length = newLength;
+ await Task.Delay(100, cancellationToken).ConfigureAwait(false);
+ }
+
+ return ResultFactory.GetStaticFileResult(Request, segmentPath, FileShare.ReadWrite);
+ }
+
+ private bool IsTranscoding(string playlistPath)
{
- // TODO: Handle if it's currently being written to
- return ResultFactory.GetStaticFileResult(Request, path, FileShare.ReadWrite);
+ var job = ApiEntryPoint.Instance.GetTranscodingJob(playlistPath, TranscodingJobType);
+
+ return job != null && !job.HasExited;
}
- private async Task<object> GetAsync(GetMasterHlsVideoStream request)
+ private async Task<object> GetAsync(GetMasterHlsVideoStream request, string method)
{
var state = await GetState(request, CancellationToken.None).ConfigureAwait(false);
- int audioBitrate;
- int videoBitrate;
- GetPlaylistBitrates(state, out audioBitrate, out videoBitrate);
+ if (string.Equals(request.AudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
+ {
+ throw new ArgumentException("Audio codec copy is not allowed here.");
+ }
- var appendBaselineStream = false;
- var baselineStreamBitrate = 64000;
+ if (string.Equals(request.VideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
+ {
+ throw new ArgumentException("Video codec copy is not allowed here.");
+ }
- var hlsVideoRequest = state.VideoRequest as GetMasterHlsVideoStream;
- if (hlsVideoRequest != null)
+ if (string.IsNullOrEmpty(request.MediaSourceId))
{
- appendBaselineStream = hlsVideoRequest.AppendBaselineStream;
- baselineStreamBitrate = hlsVideoRequest.BaselineStreamAudioBitRate ?? baselineStreamBitrate;
+ throw new ArgumentException("MediaSourceId is required");
}
- var playlistText = GetMasterPlaylistFileText(videoBitrate + audioBitrate, appendBaselineStream, baselineStreamBitrate);
+ var playlistText = string.Empty;
+
+ if (string.Equals(method, "GET", StringComparison.OrdinalIgnoreCase))
+ {
+ var audioBitrate = state.OutputAudioBitrate ?? 0;
+ var videoBitrate = state.OutputVideoBitrate ?? 0;
+
+ playlistText = GetMasterPlaylistFileText(state, videoBitrate + audioBitrate);
+ }
return ResultFactory.GetResult(playlistText, Common.Net.MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
- private string GetMasterPlaylistFileText(int bitrate, bool includeBaselineStream, int baselineStreamBitrate)
+ private string GetMasterPlaylistFileText(StreamState state, int totalBitrate)
{
var builder = new StringBuilder();
builder.AppendLine("#EXTM3U");
- // Pad a little to satisfy the apple hls validator
- var paddedBitrate = Convert.ToInt32(bitrate * 1.05);
-
var queryStringIndex = Request.RawUrl.IndexOf('?');
var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex);
// Main stream
- builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + paddedBitrate.ToString(UsCulture));
- var playlistUrl = "main.m3u8" + queryString;
- builder.AppendLine(playlistUrl);
+ var playlistUrl = (state.RunTimeTicks ?? 0) > 0 ? "main.m3u8" : "live.m3u8";
+ playlistUrl += queryString;
+
+ var request = (GetMasterHlsVideoStream)state.Request;
+
+ var subtitleStreams = state.AllMediaStreams
+ .Where(i => i.IsTextSubtitleStream)
+ .ToList();
+
+ var subtitleGroup = subtitleStreams.Count > 0 && request.SubtitleMethod == SubtitleDeliveryMethod.Hls ?
+ "subs" :
+ null;
+
+ AppendPlaylist(builder, playlistUrl, totalBitrate, subtitleGroup);
- // Low bitrate stream
- if (includeBaselineStream)
+ if (EnableAdaptiveBitrateStreaming(state))
{
- builder.AppendLine("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + baselineStreamBitrate.ToString(UsCulture));
- playlistUrl = "baseline.m3u8" + queryString;
- builder.AppendLine(playlistUrl);
+ var requestedVideoBitrate = state.VideoRequest.VideoBitRate.Value;
+
+ // By default, vary by just 200k
+ var variation = GetBitrateVariation(totalBitrate);
+
+ var newBitrate = totalBitrate - variation;
+ var variantUrl = ReplaceBitrate(playlistUrl, requestedVideoBitrate, (requestedVideoBitrate - variation));
+ AppendPlaylist(builder, variantUrl, newBitrate, subtitleGroup);
+
+ variation *= 2;
+ newBitrate = totalBitrate - variation;
+ variantUrl = ReplaceBitrate(playlistUrl, requestedVideoBitrate, (requestedVideoBitrate - variation));
+ AppendPlaylist(builder, variantUrl, newBitrate, subtitleGroup);
+ }
+
+ if (!string.IsNullOrWhiteSpace(subtitleGroup))
+ {
+ AddSubtitles(state, subtitleStreams, builder);
}
return builder.ToString();
}
- public object Get(GetMainHlsVideoStream request)
+ private string ReplaceBitrate(string url, int oldValue, int newValue)
{
- var result = GetPlaylistAsync(request, "main").Result;
+ return url.Replace(
+ "videobitrate=" + oldValue.ToString(UsCulture),
+ "videobitrate=" + newValue.ToString(UsCulture),
+ StringComparison.OrdinalIgnoreCase);
+ }
- return result;
+ private void AddSubtitles(StreamState state, IEnumerable<MediaStream> subtitles, StringBuilder builder)
+ {
+ var selectedIndex = state.SubtitleStream == null ? (int?)null : state.SubtitleStream.Index;
+
+ foreach (var stream in subtitles)
+ {
+ const string format = "#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID=\"subs\",NAME=\"{0}\",DEFAULT={1},FORCED={2},URI=\"{3}\",LANGUAGE=\"{4}\"";
+
+ var name = stream.Language;
+
+ var isDefault = selectedIndex.HasValue && selectedIndex.Value == stream.Index;
+ var isForced = stream.IsForced;
+
+ if (string.IsNullOrWhiteSpace(name)) name = stream.Codec ?? "Unknown";
+
+ var url = string.Format("{0}/Subtitles/{1}/subtitles.m3u8?SegmentLength={2}",
+ state.Request.MediaSourceId,
+ stream.Index.ToString(UsCulture),
+ 30.ToString(UsCulture));
+
+ var line = string.Format(format,
+ name,
+ isDefault ? "YES" : "NO",
+ isForced ? "YES" : "NO",
+ url,
+ stream.Language ?? "Unknown");
+
+ builder.AppendLine(line);
+ }
}
- public object Get(GetBaselineHlsVideoStream request)
+ private bool EnableAdaptiveBitrateStreaming(StreamState state)
{
- var result = GetPlaylistAsync(request, "baseline").Result;
+ var request = state.Request as GetMasterHlsVideoStream;
- return result;
+ if (request != null && !request.EnableAdaptiveBitrateStreaming)
+ {
+ return false;
+ }
+
+ if (string.IsNullOrWhiteSpace(state.MediaPath))
+ {
+ // Opening live streams is so slow it's not even worth it
+ return false;
+ }
+
+ return state.VideoRequest.VideoBitRate.HasValue;
+ }
+
+ private void AppendPlaylist(StringBuilder builder, string url, int bitrate, string subtitleGroup)
+ {
+ var header = "#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=" + bitrate.ToString(UsCulture);
+
+ if (!string.IsNullOrWhiteSpace(subtitleGroup))
+ {
+ header += string.Format(",SUBTITLES=\"{0}\"", subtitleGroup);
+ }
+
+ builder.AppendLine(header);
+ builder.AppendLine(url);
+ }
+
+ private int GetBitrateVariation(int bitrate)
+ {
+ // By default, vary by just 50k
+ var variation = 50000;
+
+ if (bitrate >= 10000000)
+ {
+ variation = 2000000;
+ }
+ else if (bitrate >= 5000000)
+ {
+ variation = 1500000;
+ }
+ else if (bitrate >= 3000000)
+ {
+ variation = 1000000;
+ }
+ else if (bitrate >= 2000000)
+ {
+ variation = 500000;
+ }
+ else if (bitrate >= 1000000)
+ {
+ variation = 300000;
+ }
+ else if (bitrate >= 600000)
+ {
+ variation = 200000;
+ }
+ else if (bitrate >= 400000)
+ {
+ variation = 100000;
+ }
+
+ return variation;
}
private async Task<object> GetPlaylistAsync(VideoStreamRequest request, string name)
@@ -240,6 +526,7 @@ namespace MediaBrowser.Api.Playback.Hls
builder.AppendLine("#EXT-X-VERSION:3");
builder.AppendLine("#EXT-X-TARGETDURATION:" + state.SegmentLength.ToString(UsCulture));
builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
+ builder.AppendLine("#EXT-X-ALLOW-CACHE:NO");
var queryStringIndex = Request.RawUrl.IndexOf('?');
var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex);
@@ -252,7 +539,7 @@ namespace MediaBrowser.Api.Playback.Hls
{
var length = seconds >= state.SegmentLength ? state.SegmentLength : seconds;
- builder.AppendLine("#EXTINF:" + length.ToString(UsCulture));
+ builder.AppendLine("#EXTINF:" + length.ToString(UsCulture) + ",");
builder.AppendLine(string.Format("hlsdynamic/{0}/{1}.ts{2}",
@@ -312,9 +599,8 @@ namespace MediaBrowser.Api.Playback.Hls
return IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf h264_mp4toannexb" : "-codec:v:0 copy";
}
- var keyFrameArg = state.ReadInputAtNativeFramerate ?
- " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+1))" :
- " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
+ var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
+ state.SegmentLength.ToString(UsCulture));
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
@@ -323,19 +609,51 @@ namespace MediaBrowser.Api.Playback.Hls
// Add resolution params, if specified
if (!hasGraphicalSubs)
{
- args += GetOutputSizeParam(state, codec, CancellationToken.None);
+ args += GetOutputSizeParam(state, codec, false);
}
// This is for internal graphical subs
if (hasGraphicalSubs)
{
- args += GetInternalGraphicalSubtitleParam(state, codec);
+ args += GetGraphicalSubtitleParam(state, codec);
}
return args;
}
/// <summary>
+ /// Gets the command line arguments.
+ /// </summary>
+ /// <param name="outputPath">The output path.</param>
+ /// <param name="state">The state.</param>
+ /// <param name="isEncoding">if set to <c>true</c> [is encoding].</param>
+ /// <returns>System.String.</returns>
+ protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
+ {
+ var threads = GetNumberOfThreads(state, false);
+
+ var inputModifier = GetInputModifier(state);
+
+ // If isEncoding is true we're actually starting ffmpeg
+ var startNumberParam = isEncoding ? GetStartNumber(state).ToString(UsCulture) : "0";
+
+ var args = string.Format("{0} -i {1} -map_metadata -1 -threads {2} {3} {4} -copyts -flags -global_header {5} -hls_time {6} -start_number {7} -hls_list_size {8} -y \"{9}\"",
+ inputModifier,
+ GetInputArgument(state),
+ threads,
+ GetMapArgs(state),
+ GetVideoArguments(state),
+ GetAudioArguments(state),
+ state.SegmentLength.ToString(UsCulture),
+ startNumberParam,
+ state.HlsListSize.ToString(UsCulture),
+ outputPath
+ ).Trim();
+
+ return args;
+ }
+
+ /// <summary>
/// Gets the segment file extension.
/// </summary>
/// <param name="state">The state.</param>
@@ -344,5 +662,13 @@ namespace MediaBrowser.Api.Playback.Hls
{
return ".ts";
}
+
+ protected override TranscodingJobType TranscodingJobType
+ {
+ get
+ {
+ return TranscodingJobType.Hls;
+ }
+ }
}
}
diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs
index 2099bcd3a..f28352588 100644
--- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs
+++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs
@@ -74,7 +74,9 @@ namespace MediaBrowser.Api.Playback.Hls
public void Delete(StopEncodingProcess request)
{
- ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, true);
+ var task = ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, path => true, true);
+
+ Task.WaitAll(task);
}
/// <summary>
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index 2379fb005..2e9b9d36f 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -10,7 +10,6 @@ using ServiceStack;
using System;
using System.IO;
using System.Linq;
-using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Api.Playback.Hls
@@ -32,6 +31,12 @@ namespace MediaBrowser.Api.Playback.Hls
public int TimeStampOffsetMs { get; set; }
}
+ [Route("/Videos/{Id}/live.m3u8", "GET")]
+ [Api(Description = "Gets a video stream using HTTP live streaming.")]
+ public class GetLiveHlsStream : VideoStreamRequest
+ {
+ }
+
/// <summary>
/// Class GetHlsVideoSegment
/// </summary>
@@ -105,7 +110,12 @@ namespace MediaBrowser.Api.Playback.Hls
/// <returns>System.Object.</returns>
public object Get(GetHlsVideoStream request)
{
- return ProcessRequest(request);
+ return ProcessRequest(request, false);
+ }
+
+ public object Get(GetLiveHlsStream request)
+ {
+ return ProcessRequest(request, true);
}
/// <summary>
@@ -159,9 +169,8 @@ namespace MediaBrowser.Api.Playback.Hls
return IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf h264_mp4toannexb" : "-codec:v:0 copy";
}
- var keyFrameArg = state.ReadInputAtNativeFramerate ?
- " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+1))" :
- " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
+ var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
+ state.SegmentLength.ToString(UsCulture));
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
@@ -170,13 +179,13 @@ namespace MediaBrowser.Api.Playback.Hls
// Add resolution params, if specified
if (!hasGraphicalSubs)
{
- args += GetOutputSizeParam(state, codec, CancellationToken.None);
+ args += GetOutputSizeParam(state, codec);
}
// This is for internal graphical subs
if (hasGraphicalSubs)
{
- args += GetInternalGraphicalSubtitleParam(state, codec);
+ args += GetGraphicalSubtitleParam(state, codec);
}
return args;
diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
index 79cf4170b..997cc7ca4 100644
--- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
@@ -7,6 +7,7 @@ using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
using ServiceStack.Web;
@@ -26,7 +27,8 @@ namespace MediaBrowser.Api.Playback.Progressive
protected readonly IImageProcessor ImageProcessor;
protected readonly IHttpClient HttpClient;
- protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IImageProcessor imageProcessor, IHttpClient httpClient) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder)
+ protected BaseProgressiveStreamingService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder, IImageProcessor imageProcessor, IHttpClient httpClient)
+ : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder)
{
ImageProcessor = imageProcessor;
HttpClient = httpClient;
@@ -52,23 +54,23 @@ namespace MediaBrowser.Api.Playback.Progressive
if (isVideoRequest)
{
var videoCodec = state.VideoRequest.VideoCodec;
-
- if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase))
- {
- return ".ts";
- }
- if (string.Equals(videoCodec, "theora", StringComparison.OrdinalIgnoreCase))
- {
- return ".ogv";
- }
- if (string.Equals(videoCodec, "vpx", StringComparison.OrdinalIgnoreCase))
- {
- return ".webm";
- }
- if (string.Equals(videoCodec, "wmv", StringComparison.OrdinalIgnoreCase))
- {
- return ".asf";
- }
+
+ if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase))
+ {
+ return ".ts";
+ }
+ if (string.Equals(videoCodec, "theora", StringComparison.OrdinalIgnoreCase))
+ {
+ return ".ogv";
+ }
+ if (string.Equals(videoCodec, "vpx", StringComparison.OrdinalIgnoreCase))
+ {
+ return ".webm";
+ }
+ if (string.Equals(videoCodec, "wmv", StringComparison.OrdinalIgnoreCase))
+ {
+ return ".asf";
+ }
}
// Try to infer based on the desired audio codec
@@ -114,7 +116,9 @@ namespace MediaBrowser.Api.Playback.Progressive
/// <returns>Task.</returns>
protected object ProcessRequest(StreamRequest request, bool isHeadRequest)
{
- var state = GetState(request, CancellationToken.None).Result;
+ var cancellationTokenSource = new CancellationTokenSource();
+
+ var state = GetState(request, cancellationTokenSource.Token).Result;
var responseHeaders = new Dictionary<string, string>();
@@ -123,13 +127,9 @@ namespace MediaBrowser.Api.Playback.Progressive
{
AddDlnaHeaders(state, responseHeaders, true);
- try
- {
- return GetStaticRemoteStreamResult(state, responseHeaders, isHeadRequest).Result;
- }
- finally
+ using (state)
{
- state.Dispose();
+ return GetStaticRemoteStreamResult(state, responseHeaders, isHeadRequest, cancellationTokenSource).Result;
}
}
@@ -151,13 +151,24 @@ namespace MediaBrowser.Api.Playback.Progressive
{
var contentType = state.GetMimeType(state.MediaPath);
- try
+ using (state)
{
- return ResultFactory.GetStaticFileResult(Request, state.MediaPath, contentType, FileShare.Read, responseHeaders, isHeadRequest);
- }
- finally
- {
- state.Dispose();
+ var throttleLimit = state.InputBitrate.HasValue ? (state.InputBitrate.Value / 8) : 0;
+
+ return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
+ {
+ ResponseHeaders = responseHeaders,
+ ContentType = contentType,
+ IsHeadRequest = isHeadRequest,
+ Path = state.MediaPath,
+ Throttle = request.Throttle,
+
+ // Pad by 20% to play it safe
+ ThrottleLimit = Convert.ToInt64(1.2 * throttleLimit),
+
+ // Three minutes
+ MinThrottlePosition = throttleLimit * 180
+ });
}
}
@@ -168,7 +179,13 @@ namespace MediaBrowser.Api.Playback.Progressive
try
{
- return ResultFactory.GetStaticFileResult(Request, outputPath, contentType, FileShare.Read, responseHeaders, isHeadRequest);
+ return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
+ {
+ ResponseHeaders = responseHeaders,
+ ContentType = contentType,
+ IsHeadRequest = isHeadRequest,
+ Path = outputPath
+ });
}
finally
{
@@ -179,7 +196,7 @@ namespace MediaBrowser.Api.Playback.Progressive
// Need to start ffmpeg
try
{
- return GetStreamResult(state, responseHeaders, isHeadRequest).Result;
+ return GetStreamResult(state, responseHeaders, isHeadRequest, cancellationTokenSource).Result;
}
catch
{
@@ -195,8 +212,9 @@ namespace MediaBrowser.Api.Playback.Progressive
/// <param name="state">The state.</param>
/// <param name="responseHeaders">The response headers.</param>
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
+ /// <param name="cancellationTokenSource">The cancellation token source.</param>
/// <returns>Task{System.Object}.</returns>
- private async Task<object> GetStaticRemoteStreamResult(StreamState state, Dictionary<string, string> responseHeaders, bool isHeadRequest)
+ private async Task<object> GetStaticRemoteStreamResult(StreamState state, Dictionary<string, string> responseHeaders, bool isHeadRequest, CancellationTokenSource cancellationTokenSource)
{
string useragent = null;
state.RemoteHttpHeaders.TryGetValue("User-Agent", out useragent);
@@ -205,7 +223,8 @@ namespace MediaBrowser.Api.Playback.Progressive
{
Url = state.MediaPath,
UserAgent = useragent,
- BufferContent = false
+ BufferContent = false,
+ CancellationToken = cancellationTokenSource.Token
};
var response = await HttpClient.GetResponse(options).ConfigureAwait(false);
@@ -246,8 +265,9 @@ namespace MediaBrowser.Api.Playback.Progressive
/// <param name="state">The state.</param>
/// <param name="responseHeaders">The response headers.</param>
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
+ /// <param name="cancellationTokenSource">The cancellation token source.</param>
/// <returns>Task{System.Object}.</returns>
- private async Task<object> GetStreamResult(StreamState state, IDictionary<string, string> responseHeaders, bool isHeadRequest)
+ private async Task<object> GetStreamResult(StreamState state, IDictionary<string, string> responseHeaders, bool isHeadRequest, CancellationTokenSource cancellationTokenSource)
{
// Use the command line args with a dummy playlist path
var outputPath = state.OutputFilePath;
@@ -283,27 +303,36 @@ namespace MediaBrowser.Api.Playback.Progressive
return streamResult;
}
- if (!File.Exists(outputPath))
- {
- await StartFfMpeg(state, outputPath, new CancellationTokenSource()).ConfigureAwait(false);
- }
- else
+ await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false);
+ try
{
- ApiEntryPoint.Instance.OnTranscodeBeginRequest(outputPath, TranscodingJobType.Progressive);
- state.Dispose();
- }
+ if (!File.Exists(outputPath))
+ {
+ await StartFfMpeg(state, outputPath, cancellationTokenSource).ConfigureAwait(false);
+ }
+ else
+ {
+ ApiEntryPoint.Instance.OnTranscodeBeginRequest(outputPath, TranscodingJobType.Progressive);
+ state.Dispose();
+ }
- var result = new ProgressiveStreamWriter(outputPath, Logger, FileSystem);
+ var job = ApiEntryPoint.Instance.GetTranscodingJob(outputPath, TranscodingJobType.Progressive);
+ var result = new ProgressiveStreamWriter(outputPath, Logger, FileSystem, job);
- result.Options["Content-Type"] = contentType;
+ result.Options["Content-Type"] = contentType;
- // Add the response headers to the result object
- foreach (var item in responseHeaders)
+ // Add the response headers to the result object
+ foreach (var item in responseHeaders)
+ {
+ result.Options[item.Key] = item.Value;
+ }
+
+ return result;
+ }
+ finally
{
- result.Options[item.Key] = item.Value;
+ ApiEntryPoint.Instance.TranscodingStartLock.Release();
}
-
- return result;
}
/// <summary>
diff --git a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
index f99cef8eb..a62f3dc9f 100644
--- a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
+++ b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs
@@ -1,7 +1,7 @@
-using MediaBrowser.Common.IO;
+using System;
+using MediaBrowser.Common.IO;
using MediaBrowser.Model.Logging;
using ServiceStack.Web;
-using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
@@ -13,6 +13,7 @@ namespace MediaBrowser.Api.Playback.Progressive
private string Path { get; set; }
private ILogger Logger { get; set; }
private readonly IFileSystem _fileSystem;
+ private readonly TranscodingJob _job;
/// <summary>
/// The _options
@@ -33,11 +34,12 @@ namespace MediaBrowser.Api.Playback.Progressive
/// <param name="path">The path.</param>
/// <param name="logger">The logger.</param>
/// <param name="fileSystem">The file system.</param>
- public ProgressiveStreamWriter(string path, ILogger logger, IFileSystem fileSystem)
+ public ProgressiveStreamWriter(string path, ILogger logger, IFileSystem fileSystem, TranscodingJob job)
{
Path = path;
Logger = logger;
_fileSystem = fileSystem;
+ _job = job;
}
/// <summary>
@@ -60,11 +62,12 @@ namespace MediaBrowser.Api.Playback.Progressive
{
try
{
- await StreamFile(Path, responseStream).ConfigureAwait(false);
+ await new ProgressiveFileCopier(_fileSystem, _job)
+ .StreamFile(Path, responseStream).ConfigureAwait(false);
}
- catch
+ catch (Exception ex)
{
- Logger.Error("Error streaming media. The client has most likely disconnected or transcoding has failed.");
+ Logger.ErrorException("Error streaming media. The client has most likely disconnected or transcoding has failed.", ex);
throw;
}
@@ -73,14 +76,20 @@ namespace MediaBrowser.Api.Playback.Progressive
ApiEntryPoint.Instance.OnTranscodeEndRequest(Path, TranscodingJobType.Progressive);
}
}
+ }
- /// <summary>
- /// Streams the file.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="outputStream">The output stream.</param>
- /// <returns>Task{System.Boolean}.</returns>
- private async Task StreamFile(string path, Stream outputStream)
+ public class ProgressiveFileCopier
+ {
+ private readonly IFileSystem _fileSystem;
+ private readonly TranscodingJob _job;
+
+ public ProgressiveFileCopier(IFileSystem fileSystem, TranscodingJob job)
+ {
+ _fileSystem = fileSystem;
+ _job = job;
+ }
+
+ public async Task StreamFile(string path, Stream outputStream)
{
var eofCount = 0;
long position = 0;
@@ -99,7 +108,10 @@ namespace MediaBrowser.Api.Playback.Progressive
if (bytesRead == 0)
{
- eofCount++;
+ if (_job == null || _job.HasExited)
+ {
+ eofCount++;
+ }
await Task.Delay(100).ConfigureAwait(false);
}
else
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index 063b056b0..639381164 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -11,7 +11,6 @@ using MediaBrowser.Model.IO;
using ServiceStack;
using System;
using System.IO;
-using System.Threading;
namespace MediaBrowser.Api.Playback.Progressive
{
@@ -144,7 +143,8 @@ namespace MediaBrowser.Api.Playback.Progressive
return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args;
}
- const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
+ var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
+ 5.ToString(UsCulture));
args += keyFrameArg;
@@ -153,7 +153,7 @@ namespace MediaBrowser.Api.Playback.Progressive
// Add resolution params, if specified
if (!hasGraphicalSubs)
{
- args += GetOutputSizeParam(state, codec, CancellationToken.None);
+ args += GetOutputSizeParam(state, codec);
}
var qualityParam = GetVideoQualityParam(state, codec, false);
@@ -166,7 +166,7 @@ namespace MediaBrowser.Api.Playback.Progressive
// This is for internal graphical subs
if (hasGraphicalSubs)
{
- args += GetInternalGraphicalSubtitleParam(state, codec);
+ args += GetGraphicalSubtitleParam(state, codec);
}
return args;
@@ -210,7 +210,7 @@ namespace MediaBrowser.Api.Playback.Progressive
args += " -ab " + bitrate.Value.ToString(UsCulture);
}
- args += " " + GetAudioFilterParam(state, true);
+ args += " " + GetAudioFilterParam(state, false);
return args;
}
diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs
index 0e4db45e3..0de8c28a9 100644
--- a/MediaBrowser.Api/Playback/StreamRequest.cs
+++ b/MediaBrowser.Api/Playback/StreamRequest.cs
@@ -1,4 +1,5 @@
-using ServiceStack;
+using MediaBrowser.Model.Dlna;
+using ServiceStack;
namespace MediaBrowser.Api.Playback
{
@@ -33,7 +34,7 @@ namespace MediaBrowser.Api.Playback
/// <value>The start time ticks.</value>
[ApiMember(Name = "StartTimeTicks", Description = "Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public long? StartTimeTicks { get; set; }
-
+
/// <summary>
/// Gets or sets the audio bit rate.
/// </summary>
@@ -69,6 +70,8 @@ namespace MediaBrowser.Api.Playback
public string DeviceProfileId { get; set; }
public string Params { get; set; }
+
+ public bool Throttle { get; set; }
}
public class VideoStreamRequest : StreamRequest
@@ -160,6 +163,9 @@ namespace MediaBrowser.Api.Playback
[ApiMember(Name = "Level", Description = "Optional. Specify a level for the h264 profile, e.g. 3, 3.1.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string Level { get; set; }
+ [ApiMember(Name = "SubtitleDeliveryMethod", Description = "Optional. Specify the subtitle delivery method.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public SubtitleDeliveryMethod SubtitleMethod { get; set; }
+
/// <summary>
/// Gets a value indicating whether this instance has fixed resolution.
/// </summary>
diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs
index 4737097cb..139a78c80 100644
--- a/MediaBrowser.Api/Playback/StreamState.cs
+++ b/MediaBrowser.Api/Playback/StreamState.cs
@@ -38,6 +38,8 @@ namespace MediaBrowser.Api.Playback
public string InputContainer { get; set; }
+ public List<MediaStream> AllMediaStreams { get; set; }
+
public MediaStream AudioStream { get; set; }
public MediaStream VideoStream { get; set; }
public MediaStream SubtitleStream { get; set; }
@@ -66,6 +68,8 @@ namespace MediaBrowser.Api.Playback
public long? RunTimeTicks;
+ public long? InputBitrate { get; set; }
+
public string OutputAudioSync = "1";
public string OutputVideoSync = "vfr";
@@ -78,6 +82,7 @@ namespace MediaBrowser.Api.Playback
SupportedAudioCodecs = new List<string>();
PlayableStreamFileNames = new List<string>();
RemoteHttpHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ AllMediaStreams = new List<MediaStream>();
}
public string InputAudioSync { get; set; }
@@ -94,6 +99,10 @@ namespace MediaBrowser.Api.Playback
public bool EnableMpegtsM2TsMode { get; set; }
public TranscodeSeekInfo TranscodeSeekInfo { get; set; }
+ public long? EncodingDurationTicks { get; set; }
+
+ public string ItemType { get; set; }
+
public string GetMimeType(string outputPath)
{
if (!string.IsNullOrEmpty(MimeType))
diff --git a/MediaBrowser.Api/PlaylistService.cs b/MediaBrowser.Api/PlaylistService.cs
new file mode 100644
index 000000000..5f4ced12e
--- /dev/null
+++ b/MediaBrowser.Api/PlaylistService.cs
@@ -0,0 +1,176 @@
+using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller.Playlists;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Playlists;
+using MediaBrowser.Model.Querying;
+using ServiceStack;
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Api
+{
+ [Route("/Playlists", "POST", Summary = "Creates a new playlist")]
+ public class CreatePlaylist : IReturn<PlaylistCreationResult>
+ {
+ [ApiMember(Name = "Name", Description = "The name of the new playlist.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string Name { get; set; }
+
+ [ApiMember(Name = "Ids", Description = "Item Ids to add to the playlist", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
+ public string Ids { get; set; }
+
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string UserId { get; set; }
+
+ [ApiMember(Name = "MediaType", Description = "The playlist media type", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string MediaType { get; set; }
+ }
+
+ [Route("/Playlists/{Id}/Items", "POST", Summary = "Adds items to a playlist")]
+ public class AddToPlaylist : IReturnVoid
+ {
+ [ApiMember(Name = "Ids", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string Ids { get; set; }
+
+ [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public string Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the user id.
+ /// </summary>
+ /// <value>The user id.</value>
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string UserId { get; set; }
+ }
+
+ [Route("/Playlists/{Id}/Items", "DELETE", Summary = "Removes items from a playlist")]
+ public class RemoveFromPlaylist : IReturnVoid
+ {
+ [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
+ public string Id { get; set; }
+
+ [ApiMember(Name = "EntryIds", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
+ public string EntryIds { get; set; }
+ }
+
+ [Route("/Playlists/{Id}/Items", "GET", Summary = "Gets the original items of a playlist")]
+ public class GetPlaylistItems : IReturn<QueryResult<BaseItemDto>>, IHasItemFields
+ {
+ [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
+ public string Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the user id.
+ /// </summary>
+ /// <value>The user id.</value>
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string UserId { get; set; }
+
+ /// <summary>
+ /// Skips over a given number of items within the results. Use for paging.
+ /// </summary>
+ /// <value>The start index.</value>
+ [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; }
+
+ /// <summary>
+ /// The maximum number of items to return
+ /// </summary>
+ /// <value>The limit.</value>
+ [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? Limit { get; set; }
+
+ /// <summary>
+ /// Fields to return within the items, in addition to basic information
+ /// </summary>
+ /// <value>The fields.</value>
+ [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ public string Fields { get; set; }
+ }
+
+ [Authenticated]
+ public class PlaylistService : BaseApiService
+ {
+ private readonly IPlaylistManager _playlistManager;
+ private readonly IDtoService _dtoService;
+ private readonly IUserManager _userManager;
+ private readonly ILibraryManager _libraryManager;
+
+ public PlaylistService(IDtoService dtoService, IPlaylistManager playlistManager, IUserManager userManager, ILibraryManager libraryManager)
+ {
+ _dtoService = dtoService;
+ _playlistManager = playlistManager;
+ _userManager = userManager;
+ _libraryManager = libraryManager;
+ }
+
+ public async Task<object> Post(CreatePlaylist request)
+ {
+ var result = await _playlistManager.CreatePlaylist(new PlaylistCreationRequest
+ {
+ Name = request.Name,
+ ItemIdList = (request.Ids ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).ToList(),
+ UserId = request.UserId,
+ MediaType = request.MediaType
+
+ }).ConfigureAwait(false);
+
+ return ToOptimizedResult(result);
+ }
+
+ public void Post(AddToPlaylist request)
+ {
+ var task = _playlistManager.AddToPlaylist(request.Id, request.Ids.Split(','), request.UserId);
+
+ Task.WaitAll(task);
+ }
+
+ public void Delete(RemoveFromPlaylist request)
+ {
+ var task = _playlistManager.RemoveFromPlaylist(request.Id, request.EntryIds.Split(','));
+
+ Task.WaitAll(task);
+ }
+
+ public object Get(GetPlaylistItems request)
+ {
+ var playlist = (Playlist)_libraryManager.GetItemById(request.Id);
+ var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(new Guid(request.UserId)) : null;
+
+ var items = playlist.GetManageableItems().ToArray();
+
+ var count = items.Length;
+
+ if (request.StartIndex.HasValue)
+ {
+ items = items.Skip(request.StartIndex.Value).ToArray();
+ }
+
+ if (request.Limit.HasValue)
+ {
+ items = items.Take(request.Limit.Value).ToArray();
+ }
+
+ var dtos = items
+ .Select(i => _dtoService.GetBaseItemDto(i.Item2, request.GetItemFields().ToList(), user))
+ .ToArray();
+
+ var index = 0;
+ foreach (var item in dtos)
+ {
+ item.PlaylistItemId = items[index].Item1.Id;
+ index++;
+ }
+
+ var result = new ItemsResult
+ {
+ Items = dtos,
+ TotalRecordCount = count
+ };
+
+ return ToOptimizedResult(result);
+ }
+ }
+}
diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs
index 31463dc3f..29cc7baf8 100644
--- a/MediaBrowser.Api/PluginService.cs
+++ b/MediaBrowser.Api/PluginService.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Security;
using MediaBrowser.Common.Updates;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Plugins;
using MediaBrowser.Model.Serialization;
@@ -100,6 +101,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class PluginsService
/// </summary>
+ [Authenticated]
public class PluginService : BaseApiService
{
/// <summary>
diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
index aaf14ce71..483133c10 100644
--- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
+++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Tasks;
using ServiceStack;
using ServiceStack.Text.Controller;
@@ -78,6 +79,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <summary>
/// Class ScheduledTasksService
/// </summary>
+ [Authenticated]
public class ScheduledTaskService : BaseApiService
{
/// <summary>
diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs
index 9fcbe39eb..61c7305b5 100644
--- a/MediaBrowser.Api/SearchService.cs
+++ b/MediaBrowser.Api/SearchService.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Search;
using ServiceStack;
@@ -79,6 +80,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class SearchService
/// </summary>
+ [Authenticated]
public class SearchService : BaseApiService
{
/// <summary>
@@ -109,9 +111,9 @@ namespace MediaBrowser.Api
/// </summary>
/// <param name="request">The request.</param>
/// <returns>System.Object.</returns>
- public object Get(GetSearchHints request)
+ public async Task<object> Get(GetSearchHints request)
{
- var result = GetSearchHintsAsync(request).Result;
+ var result = await GetSearchHintsAsync(request).ConfigureAwait(false);
return ToOptimizedSerializedResultUsingCache(result);
}
@@ -192,14 +194,14 @@ namespace MediaBrowser.Api
{
result.Series = season.Series.Name;
- result.EpisodeCount = season.GetRecursiveChildren(i => i is Episode).Count;
+ result.EpisodeCount = season.GetRecursiveChildren().Count(i => i is Episode);
}
var series = item as Series;
if (series != null)
{
- result.EpisodeCount = series.GetRecursiveChildren(i => i is Episode).Count;
+ result.EpisodeCount = series.GetRecursiveChildren().Count(i => i is Episode);
}
var album = item as MusicAlbum;
diff --git a/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
index 600d9e405..e6b525e53 100644
--- a/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs
+++ b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
@@ -7,7 +7,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-namespace MediaBrowser.Api.WebSocket
+namespace MediaBrowser.Api.Session
{
/// <summary>
/// Class SessionInfoWebSocketListener
diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/Session/SessionsService.cs
index 4cb48e9fe..e2c10c0c8 100644
--- a/MediaBrowser.Api/SessionsService.cs
+++ b/MediaBrowser.Api/Session/SessionsService.cs
@@ -1,4 +1,6 @@
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Session;
using ServiceStack;
@@ -8,12 +10,13 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-namespace MediaBrowser.Api
+namespace MediaBrowser.Api.Session
{
/// <summary>
/// Class GetSessions
/// </summary>
[Route("/Sessions", "GET", Summary = "Gets a list of sessions")]
+ [Authenticated]
public class GetSessions : IReturn<List<SessionInfoDto>>
{
[ApiMember(Name = "ControllableByUserId", Description = "Optional. Filter by sessions that a given user is allowed to remote control.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -27,6 +30,7 @@ namespace MediaBrowser.Api
/// Class DisplayContent
/// </summary>
[Route("/Sessions/{Id}/Viewing", "POST", Summary = "Instructs a session to browse to an item or view")]
+ [Authenticated]
public class DisplayContent : IReturnVoid
{
/// <summary>
@@ -59,6 +63,7 @@ namespace MediaBrowser.Api
}
[Route("/Sessions/{Id}/Playing", "POST", Summary = "Instructs a session to play an item")]
+ [Authenticated]
public class Play : IReturnVoid
{
/// <summary>
@@ -91,6 +96,7 @@ namespace MediaBrowser.Api
}
[Route("/Sessions/{Id}/Playing/{Command}", "POST", Summary = "Issues a playstate command to a client")]
+ [Authenticated]
public class SendPlaystateCommand : IReturnVoid
{
/// <summary>
@@ -115,6 +121,7 @@ namespace MediaBrowser.Api
}
[Route("/Sessions/{Id}/System/{Command}", "POST", Summary = "Issues a system command to a client")]
+ [Authenticated]
public class SendSystemCommand : IReturnVoid
{
/// <summary>
@@ -133,6 +140,7 @@ namespace MediaBrowser.Api
}
[Route("/Sessions/{Id}/Command/{Command}", "POST", Summary = "Issues a system command to a client")]
+ [Authenticated]
public class SendGeneralCommand : IReturnVoid
{
/// <summary>
@@ -151,6 +159,7 @@ namespace MediaBrowser.Api
}
[Route("/Sessions/{Id}/Command", "POST", Summary = "Issues a system command to a client")]
+ [Authenticated]
public class SendFullGeneralCommand : GeneralCommand, IReturnVoid
{
/// <summary>
@@ -162,6 +171,7 @@ namespace MediaBrowser.Api
}
[Route("/Sessions/{Id}/Message", "POST", Summary = "Issues a command to a client to display a message to the user")]
+ [Authenticated]
public class SendMessageCommand : IReturnVoid
{
/// <summary>
@@ -182,6 +192,7 @@ namespace MediaBrowser.Api
}
[Route("/Sessions/{Id}/Users/{UserId}", "POST", Summary = "Adds an additional user to a session")]
+ [Authenticated]
public class AddUserToSession : IReturnVoid
{
[ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
@@ -192,6 +203,7 @@ namespace MediaBrowser.Api
}
[Route("/Sessions/{Id}/Users/{UserId}", "DELETE", Summary = "Removes an additional user from a session")]
+ [Authenticated]
public class RemoveUserFromSession : IReturnVoid
{
[ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
@@ -202,7 +214,7 @@ namespace MediaBrowser.Api
}
[Route("/Sessions/Capabilities", "POST", Summary = "Updates capabilities for a device")]
- [Route("/Sessions/{Id}/Capabilities", "POST", Summary = "Updates capabilities for a device")]
+ [Authenticated]
public class PostCapabilities : IReturnVoid
{
/// <summary>
@@ -225,6 +237,30 @@ namespace MediaBrowser.Api
public bool SupportsMediaControl { get; set; }
}
+ [Route("/Sessions/Logout", "POST", Summary = "Reports that a session has ended")]
+ public class ReportSessionEnded : IReturnVoid
+ {
+ }
+
+ [Route("/Auth/Keys", "GET")]
+ public class GetApiKeys
+ {
+ }
+
+ [Route("/Auth/Keys/{Key}", "DELETE")]
+ public class RevokeKey
+ {
+ [ApiMember(Name = "Key", Description = "Auth Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public string Key { get; set; }
+ }
+
+ [Route("/Auth/Keys", "POST")]
+ public class CreateKey
+ {
+ [ApiMember(Name = "App", Description = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string App { get; set; }
+ }
+
/// <summary>
/// Class SessionsService
/// </summary>
@@ -236,16 +272,60 @@ namespace MediaBrowser.Api
private readonly ISessionManager _sessionManager;
private readonly IUserManager _userManager;
+ private readonly IAuthorizationContext _authContext;
+ private readonly IAuthenticationRepository _authRepo;
/// <summary>
/// Initializes a new instance of the <see cref="SessionsService" /> class.
/// </summary>
/// <param name="sessionManager">The session manager.</param>
/// <param name="userManager">The user manager.</param>
- public SessionsService(ISessionManager sessionManager, IUserManager userManager)
+ /// <param name="authContext">The authentication context.</param>
+ /// <param name="authRepo">The authentication repo.</param>
+ public SessionsService(ISessionManager sessionManager, IUserManager userManager, IAuthorizationContext authContext, IAuthenticationRepository authRepo)
{
_sessionManager = sessionManager;
_userManager = userManager;
+ _authContext = authContext;
+ _authRepo = authRepo;
+ }
+
+ public void Delete(RevokeKey request)
+ {
+ var task = _sessionManager.RevokeToken(request.Key);
+
+ Task.WaitAll(task);
+ }
+
+ public void Post(CreateKey request)
+ {
+ var task = _authRepo.Create(new AuthenticationInfo
+ {
+ AppName = request.App,
+ IsActive = true,
+ AccessToken = Guid.NewGuid().ToString("N"),
+ DateCreated = DateTime.UtcNow
+
+ }, CancellationToken.None);
+
+ Task.WaitAll(task);
+ }
+
+ public void Post(ReportSessionEnded request)
+ {
+ var auth = _authContext.GetAuthorizationInfo(Request);
+
+ _sessionManager.Logout(auth.Token);
+ }
+
+ public object Get(GetApiKeys request)
+ {
+ var result = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ IsActive = true
+ });
+
+ return ToOptimizedResult(result);
}
/// <summary>
@@ -315,21 +395,24 @@ namespace MediaBrowser.Api
public void Post(SendSystemCommand request)
{
GeneralCommandType commandType;
+ var name = request.Command;
- if (Enum.TryParse(request.Command, true, out commandType))
+ if (Enum.TryParse(name, true, out commandType))
{
- var currentSession = GetSession();
+ name = commandType.ToString();
+ }
- var command = new GeneralCommand
- {
- Name = commandType.ToString(),
- ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null
- };
+ var currentSession = GetSession();
- var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None);
+ var command = new GeneralCommand
+ {
+ Name = name,
+ ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null
+ };
- Task.WaitAll(task);
- }
+ var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None);
+
+ Task.WaitAll(task);
}
/// <summary>
@@ -422,14 +505,5 @@ namespace MediaBrowser.Api
MessageCallbackUrl = request.MessageCallbackUrl
});
}
-
- private SessionInfo GetSession()
- {
- var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
-
- return _sessionManager.Sessions.First(i => string.Equals(i.DeviceId, auth.DeviceId) &&
- string.Equals(i.Client, auth.Client) &&
- string.Equals(i.ApplicationVersion, auth.Version));
- }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Api/SimilarItemsHelper.cs b/MediaBrowser.Api/SimilarItemsHelper.cs
index 660b55f30..2da29928b 100644
--- a/MediaBrowser.Api/SimilarItemsHelper.cs
+++ b/MediaBrowser.Api/SimilarItemsHelper.cs
@@ -78,8 +78,8 @@ namespace MediaBrowser.Api
var fields = request.GetItemFields().ToList();
var inputItems = user == null
- ? libraryManager.RootFolder.GetRecursiveChildren(i => i.Id != item.Id)
- : user.RootFolder.GetRecursiveChildren(user, i => i.Id != item.Id);
+ ? libraryManager.RootFolder.GetRecursiveChildren().Where(i => i.Id != item.Id)
+ : user.RootFolder.GetRecursiveChildren(user).Where(i => i.Id != item.Id);
var items = GetSimilaritems(item, inputItems.Where(includeInSearch), getSimilarityScore)
.ToList();
diff --git a/MediaBrowser.Api/Library/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs
index 62c7ac7c0..6e2882319 100644
--- a/MediaBrowser.Api/Library/SubtitleService.cs
+++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities;
@@ -8,37 +9,17 @@ using MediaBrowser.Model.Providers;
using ServiceStack;
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Linq;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
-namespace MediaBrowser.Api.Library
+namespace MediaBrowser.Api.Subtitles
{
- [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/Stream.{Format}", "GET", Summary = "Gets subtitles in a specified format (vtt).")]
- public class GetSubtitle
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "MediaSourceId", Description = "MediaSourceId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string MediaSourceId { get; set; }
-
- [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
- public int Index { get; set; }
-
- [ApiMember(Name = "Format", Description = "Format", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Format { get; set; }
-
- [ApiMember(Name = "StartPositionTicks", Description = "StartPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public long StartPositionTicks { get; set; }
- }
-
[Route("/Videos/{Id}/Subtitles/{Index}", "DELETE", Summary = "Deletes an external subtitle file")]
+ [Authenticated]
public class DeleteSubtitle
{
/// <summary>
@@ -53,6 +34,7 @@ namespace MediaBrowser.Api.Library
}
[Route("/Items/{Id}/RemoteSearch/Subtitles/{Language}", "GET")]
+ [Authenticated]
public class SearchRemoteSubtitles : IReturn<List<RemoteSubtitleInfo>>
{
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
@@ -63,6 +45,7 @@ namespace MediaBrowser.Api.Library
}
[Route("/Items/{Id}/RemoteSearch/Subtitles/Providers", "GET")]
+ [Authenticated]
public class GetSubtitleProviders : IReturn<List<SubtitleProviderInfo>>
{
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
@@ -70,6 +53,7 @@ namespace MediaBrowser.Api.Library
}
[Route("/Items/{Id}/RemoteSearch/Subtitles/{SubtitleId}", "POST")]
+ [Authenticated]
public class DownloadRemoteSubtitles : IReturnVoid
{
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
@@ -80,12 +64,60 @@ namespace MediaBrowser.Api.Library
}
[Route("/Providers/Subtitles/Subtitles/{Id}", "GET")]
+ [Authenticated]
public class GetRemoteSubtitles : IReturnVoid
{
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
}
+ [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/Stream.{Format}", "GET", Summary = "Gets subtitles in a specified format.")]
+ [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/{StartPositionTicks}/Stream.{Format}", "GET", Summary = "Gets subtitles in a specified format.")]
+ public class GetSubtitle
+ {
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Id { get; set; }
+
+ [ApiMember(Name = "MediaSourceId", Description = "MediaSourceId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string MediaSourceId { get; set; }
+
+ [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
+ public int Index { get; set; }
+
+ [ApiMember(Name = "Format", Description = "Format", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Format { get; set; }
+
+ [ApiMember(Name = "StartPositionTicks", Description = "StartPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public long StartPositionTicks { get; set; }
+
+ [ApiMember(Name = "EndPositionTicks", Description = "EndPositionTicks", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public long? EndPositionTicks { get; set; }
+ }
+
+ [Route("/Videos/{Id}/{MediaSourceId}/Subtitles/{Index}/subtitles.m3u8", "GET", Summary = "Gets an HLS subtitle playlist.")]
+ public class GetSubtitlePlaylist
+ {
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Id { get; set; }
+
+ [ApiMember(Name = "MediaSourceId", Description = "MediaSourceId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string MediaSourceId { get; set; }
+
+ [ApiMember(Name = "Index", Description = "The subtitle stream index", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
+ public int Index { get; set; }
+
+ [ApiMember(Name = "SegmentLength", Description = "The subtitle srgment length", IsRequired = true, DataType = "int", ParameterType = "path", Verb = "GET")]
+ public int SegmentLength { get; set; }
+ }
+
public class SubtitleService : BaseApiService
{
private readonly ILibraryManager _libraryManager;
@@ -99,16 +131,59 @@ namespace MediaBrowser.Api.Library
_subtitleEncoder = subtitleEncoder;
}
- public object Get(SearchRemoteSubtitles request)
+ public object Get(GetSubtitlePlaylist request)
{
- var video = (Video)_libraryManager.GetItemById(request.Id);
+ var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
- var response = _subtitleManager.SearchSubtitles(video, request.Language, CancellationToken.None).Result;
+ var mediaSource = item.GetMediaSources(false)
+ .First(i => string.Equals(i.Id, request.MediaSourceId ?? request.Id));
- return ToOptimizedResult(response);
+ var builder = new StringBuilder();
+
+ var runtime = mediaSource.RunTimeTicks ?? -1;
+
+ if (runtime <= 0)
+ {
+ throw new ArgumentException("HLS Subtitles are not supported for this media.");
+ }
+
+ builder.AppendLine("#EXTM3U");
+ builder.AppendLine("#EXT-X-TARGETDURATION:" + request.SegmentLength.ToString(CultureInfo.InvariantCulture));
+ builder.AppendLine("#EXT-X-VERSION:3");
+ builder.AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
+
+ long positionTicks = 0;
+ var segmentLengthTicks = TimeSpan.FromSeconds(request.SegmentLength).Ticks;
+
+ while (positionTicks < runtime)
+ {
+ var remaining = runtime - positionTicks;
+ var lengthTicks = Math.Min(remaining, segmentLengthTicks);
+
+ builder.AppendLine("#EXTINF:" + TimeSpan.FromTicks(lengthTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture));
+
+ var endPositionTicks = Math.Min(runtime, positionTicks + segmentLengthTicks);
+
+ var url = string.Format("stream.srt?StartPositionTicks={0}&EndPositionTicks={1}",
+ positionTicks.ToString(CultureInfo.InvariantCulture),
+ endPositionTicks.ToString(CultureInfo.InvariantCulture));
+
+ builder.AppendLine(url);
+
+ positionTicks += segmentLengthTicks;
+ }
+
+ builder.AppendLine("#EXT-X-ENDLIST");
+
+ return ResultFactory.GetResult(builder.ToString(), Common.Net.MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
+
public object Get(GetSubtitle request)
{
+ if (string.Equals(request.Format, "js", StringComparison.OrdinalIgnoreCase))
+ {
+ request.Format = "json";
+ }
if (string.IsNullOrEmpty(request.Format))
{
var item = (Video)_libraryManager.GetItemById(new Guid(request.Id));
@@ -129,14 +204,24 @@ namespace MediaBrowser.Api.Library
private async Task<Stream> GetSubtitles(GetSubtitle request)
{
- return await _subtitleEncoder.GetSubtitles(request.Id,
- request.MediaSourceId,
- request.Index,
+ return await _subtitleEncoder.GetSubtitles(request.Id,
+ request.MediaSourceId,
+ request.Index,
request.Format,
request.StartPositionTicks,
+ request.EndPositionTicks,
CancellationToken.None).ConfigureAwait(false);
}
+ public object Get(SearchRemoteSubtitles request)
+ {
+ var video = (Video)_libraryManager.GetItemById(request.Id);
+
+ var response = _subtitleManager.SearchSubtitles(video, request.Language, CancellationToken.None).Result;
+
+ return ToOptimizedResult(response);
+ }
+
public void Delete(DeleteSubtitle request)
{
var task = _subtitleManager.DeleteSubtitles(request.Id, request.Index);
diff --git a/MediaBrowser.Api/Sync/SyncService.cs b/MediaBrowser.Api/Sync/SyncService.cs
new file mode 100644
index 000000000..9cf19d160
--- /dev/null
+++ b/MediaBrowser.Api/Sync/SyncService.cs
@@ -0,0 +1,104 @@
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller.Sync;
+using MediaBrowser.Model.Querying;
+using MediaBrowser.Model.Sync;
+using ServiceStack;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Api.Sync
+{
+ [Route("/Sync/Jobs/{Id}", "DELETE", Summary = "Cancels a sync job.")]
+ public class CancelSyncJob : IReturnVoid
+ {
+ [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Id { get; set; }
+ }
+
+ [Route("/Sync/Jobs/{Id}", "GET", Summary = "Gets a sync job.")]
+ public class GetSyncJob : IReturn<SyncJob>
+ {
+ [ApiMember(Name = "Id", Description = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Id { get; set; }
+ }
+
+ [Route("/Sync/Jobs", "GET", Summary = "Gets sync jobs.")]
+ public class GetSyncJobs : IReturn<QueryResult<SyncJob>>
+ {
+ /// <summary>
+ /// Skips over a given number of items within the results. Use for paging.
+ /// </summary>
+ /// <value>The start index.</value>
+ [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; }
+
+ /// <summary>
+ /// The maximum number of items to return
+ /// </summary>
+ /// <value>The limit.</value>
+ [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? Limit { get; set; }
+ }
+
+ [Route("/Sync/Jobs", "POST", Summary = "Gets sync jobs.")]
+ public class CreateSyncJob : SyncJobRequest, IReturn<SyncJobCreationResult>
+ {
+ }
+
+ [Route("/Sync/Targets", "GET", Summary = "Gets a list of available sync targets.")]
+ public class GetSyncTarget : IReturn<List<SyncTarget>>
+ {
+ [ApiMember(Name = "UserId", Description = "UserId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string UserId { get; set; }
+ }
+
+ [Authenticated]
+ public class SyncService : BaseApiService
+ {
+ private readonly ISyncManager _syncManager;
+
+ public SyncService(ISyncManager syncManager)
+ {
+ _syncManager = syncManager;
+ }
+
+ public object Get(GetSyncTarget request)
+ {
+ var result = _syncManager.GetSyncTargets(request.UserId);
+
+ return ToOptimizedResult(result);
+ }
+
+ public object Get(GetSyncJobs request)
+ {
+ var result = _syncManager.GetJobs(new SyncJobQuery
+ {
+ StartIndex = request.StartIndex,
+ Limit = request.Limit
+ });
+
+ return ToOptimizedResult(result);
+ }
+
+ public object Get(GetSyncJob request)
+ {
+ var result = _syncManager.GetJob(request.Id);
+
+ return ToOptimizedResult(result);
+ }
+
+ public void Delete(CancelSyncJob request)
+ {
+ var task = _syncManager.CancelJob(request.Id);
+
+ Task.WaitAll(task);
+ }
+
+ public async Task<object> Post(CreateSyncJob request)
+ {
+ var result = await _syncManager.CreateJob(request).ConfigureAwait(false);
+
+ return ToOptimizedResult(result);
+ }
+ }
+}
diff --git a/MediaBrowser.Api/System/ActivityLogService.cs b/MediaBrowser.Api/System/ActivityLogService.cs
new file mode 100644
index 000000000..8dc3079c7
--- /dev/null
+++ b/MediaBrowser.Api/System/ActivityLogService.cs
@@ -0,0 +1,53 @@
+using MediaBrowser.Controller.Activity;
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Model.Activity;
+using MediaBrowser.Model.Querying;
+using ServiceStack;
+using System;
+using System.Globalization;
+
+namespace MediaBrowser.Api.System
+{
+ [Route("/System/ActivityLog/Entries", "GET", Summary = "Gets activity log entries")]
+ public class GetActivityLogs : IReturn<QueryResult<ActivityLogEntry>>
+ {
+ /// <summary>
+ /// Skips over a given number of items within the results. Use for paging.
+ /// </summary>
+ /// <value>The start index.</value>
+ [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; }
+
+ /// <summary>
+ /// The maximum number of items to return
+ /// </summary>
+ /// <value>The limit.</value>
+ [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? Limit { get; set; }
+
+ [ApiMember(Name = "MinDate", Description = "Optional. The minimum date. Format = ISO", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string MinDate { get; set; }
+ }
+
+ [Authenticated]
+ public class ActivityLogService : BaseApiService
+ {
+ private readonly IActivityManager _activityManager;
+
+ public ActivityLogService(IActivityManager activityManager)
+ {
+ _activityManager = activityManager;
+ }
+
+ public object Get(GetActivityLogs request)
+ {
+ DateTime? minDate = string.IsNullOrWhiteSpace(request.MinDate) ?
+ (DateTime?)null :
+ DateTime.Parse(request.MinDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime();
+
+ var result = _activityManager.GetActivityLogEntries(minDate, request.StartIndex, request.Limit);
+
+ return ToOptimizedResult(result);
+ }
+ }
+}
diff --git a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs
new file mode 100644
index 000000000..4629b2a8c
--- /dev/null
+++ b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs
@@ -0,0 +1,67 @@
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Activity;
+using MediaBrowser.Model.Activity;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.Logging;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Api.System
+{
+ /// <summary>
+ /// Class SessionInfoWebSocketListener
+ /// </summary>
+ class ActivityLogWebSocketListener : BasePeriodicWebSocketListener<List<ActivityLogEntry>, WebSocketListenerState>
+ {
+ /// <summary>
+ /// Gets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ protected override string Name
+ {
+ get { return "ActivityLogEntry"; }
+ }
+
+ /// <summary>
+ /// The _kernel
+ /// </summary>
+ private readonly IActivityManager _activityManager;
+
+ public ActivityLogWebSocketListener(ILogger logger, IActivityManager activityManager)
+ : base(logger)
+ {
+ _activityManager = activityManager;
+ _activityManager.EntryCreated += _activityManager_EntryCreated;
+ }
+
+ void _activityManager_EntryCreated(object sender, GenericEventArgs<ActivityLogEntry> e)
+ {
+ SendData(true);
+ }
+
+ /// <summary>
+ /// Gets the data to send.
+ /// </summary>
+ /// <param name="state">The state.</param>
+ /// <returns>Task{SystemInfo}.</returns>
+ protected override Task<List<ActivityLogEntry>> GetDataToSend(WebSocketListenerState state)
+ {
+ return Task.FromResult(new List<ActivityLogEntry>());
+ }
+
+ protected override bool SendOnTimer
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ protected override void Dispose(bool dispose)
+ {
+ _activityManager.EntryCreated -= _activityManager_EntryCreated;
+
+ base.Dispose(dispose);
+ }
+ }
+}
diff --git a/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs b/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs
index 2940bcef0..c20cef3b3 100644
--- a/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs
+++ b/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs
@@ -4,7 +4,7 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.System;
using System.Threading.Tasks;
-namespace MediaBrowser.Api.WebSocket
+namespace MediaBrowser.Api.System
{
/// <summary>
/// Class SystemInfoWebSocketListener
diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs
new file mode 100644
index 000000000..cae648ae0
--- /dev/null
+++ b/MediaBrowser.Api/System/SystemService.cs
@@ -0,0 +1,205 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Model.System;
+using ServiceStack;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Api.System
+{
+ /// <summary>
+ /// Class GetSystemInfo
+ /// </summary>
+ [Route("/System/Info", "GET", Summary = "Gets information about the server")]
+ [Authenticated]
+ public class GetSystemInfo : IReturn<SystemInfo>
+ {
+
+ }
+
+ [Route("/System/Info/Public", "GET", Summary = "Gets public information about the server")]
+ public class GetPublicSystemInfo : IReturn<PublicSystemInfo>
+ {
+
+ }
+
+ /// <summary>
+ /// Class RestartApplication
+ /// </summary>
+ [Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")]
+ [Authenticated]
+ public class RestartApplication
+ {
+ }
+
+ /// <summary>
+ /// This is currently not authenticated because the uninstaller needs to be able to shutdown the server.
+ /// </summary>
+ [Route("/System/Shutdown", "POST", Summary = "Shuts down the application")]
+ public class ShutdownApplication
+ {
+ }
+
+ [Route("/System/Logs", "GET", Summary = "Gets a list of available server log files")]
+ [Authenticated]
+ public class GetServerLogs : IReturn<List<LogFile>>
+ {
+ }
+
+ [Route("/System/Endpoint", "GET", Summary = "Gets information about the request endpoint")]
+ [Authenticated]
+ public class GetEndpointInfo : IReturn<EndpointInfo>
+ {
+ public string Endpoint { get; set; }
+ }
+
+ [Route("/System/Logs/Log", "GET", Summary = "Gets a log file")]
+ public class GetLogFile
+ {
+ [ApiMember(Name = "Name", Description = "The log file name.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ public string Name { get; set; }
+ }
+
+ /// <summary>
+ /// Class SystemInfoService
+ /// </summary>
+ public class SystemService : BaseApiService
+ {
+ /// <summary>
+ /// The _app host
+ /// </summary>
+ private readonly IServerApplicationHost _appHost;
+ private readonly IApplicationPaths _appPaths;
+ private readonly IFileSystem _fileSystem;
+
+ private readonly INetworkManager _network;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SystemService" /> class.
+ /// </summary>
+ /// <param name="appHost">The app host.</param>
+ /// <param name="appPaths">The application paths.</param>
+ /// <param name="fileSystem">The file system.</param>
+ /// <exception cref="ArgumentNullException">jsonSerializer</exception>
+ public SystemService(IServerApplicationHost appHost, IApplicationPaths appPaths, IFileSystem fileSystem, INetworkManager network)
+ {
+ _appHost = appHost;
+ _appPaths = appPaths;
+ _fileSystem = fileSystem;
+ _network = network;
+ }
+
+ public object Get(GetServerLogs request)
+ {
+ List<FileInfo> files;
+
+ try
+ {
+ files = new DirectoryInfo(_appPaths.LogDirectoryPath)
+ .EnumerateFiles("*", SearchOption.AllDirectories)
+ .Where(i => string.Equals(i.Extension, ".txt", global::System.StringComparison.OrdinalIgnoreCase))
+ .ToList();
+ }
+ catch (DirectoryNotFoundException)
+ {
+ files = new List<FileInfo>();
+ }
+
+ var result = files.Select(i => new LogFile
+ {
+ DateCreated = _fileSystem.GetCreationTimeUtc(i),
+ DateModified = _fileSystem.GetLastWriteTimeUtc(i),
+ Name = i.Name,
+ Size = i.Length
+
+ }).OrderByDescending(i => i.DateModified)
+ .ThenByDescending(i => i.DateCreated)
+ .ThenBy(i => i.Name)
+ .ToList();
+
+ return ToOptimizedResult(result);
+ }
+
+ public object Get(GetLogFile request)
+ {
+ var file = new DirectoryInfo(_appPaths.LogDirectoryPath)
+ .EnumerateFiles("*", SearchOption.AllDirectories)
+ .First(i => string.Equals(i.Name, request.Name, global::System.StringComparison.OrdinalIgnoreCase));
+
+ return ResultFactory.GetStaticFileResult(Request, file.FullName, FileShare.ReadWrite);
+ }
+
+ /// <summary>
+ /// Gets the specified request.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ /// <returns>System.Object.</returns>
+ public object Get(GetSystemInfo request)
+ {
+ var result = _appHost.GetSystemInfo();
+
+ return ToOptimizedResult(result);
+ }
+
+ public object Get(GetPublicSystemInfo request)
+ {
+ var result = _appHost.GetSystemInfo();
+
+ var publicInfo = new PublicSystemInfo
+ {
+ Id = result.Id,
+ ServerName = result.ServerName,
+ Version = result.Version
+ };
+
+ return ToOptimizedResult(publicInfo);
+ }
+
+ /// <summary>
+ /// Posts the specified request.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ public void Post(RestartApplication request)
+ {
+ Task.Run(async () =>
+ {
+ await Task.Delay(100).ConfigureAwait(false);
+ await _appHost.Restart().ConfigureAwait(false);
+ });
+ }
+
+ /// <summary>
+ /// Posts the specified request.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ public void Post(ShutdownApplication request)
+ {
+ Task.Run(async () =>
+ {
+ await Task.Delay(100).ConfigureAwait(false);
+ await _appHost.Shutdown().ConfigureAwait(false);
+ });
+ }
+
+ public object Get(GetEndpointInfo request)
+ {
+ return ToOptimizedResult(new EndpointInfo
+ {
+ IsLocal = Request.IsLocal,
+ IsInNetwork = _network.IsInLocalNetwork(request.Endpoint ?? Request.RemoteIp)
+ });
+ }
+ }
+
+ public class EndpointInfo
+ {
+ public bool IsLocal { get; set; }
+ public bool IsInNetwork { get; set; }
+ }
+}
diff --git a/MediaBrowser.Api/SystemService.cs b/MediaBrowser.Api/SystemService.cs
deleted file mode 100644
index 2f0741434..000000000
--- a/MediaBrowser.Api/SystemService.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-using MediaBrowser.Controller;
-using MediaBrowser.Model.System;
-using ServiceStack;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Api
-{
- /// <summary>
- /// Class GetSystemInfo
- /// </summary>
- [Route("/System/Info", "GET", Summary = "Gets information about the server")]
- public class GetSystemInfo : IReturn<SystemInfo>
- {
-
- }
-
- /// <summary>
- /// Class RestartApplication
- /// </summary>
- [Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")]
- public class RestartApplication
- {
- }
-
- [Route("/System/Shutdown", "POST", Summary = "Shuts down the application")]
- public class ShutdownApplication
- {
- }
-
- /// <summary>
- /// Class SystemInfoService
- /// </summary>
- public class SystemService : BaseApiService
- {
- /// <summary>
- /// The _app host
- /// </summary>
- private readonly IServerApplicationHost _appHost;
-
-
- /// <summary>
- /// Initializes a new instance of the <see cref="SystemService" /> class.
- /// </summary>
- /// <param name="appHost">The app host.</param>
- /// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
- public SystemService(IServerApplicationHost appHost)
- {
- _appHost = appHost;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetSystemInfo request)
- {
- var result = _appHost.GetSystemInfo();
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(RestartApplication request)
- {
- Task.Run(async () =>
- {
- await Task.Delay(100).ConfigureAwait(false);
- await _appHost.Restart().ConfigureAwait(false);
- });
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(ShutdownApplication request)
- {
- Task.Run(async () =>
- {
- await Task.Delay(100).ConfigureAwait(false);
- await _appHost.Shutdown().ConfigureAwait(false);
- });
- }
-
- }
-}
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index 6776cbf17..c32e67216 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
@@ -175,6 +176,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class TvShowsService
/// </summary>
+ [Authenticated]
public class TvShowsService : BaseApiService
{
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs
index 20b0f5fb1..07015ecae 100644
--- a/MediaBrowser.Api/UserLibrary/ArtistsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ArtistsService.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
@@ -46,6 +47,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary>
/// Class ArtistsService
/// </summary>
+ [Authenticated]
public class ArtistsService : BaseItemsByNameService<MusicArtist>
{
/// <summary>
@@ -88,10 +90,10 @@ namespace MediaBrowser.Api.UserLibrary
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, fields.ToList(), user);
}
- return DtoService.GetItemByNameDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, fields.ToList());
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
index 7cd518a18..f23610014 100644
--- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
+++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
@@ -1,9 +1,9 @@
-using System.Collections.Generic;
-using System.Linq;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using ServiceStack;
using System;
+using System.Collections.Generic;
+using System.Linq;
namespace MediaBrowser.Api.UserLibrary
{
diff --git a/MediaBrowser.Api/UserLibrary/GameGenresService.cs b/MediaBrowser.Api/UserLibrary/GameGenresService.cs
index 34eadc3c3..49e979e55 100644
--- a/MediaBrowser.Api/UserLibrary/GameGenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/GameGenresService.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@@ -41,6 +42,7 @@ namespace MediaBrowser.Api.UserLibrary
public Guid? UserId { get; set; }
}
+ [Authenticated]
public class GameGenresService : BaseItemsByNameService<GameGenre>
{
public GameGenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService)
@@ -76,10 +78,10 @@ namespace MediaBrowser.Api.UserLibrary
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, fields.ToList(), user);
}
- return DtoService.GetItemByNameDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, fields.ToList());
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs
index 58dec11f6..c8c45c1bb 100644
--- a/MediaBrowser.Api/UserLibrary/GenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/GenresService.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
@@ -46,6 +47,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary>
/// Class GenresService
/// </summary>
+ [Authenticated]
public class GenresService : BaseItemsByNameService<Genre>
{
public GenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService)
@@ -81,10 +83,10 @@ namespace MediaBrowser.Api.UserLibrary
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, fields.ToList(), user);
}
- return DtoService.GetItemByNameDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, fields.ToList());
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index c926c16ff..25821c213 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -6,6 +6,7 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
@@ -246,6 +247,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary>
/// Class ItemsService
/// </summary>
+ [Authenticated]
public class ItemsService : BaseApiService
{
/// <summary>
@@ -1428,7 +1430,7 @@ namespace MediaBrowser.Api.UserLibrary
nextId = list[index + 1].Id;
}
- return list.Where(i => i.Id == previousId || i.Id == nextId);
+ return list.Where(i => i.Id == previousId || i.Id == nextId || i.Id == adjacentToIdGuid);
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
index 9b7a941d8..f50f0a0bd 100644
--- a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
@@ -41,6 +42,7 @@ namespace MediaBrowser.Api.UserLibrary
public Guid? UserId { get; set; }
}
+ [Authenticated]
public class MusicGenresService : BaseItemsByNameService<MusicGenre>
{
public MusicGenresService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService)
@@ -76,10 +78,10 @@ namespace MediaBrowser.Api.UserLibrary
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, fields.ToList(), user);
}
- return DtoService.GetItemByNameDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, fields.ToList());
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs
index f7ea4198d..cf9959e53 100644
--- a/MediaBrowser.Api/UserLibrary/PersonsService.cs
+++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
@@ -51,6 +52,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary>
/// Class PersonsService
/// </summary>
+ [Authenticated]
public class PersonsService : BaseItemsByNameService<Person>
{
/// <summary>
@@ -93,10 +95,10 @@ namespace MediaBrowser.Api.UserLibrary
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, fields.ToList(), user);
}
- return DtoService.GetItemByNameDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, fields.ToList());
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs
new file mode 100644
index 000000000..2abb76dc8
--- /dev/null
+++ b/MediaBrowser.Api/UserLibrary/PlaystateService.cs
@@ -0,0 +1,388 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Session;
+using ServiceStack;
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Api.UserLibrary
+{
+ /// <summary>
+ /// Class MarkPlayedItem
+ /// </summary>
+ [Route("/Users/{UserId}/PlayedItems/{Id}", "POST")]
+ [Api(Description = "Marks an item as played")]
+ public class MarkPlayedItem : IReturn<UserItemDataDto>
+ {
+ /// <summary>
+ /// Gets or sets the user id.
+ /// </summary>
+ /// <value>The user id.</value>
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public Guid UserId { get; set; }
+
+ [ApiMember(Name = "DatePlayed", Description = "The date the item was played (if any). Format = yyyyMMddHHmmss", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string DatePlayed { get; set; }
+
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public string Id { get; set; }
+ }
+
+ /// <summary>
+ /// Class MarkUnplayedItem
+ /// </summary>
+ [Route("/Users/{UserId}/PlayedItems/{Id}", "DELETE")]
+ [Api(Description = "Marks an item as unplayed")]
+ public class MarkUnplayedItem : IReturn<UserItemDataDto>
+ {
+ /// <summary>
+ /// Gets or sets the user id.
+ /// </summary>
+ /// <value>The user id.</value>
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
+ public Guid UserId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
+ public string Id { get; set; }
+ }
+
+ [Route("/Sessions/Playing", "POST")]
+ [Api(Description = "Reports playback has started within a session")]
+ public class ReportPlaybackStart : PlaybackStartInfo, IReturnVoid
+ {
+ }
+
+ [Route("/Sessions/Playing/Progress", "POST")]
+ [Api(Description = "Reports playback progress within a session")]
+ public class ReportPlaybackProgress : PlaybackProgressInfo, IReturnVoid
+ {
+ }
+
+ [Route("/Sessions/Playing/Stopped", "POST")]
+ [Api(Description = "Reports playback has stopped within a session")]
+ public class ReportPlaybackStopped : PlaybackStopInfo, IReturnVoid
+ {
+ }
+
+ /// <summary>
+ /// Class OnPlaybackStart
+ /// </summary>
+ [Route("/Users/{UserId}/PlayingItems/{Id}", "POST")]
+ [Api(Description = "Reports that a user has begun playing an item")]
+ public class OnPlaybackStart : IReturnVoid
+ {
+ /// <summary>
+ /// Gets or sets the user id.
+ /// </summary>
+ /// <value>The user id.</value>
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public Guid UserId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public string Id { get; set; }
+
+ [ApiMember(Name = "MediaSourceId", Description = "The id of the MediaSource", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string MediaSourceId { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this <see cref="UpdateUserItemRating" /> is likes.
+ /// </summary>
+ /// <value><c>true</c> if likes; otherwise, <c>false</c>.</value>
+ [ApiMember(Name = "CanSeek", Description = "Indicates if the client can seek", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
+ public bool CanSeek { get; set; }
+
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ [ApiMember(Name = "QueueableMediaTypes", Description = "A list of media types that can be queued from this item, comma delimited. Audio,Video,Book,Game", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
+ public string QueueableMediaTypes { get; set; }
+
+ [ApiMember(Name = "AudioStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
+ public int? AudioStreamIndex { get; set; }
+
+ [ApiMember(Name = "SubtitleStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
+ public int? SubtitleStreamIndex { get; set; }
+ }
+
+ /// <summary>
+ /// Class OnPlaybackProgress
+ /// </summary>
+ [Route("/Users/{UserId}/PlayingItems/{Id}/Progress", "POST")]
+ [Api(Description = "Reports a user's playback progress")]
+ public class OnPlaybackProgress : IReturnVoid
+ {
+ /// <summary>
+ /// Gets or sets the user id.
+ /// </summary>
+ /// <value>The user id.</value>
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public Guid UserId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public string Id { get; set; }
+
+ [ApiMember(Name = "MediaSourceId", Description = "The id of the MediaSource", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string MediaSourceId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the position ticks.
+ /// </summary>
+ /// <value>The position ticks.</value>
+ [ApiMember(Name = "PositionTicks", Description = "Optional. The current position, in ticks. 1 tick = 10000 ms", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
+ public long? PositionTicks { get; set; }
+
+ [ApiMember(Name = "IsPaused", Description = "Indicates if the player is paused.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
+ public bool IsPaused { get; set; }
+
+ [ApiMember(Name = "IsMuted", Description = "Indicates if the player is muted.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
+ public bool IsMuted { get; set; }
+
+ [ApiMember(Name = "AudioStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
+ public int? AudioStreamIndex { get; set; }
+
+ [ApiMember(Name = "SubtitleStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
+ public int? SubtitleStreamIndex { get; set; }
+
+ [ApiMember(Name = "VolumeLevel", Description = "Scale of 0-100", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
+ public int? VolumeLevel { get; set; }
+ }
+
+ /// <summary>
+ /// Class OnPlaybackStopped
+ /// </summary>
+ [Route("/Users/{UserId}/PlayingItems/{Id}", "DELETE")]
+ [Api(Description = "Reports that a user has stopped playing an item")]
+ public class OnPlaybackStopped : IReturnVoid
+ {
+ /// <summary>
+ /// Gets or sets the user id.
+ /// </summary>
+ /// <value>The user id.</value>
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
+ public Guid UserId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
+ public string Id { get; set; }
+
+ [ApiMember(Name = "MediaSourceId", Description = "The id of the MediaSource", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
+ public string MediaSourceId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the position ticks.
+ /// </summary>
+ /// <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; }
+ }
+
+ [Authenticated]
+ public class PlaystateService : BaseApiService
+ {
+ private readonly IUserManager _userManager;
+ private readonly IUserDataManager _userDataRepository;
+ private readonly ILibraryManager _libraryManager;
+ private readonly ISessionManager _sessionManager;
+
+ public PlaystateService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, ISessionManager sessionManager)
+ {
+ _userManager = userManager;
+ _userDataRepository = userDataRepository;
+ _libraryManager = libraryManager;
+ _sessionManager = sessionManager;
+ }
+
+ /// <summary>
+ /// Posts the specified request.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ public object Post(MarkPlayedItem request)
+ {
+ var result = MarkPlayed(request).Result;
+
+ return ToOptimizedResult(result);
+ }
+
+ private async Task<UserItemDataDto> MarkPlayed(MarkPlayedItem request)
+ {
+ var user = _userManager.GetUserById(request.UserId);
+
+ DateTime? datePlayed = null;
+
+ if (!string.IsNullOrEmpty(request.DatePlayed))
+ {
+ datePlayed = DateTime.ParseExact(request.DatePlayed, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
+ }
+
+ var session = GetSession();
+
+ var dto = await UpdatePlayedStatus(user, request.Id, true, datePlayed).ConfigureAwait(false);
+
+ foreach (var additionalUserInfo in session.AdditionalUsers)
+ {
+ var additionalUser = _userManager.GetUserById(new Guid(additionalUserInfo.UserId));
+
+ await UpdatePlayedStatus(additionalUser, request.Id, true, datePlayed).ConfigureAwait(false);
+ }
+
+ return dto;
+ }
+
+ /// <summary>
+ /// Posts the specified request.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ public void Post(OnPlaybackStart request)
+ {
+ var queueableMediaTypes = (request.QueueableMediaTypes ?? string.Empty);
+
+ Post(new ReportPlaybackStart
+ {
+ CanSeek = request.CanSeek,
+ ItemId = request.Id,
+ QueueableMediaTypes = queueableMediaTypes.Split(',').ToList(),
+ MediaSourceId = request.MediaSourceId,
+ AudioStreamIndex = request.AudioStreamIndex,
+ SubtitleStreamIndex = request.SubtitleStreamIndex
+ });
+ }
+
+ public void Post(ReportPlaybackStart request)
+ {
+ request.SessionId = GetSession().Id;
+
+ var task = _sessionManager.OnPlaybackStart(request);
+
+ Task.WaitAll(task);
+ }
+
+ /// <summary>
+ /// Posts the specified request.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ public void Post(OnPlaybackProgress request)
+ {
+ Post(new ReportPlaybackProgress
+ {
+ ItemId = request.Id,
+ PositionTicks = request.PositionTicks,
+ IsMuted = request.IsMuted,
+ IsPaused = request.IsPaused,
+ MediaSourceId = request.MediaSourceId,
+ AudioStreamIndex = request.AudioStreamIndex,
+ SubtitleStreamIndex = request.SubtitleStreamIndex,
+ VolumeLevel = request.VolumeLevel
+ });
+ }
+
+ public void Post(ReportPlaybackProgress request)
+ {
+ request.SessionId = GetSession().Id;
+
+ var task = _sessionManager.OnPlaybackProgress(request);
+
+ Task.WaitAll(task);
+ }
+
+ /// <summary>
+ /// Posts the specified request.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ public void Delete(OnPlaybackStopped request)
+ {
+ Post(new ReportPlaybackStopped
+ {
+ ItemId = request.Id,
+ PositionTicks = request.PositionTicks,
+ MediaSourceId = request.MediaSourceId
+ });
+ }
+
+ public void Post(ReportPlaybackStopped request)
+ {
+ request.SessionId = GetSession().Id;
+
+ var task = _sessionManager.OnPlaybackStopped(request);
+
+ Task.WaitAll(task);
+ }
+
+ /// <summary>
+ /// Deletes the specified request.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ public object Delete(MarkUnplayedItem request)
+ {
+ var task = MarkUnplayed(request);
+
+ return ToOptimizedResult(task.Result);
+ }
+
+ private async Task<UserItemDataDto> MarkUnplayed(MarkUnplayedItem request)
+ {
+ var user = _userManager.GetUserById(request.UserId);
+
+ var session = GetSession();
+
+ var dto = await UpdatePlayedStatus(user, request.Id, false, null).ConfigureAwait(false);
+
+ foreach (var additionalUserInfo in session.AdditionalUsers)
+ {
+ var additionalUser = _userManager.GetUserById(new Guid(additionalUserInfo.UserId));
+
+ await UpdatePlayedStatus(additionalUser, request.Id, false, null).ConfigureAwait(false);
+ }
+
+ return dto;
+ }
+
+ /// <summary>
+ /// Updates the played status.
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <param name="itemId">The item id.</param>
+ /// <param name="wasPlayed">if set to <c>true</c> [was played].</param>
+ /// <param name="datePlayed">The date played.</param>
+ /// <returns>Task.</returns>
+ private async Task<UserItemDataDto> UpdatePlayedStatus(User user, string itemId, bool wasPlayed, DateTime? datePlayed)
+ {
+ var item = _libraryManager.GetItemById(itemId);
+
+ if (wasPlayed)
+ {
+ await item.MarkPlayed(user, datePlayed, _userDataRepository).ConfigureAwait(false);
+ }
+ else
+ {
+ await item.MarkUnplayed(user, _userDataRepository).ConfigureAwait(false);
+ }
+
+ return _userDataRepository.GetUserDataDto(item, user);
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs
index 7eff5054b..2024d779b 100644
--- a/MediaBrowser.Api/UserLibrary/StudiosService.cs
+++ b/MediaBrowser.Api/UserLibrary/StudiosService.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
@@ -43,6 +44,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary>
/// Class StudiosService
/// </summary>
+ [Authenticated]
public class StudiosService : BaseItemsByNameService<Studio>
{
public StudiosService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService)
@@ -78,10 +80,10 @@ namespace MediaBrowser.Api.UserLibrary
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, fields.ToList(), user);
}
- return DtoService.GetItemByNameDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, fields.ToList());
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
index 96bbd6dff..44b5b0e9b 100644
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
@@ -3,16 +3,14 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Session;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Session;
using ServiceStack;
using System;
using System.Collections.Generic;
-using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -188,260 +186,97 @@ namespace MediaBrowser.Api.UserLibrary
}
/// <summary>
- /// Class MarkPlayedItem
- /// </summary>
- [Route("/Users/{UserId}/PlayedItems/{Id}", "POST")]
- [Api(Description = "Marks an item as played")]
- public class MarkPlayedItem : IReturn<UserItemDataDto>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "DatePlayed", Description = "The date the item was played (if any). Format = yyyyMMddHHmmss", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string DatePlayed { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
- }
-
- /// <summary>
- /// Class MarkUnplayedItem
- /// </summary>
- [Route("/Users/{UserId}/PlayedItems/{Id}", "DELETE")]
- [Api(Description = "Marks an item as unplayed")]
- public class MarkUnplayedItem : IReturn<UserItemDataDto>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
- }
-
- [Route("/Sessions/Playing", "POST")]
- [Api(Description = "Reports playback has started within a session")]
- public class ReportPlaybackStart : PlaybackStartInfo, IReturnVoid
- {
- }
-
- [Route("/Sessions/Playing/Progress", "POST")]
- [Api(Description = "Reports playback progress within a session")]
- public class ReportPlaybackProgress : PlaybackProgressInfo, IReturnVoid
- {
- }
-
- [Route("/Sessions/Playing/Stopped", "POST")]
- [Api(Description = "Reports playback has stopped within a session")]
- public class ReportPlaybackStopped : PlaybackStopInfo, IReturnVoid
- {
- }
-
- /// <summary>
- /// Class OnPlaybackStart
+ /// Class GetLocalTrailers
/// </summary>
- [Route("/Users/{UserId}/PlayingItems/{Id}", "POST")]
- [Api(Description = "Reports that a user has begun playing an item")]
- public class OnPlaybackStart : IReturnVoid
+ [Route("/Users/{UserId}/Items/{Id}/LocalTrailers", "GET")]
+ [Api(Description = "Gets local trailers for an item")]
+ public class GetLocalTrailers : IReturn<List<BaseItemDto>>
{
/// <summary>
/// Gets or sets the user id.
/// </summary>
/// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public Guid UserId { get; set; }
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
-
- [ApiMember(Name = "MediaSourceId", Description = "The id of the MediaSource", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string MediaSourceId { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this <see cref="UpdateUserItemRating" /> is likes.
- /// </summary>
- /// <value><c>true</c> if likes; otherwise, <c>false</c>.</value>
- [ApiMember(Name = "CanSeek", Description = "Indicates if the client can seek", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
- public bool CanSeek { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "QueueableMediaTypes", Description = "A list of media types that can be queued from this item, comma delimited. Audio,Video,Book,Game", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
- public string QueueableMediaTypes { get; set; }
-
- [ApiMember(Name = "AudioStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
- public int? AudioStreamIndex { get; set; }
-
- [ApiMember(Name = "SubtitleStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
- public int? SubtitleStreamIndex { get; set; }
}
/// <summary>
- /// Class OnPlaybackProgress
+ /// Class GetSpecialFeatures
/// </summary>
- [Route("/Users/{UserId}/PlayingItems/{Id}/Progress", "POST")]
- [Api(Description = "Reports a user's playback progress")]
- public class OnPlaybackProgress : IReturnVoid
+ [Route("/Users/{UserId}/Items/{Id}/SpecialFeatures", "GET")]
+ [Api(Description = "Gets special features for an item")]
+ public class GetSpecialFeatures : IReturn<List<BaseItemDto>>
{
/// <summary>
/// Gets or sets the user id.
/// </summary>
/// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public Guid UserId { get; set; }
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ [ApiMember(Name = "Id", Description = "Movie Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
-
- [ApiMember(Name = "MediaSourceId", Description = "The id of the MediaSource", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string MediaSourceId { get; set; }
-
- /// <summary>
- /// Gets or sets the position ticks.
- /// </summary>
- /// <value>The position ticks.</value>
- [ApiMember(Name = "PositionTicks", Description = "Optional. The current position, in ticks. 1 tick = 10000 ms", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
- public long? PositionTicks { get; set; }
-
- [ApiMember(Name = "IsPaused", Description = "Indicates if the player is paused.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
- public bool IsPaused { get; set; }
-
- [ApiMember(Name = "IsMuted", Description = "Indicates if the player is muted.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
- public bool IsMuted { get; set; }
-
- [ApiMember(Name = "AudioStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
- public int? AudioStreamIndex { get; set; }
-
- [ApiMember(Name = "SubtitleStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
- public int? SubtitleStreamIndex { get; set; }
-
- [ApiMember(Name = "VolumeLevel", Description = "Scale of 0-100", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")]
- public int? VolumeLevel { get; set; }
}
- /// <summary>
- /// Class OnPlaybackStopped
- /// </summary>
- [Route("/Users/{UserId}/PlayingItems/{Id}", "DELETE")]
- [Api(Description = "Reports that a user has stopped playing an item")]
- public class OnPlaybackStopped : IReturnVoid
+ [Route("/Users/{UserId}/Items/Latest", "GET", Summary = "Gets latest media")]
+ public class GetLatestMedia : IReturn<List<BaseItemDto>>, IHasItemFields
{
/// <summary>
/// Gets or sets the user id.
/// </summary>
/// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
+ [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public Guid UserId { get; set; }
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
+ [ApiMember(Name = "Limit", Description = "Limit", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int Limit { get; set; }
- [ApiMember(Name = "MediaSourceId", Description = "The id of the MediaSource", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string MediaSourceId { get; set; }
+ [ApiMember(Name = "ParentId", Description = "Specify this to localize the search to a specific item or folder. Omit to use the root", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string ParentId { get; set; }
- /// <summary>
- /// Gets or sets the position ticks.
- /// </summary>
- /// <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 = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ public string Fields { get; set; }
- /// <summary>
- /// Class GetLocalTrailers
- /// </summary>
- [Route("/Users/{UserId}/Items/{Id}/LocalTrailers", "GET")]
- [Api(Description = "Gets local trailers for an item")]
- public class GetLocalTrailers : IReturn<List<BaseItemDto>>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid UserId { get; set; }
+ [ApiMember(Name = "IncludeItemTypes", Description = "Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ public string IncludeItemTypes { get; set; }
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
+ [ApiMember(Name = "IsFolder", Description = "Filter by items that are folders, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
+ public bool? IsFolder { get; set; }
- /// <summary>
- /// Class GetSpecialFeatures
- /// </summary>
- [Route("/Users/{UserId}/Items/{Id}/SpecialFeatures", "GET")]
- [Api(Description = "Gets special features for an item")]
- public class GetSpecialFeatures : IReturn<List<BaseItemDto>>
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid UserId { get; set; }
+ [ApiMember(Name = "IsPlayed", Description = "Filter by items that are played, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
+ public bool? IsPlayed { get; set; }
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Movie Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
+ [ApiMember(Name = "GroupItems", Description = "Whether or not to group items into a parent container.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
+ public bool GroupItems { get; set; }
+
+ public GetLatestMedia()
+ {
+ Limit = 20;
+ GroupItems = true;
+ }
}
-
/// <summary>
/// Class UserLibraryService
/// </summary>
+ [Authenticated]
public class UserLibraryService : BaseApiService
{
- /// <summary>
- /// The _user manager
- /// </summary>
private readonly IUserManager _userManager;
- /// <summary>
- /// The _user data repository
- /// </summary>
private readonly IUserDataManager _userDataRepository;
- /// <summary>
- /// The _library manager
- /// </summary>
private readonly ILibraryManager _libraryManager;
-
- private readonly ISessionManager _sessionManager;
private readonly IDtoService _dtoService;
-
private readonly IUserViewManager _userViewManager;
/// <summary>
@@ -450,15 +285,14 @@ namespace MediaBrowser.Api.UserLibrary
/// <param name="userManager">The user manager.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="userDataRepository">The user data repository.</param>
- /// <param name="sessionManager">The session manager.</param>
/// <param name="dtoService">The dto service.</param>
+ /// <param name="userViewManager">The user view manager.</param>
/// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
- public UserLibraryService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, ISessionManager sessionManager, IDtoService dtoService, IUserViewManager userViewManager)
+ public UserLibraryService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, IUserViewManager userViewManager)
{
_userManager = userManager;
_libraryManager = libraryManager;
_userDataRepository = userDataRepository;
- _sessionManager = sessionManager;
_dtoService = dtoService;
_userViewManager = userViewManager;
}
@@ -475,7 +309,98 @@ namespace MediaBrowser.Api.UserLibrary
return ToOptimizedSerializedResultUsingCache(result);
}
- public object Get(GetUserViews request)
+ public object Get(GetLatestMedia request)
+ {
+ var user = _userManager.GetUserById(request.UserId);
+
+ // Avoid implicitly captured closure
+ var libraryItems = GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId)
+ .OrderByDescending(i => i.DateCreated)
+ .Where(i => i.LocationType != LocationType.Virtual);
+
+
+ //if (request.IsFolder.HasValue)
+ //{
+ //var val = request.IsFolder.Value;
+ libraryItems = libraryItems.Where(f => f.IsFolder == false);
+ //}
+
+ if (!string.IsNullOrEmpty(request.IncludeItemTypes))
+ {
+ var vals = request.IncludeItemTypes.Split(',');
+ libraryItems = libraryItems.Where(f => vals.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase));
+ }
+
+ var currentUser = user;
+
+ if (request.IsPlayed.HasValue)
+ {
+ var takeLimit = request.Limit * 20;
+
+ var val = request.IsPlayed.Value;
+ libraryItems = libraryItems.Where(f => f.IsPlayed(currentUser) == val)
+ .Take(takeLimit);
+ }
+
+ // Avoid implicitly captured closure
+ var items = libraryItems
+ .ToList();
+
+ var list = new List<Tuple<BaseItem, List<BaseItem>>>();
+
+ foreach (var item in items)
+ {
+ // Only grab the index container for media
+ var container = item.IsFolder || !request.GroupItems ? null : item.LatestItemsIndexContainer;
+
+ if (container == null)
+ {
+ list.Add(new Tuple<BaseItem, List<BaseItem>>(null, new List<BaseItem> { item }));
+ }
+ else
+ {
+ var current = list.FirstOrDefault(i => i.Item1 != null && i.Item1.Id == container.Id);
+
+ if (current != null)
+ {
+ current.Item2.Add(item);
+ }
+ else
+ {
+ list.Add(new Tuple<BaseItem, List<BaseItem>>(container, new List<BaseItem> { item }));
+ }
+ }
+
+ if (list.Count >= request.Limit)
+ {
+ break;
+ }
+ }
+
+ var fields = request.GetItemFields().ToList();
+
+ var dtos = list.Select(i =>
+ {
+ var item = i.Item2[0];
+ var childCount = 0;
+
+ if (i.Item1 != null && i.Item2.Count > 0)
+ {
+ item = i.Item1;
+ childCount = i.Item2.Count;
+ }
+
+ var dto = _dtoService.GetBaseItemDto(item, fields, user);
+
+ dto.ChildCount = childCount;
+
+ return dto;
+ });
+
+ return ToOptimizedResult(dtos.ToList());
+ }
+
+ public async Task<object> Get(GetUserViews request)
{
var user = _userManager.GetUserById(new Guid(request.UserId));
@@ -493,10 +418,9 @@ namespace MediaBrowser.Api.UserLibrary
query.IncludeExternalContent = request.IncludeExternalContent.Value;
}
- var folders = _userViewManager.GetUserViews(query, CancellationToken.None).Result;
+ var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false);
- var dtos = folders.OrderBy(i => i.SortName)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
+ var dtos = folders.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
.ToArray();
var result = new QueryResult<BaseItemDto>
@@ -541,7 +465,8 @@ namespace MediaBrowser.Api.UserLibrary
if (series != null)
{
var dtos = series
- .GetRecursiveChildren(i => i is Episode && i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0)
+ .GetRecursiveChildren()
+ .Where(i => i is Episode && i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0)
.OrderBy(i =>
{
if (i.PremiereDate.HasValue)
@@ -714,9 +639,7 @@ namespace MediaBrowser.Api.UserLibrary
await _userDataRepository.SaveUserData(user.Id, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None).ConfigureAwait(false);
- data = _userDataRepository.GetUserData(user.Id, key);
-
- return _dtoService.GetUserItemDataDto(data);
+ return _userDataRepository.GetUserDataDto(item, user);
}
/// <summary>
@@ -763,177 +686,7 @@ namespace MediaBrowser.Api.UserLibrary
await _userDataRepository.SaveUserData(user.Id, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None).ConfigureAwait(false);
- data = _userDataRepository.GetUserData(user.Id, key);
-
- return _dtoService.GetUserItemDataDto(data);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public object Post(MarkPlayedItem request)
- {
- var result = MarkPlayed(request).Result;
-
- return ToOptimizedResult(result);
- }
-
- private async Task<UserItemDataDto> MarkPlayed(MarkPlayedItem request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- DateTime? datePlayed = null;
-
- if (!string.IsNullOrEmpty(request.DatePlayed))
- {
- datePlayed = DateTime.ParseExact(request.DatePlayed, "yyyyMMddHHmmss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
- }
-
- var session = GetSession(_sessionManager);
-
- var dto = await UpdatePlayedStatus(user, request.Id, true, datePlayed).ConfigureAwait(false);
-
- foreach (var additionalUserInfo in session.AdditionalUsers)
- {
- var additionalUser = _userManager.GetUserById(new Guid(additionalUserInfo.UserId));
-
- await UpdatePlayedStatus(additionalUser, request.Id, true, datePlayed).ConfigureAwait(false);
- }
-
- return dto;
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(OnPlaybackStart request)
- {
- var queueableMediaTypes = (request.QueueableMediaTypes ?? string.Empty);
-
- Post(new ReportPlaybackStart
- {
- CanSeek = request.CanSeek,
- ItemId = request.Id,
- QueueableMediaTypes = queueableMediaTypes.Split(',').ToList(),
- MediaSourceId = request.MediaSourceId,
- AudioStreamIndex = request.AudioStreamIndex,
- SubtitleStreamIndex = request.SubtitleStreamIndex
- });
- }
-
- public void Post(ReportPlaybackStart request)
- {
- request.SessionId = GetSession(_sessionManager).Id;
-
- var task = _sessionManager.OnPlaybackStart(request);
-
- Task.WaitAll(task);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(OnPlaybackProgress request)
- {
- Post(new ReportPlaybackProgress
- {
- ItemId = request.Id,
- PositionTicks = request.PositionTicks,
- IsMuted = request.IsMuted,
- IsPaused = request.IsPaused,
- MediaSourceId = request.MediaSourceId,
- AudioStreamIndex = request.AudioStreamIndex,
- SubtitleStreamIndex = request.SubtitleStreamIndex,
- VolumeLevel = request.VolumeLevel
- });
- }
-
- public void Post(ReportPlaybackProgress request)
- {
- request.SessionId = GetSession(_sessionManager).Id;
-
- var task = _sessionManager.OnPlaybackProgress(request);
-
- Task.WaitAll(task);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Delete(OnPlaybackStopped request)
- {
- Post(new ReportPlaybackStopped
- {
- ItemId = request.Id,
- PositionTicks = request.PositionTicks,
- MediaSourceId = request.MediaSourceId
- });
- }
-
- public void Post(ReportPlaybackStopped request)
- {
- request.SessionId = GetSession(_sessionManager).Id;
-
- var task = _sessionManager.OnPlaybackStopped(request);
-
- Task.WaitAll(task);
- }
-
- /// <summary>
- /// Deletes the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public object Delete(MarkUnplayedItem request)
- {
- var task = MarkUnplayed(request);
-
- return ToOptimizedResult(task.Result);
- }
-
- private async Task<UserItemDataDto> MarkUnplayed(MarkUnplayedItem request)
- {
- var user = _userManager.GetUserById(request.UserId);
-
- var session = GetSession(_sessionManager);
-
- var dto = await UpdatePlayedStatus(user, request.Id, false, null).ConfigureAwait(false);
-
- foreach (var additionalUserInfo in session.AdditionalUsers)
- {
- var additionalUser = _userManager.GetUserById(new Guid(additionalUserInfo.UserId));
-
- await UpdatePlayedStatus(additionalUser, request.Id, false, null).ConfigureAwait(false);
- }
-
- return dto;
- }
-
- /// <summary>
- /// Updates the played status.
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="itemId">The item id.</param>
- /// <param name="wasPlayed">if set to <c>true</c> [was played].</param>
- /// <param name="datePlayed">The date played.</param>
- /// <returns>Task.</returns>
- private async Task<UserItemDataDto> UpdatePlayedStatus(User user, string itemId, bool wasPlayed, DateTime? datePlayed)
- {
- var item = _libraryManager.GetItemById(itemId);
-
- if (wasPlayed)
- {
- await item.MarkPlayed(user, datePlayed, _userDataRepository).ConfigureAwait(false);
- }
- else
- {
- await item.MarkUnplayed(user, _userDataRepository).ConfigureAwait(false);
- }
-
- return _dtoService.GetUserItemDataDto(_userDataRepository.GetUserData(user.Id, item.GetUserDataKey()));
+ return _userDataRepository.GetUserDataDto(item, user);
}
}
}
diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs
index 8a3bc12b2..2b300f900 100644
--- a/MediaBrowser.Api/UserLibrary/YearsService.cs
+++ b/MediaBrowser.Api/UserLibrary/YearsService.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
@@ -43,6 +44,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary>
/// Class YearsService
/// </summary>
+ [Authenticated]
public class YearsService : BaseItemsByNameService<Year>
{
public YearsService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IDtoService dtoService)
@@ -78,10 +80,10 @@ namespace MediaBrowser.Api.UserLibrary
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetItemByNameDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, fields.ToList(), user);
}
- return DtoService.GetItemByNameDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, fields.ToList());
}
/// <summary>
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
index 1932c8f93..2c504bee1 100644
--- a/MediaBrowser.Api/UserService.cs
+++ b/MediaBrowser.Api/UserService.cs
@@ -1,9 +1,11 @@
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Users;
using ServiceStack;
using ServiceStack.Text.Controller;
@@ -18,6 +20,7 @@ namespace MediaBrowser.Api
/// Class GetUsers
/// </summary>
[Route("/Users", "GET", Summary = "Gets a list of users")]
+ [Authenticated]
public class GetUsers : IReturn<List<UserDto>>
{
[ApiMember(Name = "IsHidden", Description = "Optional filter by IsHidden=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
@@ -36,6 +39,7 @@ namespace MediaBrowser.Api
/// Class GetUser
/// </summary>
[Route("/Users/{Id}", "GET", Summary = "Gets a user by Id")]
+ [Authenticated]
public class GetUser : IReturn<UserDto>
{
/// <summary>
@@ -50,6 +54,7 @@ namespace MediaBrowser.Api
/// Class DeleteUser
/// </summary>
[Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")]
+ [Authenticated]
public class DeleteUser : IReturnVoid
{
/// <summary>
@@ -106,6 +111,7 @@ namespace MediaBrowser.Api
/// Class UpdateUserPassword
/// </summary>
[Route("/Users/{Id}/Password", "POST", Summary = "Updates a user's password")]
+ [Authenticated]
public class UpdateUserPassword : IReturnVoid
{
/// <summary>
@@ -137,6 +143,7 @@ namespace MediaBrowser.Api
/// Class UpdateUser
/// </summary>
[Route("/Users/{Id}", "POST", Summary = "Updates a user")]
+ [Authenticated]
public class UpdateUser : UserDto, IReturnVoid
{
}
@@ -145,6 +152,7 @@ namespace MediaBrowser.Api
/// Class CreateUser
/// </summary>
[Route("/Users", "POST", Summary = "Creates a user")]
+ [Authenticated]
public class CreateUser : UserDto, IReturn<UserDto>
{
}
@@ -152,48 +160,68 @@ namespace MediaBrowser.Api
/// <summary>
/// Class UsersService
/// </summary>
- public class UserService : BaseApiService
+ public class UserService : BaseApiService, IHasAuthorization
{
/// <summary>
- /// The _XML serializer
- /// </summary>
- private readonly IXmlSerializer _xmlSerializer;
-
- /// <summary>
/// The _user manager
/// </summary>
private readonly IUserManager _userManager;
private readonly IDtoService _dtoService;
private readonly ISessionManager _sessionMananger;
+ private readonly IServerConfigurationManager _config;
+ private readonly INetworkManager _networkManager;
+
+ public IAuthorizationContext AuthorizationContext { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="UserService" /> class.
/// </summary>
- /// <param name="xmlSerializer">The XML serializer.</param>
/// <param name="userManager">The user manager.</param>
/// <param name="dtoService">The dto service.</param>
+ /// <param name="sessionMananger">The session mananger.</param>
/// <exception cref="System.ArgumentNullException">xmlSerializer</exception>
- public UserService(IXmlSerializer xmlSerializer, IUserManager userManager, IDtoService dtoService, ISessionManager sessionMananger)
- : base()
+ public UserService(IUserManager userManager, IDtoService dtoService, ISessionManager sessionMananger, IServerConfigurationManager config, INetworkManager networkManager)
{
- if (xmlSerializer == null)
- {
- throw new ArgumentNullException("xmlSerializer");
- }
-
- _xmlSerializer = xmlSerializer;
_userManager = userManager;
_dtoService = dtoService;
_sessionMananger = sessionMananger;
+ _config = config;
+ _networkManager = networkManager;
}
public object Get(GetPublicUsers request)
{
+ var authInfo = AuthorizationContext.GetAuthorizationInfo(Request);
+ var isDashboard = string.Equals(authInfo.Client, "Dashboard", StringComparison.OrdinalIgnoreCase);
+
+ if ((Request.IsLocal && isDashboard) ||
+ !_config.Configuration.IsStartupWizardCompleted)
+ {
+ return Get(new GetUsers
+ {
+ IsDisabled = false
+ });
+ }
+
+ // TODO: Uncomment this once all clients can handle an empty user list.
return Get(new GetUsers
{
IsHidden = false,
IsDisabled = false
});
+
+ //// TODO: Add or is authenticated
+ //if (Request.IsLocal || IsInLocalNetwork(Request.RemoteIp))
+ //{
+ // return Get(new GetUsers
+ // {
+ // IsHidden = false,
+ // IsDisabled = false
+ // });
+ //}
+
+ //// Return empty when external
+ //return ToOptimizedResult(new List<UserDto>());
}
/// <summary>
@@ -217,7 +245,7 @@ namespace MediaBrowser.Api
var result = users
.OrderBy(u => u.Name)
- .Select(_dtoService.GetUserDto)
+ .Select(i => _userManager.GetUserDto(i, Request.RemoteIp))
.ToList();
return ToOptimizedSerializedResultUsingCache(result);
@@ -237,7 +265,7 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException("User not found");
}
- var result = _dtoService.GetUserDto(user);
+ var result = _userManager.GetUserDto(user, Request.RemoteIp);
return ToOptimizedSerializedResultUsingCache(result);
}
@@ -248,6 +276,13 @@ namespace MediaBrowser.Api
/// <param name="request">The request.</param>
public void Delete(DeleteUser request)
{
+ var task = DeleteAsync(request);
+
+ Task.WaitAll(task);
+ }
+
+ public async Task DeleteAsync(DeleteUser request)
+ {
var user = _userManager.GetUserById(request.Id);
if (user == null)
@@ -255,9 +290,8 @@ namespace MediaBrowser.Api
throw new ResourceNotFoundException("User not found");
}
- var task = _userManager.DeleteUser(user);
-
- Task.WaitAll(task);
+ await _sessionMananger.RevokeUserTokens(user.Id.ToString("N")).ConfigureAwait(false);
+ await _userManager.DeleteUser(user).ConfigureAwait(false);
}
/// <summary>
@@ -266,67 +300,54 @@ namespace MediaBrowser.Api
/// <param name="request">The request.</param>
public object Post(AuthenticateUser request)
{
- // No response needed. Will throw an exception on failure.
- var result = AuthenticateUser(request).Result;
-
- return result;
- }
-
- public object Post(AuthenticateUserByName request)
- {
- var user = _userManager.Users.FirstOrDefault(i => string.Equals(request.Username, i.Name, StringComparison.OrdinalIgnoreCase));
+ var user = _userManager.GetUserById(request.Id);
if (user == null)
{
- throw new ArgumentException(string.Format("User {0} not found.", request.Username));
+ throw new ResourceNotFoundException("User not found");
}
- var result = AuthenticateUser(new AuthenticateUser { Id = user.Id, Password = request.Password }).Result;
-
- return ToOptimizedResult(result);
+ return Post(new AuthenticateUserByName
+ {
+ Username = user.Name,
+ Password = request.Password
+ });
}
- private async Task<AuthenticationResult> AuthenticateUser(AuthenticateUser request)
+ public async Task<object> Post(AuthenticateUserByName request)
{
- var user = _userManager.GetUserById(request.Id);
+ var auth = AuthorizationContext.GetAuthorizationInfo(Request);
- if (user == null)
+ if (string.IsNullOrWhiteSpace(auth.Client))
{
- throw new ResourceNotFoundException("User not found");
+ auth.Client = "Unknown app";
}
-
- var auth = AuthorizationRequestFilterAttribute.GetAuthorization(Request);
-
- // Login in the old way if the header is missing
- if (string.IsNullOrEmpty(auth.Client) ||
- string.IsNullOrEmpty(auth.Device) ||
- string.IsNullOrEmpty(auth.DeviceId) ||
- string.IsNullOrEmpty(auth.Version))
+ if (string.IsNullOrWhiteSpace(auth.Device))
{
- var success = await _userManager.AuthenticateUser(user, request.Password).ConfigureAwait(false);
-
- if (!success)
- {
- // Unauthorized
- throw new UnauthorizedAccessException("Invalid user or password entered.");
- }
-
- return new AuthenticationResult
- {
- User = _dtoService.GetUserDto(user)
- };
+ auth.Device = "Unknown device";
+ }
+ if (string.IsNullOrWhiteSpace(auth.Version))
+ {
+ auth.Version = "Unknown version";
+ }
+ if (string.IsNullOrWhiteSpace(auth.DeviceId))
+ {
+ auth.DeviceId = "Unknown device id";
}
- var session = await _sessionMananger.AuthenticateNewSession(user, request.Password, auth.Client, auth.Version,
- auth.DeviceId, auth.Device, Request.RemoteIp).ConfigureAwait(false);
-
- var result = new AuthenticationResult
+ var result = await _sessionMananger.AuthenticateNewSession(new AuthenticationRequest
{
- User = _dtoService.GetUserDto(user),
- SessionInfo = _sessionMananger.GetSessionInfoDto(session)
- };
+ App = auth.Client,
+ AppVersion = auth.Version,
+ DeviceId = auth.DeviceId,
+ DeviceName = auth.Device,
+ Password = request.Password,
+ RemoteEndPoint = Request.RemoteIp,
+ Username = request.Username
+
+ }, Request.IsLocal).ConfigureAwait(false);
- return result;
+ return ToOptimizedResult(result);
}
/// <summary>
@@ -335,6 +356,12 @@ namespace MediaBrowser.Api
/// <param name="request">The request.</param>
public void Post(UpdateUserPassword request)
{
+ var task = PostAsync(request);
+ Task.WaitAll(task);
+ }
+
+ public async Task PostAsync(UpdateUserPassword request)
+ {
var user = _userManager.GetUserById(request.Id);
if (user == null)
@@ -344,31 +371,34 @@ namespace MediaBrowser.Api
if (request.ResetPassword)
{
- var task = _userManager.ResetPassword(user);
-
- Task.WaitAll(task);
+ await _userManager.ResetPassword(user).ConfigureAwait(false);
}
else
{
- var success = _userManager.AuthenticateUser(user, request.CurrentPassword).Result;
+ var success = await _userManager.AuthenticateUser(user.Name, request.CurrentPassword, Request.RemoteIp).ConfigureAwait(false);
if (!success)
{
- throw new UnauthorizedAccessException("Invalid user or password entered.");
+ throw new ArgumentException("Invalid user or password entered.");
}
- var task = _userManager.ChangePassword(user, request.NewPassword);
-
- Task.WaitAll(task);
+ await _userManager.ChangePassword(user, request.NewPassword).ConfigureAwait(false);
}
}
-
+
/// <summary>
/// Posts the specified request.
/// </summary>
/// <param name="request">The request.</param>
public void Post(UpdateUser request)
{
+ var task = PostAsync(request);
+
+ Task.WaitAll(task);
+ }
+
+ public async Task PostAsync(UpdateUser request)
+ {
// We need to parse this manually because we told service stack not to with IRequiresRequestStream
// https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs
var pathInfo = PathInfo.Parse(Request.PathInfo);
@@ -400,11 +430,15 @@ namespace MediaBrowser.Api
{
throw new ArgumentException("There must be at least one enabled user in the system.");
}
+
+ await _sessionMananger.RevokeUserTokens(user.Id.ToString("N")).ConfigureAwait(false);
}
- var task = user.Name.Equals(dtoUser.Name, StringComparison.Ordinal) ? _userManager.UpdateUser(user) : _userManager.RenameUser(user, dtoUser.Name);
+ var task = user.Name.Equals(dtoUser.Name, StringComparison.Ordinal) ?
+ _userManager.UpdateUser(user) :
+ _userManager.RenameUser(user, dtoUser.Name);
- Task.WaitAll(task);
+ await task.ConfigureAwait(false);
user.UpdateConfiguration(dtoUser.Configuration);
}
@@ -422,7 +456,7 @@ namespace MediaBrowser.Api
newUser.UpdateConfiguration(dtoUser.Configuration);
- var result = _dtoService.GetUserDto(newUser);
+ var result = _userManager.GetUserDto(newUser, Request.RemoteIp);
return ToOptimizedResult(result);
}
diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs
index f62e37f79..c964ab458 100644
--- a/MediaBrowser.Api/VideosService.cs
+++ b/MediaBrowser.Api/VideosService.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Querying;
using ServiceStack;
@@ -41,6 +42,7 @@ namespace MediaBrowser.Api
public string Ids { get; set; }
}
+ [Authenticated]
public class VideosService : BaseApiService
{
private readonly ILibraryManager _libraryManager;
@@ -97,12 +99,12 @@ namespace MediaBrowser.Api
public void Delete(DeleteAlternateSources request)
{
- var task = RemoveAlternateVersions(request);
+ var task = DeleteAsync(request);
Task.WaitAll(task);
}
- private async Task RemoveAlternateVersions(DeleteAlternateSources request)
+ public async Task DeleteAsync(DeleteAlternateSources request)
{
var video = (Video)_libraryManager.GetItemById(request.Id);
@@ -119,12 +121,12 @@ namespace MediaBrowser.Api
public void Post(MergeVersions request)
{
- var task = MergeVersions(request);
+ var task = PostAsync(request);
Task.WaitAll(task);
}
- private async Task MergeVersions(MergeVersions request)
+ public async Task PostAsync(MergeVersions request)
{
var items = request.Ids.Split(',')
.Select(i => new Guid(i))
@@ -170,12 +172,12 @@ namespace MediaBrowser.Api
return 0;
})
.ThenByDescending(i =>
- {
- var stream = i.GetDefaultVideoStream();
+ {
+ var stream = i.GetDefaultVideoStream();
- return stream == null || stream.Width == null ? 0 : stream.Width.Value;
+ return stream == null || stream.Width == null ? 0 : stream.Width.Value;
- }).First();
+ }).First();
}
foreach (var item in videos.Where(i => i.Id != primaryVersion.Id))
diff --git a/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs b/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs
deleted file mode 100644
index 46dabb042..000000000
--- a/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs
+++ /dev/null
@@ -1,149 +0,0 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.IO;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Api.WebSocket
-{
- /// <summary>
- /// Class ScheduledTasksWebSocketListener
- /// </summary>
- public class LogFileWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<string>, LogFileWebSocketState>
- {
- /// <summary>
- /// Gets the name.
- /// </summary>
- /// <value>The name.</value>
- protected override string Name
- {
- get { return "LogFile"; }
- }
-
- /// <summary>
- /// The _kernel
- /// </summary>
- private readonly ILogManager _logManager;
- private readonly IFileSystem _fileSystem;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="LogFileWebSocketListener" /> class.
- /// </summary>
- /// <param name="logger">The logger.</param>
- /// <param name="logManager">The log manager.</param>
- public LogFileWebSocketListener(ILogger logger, ILogManager logManager, IFileSystem fileSystem)
- : base(logger)
- {
- _logManager = logManager;
- _fileSystem = fileSystem;
- _logManager.LoggerLoaded += kernel_LoggerLoaded;
- }
-
- /// <summary>
- /// Gets the data to send.
- /// </summary>
- /// <param name="state">The state.</param>
- /// <returns>IEnumerable{System.String}.</returns>
- protected override async Task<IEnumerable<string>> GetDataToSend(LogFileWebSocketState state)
- {
- if (!string.Equals(_logManager.LogFilePath, state.LastLogFilePath))
- {
- state.LastLogFilePath = _logManager.LogFilePath;
- state.StartLine = 0;
- }
-
- var lines = await GetLogLines(state.LastLogFilePath, state.StartLine, _fileSystem).ConfigureAwait(false);
-
- state.StartLine += lines.Count;
-
- return lines;
- }
-
- /// <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 override void Dispose(bool dispose)
- {
- if (dispose)
- {
- _logManager.LoggerLoaded -= kernel_LoggerLoaded;
- }
- base.Dispose(dispose);
- }
-
- /// <summary>
- /// Handles the LoggerLoaded event of the kernel control.
- /// </summary>
- /// <param name="sender">The source of the event.</param>
- /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
- void kernel_LoggerLoaded(object sender, EventArgs e)
- {
- // Reset the startline for each connection whenever the logger reloads
- lock (ActiveConnections)
- {
- foreach (var connection in ActiveConnections)
- {
- connection.Item4.StartLine = 0;
- }
- }
- }
-
- /// <summary>
- /// Gets the log lines.
- /// </summary>
- /// <param name="logFilePath">The log file path.</param>
- /// <param name="startLine">The start line.</param>
- /// <returns>Task{IEnumerable{System.String}}.</returns>
- internal static async Task<List<string>> GetLogLines(string logFilePath, int startLine, IFileSystem fileSystem)
- {
- var lines = new List<string>();
-
- using (var fs = fileSystem.GetFileStream(logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
- {
- using (var reader = new StreamReader(fs))
- {
- while (!reader.EndOfStream)
- {
- var line = await reader.ReadLineAsync().ConfigureAwait(false);
-
- if (line.IndexOf("Info -", StringComparison.OrdinalIgnoreCase) != -1 ||
- line.IndexOf("Warn -", StringComparison.OrdinalIgnoreCase) != -1 ||
- line.IndexOf("Error -", StringComparison.OrdinalIgnoreCase) != -1)
- {
- lines.Add(line);
- }
- }
- }
- }
-
- if (startLine > 0)
- {
- lines = lines.Skip(startLine).ToList();
- }
-
- return lines;
- }
- }
-
- /// <summary>
- /// Class LogFileWebSocketState
- /// </summary>
- public class LogFileWebSocketState : WebSocketListenerState
- {
- /// <summary>
- /// Gets or sets the last log file path.
- /// </summary>
- /// <value>The last log file path.</value>
- public string LastLogFilePath { get; set; }
- /// <summary>
- /// Gets or sets the start line.
- /// </summary>
- /// <value>The start line.</value>
- public int StartLine { get; set; }
- }
-}
diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
index 7bd0ca748..80f017f52 100644
--- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
+++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
@@ -211,6 +211,8 @@ namespace MediaBrowser.Common.Implementations
JsonSerializer = CreateJsonSerializer();
Logger = LogManager.GetLogger("App");
+ OnLoggerLoaded(true);
+ LogManager.LoggerLoaded += (s, e) => OnLoggerLoaded(false);
IsFirstRun = !ConfigurationManager.CommonConfiguration.IsStartupWizardCompleted;
progress.Report(2);
@@ -219,16 +221,11 @@ namespace MediaBrowser.Common.Implementations
? LogSeverity.Debug
: LogSeverity.Info;
- // Put the app config in the log for troubleshooting purposes
- Logger.LogMultiline("Application Configuration:", LogSeverity.Info, new StringBuilder(JsonSerializer.SerializeToString(ConfigurationManager.CommonConfiguration)));
-
progress.Report(3);
DiscoverTypes();
progress.Report(14);
- Logger.Info("Version {0} initializing", ApplicationVersion);
-
SetHttpLimit();
progress.Report(15);
@@ -245,6 +242,47 @@ namespace MediaBrowser.Common.Implementations
progress.Report(100);
}
+ protected virtual void OnLoggerLoaded(bool isFirstLoad)
+ {
+ Logger.Info("Application version: {0}", ApplicationVersion);
+
+ if (!isFirstLoad)
+ {
+ LogEnvironmentInfo(Logger, ApplicationPaths);
+ }
+
+ // Put the app config in the log for troubleshooting purposes
+ Logger.LogMultiline("Application configuration:", LogSeverity.Info, new StringBuilder(JsonSerializer.SerializeToString(ConfigurationManager.CommonConfiguration)));
+
+ if (Plugins != null)
+ {
+ var pluginBuilder = new StringBuilder();
+
+ foreach (var plugin in Plugins)
+ {
+ pluginBuilder.AppendLine(string.Format("{0} {1}", plugin.Name, plugin.Version));
+ }
+
+ Logger.LogMultiline("Plugins:", LogSeverity.Info, pluginBuilder);
+ }
+ }
+
+ public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths)
+ {
+ logger.Info("Command line: {0}", string.Join(" ", Environment.GetCommandLineArgs()));
+
+ logger.Info("Server: {0}", Environment.MachineName);
+ logger.Info("Operating system: {0}", Environment.OSVersion.ToString());
+ logger.Info("Processor count: {0}", Environment.ProcessorCount);
+ logger.Info("64-Bit OS: {0}", Environment.Is64BitOperatingSystem);
+ logger.Info("64-Bit Process: {0}", Environment.Is64BitProcess);
+ logger.Info("Program data path: {0}", appPaths.ProgramDataPath);
+
+ logger.Info("Application Path: {0}", appPaths.ApplicationPath);
+
+ logger.Info("*** When reporting issues please include the entire log file. ***".ToUpper());
+ }
+
protected virtual IJsonSerializer CreateJsonSerializer()
{
return new JsonSerializer();
@@ -342,6 +380,7 @@ namespace MediaBrowser.Common.Implementations
/// </summary>
protected virtual void FindParts()
{
+ ConfigurationManager.AddParts(GetExports<IConfigurationFactory>());
Plugins = GetExports<IPlugin>();
}
@@ -393,7 +432,7 @@ namespace MediaBrowser.Common.Implementations
HttpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, Logger, FileSystemManager, ConfigurationManager);
RegisterSingleInstance(HttpClient);
- NetworkManager = CreateNetworkManager();
+ NetworkManager = CreateNetworkManager(LogManager.GetLogger("NetworkManager"));
RegisterSingleInstance(NetworkManager);
SecurityManager = new PluginSecurityManager(this, HttpClient, JsonSerializer, ApplicationPaths, NetworkManager, LogManager);
@@ -461,7 +500,7 @@ namespace MediaBrowser.Common.Implementations
}
}
- protected abstract INetworkManager CreateNetworkManager();
+ protected abstract INetworkManager CreateNetworkManager(ILogger logger);
/// <summary>
/// Creates an instance of type and resolves all constructor dependancies
@@ -631,6 +670,7 @@ namespace MediaBrowser.Common.Implementations
return parts;
}
+ private Version _version;
/// <summary>
/// Gets the current application version
/// </summary>
@@ -639,7 +679,7 @@ namespace MediaBrowser.Common.Implementations
{
get
{
- return GetType().Assembly.GetName().Version;
+ return _version ?? (_version = GetType().Assembly.GetName().Version);
}
}
diff --git a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs
index 8c4840ea7..cb6121c9f 100644
--- a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs
+++ b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs
@@ -1,10 +1,13 @@
-using System.IO;
-using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Events;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
using System.Threading;
namespace MediaBrowser.Common.Implementations.Configuration
@@ -26,6 +29,16 @@ namespace MediaBrowser.Common.Implementations.Configuration
public event EventHandler<EventArgs> ConfigurationUpdated;
/// <summary>
+ /// Occurs when [configuration updating].
+ /// </summary>
+ public event EventHandler<ConfigurationUpdateEventArgs> NamedConfigurationUpdating;
+
+ /// <summary>
+ /// Occurs when [named configuration updated].
+ /// </summary>
+ public event EventHandler<ConfigurationUpdateEventArgs> NamedConfigurationUpdated;
+
+ /// <summary>
/// Gets the logger.
/// </summary>
/// <value>The logger.</value>
@@ -74,6 +87,9 @@ namespace MediaBrowser.Common.Implementations.Configuration
}
}
+ private ConfigurationStore[] _configurationStores = {};
+ private IConfigurationFactory[] _configurationFactories;
+
/// <summary>
/// Initializes a new instance of the <see cref="BaseConfigurationManager" /> class.
/// </summary>
@@ -89,10 +105,14 @@ namespace MediaBrowser.Common.Implementations.Configuration
UpdateCachePath();
}
- /// <summary>
- /// The _save lock
- /// </summary>
- private readonly object _configurationSaveLock = new object();
+ public void AddParts(IEnumerable<IConfigurationFactory> factories)
+ {
+ _configurationFactories = factories.ToArray();
+
+ _configurationStores = _configurationFactories
+ .SelectMany(i => i.GetConfigurations())
+ .ToArray();
+ }
/// <summary>
/// Saves the configuration.
@@ -103,7 +123,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
Directory.CreateDirectory(Path.GetDirectoryName(path));
- lock (_configurationSaveLock)
+ lock (_configurationSyncLock)
{
XmlSerializer.SerializeToFile(CommonConfiguration, path);
}
@@ -144,8 +164,8 @@ namespace MediaBrowser.Common.Implementations.Configuration
/// </summary>
private void UpdateCachePath()
{
- ((BaseApplicationPaths)CommonApplicationPaths).CachePath = string.IsNullOrEmpty(CommonConfiguration.CachePath) ?
- null :
+ ((BaseApplicationPaths)CommonApplicationPaths).CachePath = string.IsNullOrEmpty(CommonConfiguration.CachePath) ?
+ null :
CommonConfiguration.CachePath;
}
@@ -168,5 +188,70 @@ namespace MediaBrowser.Common.Implementations.Configuration
}
}
}
+
+ private readonly ConcurrentDictionary<string, object> _configurations = new ConcurrentDictionary<string, object>();
+
+ private string GetConfigurationFile(string key)
+ {
+ return Path.Combine(CommonApplicationPaths.ConfigurationDirectoryPath, key.ToLower() + ".xml");
+ }
+
+ public object GetConfiguration(string key)
+ {
+ return _configurations.GetOrAdd(key, k =>
+ {
+ var file = GetConfigurationFile(key);
+
+ var configurationType = _configurationStores
+ .First(i => string.Equals(i.Key, key, StringComparison.OrdinalIgnoreCase))
+ .ConfigurationType;
+
+ lock (_configurationSyncLock)
+ {
+ return ConfigurationHelper.GetXmlConfiguration(configurationType, file, XmlSerializer);
+ }
+ });
+ }
+
+ public void SaveConfiguration(string key, object configuration)
+ {
+ var configurationType = GetConfigurationType(key);
+
+ if (configuration.GetType() != configurationType)
+ {
+ throw new ArgumentException("Expected configuration type is " + configurationType.Name);
+ }
+
+ EventHelper.FireEventIfNotNull(NamedConfigurationUpdating, this, new ConfigurationUpdateEventArgs
+ {
+ Key = key,
+ NewConfiguration = configuration
+
+ }, Logger);
+
+ _configurations.AddOrUpdate(key, configuration, (k, v) => configuration);
+
+ var path = GetConfigurationFile(key);
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+
+ lock (_configurationSyncLock)
+ {
+ XmlSerializer.SerializeToFile(configuration, path);
+ }
+
+ EventHelper.FireEventIfNotNull(NamedConfigurationUpdated, this, new ConfigurationUpdateEventArgs
+ {
+ Key = key,
+ NewConfiguration = configuration
+
+ }, Logger);
+ }
+
+ public Type GetConfigurationType(string key)
+ {
+ return _configurationStores
+ .First(i => string.Equals(i.Key, key, StringComparison.OrdinalIgnoreCase))
+ .ConfigurationType;
+ }
}
}
diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
index 5efb39cbc..11a5cdf08 100644
--- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
+++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
@@ -107,7 +107,6 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
return client;
}
- private PropertyInfo _httpBehaviorPropertyInfo;
private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression)
{
var request = (HttpWebRequest)WebRequest.Create(options.Url);
@@ -118,7 +117,11 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
- request.KeepAlive = options.EnableKeepAlive;
+ if (options.EnableKeepAlive)
+ {
+ request.KeepAlive = true;
+ }
+
request.Method = method;
request.Pipelined = true;
request.Timeout = 20000;
@@ -133,21 +136,6 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
request.Referer = options.Referer;
}
-#if !__MonoCS__
- if (options.EnableKeepAlive)
- {
- // This is a hack to prevent KeepAlive from getting disabled internally by the HttpWebRequest
- // May need to remove this for mono
- var sp = request.ServicePoint;
- if (_httpBehaviorPropertyInfo == null)
- {
- _httpBehaviorPropertyInfo = sp.GetType().GetProperty("HttpBehaviour", BindingFlags.Instance | BindingFlags.NonPublic);
- }
-
- _httpBehaviorPropertyInfo.SetValue(sp, (byte)0, null);
- }
-#endif
-
return request;
}
diff --git a/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs b/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs
index dfe93c5c9..2d67ec975 100644
--- a/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs
+++ b/MediaBrowser.Common.Implementations/IO/CommonFileSystem.cs
@@ -367,5 +367,20 @@ namespace MediaBrowser.Common.Implementations.IO
return newPath;
}
+
+ public string GetFileNameWithoutExtension(FileSystemInfo info)
+ {
+ if (info is DirectoryInfo)
+ {
+ return info.Name;
+ }
+
+ return Path.GetFileNameWithoutExtension(info.FullName);
+ }
+
+ public string GetFileNameWithoutExtension(string path)
+ {
+ return Path.GetFileNameWithoutExtension(path);
+ }
}
}
diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
index f06d1bc67..abb2f2089 100644
--- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
+++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
@@ -48,17 +48,17 @@
<RunPostBuildEvent>Always</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
- <Reference Include="NLog, Version=3.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
+ <Reference Include="NLog, Version=3.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\NLog.3.0.0.0\lib\net45\NLog.dll</HintPath>
+ <HintPath>..\packages\NLog.3.1.0.0\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="SimpleInjector, Version=2.5.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\SimpleInjector.2.5.0\lib\net45\SimpleInjector.dll</HintPath>
+ <HintPath>..\packages\SimpleInjector.2.5.2\lib\net45\SimpleInjector.dll</HintPath>
</Reference>
- <Reference Include="SimpleInjector.Diagnostics, Version=2.5.0.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
+ <Reference Include="SimpleInjector.Diagnostics, Version=2.5.2.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\SimpleInjector.2.5.0\lib\net45\SimpleInjector.Diagnostics.dll</HintPath>
+ <HintPath>..\packages\SimpleInjector.2.5.2\lib\net45\SimpleInjector.Diagnostics.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
@@ -122,7 +122,7 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="$(SolutionDir)\.nuget\nuget.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
<PropertyGroup>
<PostBuildEvent Condition=" '$(ConfigurationName)' != 'Release Mono' ">if '$(ConfigurationName)' == 'Release' (
xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\" /y /d /r /i
@@ -135,4 +135,4 @@ xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\" /y /d /r /i
<Target Name="AfterBuild">
</Target>
-->
-</Project> \ No newline at end of file
+</Project>
diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
index e15c32518..8159be634 100644
--- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
+++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs
@@ -1,4 +1,5 @@
-using System;
+using MediaBrowser.Model.Logging;
+using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
@@ -10,6 +11,13 @@ namespace MediaBrowser.Common.Implementations.Networking
{
public abstract class BaseNetworkManager
{
+ protected ILogger Logger { get; private set; }
+
+ protected BaseNetworkManager(ILogger logger)
+ {
+ Logger = logger;
+ }
+
/// <summary>
/// Gets the machine's local ip address
/// </summary>
@@ -26,6 +34,81 @@ namespace MediaBrowser.Common.Implementations.Networking
return GetLocalIpAddressesFallback();
}
+ public bool IsInLocalNetwork(string endpoint)
+ {
+ return IsInLocalNetworkInternal(endpoint, true);
+ }
+
+ public bool IsInLocalNetworkInternal(string endpoint, bool resolveHost)
+ {
+ if (string.IsNullOrWhiteSpace(endpoint))
+ {
+ throw new ArgumentNullException("endpoint");
+ }
+
+ const int lengthMatch = 4;
+
+ if (endpoint.Length >= lengthMatch)
+ {
+ var prefix = endpoint.Substring(0, lengthMatch);
+
+ if (GetLocalIpAddresses()
+ .Any(i => i.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
+ {
+ return true;
+ }
+ }
+
+ // Private address space:
+ // http://en.wikipedia.org/wiki/Private_network
+
+ var isPrivate =
+
+ // If url was requested with computer name, we may see this
+ endpoint.IndexOf("::", StringComparison.OrdinalIgnoreCase) != -1 ||
+
+ endpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) ||
+ endpoint.StartsWith("192.", StringComparison.OrdinalIgnoreCase) ||
+ endpoint.StartsWith("172.", StringComparison.OrdinalIgnoreCase) ||
+ endpoint.StartsWith("169.", StringComparison.OrdinalIgnoreCase);
+
+ if (isPrivate)
+ {
+ return true;
+ }
+
+ IPAddress address;
+ if (resolveHost && !IPAddress.TryParse(endpoint, out address))
+ {
+ var host = new Uri(endpoint).DnsSafeHost;
+
+ Logger.Debug("Resolving host {0}", host);
+
+ try
+ {
+ address = GetIpAddresses(host).FirstOrDefault();
+
+ if (address != null)
+ {
+ Logger.Debug("{0} resolved to {1}", host, address);
+
+ return IsInLocalNetworkInternal(address.ToString(), false);
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error resovling hostname {0}", ex, host);
+ }
+ }
+
+ return false;
+ }
+
+ public IEnumerable<IPAddress> GetIpAddresses(string hostName)
+ {
+ return Dns.GetHostAddresses(hostName);
+ }
+
private IEnumerable<IPAddress> GetIPsDefault()
{
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces())
@@ -63,7 +146,7 @@ namespace MediaBrowser.Common.Implementations.Networking
.Select(i => i.ToString())
.Reverse();
}
-
+
/// <summary>
/// Gets a random port number that is currently available
/// </summary>
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
index 68222d843..0dc67f8c0 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
@@ -547,6 +547,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
if (ex != null)
{
result.ErrorMessage = ex.Message;
+ result.LongErrorMessage = ex.StackTrace;
}
var path = GetHistoryFilePath();
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
index ddaa8df7d..fcb7b159b 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
@@ -46,7 +46,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
return new ITaskTrigger[] {
// At startup
- new StartupTrigger (),
+ new StartupTrigger {DelayMs = 60000},
// Every so often
new IntervalTrigger { Interval = TimeSpan.FromHours(24)}
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
index e5c5638c0..3b0c02dc6 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
@@ -43,7 +43,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
return new ITaskTrigger[] {
// At startup
- new StartupTrigger (),
+ new StartupTrigger {DelayMs = 30000},
// Every so often
new IntervalTrigger { Interval = TimeSpan.FromHours(24)}
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs
index f70b849ee..e31fc4abe 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs
@@ -41,7 +41,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
return new ITaskTrigger[] {
// At startup
- new StartupTrigger (),
+ new StartupTrigger(),
// Every so often
new IntervalTrigger { Interval = TimeSpan.FromHours(24)}
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/SystemUpdateTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/SystemUpdateTask.cs
index 641d402bd..6a9443ad7 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/SystemUpdateTask.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/SystemUpdateTask.cs
@@ -52,7 +52,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
return new ITaskTrigger[] {
// At startup
- new StartupTrigger (),
+ new StartupTrigger(),
// Every so often
new IntervalTrigger { Interval = TimeSpan.FromHours(24)}
diff --git a/MediaBrowser.Common.Implementations/Security/UsageReporter.cs b/MediaBrowser.Common.Implementations/Security/UsageReporter.cs
index 6982d49fd..89ca0a0e4 100644
--- a/MediaBrowser.Common.Implementations/Security/UsageReporter.cs
+++ b/MediaBrowser.Common.Implementations/Security/UsageReporter.cs
@@ -26,16 +26,13 @@ namespace MediaBrowser.Common.Implementations.Security
var mac = _networkManager.GetMacAddress();
- var plugins = string.Join("|", _applicationHost.Plugins.Select(i => i.Name).ToArray());
-
var data = new Dictionary<string, string>
{
{ "feature", _applicationHost.Name },
{ "mac", mac },
{ "ver", _applicationHost.ApplicationVersion.ToString() },
{ "platform", Environment.OSVersion.VersionString },
- { "isservice", _applicationHost.IsRunningAsService.ToString().ToLower()},
- { "plugins", plugins}
+ { "isservice", _applicationHost.IsRunningAsService.ToString().ToLower()}
};
return _httpClient.Post(Constants.Constants.MbAdminUrl + "service/registration/ping", data, cancellationToken);
diff --git a/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs b/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs
index 130e21b6e..e7fd12178 100644
--- a/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs
+++ b/MediaBrowser.Common.Implementations/Serialization/JsonSerializer.cs
@@ -210,25 +210,5 @@ namespace MediaBrowser.Common.Implementations.Serialization
return ServiceStack.Text.JsonSerializer.SerializeToString(obj, obj.GetType());
}
-
- /// <summary>
- /// Serializes to bytes.
- /// </summary>
- /// <param name="obj">The obj.</param>
- /// <returns>System.Byte[][].</returns>
- /// <exception cref="System.ArgumentNullException">obj</exception>
- public byte[] SerializeToBytes(object obj)
- {
- if (obj == null)
- {
- throw new ArgumentNullException("obj");
- }
-
- using (var stream = new MemoryStream())
- {
- SerializeToStream(obj, stream);
- return stream.ToArray();
- }
- }
}
}
diff --git a/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs b/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs
index 06c60dacd..cef744753 100644
--- a/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs
+++ b/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs
@@ -91,20 +91,5 @@ namespace MediaBrowser.Common.Implementations.Serialization
return DeserializeFromStream(type, stream);
}
}
-
- /// <summary>
- /// Serializes to bytes.
- /// </summary>
- /// <param name="obj">The obj.</param>
- /// <returns>System.Byte[][].</returns>
- public byte[] SerializeToBytes(object obj)
- {
- using (var stream = new MemoryStream())
- {
- SerializeToStream(obj, stream);
-
- return stream.ToArray();
- }
- }
}
}
diff --git a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
index 895c43076..e4c88e656 100644
--- a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
+++ b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
@@ -68,7 +68,7 @@ namespace MediaBrowser.Common.Implementations.Updates
/// <param name="newVersion">The new version.</param>
private void OnPluginUpdated(IPlugin plugin, PackageVersionInfo newVersion)
{
- _logger.Info("Plugin updated: {0} {1} {2}", newVersion.name, newVersion.version, newVersion.classification);
+ _logger.Info("Plugin updated: {0} {1} {2}", newVersion.name, newVersion.versionStr ?? string.Empty, newVersion.classification);
EventHelper.FireEventIfNotNull(PluginUpdated, this, new GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> { Argument = new Tuple<IPlugin, PackageVersionInfo>(plugin, newVersion) }, _logger);
@@ -87,7 +87,7 @@ namespace MediaBrowser.Common.Implementations.Updates
/// <param name="package">The package.</param>
private void OnPluginInstalled(PackageVersionInfo package)
{
- _logger.Info("New plugin installed: {0} {1} {2}", package.name, package.version, package.classification);
+ _logger.Info("New plugin installed: {0} {1} {2}", package.name, package.versionStr ?? string.Empty, package.classification);
EventHelper.FireEventIfNotNull(PluginInstalled, this, new GenericEventArgs<PackageVersionInfo> { Argument = package }, _logger);
@@ -133,6 +133,16 @@ namespace MediaBrowser.Common.Implementations.Updates
_logger = logger;
}
+ private Version GetPackageVersion(PackageVersionInfo version)
+ {
+ return new Version(ValueOrDefault(version.versionStr, "0.0.0.1"));
+ }
+
+ private static string ValueOrDefault(string str, string def)
+ {
+ return string.IsNullOrEmpty(str) ? def : str;
+ }
+
/// <summary>
/// Gets all available packages.
/// </summary>
@@ -167,17 +177,27 @@ namespace MediaBrowser.Common.Implementations.Updates
{
if (_lastPackageListResult != null)
{
- // Let dev users get results more often for testing purposes
- var cacheLength = _config.CommonConfiguration.SystemUpdateLevel == PackageVersionClass.Dev
- ? TimeSpan.FromMinutes(3)
- : TimeSpan.FromHours(6);
+ TimeSpan cacheLength;
+
+ switch (_config.CommonConfiguration.SystemUpdateLevel)
+ {
+ case PackageVersionClass.Beta:
+ cacheLength = TimeSpan.FromMinutes(30);
+ break;
+ case PackageVersionClass.Dev:
+ cacheLength = TimeSpan.FromMinutes(3);
+ break;
+ default:
+ cacheLength = TimeSpan.FromHours(6);
+ break;
+ }
if ((DateTime.UtcNow - _lastPackageListResult.Item2) < cacheLength)
{
return _lastPackageListResult.Item1;
}
}
-
+
using (var json = await _httpClient.Get(Constants.Constants.MbAdminUrl + "service/MB3Packages.json", cancellationToken).ConfigureAwait(false))
{
cancellationToken.ThrowIfCancellationRequested();
@@ -197,7 +217,7 @@ namespace MediaBrowser.Common.Implementations.Updates
foreach (var package in packages)
{
package.versions = package.versions.Where(v => !string.IsNullOrWhiteSpace(v.sourceUrl))
- .OrderByDescending(v => v.version).ToList();
+ .OrderByDescending(GetPackageVersion).ToList();
}
// Remove packages with no versions
@@ -211,7 +231,7 @@ namespace MediaBrowser.Common.Implementations.Updates
foreach (var package in packages)
{
package.versions = package.versions.Where(v => !string.IsNullOrWhiteSpace(v.sourceUrl))
- .OrderByDescending(v => v.version).ToList();
+ .OrderByDescending(GetPackageVersion).ToList();
}
if (packageType.HasValue)
@@ -264,7 +284,7 @@ namespace MediaBrowser.Common.Implementations.Updates
{
var packages = await GetAvailablePackages(CancellationToken.None).ConfigureAwait(false);
- var package = packages.FirstOrDefault(p => string.Equals(p.guid, guid ?? "none", StringComparison.OrdinalIgnoreCase))
+ var package = packages.FirstOrDefault(p => string.Equals(p.guid, guid ?? "none", StringComparison.OrdinalIgnoreCase))
?? packages.FirstOrDefault(p => p.name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (package == null)
@@ -272,7 +292,7 @@ namespace MediaBrowser.Common.Implementations.Updates
return null;
}
- return package.versions.FirstOrDefault(v => v.version.Equals(version) && v.classification == classification);
+ return package.versions.FirstOrDefault(v => GetPackageVersion(v).Equals(version) && v.classification == classification);
}
/// <summary>
@@ -300,7 +320,7 @@ namespace MediaBrowser.Common.Implementations.Updates
/// <returns>PackageVersionInfo.</returns>
public PackageVersionInfo GetLatestCompatibleVersion(IEnumerable<PackageInfo> availablePackages, string name, string guid, Version currentServerVersion, PackageVersionClass classification = PackageVersionClass.Release)
{
- var package = availablePackages.FirstOrDefault(p => string.Equals(p.guid, guid ?? "none", StringComparison.OrdinalIgnoreCase))
+ var package = availablePackages.FirstOrDefault(p => string.Equals(p.guid, guid ?? "none", StringComparison.OrdinalIgnoreCase))
?? availablePackages.FirstOrDefault(p => p.name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (package == null)
@@ -309,7 +329,7 @@ namespace MediaBrowser.Common.Implementations.Updates
}
return package.versions
- .OrderByDescending(v => v.version)
+ .OrderByDescending(GetPackageVersion)
.FirstOrDefault(v => v.classification <= classification && IsPackageVersionUpToDate(v, currentServerVersion));
}
@@ -338,7 +358,7 @@ namespace MediaBrowser.Common.Implementations.Updates
{
var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Id.ToString(), applicationVersion, _config.CommonConfiguration.SystemUpdateLevel);
- return latestPluginInfo != null && latestPluginInfo.version != null && latestPluginInfo.version > p.Version ? latestPluginInfo : null;
+ return latestPluginInfo != null && GetPackageVersion(latestPluginInfo) > p.Version ? latestPluginInfo : null;
}).Where(i => i != null).ToList();
diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config
index f00c85d71..4f2a4c224 100644
--- a/MediaBrowser.Common.Implementations/packages.config
+++ b/MediaBrowser.Common.Implementations/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="NLog" version="3.0.0.0" targetFramework="net45" />
+ <package id="NLog" version="3.1.0.0" targetFramework="net45" />
<package id="sharpcompress" version="0.10.2" targetFramework="net45" />
- <package id="SimpleInjector" version="2.5.0" targetFramework="net45" />
+ <package id="SimpleInjector" version="2.5.2" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Common/Configuration/ConfigurationHelper.cs b/MediaBrowser.Common/Configuration/ConfigurationHelper.cs
index 64c2e87de..8c904b0db 100644
--- a/MediaBrowser.Common/Configuration/ConfigurationHelper.cs
+++ b/MediaBrowser.Common/Configuration/ConfigurationHelper.cs
@@ -36,21 +36,25 @@ namespace MediaBrowser.Common.Configuration
configuration = Activator.CreateInstance(type);
}
- // Take the object we just got and serialize it back to bytes
- var newBytes = xmlSerializer.SerializeToBytes(configuration);
-
- // If the file didn't exist before, or if something has changed, re-save
- if (buffer == null || !buffer.SequenceEqual(newBytes))
+ using (var stream = new MemoryStream())
{
- Directory.CreateDirectory(Path.GetDirectoryName(path));
-
- // Save it after load in case we got new items
- File.WriteAllBytes(path, newBytes);
- }
+ xmlSerializer.SerializeToStream(configuration, stream);
- return configuration;
- }
+ // Take the object we just got and serialize it back to bytes
+ var newBytes = stream.ToArray();
+
+ // If the file didn't exist before, or if something has changed, re-save
+ if (buffer == null || !buffer.SequenceEqual(newBytes))
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+ // Save it after load in case we got new items
+ File.WriteAllBytes(path, newBytes);
+ }
+
+ return configuration;
+ }
+ }
/// <summary>
/// Reads an xml configuration file from the file system
diff --git a/MediaBrowser.Common/Configuration/ConfigurationUpdateEventArgs.cs b/MediaBrowser.Common/Configuration/ConfigurationUpdateEventArgs.cs
new file mode 100644
index 000000000..310e2aa63
--- /dev/null
+++ b/MediaBrowser.Common/Configuration/ConfigurationUpdateEventArgs.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace MediaBrowser.Common.Configuration
+{
+ public class ConfigurationUpdateEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Gets or sets the key.
+ /// </summary>
+ /// <value>The key.</value>
+ public string Key { get; set; }
+ /// <summary>
+ /// Gets or sets the new configuration.
+ /// </summary>
+ /// <value>The new configuration.</value>
+ public object NewConfiguration { get; set; }
+ }
+}
diff --git a/MediaBrowser.Common/Configuration/IConfigurationFactory.cs b/MediaBrowser.Common/Configuration/IConfigurationFactory.cs
new file mode 100644
index 000000000..d418d0a42
--- /dev/null
+++ b/MediaBrowser.Common/Configuration/IConfigurationFactory.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Common.Configuration
+{
+ public interface IConfigurationFactory
+ {
+ IEnumerable<ConfigurationStore> GetConfigurations();
+ }
+
+ public class ConfigurationStore
+ {
+ public string Key { get; set; }
+
+ public Type ConfigurationType { get; set; }
+ }
+}
diff --git a/MediaBrowser.Common/Configuration/IConfigurationManager.cs b/MediaBrowser.Common/Configuration/IConfigurationManager.cs
index 0d0759b66..d826a3ee7 100644
--- a/MediaBrowser.Common/Configuration/IConfigurationManager.cs
+++ b/MediaBrowser.Common/Configuration/IConfigurationManager.cs
@@ -1,15 +1,26 @@
using MediaBrowser.Model.Configuration;
using System;
+using System.Collections.Generic;
namespace MediaBrowser.Common.Configuration
{
public interface IConfigurationManager
{
/// <summary>
+ /// Occurs when [configuration updating].
+ /// </summary>
+ event EventHandler<ConfigurationUpdateEventArgs> NamedConfigurationUpdating;
+
+ /// <summary>
/// Occurs when [configuration updated].
/// </summary>
event EventHandler<EventArgs> ConfigurationUpdated;
-
+
+ /// <summary>
+ /// Occurs when [named configuration updated].
+ /// </summary>
+ event EventHandler<ConfigurationUpdateEventArgs> NamedConfigurationUpdated;
+
/// <summary>
/// Gets or sets the application paths.
/// </summary>
@@ -32,5 +43,40 @@ namespace MediaBrowser.Common.Configuration
/// </summary>
/// <param name="newConfiguration">The new configuration.</param>
void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration);
+
+ /// <summary>
+ /// Gets the configuration.
+ /// </summary>
+ /// <param name="key">The key.</param>
+ /// <returns>System.Object.</returns>
+ object GetConfiguration(string key);
+
+ /// <summary>
+ /// Gets the type of the configuration.
+ /// </summary>
+ /// <param name="key">The key.</param>
+ /// <returns>Type.</returns>
+ Type GetConfigurationType(string key);
+
+ /// <summary>
+ /// Saves the configuration.
+ /// </summary>
+ /// <param name="key">The key.</param>
+ /// <param name="configuration">The configuration.</param>
+ void SaveConfiguration(string key, object configuration);
+
+ /// <summary>
+ /// Adds the parts.
+ /// </summary>
+ /// <param name="factories">The factories.</param>
+ void AddParts(IEnumerable<IConfigurationFactory> factories);
+ }
+
+ public static class ConfigurationManagerExtensions
+ {
+ public static T GetConfiguration<T>(this IConfigurationManager manager, string key)
+ {
+ return (T)manager.GetConfiguration(key);
+ }
}
}
diff --git a/MediaBrowser.Common/IO/IFileSystem.cs b/MediaBrowser.Common/IO/IFileSystem.cs
index de9b7e88a..27307a0e9 100644
--- a/MediaBrowser.Common/IO/IFileSystem.cs
+++ b/MediaBrowser.Common/IO/IFileSystem.cs
@@ -112,5 +112,19 @@ namespace MediaBrowser.Common.IO
/// <param name="to">To.</param>
/// <returns>System.String.</returns>
string SubstitutePath(string path, string from, string to);
+
+ /// <summary>
+ /// Gets the file name without extension.
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <returns>System.String.</returns>
+ string GetFileNameWithoutExtension(FileSystemInfo info);
+
+ /// <summary>
+ /// Gets the file name without extension.
+ /// </summary>
+ /// <param name="path">The path.</param>
+ /// <returns>System.String.</returns>
+ string GetFileNameWithoutExtension(string path);
}
}
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj
index 2e7db5c35..661073c89 100644
--- a/MediaBrowser.Common/MediaBrowser.Common.csproj
+++ b/MediaBrowser.Common/MediaBrowser.Common.csproj
@@ -55,7 +55,9 @@
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="Configuration\ConfigurationHelper.cs" />
+ <Compile Include="Configuration\ConfigurationUpdateEventArgs.cs" />
<Compile Include="Configuration\IConfigurationManager.cs" />
+ <Compile Include="Configuration\IConfigurationFactory.cs" />
<Compile Include="Constants\Constants.cs" />
<Compile Include="Events\EventHelper.cs" />
<Compile Include="Extensions\BaseExtensions.cs" />
@@ -76,7 +78,6 @@
<Compile Include="Net\INetworkManager.cs" />
<Compile Include="Net\IWebSocket.cs" />
<Compile Include="Net\IWebSocketConnection.cs" />
- <Compile Include="Net\IWebSocketServer.cs" />
<Compile Include="Net\MimeTypes.cs" />
<Compile Include="Net\WebSocketConnectEventArgs.cs" />
<Compile Include="Net\WebSocketMessageInfo.cs" />
@@ -115,7 +116,7 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="$(SolutionDir)\.nuget\nuget.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
<PropertyGroup>
<PostBuildEvent Condition=" '$(ConfigurationName)' != 'Release Mono' ">if '$(ConfigurationName)' == 'Release' (
xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\" /y /d /r /i
@@ -128,4 +129,4 @@ xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\" /y /d /r /i
<Target Name="AfterBuild">
</Target>
-->
-</Project> \ No newline at end of file
+</Project>
diff --git a/MediaBrowser.Common/Net/HttpRequestOptions.cs b/MediaBrowser.Common/Net/HttpRequestOptions.cs
index 3cba84334..a2b42dedb 100644
--- a/MediaBrowser.Common/Net/HttpRequestOptions.cs
+++ b/MediaBrowser.Common/Net/HttpRequestOptions.cs
@@ -106,7 +106,6 @@ namespace MediaBrowser.Common.Net
{
EnableHttpCompression = true;
BufferContent = true;
- EnableKeepAlive = true;
RequestHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs
index b5f1c8294..979dae49c 100644
--- a/MediaBrowser.Common/Net/INetworkManager.cs
+++ b/MediaBrowser.Common/Net/INetworkManager.cs
@@ -44,5 +44,12 @@ namespace MediaBrowser.Common.Net
/// <param name="endpointstring">The endpointstring.</param>
/// <returns>IPEndPoint.</returns>
IPEndPoint Parse(string endpointstring);
+
+ /// <summary>
+ /// Determines whether [is in local network] [the specified endpoint].
+ /// </summary>
+ /// <param name="endpoint">The endpoint.</param>
+ /// <returns><c>true</c> if [is in local network] [the specified endpoint]; otherwise, <c>false</c>.</returns>
+ bool IsInLocalNetwork(string endpoint);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Common/Net/IServerManager.cs b/MediaBrowser.Common/Net/IServerManager.cs
index f81c99ac6..84e578579 100644
--- a/MediaBrowser.Common/Net/IServerManager.cs
+++ b/MediaBrowser.Common/Net/IServerManager.cs
@@ -11,28 +11,10 @@ namespace MediaBrowser.Common.Net
public interface IServerManager : IDisposable
{
/// <summary>
- /// Gets a value indicating whether [supports web socket].
- /// </summary>
- /// <value><c>true</c> if [supports web socket]; otherwise, <c>false</c>.</value>
- bool SupportsNativeWebSocket { get; }
-
- /// <summary>
- /// Gets the web socket port number.
- /// </summary>
- /// <value>The web socket port number.</value>
- int WebSocketPortNumber { get; }
-
- /// <summary>
/// Starts this instance.
/// </summary>
/// <param name="urlPrefixes">The URL prefixes.</param>
- /// <param name="enableHttpLogging">if set to <c>true</c> [enable HTTP logging].</param>
- void Start(IEnumerable<string> urlPrefixes, bool enableHttpLogging);
-
- /// <summary>
- /// Starts the web socket server.
- /// </summary>
- void StartWebSocketServer();
+ void Start(IEnumerable<string> urlPrefixes);
/// <summary>
/// Sends a message to all clients currently connected via a web socket
diff --git a/MediaBrowser.Common/Net/IWebSocket.cs b/MediaBrowser.Common/Net/IWebSocket.cs
index 05f7975bc..b31a95319 100644
--- a/MediaBrowser.Common/Net/IWebSocket.cs
+++ b/MediaBrowser.Common/Net/IWebSocket.cs
@@ -32,15 +32,23 @@ namespace MediaBrowser.Common.Net
/// </summary>
/// <value>The on receive.</value>
Action<string> OnReceive { get; set; }
-
+
/// <summary>
/// Sends the async.
/// </summary>
/// <param name="bytes">The bytes.</param>
- /// <param name="type">The type.</param>
/// <param name="endOfMessage">if set to <c>true</c> [end of message].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task SendAsync(byte[] bytes, WebSocketMessageType type, bool endOfMessage, CancellationToken cancellationToken);
+ Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Sends the asynchronous.
+ /// </summary>
+ /// <param name="text">The text.</param>
+ /// <param name="endOfMessage">if set to <c>true</c> [end of message].</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Common/Net/IWebSocketConnection.cs b/MediaBrowser.Common/Net/IWebSocketConnection.cs
index 9f9dfaeca..b7715e20b 100644
--- a/MediaBrowser.Common/Net/IWebSocketConnection.cs
+++ b/MediaBrowser.Common/Net/IWebSocketConnection.cs
@@ -63,11 +63,10 @@ namespace MediaBrowser.Common.Net
/// <summary>
/// Sends a message asynchronously.
/// </summary>
- /// <param name="buffer">The buffer.</param>
- /// <param name="type">The type.</param>
+ /// <param name="text">The text.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">buffer</exception>
- Task SendAsync(byte[] buffer, WebSocketMessageType type, CancellationToken cancellationToken);
+ Task SendAsync(string text, CancellationToken cancellationToken);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Common/Net/IWebSocketServer.cs b/MediaBrowser.Common/Net/IWebSocketServer.cs
deleted file mode 100644
index 187e03e09..000000000
--- a/MediaBrowser.Common/Net/IWebSocketServer.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System;
-
-namespace MediaBrowser.Common.Net
-{
- /// <summary>
- /// Interface IWebSocketServer
- /// </summary>
- public interface IWebSocketServer : IDisposable
- {
- /// <summary>
- /// Starts the specified port number.
- /// </summary>
- /// <param name="portNumber">The port number.</param>
- void Start(int portNumber);
-
- /// <summary>
- /// Stops this instance.
- /// </summary>
- void Stop();
-
- /// <summary>
- /// Occurs when [web socket connected].
- /// </summary>
- event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
-
- /// <summary>
- /// Gets the port.
- /// </summary>
- /// <value>The port.</value>
- int Port { get; }
- }
-}
diff --git a/MediaBrowser.Common/Net/MimeTypes.cs b/MediaBrowser.Common/Net/MimeTypes.cs
index d85a2fd1e..bd9668d80 100644
--- a/MediaBrowser.Common/Net/MimeTypes.cs
+++ b/MediaBrowser.Common/Net/MimeTypes.cs
@@ -143,6 +143,10 @@ namespace MediaBrowser.Common.Net
{
return "image/png";
}
+ if (ext.Equals(".webp", StringComparison.OrdinalIgnoreCase))
+ {
+ return "image/webp";
+ }
if (ext.Equals(".ico", StringComparison.OrdinalIgnoreCase))
{
return "image/vnd.microsoft.icon";
@@ -199,6 +203,14 @@ namespace MediaBrowser.Common.Net
{
return "application/x-javascript";
}
+ if (ext.Equals(".json", StringComparison.OrdinalIgnoreCase))
+ {
+ return JsonMimeType;
+ }
+ if (ext.Equals(".map", StringComparison.OrdinalIgnoreCase))
+ {
+ return "application/x-javascript";
+ }
if (ext.Equals(".woff", StringComparison.OrdinalIgnoreCase))
{
@@ -228,6 +240,16 @@ namespace MediaBrowser.Common.Net
return "text/vtt";
}
+ if (ext.Equals(".ttml", StringComparison.OrdinalIgnoreCase))
+ {
+ return "application/ttml+xml";
+ }
+
+ if (ext.Equals(".bif", StringComparison.OrdinalIgnoreCase))
+ {
+ return "application/octet-stream";
+ }
+
throw new ArgumentException("Argument not supported: " + path);
}
}
diff --git a/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs
index fc6963070..6989dea06 100644
--- a/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs
+++ b/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs
@@ -13,4 +13,9 @@
/// <value><c>true</c> if this instance is enabled; otherwise, <c>false</c>.</value>
bool IsEnabled { get; }
}
+
+ public interface IScheduledTaskActivityLog
+ {
+ bool IsActivityLogged { get; }
+ }
} \ No newline at end of file
diff --git a/MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs b/MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs
index 6dc5c6b38..17e4628d0 100644
--- a/MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs
+++ b/MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs
@@ -8,6 +8,13 @@ namespace MediaBrowser.Common.ScheduledTasks
/// </summary>
public class StartupTrigger : ITaskTrigger
{
+ public int DelayMs { get; set; }
+
+ public StartupTrigger()
+ {
+ DelayMs = 3000;
+ }
+
/// <summary>
/// Stars waiting for the trigger action
/// </summary>
@@ -16,7 +23,7 @@ namespace MediaBrowser.Common.ScheduledTasks
{
if (isApplicationStartup)
{
- await Task.Delay(3000).ConfigureAwait(false);
+ await Task.Delay(DelayMs).ConfigureAwait(false);
OnTriggered();
}
diff --git a/MediaBrowser.Controller/Activity/IActivityManager.cs b/MediaBrowser.Controller/Activity/IActivityManager.cs
new file mode 100644
index 000000000..728548911
--- /dev/null
+++ b/MediaBrowser.Controller/Activity/IActivityManager.cs
@@ -0,0 +1,17 @@
+using MediaBrowser.Model.Activity;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.Querying;
+using System;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Activity
+{
+ public interface IActivityManager
+ {
+ event EventHandler<GenericEventArgs<ActivityLogEntry>> EntryCreated;
+
+ Task Create(ActivityLogEntry entry);
+
+ QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit);
+ }
+}
diff --git a/MediaBrowser.Controller/Activity/IActivityRepository.cs b/MediaBrowser.Controller/Activity/IActivityRepository.cs
new file mode 100644
index 000000000..7ccbc2e99
--- /dev/null
+++ b/MediaBrowser.Controller/Activity/IActivityRepository.cs
@@ -0,0 +1,14 @@
+using MediaBrowser.Model.Activity;
+using MediaBrowser.Model.Querying;
+using System;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Activity
+{
+ public interface IActivityRepository
+ {
+ Task Create(ActivityLogEntry entry);
+
+ QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit);
+ }
+}
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index 3d9d0d381..df38259b4 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -4,7 +4,7 @@ using System.Linq;
namespace MediaBrowser.Controller.Channels
{
- public class Channel : BaseItem
+ public class Channel : Folder
{
public string OriginalChannelName { get; set; }
diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
index afc6493e4..077138f3c 100644
--- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Configuration;
-using System.Collections.Generic;
namespace MediaBrowser.Controller.Channels
{
@@ -15,7 +14,6 @@ namespace MediaBrowser.Controller.Channels
public ChannelFolderType ChannelFolderType { get; set; }
public string OriginalImageUrl { get; set; }
- public List<string> Tags { get; set; }
protected override bool GetBlockUnratedValue(UserConfiguration config)
{
@@ -31,11 +29,6 @@ namespace MediaBrowser.Controller.Channels
}
}
- public ChannelFolderItem()
- {
- Tags = new List<string>();
- }
-
public override string GetUserDataKey()
{
return ExternalId;
diff --git a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
index 707807bd5..3c7df91c1 100644
--- a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
+++ b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
@@ -10,6 +10,8 @@ namespace MediaBrowser.Controller.Channels
{
public string Name { get; set; }
+ public string SeriesName { get; set; }
+
public string Id { get; set; }
public ChannelItemType Type { get; set; }
@@ -28,8 +30,6 @@ namespace MediaBrowser.Controller.Channels
public long? RunTimeTicks { get; set; }
- public bool IsInfiniteStream { get; set; }
-
public string ImageUrl { get; set; }
public ChannelMediaType MediaType { get; set; }
@@ -43,9 +43,14 @@ namespace MediaBrowser.Controller.Channels
public int? ProductionYear { get; set; }
public DateTime? DateCreated { get; set; }
-
+
+ public int? IndexNumber { get; set; }
+ public int? ParentIndexNumber { get; set; }
+
public List<ChannelMediaInfo> MediaSources { get; set; }
-
+
+ public bool IsInfiniteStream { get; set; }
+
public ChannelItemInfo()
{
MediaSources = new List<ChannelMediaInfo>();
diff --git a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
index 64b480414..f16fd1120 100644
--- a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
+++ b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
@@ -29,6 +29,8 @@ namespace MediaBrowser.Controller.Channels
public MediaProtocol Protocol { get; set; }
+ public long? RunTimeTicks { get; set; }
+
public ChannelMediaInfo()
{
RequiredHttpHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
diff --git a/MediaBrowser.Controller/Channels/IChannelFactory.cs b/MediaBrowser.Controller/Channels/IChannelFactory.cs
index e275227ff..c7ed92586 100644
--- a/MediaBrowser.Controller/Channels/IChannelFactory.cs
+++ b/MediaBrowser.Controller/Channels/IChannelFactory.cs
@@ -6,4 +6,9 @@ namespace MediaBrowser.Controller.Channels
{
IEnumerable<IChannel> GetChannels();
}
+
+ public interface IFactoryChannel
+ {
+
+ }
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Channels/IChannelManager.cs b/MediaBrowser.Controller/Channels/IChannelManager.cs
index 744eab96e..252e2aee5 100644
--- a/MediaBrowser.Controller/Channels/IChannelManager.cs
+++ b/MediaBrowser.Controller/Channels/IChannelManager.cs
@@ -44,6 +44,14 @@ namespace MediaBrowser.Controller.Channels
Channel GetChannel(string id);
/// <summary>
+ /// Gets the channels internal.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task&lt;QueryResult&lt;Channel&gt;&gt;.</returns>
+ Task<QueryResult<Channel>> GetChannelsInternal(ChannelQuery query, CancellationToken cancellationToken);
+
+ /// <summary>
/// Gets the channels.
/// </summary>
/// <param name="query">The query.</param>
@@ -76,6 +84,14 @@ namespace MediaBrowser.Controller.Channels
Task<QueryResult<BaseItemDto>> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken);
/// <summary>
+ /// Gets the channel items internal.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task&lt;QueryResult&lt;BaseItem&gt;&gt;.</returns>
+ Task<QueryResult<BaseItem>> GetChannelItemsInternal(ChannelItemQuery query, CancellationToken cancellationToken);
+
+ /// <summary>
/// Gets the cached channel item media sources.
/// </summary>
/// <param name="id">The identifier.</param>
diff --git a/MediaBrowser.Controller/Chapters/IChapterManager.cs b/MediaBrowser.Controller/Chapters/IChapterManager.cs
index b8f29d1ce..676ef9c56 100644
--- a/MediaBrowser.Controller/Chapters/IChapterManager.cs
+++ b/MediaBrowser.Controller/Chapters/IChapterManager.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Model.Chapters;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Chapters
@@ -70,5 +71,11 @@ namespace MediaBrowser.Controller.Chapters
/// </summary>
/// <returns>IEnumerable{ChapterProviderInfo}.</returns>
IEnumerable<ChapterProviderInfo> GetProviders();
+
+ /// <summary>
+ /// Gets the configuration.
+ /// </summary>
+ /// <returns>ChapterOptions.</returns>
+ ChapterOptions GetConfiguration();
}
}
diff --git a/MediaBrowser.Controller/Collections/CollectionEvents.cs b/MediaBrowser.Controller/Collections/CollectionEvents.cs
new file mode 100644
index 000000000..80f66a444
--- /dev/null
+++ b/MediaBrowser.Controller/Collections/CollectionEvents.cs
@@ -0,0 +1,37 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Collections
+{
+ public class CollectionCreatedEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Gets or sets the collection.
+ /// </summary>
+ /// <value>The collection.</value>
+ public BoxSet Collection { get; set; }
+
+ /// <summary>
+ /// Gets or sets the options.
+ /// </summary>
+ /// <value>The options.</value>
+ public CollectionCreationOptions Options { get; set; }
+ }
+
+ public class CollectionModifiedEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Gets or sets the collection.
+ /// </summary>
+ /// <value>The collection.</value>
+ public BoxSet Collection { get; set; }
+
+ /// <summary>
+ /// Gets or sets the items changed.
+ /// </summary>
+ /// <value>The items changed.</value>
+ public List<BaseItem> ItemsChanged { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Collections/ICollectionManager.cs b/MediaBrowser.Controller/Collections/ICollectionManager.cs
index b63c49f99..9130f68d4 100644
--- a/MediaBrowser.Controller/Collections/ICollectionManager.cs
+++ b/MediaBrowser.Controller/Collections/ICollectionManager.cs
@@ -9,6 +9,21 @@ namespace MediaBrowser.Controller.Collections
public interface ICollectionManager
{
/// <summary>
+ /// Occurs when [collection created].
+ /// </summary>
+ event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
+
+ /// <summary>
+ /// Occurs when [items added to collection].
+ /// </summary>
+ event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
+
+ /// <summary>
+ /// Occurs when [items removed from collection].
+ /// </summary>
+ event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
+
+ /// <summary>
/// Creates the collection.
/// </summary>
/// <param name="options">The options.</param>
@@ -38,5 +53,12 @@ namespace MediaBrowser.Controller.Collections
/// <param name="user">The user.</param>
/// <returns>IEnumerable{BaseItem}.</returns>
IEnumerable<BaseItem> CollapseItemsWithinBoxSets(IEnumerable<BaseItem> items, User user);
+
+ /// <summary>
+ /// Gets the collections folder.
+ /// </summary>
+ /// <param name="userId">The user identifier.</param>
+ /// <returns>Folder.</returns>
+ Folder GetCollectionsFolder(string userId);
}
}
diff --git a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs b/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs
index 6a2343a00..13c9f8d84 100644
--- a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs
+++ b/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs
@@ -1,7 +1,5 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Events;
-using System;
namespace MediaBrowser.Controller.Configuration
{
@@ -11,11 +9,6 @@ namespace MediaBrowser.Controller.Configuration
public interface IServerConfigurationManager : IConfigurationManager
{
/// <summary>
- /// Occurs when [configuration updating].
- /// </summary>
- event EventHandler<GenericEventArgs<ServerConfiguration>> ConfigurationUpdating;
-
- /// <summary>
/// Gets the application paths.
/// </summary>
/// <value>The application paths.</value>
@@ -26,5 +19,11 @@ namespace MediaBrowser.Controller.Configuration
/// </summary>
/// <value>The configuration.</value>
ServerConfiguration Configuration { get; }
+
+ /// <summary>
+ /// Sets the preferred metadata service.
+ /// </summary>
+ /// <param name="service">The service.</param>
+ void DisableMetadataService(string service);
}
}
diff --git a/MediaBrowser.Controller/Connect/IConnectManager.cs b/MediaBrowser.Controller/Connect/IConnectManager.cs
new file mode 100644
index 000000000..83f565472
--- /dev/null
+++ b/MediaBrowser.Controller/Connect/IConnectManager.cs
@@ -0,0 +1,9 @@
+
+namespace MediaBrowser.Controller.Connect
+{
+ public interface IConnectManager
+ {
+ string WanIpAddress { get; }
+ string WanApiAddress { get; }
+ }
+}
diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
index 51466c4f9..a0128f111 100644
--- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs
+++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
@@ -73,6 +73,13 @@ namespace MediaBrowser.Controller.Drawing
/// <param name="toStream">To stream.</param>
/// <returns>Task.</returns>
Task ProcessImage(ImageProcessingOptions options, Stream toStream);
+
+ /// <summary>
+ /// Processes the image.
+ /// </summary>
+ /// <param name="options">The options.</param>
+ /// <returns>Task.</returns>
+ Task<string> ProcessImage(ImageProcessingOptions options);
/// <summary>
/// Gets the enhanced image.
diff --git a/MediaBrowser.Controller/Drawing/ImageExtensions.cs b/MediaBrowser.Controller/Drawing/ImageExtensions.cs
index c7e1968e7..2511659c3 100644
--- a/MediaBrowser.Controller/Drawing/ImageExtensions.cs
+++ b/MediaBrowser.Controller/Drawing/ImageExtensions.cs
@@ -72,39 +72,6 @@ namespace MediaBrowser.Controller.Drawing
}
/// <summary>
- /// Determines whether [is pixel format supported by graphics object] [the specified format].
- /// </summary>
- /// <param name="format">The format.</param>
- /// <returns><c>true</c> if [is pixel format supported by graphics object] [the specified format]; otherwise, <c>false</c>.</returns>
- public static bool IsPixelFormatSupportedByGraphicsObject(PixelFormat format)
- {
- // http://msdn.microsoft.com/en-us/library/system.drawing.graphics.fromimage.aspx
-
- if ((format & PixelFormat.Indexed) == PixelFormat.Indexed)
- {
- return false;
- }
- if ((format & PixelFormat.Undefined) == PixelFormat.Undefined)
- {
- return false;
- }
- if ((format & PixelFormat.DontCare) == PixelFormat.DontCare)
- {
- return false;
- }
- if ((format & PixelFormat.Format16bppArgb1555) == PixelFormat.Format16bppArgb1555)
- {
- return false;
- }
- if ((format & PixelFormat.Format16bppGrayScale) == PixelFormat.Format16bppGrayScale)
- {
- return false;
- }
-
- return true;
- }
-
- /// <summary>
/// Crops an image by removing whitespace and transparency from the edges
/// </summary>
/// <param name="bmp">The BMP.</param>
diff --git a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs
index 912ad012d..f4a76be00 100644
--- a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs
+++ b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Drawing;
using System.Collections.Generic;
+using System.IO;
namespace MediaBrowser.Controller.Drawing
{
@@ -34,39 +35,36 @@ namespace MediaBrowser.Controller.Drawing
public int? UnplayedCount { get; set; }
public double? PercentPlayed { get; set; }
-
+
public string BackgroundColor { get; set; }
- public bool HasDefaultOptions()
+ public bool HasDefaultOptions(string originalImagePath)
{
- return HasDefaultOptionsWithoutSize() &&
- !Width.HasValue &&
- !Height.HasValue &&
- !MaxWidth.HasValue &&
+ return HasDefaultOptionsWithoutSize(originalImagePath) &&
+ !Width.HasValue &&
+ !Height.HasValue &&
+ !MaxWidth.HasValue &&
!MaxHeight.HasValue;
}
- public bool HasDefaultOptionsWithoutSize()
+ public bool HasDefaultOptionsWithoutSize(string originalImagePath)
{
return (!Quality.HasValue || Quality.Value == 100) &&
- IsOutputFormatDefault &&
+ IsOutputFormatDefault(originalImagePath) &&
!AddPlayedIndicator &&
!PercentPlayed.HasValue &&
!UnplayedCount.HasValue &&
string.IsNullOrEmpty(BackgroundColor);
}
- private bool IsOutputFormatDefault
+ private bool IsOutputFormatDefault(string originalImagePath)
{
- get
+ if (OutputFormat == ImageOutputFormat.Original)
{
- if (OutputFormat == ImageOutputFormat.Original)
- {
- return true;
- }
-
- return false;
+ return true;
}
+
+ return string.Equals(Path.GetExtension(originalImagePath), "." + OutputFormat);
}
}
}
diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs
index 0482e140b..fc15eedf0 100644
--- a/MediaBrowser.Controller/Dto/IDtoService.cs
+++ b/MediaBrowser.Controller/Dto/IDtoService.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
+using System;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Dto
@@ -16,6 +17,7 @@ namespace MediaBrowser.Controller.Dto
/// </summary>
/// <param name="user">The user.</param>
/// <returns>UserDto.</returns>
+ [Obsolete]
UserDto GetUserDto(User user);
/// <summary>
@@ -26,13 +28,6 @@ namespace MediaBrowser.Controller.Dto
string GetDtoId(BaseItem item);
/// <summary>
- /// Gets the user item data dto.
- /// </summary>
- /// <param name="data">The data.</param>
- /// <returns>UserItemDataDto.</returns>
- UserItemDataDto GetUserItemDataDto(UserItemData data);
-
- /// <summary>
/// Attaches the primary image aspect ratio.
/// </summary>
/// <param name="dto">The dto.</param>
@@ -50,16 +45,6 @@ namespace MediaBrowser.Controller.Dto
BaseItemDto GetBaseItemDto(BaseItem item, List<ItemFields> fields, User user = null, BaseItem owner = null);
/// <summary>
- /// Gets the item by name dto.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="fields">The fields.</param>
- /// <param name="user">The user.</param>
- /// <returns>BaseItemDto.</returns>
- BaseItemDto GetItemByNameDto<T>(T item, List<ItemFields> fields, User user = null)
- where T : BaseItem, IItemByName;
-
- /// <summary>
/// Gets the chapter information dto.
/// </summary>
/// <param name="chapterInfo">The chapter information.</param>
@@ -68,6 +53,13 @@ namespace MediaBrowser.Controller.Dto
ChapterInfoDto GetChapterInfoDto(ChapterInfo chapterInfo, BaseItem item);
/// <summary>
+ /// Gets the user item data dto.
+ /// </summary>
+ /// <param name="data">The data.</param>
+ /// <returns>UserItemDataDto.</returns>
+ UserItemDataDto GetUserItemDataDto(UserItemData data);
+
+ /// <summary>
/// Gets the item by name dto.
/// </summary>
/// <param name="item">The item.</param>
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 0900cc1ef..25d41565a 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -14,13 +14,14 @@ namespace MediaBrowser.Controller.Entities.Audio
/// <summary>
/// Class Audio
/// </summary>
- public class Audio : BaseItem,
- IHasAlbumArtist,
- IHasArtist,
- IHasMusicGenres,
- IHasLookupInfo<SongInfo>,
+ public class Audio : BaseItem,
+ IHasAlbumArtist,
+ IHasArtist,
+ IHasMusicGenres,
+ IHasLookupInfo<SongInfo>,
IHasTags,
- IHasMediaSources
+ IHasMediaSources,
+ IThemeMedia
{
public string FormatName { get; set; }
public long? Size { get; set; }
@@ -28,12 +29,21 @@ namespace MediaBrowser.Controller.Entities.Audio
public int? TotalBitrate { get; set; }
public List<string> Tags { get; set; }
+ public bool IsThemeMedia { get; set; }
+
public Audio()
{
Artists = new List<string>();
+ AlbumArtists = new List<string>();
Tags = new List<string>();
}
+ [IgnoreDataMember]
+ public override bool SupportsAddingToPlaylist
+ {
+ get { return LocationType == LocationType.FileSystem && RunTimeTicks.HasValue; }
+ }
+
/// <summary>
/// Gets or sets a value indicating whether this instance has embedded image.
/// </summary>
@@ -64,7 +74,16 @@ namespace MediaBrowser.Controller.Entities.Audio
{
get
{
- return Parents.OfType<MusicAlbum>().FirstOrDefault() ?? new MusicAlbum { Name = "<Unknown>" };
+ return LatestItemsIndexContainer ?? new MusicAlbum { Name = "Unknown Album" };
+ }
+ }
+
+ [IgnoreDataMember]
+ public override Folder LatestItemsIndexContainer
+ {
+ get
+ {
+ return Parents.OfType<MusicAlbum>().FirstOrDefault();
}
}
@@ -74,12 +93,14 @@ namespace MediaBrowser.Controller.Entities.Audio
/// <value>The artist.</value>
public List<string> Artists { get; set; }
+ public List<string> AlbumArtists { get; set; }
+
[IgnoreDataMember]
public List<string> AllArtists
{
get
{
- var list = AlbumArtists;
+ var list = AlbumArtists.ToList();
list.AddRange(Artists);
@@ -88,41 +109,17 @@ namespace MediaBrowser.Controller.Entities.Audio
}
}
- [IgnoreDataMember]
- public List<string> AlbumArtists
- {
- get
- {
- var list = new List<string>();
-
- if (!string.IsNullOrEmpty(AlbumArtist))
- {
- list.Add(AlbumArtist);
- }
-
- return list;
- }
- set
- {
- AlbumArtist = value.FirstOrDefault();
- }
- }
-
/// <summary>
/// Gets or sets the album.
/// </summary>
/// <value>The album.</value>
public string Album { get; set; }
- /// <summary>
- /// Gets or sets the album artist.
- /// </summary>
- /// <value>The album artist.</value>
- public string AlbumArtist { get; set; }
/// <summary>
/// Gets the type of the media.
/// </summary>
/// <value>The type of the media.</value>
+ [IgnoreDataMember]
public override string MediaType
{
get
@@ -204,7 +201,7 @@ namespace MediaBrowser.Controller.Entities.Audio
private static MediaSourceInfo GetVersionInfo(Audio i, bool enablePathSubstituion)
{
var locationType = i.LocationType;
-
+
var info = new MediaSourceInfo
{
Id = i.Id.ToString("N"),
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index a4d9278e5..dc9f83b3c 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -11,15 +11,21 @@ namespace MediaBrowser.Controller.Entities.Audio
/// <summary>
/// Class MusicAlbum
/// </summary>
- public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasTags, IHasLookupInfo<AlbumInfo>
+ public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>
{
public List<Guid> SoundtrackIds { get; set; }
public MusicAlbum()
{
- Artists = new List<string>();
SoundtrackIds = new List<Guid>();
- Tags = new List<string>();
+ Artists = new List<string>();
+ AlbumArtists = new List<string>();
+ }
+
+ [IgnoreDataMember]
+ public override bool SupportsAddingToPlaylist
+ {
+ get { return true; }
}
[IgnoreDataMember]
@@ -36,7 +42,7 @@ namespace MediaBrowser.Controller.Entities.Audio
{
get
{
- var list = AlbumArtists;
+ var list = AlbumArtists.ToList();
list.AddRange(Artists);
@@ -45,31 +51,30 @@ namespace MediaBrowser.Controller.Entities.Audio
}
}
+ public List<string> AlbumArtists { get; set; }
+
[IgnoreDataMember]
- public List<string> AlbumArtists
+ public string AlbumArtist
{
- get
- {
- var list = new List<string>();
-
- if (!string.IsNullOrEmpty(AlbumArtist))
- {
- list.Add(AlbumArtist);
- }
+ get { return AlbumArtists.FirstOrDefault(); }
+ }
- return list;
- }
- set
+ /// <summary>
+ /// Gets the tracks.
+ /// </summary>
+ /// <value>The tracks.</value>
+ public IEnumerable<Audio> Tracks
+ {
+ get
{
- AlbumArtist = value.FirstOrDefault();
+ return RecursiveChildren.OfType<Audio>();
}
}
- /// <summary>
- /// Gets or sets the tags.
- /// </summary>
- /// <value>The tags.</value>
- public List<string> Tags { get; set; }
+ protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
+ {
+ return Tracks;
+ }
/// <summary>
/// Songs will group into us so don't also include us in the index
@@ -124,8 +129,6 @@ namespace MediaBrowser.Controller.Entities.Audio
return AllArtists.Contains(artist, StringComparer.OrdinalIgnoreCase);
}
- public string AlbumArtist { get; set; }
-
public List<string> Artists { get; set; }
/// <summary>
@@ -177,6 +180,7 @@ namespace MediaBrowser.Controller.Entities.Audio
}
}
+ [Obsolete]
public class MusicAlbumDisc : Folder
{
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index 0a5d8eec0..070572b9b 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Progress;
+using System.Runtime.Serialization;
+using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
@@ -13,16 +14,9 @@ namespace MediaBrowser.Controller.Entities.Audio
/// <summary>
/// Class MusicArtist
/// </summary>
- public class MusicArtist : Folder, IMetadataContainer, IItemByName, IHasMusicGenres, IHasDualAccess, IHasTags, IHasProductionLocations, IHasLookupInfo<ArtistInfo>
+ public class MusicArtist : Folder, IMetadataContainer, IItemByName, IHasMusicGenres, IHasDualAccess, IHasProductionLocations, IHasLookupInfo<ArtistInfo>
{
public bool IsAccessedByName { get; set; }
-
- /// <summary>
- /// Gets or sets the tags.
- /// </summary>
- /// <value>The tags.</value>
- public List<string> Tags { get; set; }
-
public List<string> ProductionLocations { get; set; }
public override bool IsFolder
@@ -33,6 +27,12 @@ namespace MediaBrowser.Controller.Entities.Audio
}
}
+ [IgnoreDataMember]
+ public override bool SupportsAddingToPlaylist
+ {
+ get { return true; }
+ }
+
protected override IEnumerable<BaseItem> ActualChildren
{
get
@@ -60,7 +60,6 @@ namespace MediaBrowser.Controller.Entities.Audio
public MusicArtist()
{
- Tags = new List<string>();
ProductionLocations = new List<string>();
}
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
index bce9da4d1..928eb6463 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities.Audio
{
@@ -18,6 +19,12 @@ namespace MediaBrowser.Controller.Entities.Audio
return "MusicGenre-" + Name;
}
+ [IgnoreDataMember]
+ public override bool SupportsAddingToPlaylist
+ {
+ get { return true; }
+ }
+
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index a2ff1b4fd..26b28ec72 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -2,10 +2,12 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Logging;
@@ -51,12 +53,30 @@ namespace MediaBrowser.Controller.Entities
public List<ItemImageInfo> ImageInfos { get; set; }
+ [IgnoreDataMember]
+ public virtual bool SupportsAddingToPlaylist
+ {
+ get
+ {
+ return false;
+ }
+ }
+
/// <summary>
/// Gets a value indicating whether this instance is in mixed folder.
/// </summary>
/// <value><c>true</c> if this instance is in mixed folder; otherwise, <c>false</c>.</value>
public bool IsInMixedFolder { get; set; }
+ [IgnoreDataMember]
+ public virtual bool SupportsRemoteImageDownloading
+ {
+ get
+ {
+ return true;
+ }
+ }
+
private string _name;
/// <summary>
/// Gets or sets the name.
@@ -134,6 +154,11 @@ namespace MediaBrowser.Controller.Entities
}
}
+ public virtual bool IsHiddenFromUser(User user)
+ {
+ return false;
+ }
+
[IgnoreDataMember]
public virtual bool IsOwnedItem
{
@@ -168,6 +193,7 @@ namespace MediaBrowser.Controller.Entities
}
}
+ [IgnoreDataMember]
public virtual bool SupportsLocalMetadata
{
get
@@ -213,6 +239,7 @@ namespace MediaBrowser.Controller.Entities
public static IItemRepository ItemRepository { get; set; }
public static IFileSystem FileSystem { get; set; }
public static IUserDataManager UserDataManager { get; set; }
+ public static ILiveTvManager LiveTvManager { get; set; }
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
@@ -523,10 +550,10 @@ namespace MediaBrowser.Controller.Entities
.Where(i => string.Equals(i.Name, TrailerFolderName, StringComparison.OrdinalIgnoreCase))
.SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly))
.ToList();
-
+
// Support plex/xbmc convention
files.AddRange(fileSystemChildren.OfType<FileInfo>()
- .Where(i => System.IO.Path.GetFileNameWithoutExtension(i.Name).EndsWith(XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase) && !string.Equals(Path, i.FullName, StringComparison.OrdinalIgnoreCase))
+ .Where(i => FileSystem.GetFileNameWithoutExtension(i).EndsWith(XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase) && !string.Equals(Path, i.FullName, StringComparison.OrdinalIgnoreCase))
);
return LibraryManager.ResolvePaths<Trailer>(files, directoryService, null).Select(video =>
@@ -558,7 +585,7 @@ namespace MediaBrowser.Controller.Entities
// Support plex/xbmc convention
files.AddRange(fileSystemChildren.OfType<FileInfo>()
- .Where(i => string.Equals(System.IO.Path.GetFileNameWithoutExtension(i.Name), ThemeSongFilename, StringComparison.OrdinalIgnoreCase))
+ .Where(i => string.Equals(FileSystem.GetFileNameWithoutExtension(i), ThemeSongFilename, StringComparison.OrdinalIgnoreCase))
);
return LibraryManager.ResolvePaths<Audio.Audio>(files, directoryService, null).Select(audio =>
@@ -724,7 +751,18 @@ namespace MediaBrowser.Controller.Entities
var themeVideosChanged = !item.ThemeVideoIds.SequenceEqual(newThemeVideoIds);
- var tasks = newThemeVideos.Select(i => i.RefreshMetadata(options, cancellationToken));
+ var tasks = newThemeVideos.Select(i =>
+ {
+ var subOptions = new MetadataRefreshOptions(options);
+
+ if (!i.IsThemeMedia)
+ {
+ i.IsThemeMedia = true;
+ subOptions.ForceSave = true;
+ }
+
+ return i.RefreshMetadata(subOptions, cancellationToken);
+ });
await Task.WhenAll(tasks).ConfigureAwait(false);
@@ -743,7 +781,18 @@ namespace MediaBrowser.Controller.Entities
var themeSongsChanged = !item.ThemeSongIds.SequenceEqual(newThemeSongIds);
- var tasks = newThemeSongs.Select(i => i.RefreshMetadata(options, cancellationToken));
+ var tasks = newThemeSongs.Select(i =>
+ {
+ var subOptions = new MetadataRefreshOptions(options);
+
+ if (!i.IsThemeMedia)
+ {
+ i.IsThemeMedia = true;
+ subOptions.ForceSave = true;
+ }
+
+ return i.RefreshMetadata(subOptions, cancellationToken);
+ });
await Task.WhenAll(tasks).ConfigureAwait(false);
@@ -790,6 +839,12 @@ namespace MediaBrowser.Controller.Entities
get { return null; }
}
+ [IgnoreDataMember]
+ public virtual Folder LatestItemsIndexContainer
+ {
+ get { return null; }
+ }
+
/// <summary>
/// Gets the user data key.
/// </summary>
@@ -994,6 +1049,18 @@ 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);
@@ -1016,7 +1083,10 @@ namespace MediaBrowser.Controller.Entities
{
if (info.ItemYear.HasValue)
{
- return info.ItemYear.Value == (i.ProductionYear ?? -1);
+ if (info.ItemYear.Value != (i.ProductionYear ?? -1))
+ {
+ return false;
+ }
}
return true;
}
@@ -1514,6 +1584,11 @@ namespace MediaBrowser.Controller.Entities
public virtual bool IsUnplayed(User user)
{
+ if (user == null)
+ {
+ throw new ArgumentNullException("user");
+ }
+
var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey());
return userdata == null || !userdata.Played;
@@ -1547,7 +1622,7 @@ namespace MediaBrowser.Controller.Entities
if (string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Path))
{
- Name = System.IO.Path.GetFileNameWithoutExtension(Path);
+ Name = FileSystem.GetFileNameWithoutExtension(Path);
hasChanges = true;
}
@@ -1566,5 +1641,19 @@ namespace MediaBrowser.Controller.Entities
return path;
}
+
+ public virtual void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
+ {
+ if (RunTimeTicks.HasValue)
+ {
+ double pct = RunTimeTicks.Value;
+
+ if (pct > 0)
+ {
+ pct = userData.PlaybackPositionTicks / pct;
+ dto.PlayedPercentage = 100 * pct;
+ }
+ }
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/BasePluginFolder.cs b/MediaBrowser.Controller/Entities/BasePluginFolder.cs
index e1383923f..b30bd81b9 100644
--- a/MediaBrowser.Controller/Entities/BasePluginFolder.cs
+++ b/MediaBrowser.Controller/Entities/BasePluginFolder.cs
@@ -7,14 +7,9 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public abstract class BasePluginFolder : Folder, ICollectionFolder, IByReferenceItem
{
- protected BasePluginFolder()
- {
- DisplayMediaType = "CollectionFolder";
- }
-
public virtual string CollectionType
{
- get { return Model.Entities.CollectionType.BoxSets; }
+ get { return null; }
}
}
}
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 87b1cc7a3..356f2b603 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -4,8 +4,8 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
-using MoreLinq;
using System;
using System.Collections;
using System.Collections.Generic;
@@ -14,18 +14,20 @@ using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using MoreLinq;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class Folder
/// </summary>
- public class Folder : BaseItem, IHasThemeMedia
+ public class Folder : BaseItem, IHasThemeMedia, IHasTags
{
public static IUserManager UserManager { get; set; }
public List<Guid> ThemeSongIds { get; set; }
public List<Guid> ThemeVideoIds { get; set; }
+ public List<string> Tags { get; set; }
public Folder()
{
@@ -33,6 +35,13 @@ namespace MediaBrowser.Controller.Entities
ThemeSongIds = new List<Guid>();
ThemeVideoIds = new List<Guid>();
+ Tags = new List<string>();
+ }
+
+ [IgnoreDataMember]
+ public virtual bool IsPreSorted
+ {
+ get { return false; }
}
/// <summary>
@@ -264,7 +273,7 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public IEnumerable<BaseItem> Children
{
- get { return ActualChildren.Where(i => !i.IsHidden); }
+ get { return ActualChildren; }
}
/// <summary>
@@ -445,11 +454,6 @@ namespace MediaBrowser.Controller.Entities
cancellationToken.ThrowIfCancellationRequested();
- if (this is UserRootFolder)
- {
- var b = true;
- }
-
foreach (var child in nonCachedChildren)
{
BaseItem currentChild;
@@ -775,6 +779,11 @@ namespace MediaBrowser.Controller.Entities
/// <exception cref="System.ArgumentNullException"></exception>
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
{
+ return GetChildren(user, includeLinkedChildren, false);
+ }
+
+ internal IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren, bool includeHidden)
+ {
if (user == null)
{
throw new ArgumentNullException();
@@ -785,7 +794,7 @@ namespace MediaBrowser.Controller.Entities
var list = new List<BaseItem>();
- var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, false, null);
+ var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, includeHidden, false);
return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list;
}
@@ -801,10 +810,10 @@ namespace MediaBrowser.Controller.Entities
/// <param name="user">The user.</param>
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
/// <param name="list">The list.</param>
+ /// <param name="includeHidden">if set to <c>true</c> [include hidden].</param>
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
- /// <param name="filter">The filter.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
- private bool AddChildrenToList(User user, bool includeLinkedChildren, List<BaseItem> list, bool recursive, Func<BaseItem, bool> filter)
+ private bool AddChildrenToList(User user, bool includeLinkedChildren, List<BaseItem> list, bool includeHidden, bool recursive)
{
var hasLinkedChildren = false;
@@ -812,7 +821,7 @@ namespace MediaBrowser.Controller.Entities
{
if (child.IsVisible(user))
{
- if (filter == null || filter(child))
+ if (includeHidden || !child.IsHiddenFromUser(user))
{
list.Add(child);
}
@@ -821,7 +830,7 @@ namespace MediaBrowser.Controller.Entities
{
var folder = (Folder)child;
- if (folder.AddChildrenToList(user, includeLinkedChildren, list, true, filter))
+ if (folder.AddChildrenToList(user, includeLinkedChildren, list, includeHidden, true))
{
hasLinkedChildren = true;
}
@@ -831,13 +840,8 @@ namespace MediaBrowser.Controller.Entities
if (includeLinkedChildren)
{
- foreach (var child in GetLinkedChildren())
+ foreach (var child in GetLinkedChildren(user))
{
- if (filter != null && !filter(child))
- {
- continue;
- }
-
if (child.IsVisible(user))
{
hasLinkedChildren = true;
@@ -857,20 +861,7 @@ namespace MediaBrowser.Controller.Entities
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
/// <returns>IEnumerable{BaseItem}.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
- public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true)
- {
- return GetRecursiveChildren(user, null, includeLinkedChildren);
- }
-
- /// <summary>
- /// Gets the recursive children.
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="filter">The filter.</param>
- /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
- /// <returns>IList{BaseItem}.</returns>
- /// <exception cref="System.ArgumentNullException"></exception>
- public IList<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter, bool includeLinkedChildren = true)
+ public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true)
{
if (user == null)
{
@@ -879,7 +870,7 @@ namespace MediaBrowser.Controller.Entities
var list = new List<BaseItem>();
- var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, true, filter);
+ var hasLinkedChildren = AddChildrenToList(user, includeLinkedChildren, list, false, true);
return hasLinkedChildren ? list.DistinctBy(i => i.Id).ToList() : list;
}
@@ -890,19 +881,9 @@ namespace MediaBrowser.Controller.Entities
/// <returns>IList{BaseItem}.</returns>
public IList<BaseItem> GetRecursiveChildren()
{
- return GetRecursiveChildren(i => true);
- }
-
- /// <summary>
- /// Gets the recursive children.
- /// </summary>
- /// <param name="filter">The filter.</param>
- /// <returns>IEnumerable{BaseItem}.</returns>
- public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter)
- {
var list = new List<BaseItem>();
- AddChildrenToList(list, true, filter);
+ AddChildrenToList(list, true, null);
return list;
}
@@ -943,6 +924,74 @@ namespace MediaBrowser.Controller.Entities
.Where(i => i != null);
}
+ protected virtual bool FilterLinkedChildrenPerUser
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public IEnumerable<BaseItem> GetLinkedChildren(User user)
+ {
+ if (!FilterLinkedChildrenPerUser || user == null)
+ {
+ return GetLinkedChildren();
+ }
+
+ var locations = user.RootFolder
+ .GetChildren(user, true)
+ .OfType<CollectionFolder>()
+ .SelectMany(i => i.PhysicalLocations)
+ .ToList();
+
+ return LinkedChildren
+ .Select(i =>
+ {
+ var requiresPostFilter = true;
+
+ if (!string.IsNullOrWhiteSpace(i.Path))
+ {
+ requiresPostFilter = false;
+
+ if (!locations.Any(l => FileSystem.ContainsSubPath(l, i.Path)))
+ {
+ return null;
+ }
+ }
+
+ var child = GetLinkedChild(i);
+
+ if (requiresPostFilter && child != null)
+ {
+ if (string.IsNullOrWhiteSpace(child.Path))
+ {
+ Logger.Debug("Found LinkedChild with null path: {0}", child.Name);
+ return child;
+ }
+
+ if (!locations.Any(l => FileSystem.ContainsSubPath(l, child.Path)))
+ {
+ return null;
+ }
+ }
+
+ return child;
+ })
+ .Where(i => i != null);
+ }
+
+ /// <summary>
+ /// Gets the linked children.
+ /// </summary>
+ /// <returns>IEnumerable{BaseItem}.</returns>
+ public IEnumerable<Tuple<LinkedChild,BaseItem>> GetLinkedChildrenInfos()
+ {
+ return LinkedChildren
+ .Select(i => new Tuple<LinkedChild,BaseItem>(i, GetLinkedChild(i)))
+ .Where(i => i.Item2 != null);
+ }
+
protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemInfo> fileSystemChildren, CancellationToken cancellationToken)
{
var changesFound = false;
@@ -1104,9 +1153,67 @@ namespace MediaBrowser.Controller.Entities
.All(i => i.IsUnplayed(user));
}
- public IEnumerable<BaseItem> GetHiddenChildren()
+ public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
{
- return ActualChildren.Where(i => i.IsHidden);
+ var recursiveItemCount = 0;
+ var unplayed = 0;
+
+ double totalPercentPlayed = 0;
+
+ IEnumerable<BaseItem> children;
+ var folder = this;
+
+ var season = folder as Season;
+
+ if (season != null)
+ {
+ children = season.GetEpisodes(user).Where(i => i.LocationType != LocationType.Virtual);
+ }
+ else
+ {
+ children = folder.GetRecursiveChildren(user)
+ .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual);
+ }
+
+ // Loop through each recursive child
+ foreach (var child in children)
+ {
+ recursiveItemCount++;
+
+ var isUnplayed = true;
+
+ var itemUserData = UserDataManager.GetUserData(user.Id, child.GetUserDataKey());
+
+ // Incrememt totalPercentPlayed
+ if (itemUserData != null)
+ {
+ if (itemUserData.Played)
+ {
+ totalPercentPlayed += 100;
+
+ isUnplayed = false;
+ }
+ else if (itemUserData.PlaybackPositionTicks > 0 && child.RunTimeTicks.HasValue && child.RunTimeTicks.Value > 0)
+ {
+ double itemPercent = itemUserData.PlaybackPositionTicks;
+ itemPercent /= child.RunTimeTicks.Value;
+ totalPercentPlayed += itemPercent;
+ }
+ }
+
+ if (isUnplayed)
+ {
+ unplayed++;
+ }
+ }
+
+ dto.UnplayedItemCount = unplayed;
+
+ if (recursiveItemCount > 0)
+ {
+ dto.PlayedPercentage = totalPercentPlayed / recursiveItemCount;
+ dto.Played = dto.PlayedPercentage.Value >= 100;
+ }
}
}
}
diff --git a/MediaBrowser.Controller/Entities/IHasImages.cs b/MediaBrowser.Controller/Entities/IHasImages.cs
index bac226369..67acc1cae 100644
--- a/MediaBrowser.Controller/Entities/IHasImages.cs
+++ b/MediaBrowser.Controller/Entities/IHasImages.cs
@@ -154,6 +154,12 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value><c>true</c> if this instance is locked; otherwise, <c>false</c>.</value>
bool IsLocked { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether [supports remote image downloading].
+ /// </summary>
+ /// <value><c>true</c> if [supports remote image downloading]; otherwise, <c>false</c>.</value>
+ bool SupportsRemoteImageDownloading { get; }
}
public static class HasImagesExtensions
diff --git a/MediaBrowser.Controller/Entities/IHasMediaSources.cs b/MediaBrowser.Controller/Entities/IHasMediaSources.cs
index da040f296..d487362f5 100644
--- a/MediaBrowser.Controller/Entities/IHasMediaSources.cs
+++ b/MediaBrowser.Controller/Entities/IHasMediaSources.cs
@@ -10,6 +10,12 @@ namespace MediaBrowser.Controller.Entities
public interface IHasMediaSources
{
/// <summary>
+ /// Gets the identifier.
+ /// </summary>
+ /// <value>The identifier.</value>
+ Guid Id { get; }
+
+ /// <summary>
/// Gets the media sources.
/// </summary>
/// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
diff --git a/MediaBrowser.Controller/Entities/IHasUserData.cs b/MediaBrowser.Controller/Entities/IHasUserData.cs
index 780181a61..d576d90c4 100644
--- a/MediaBrowser.Controller/Entities/IHasUserData.cs
+++ b/MediaBrowser.Controller/Entities/IHasUserData.cs
@@ -1,4 +1,6 @@
-
+using MediaBrowser.Model.Dto;
+using System;
+
namespace MediaBrowser.Controller.Entities
{
/// <summary>
@@ -7,9 +9,23 @@ namespace MediaBrowser.Controller.Entities
public interface IHasUserData
{
/// <summary>
+ /// Gets or sets the identifier.
+ /// </summary>
+ /// <value>The identifier.</value>
+ Guid Id { get; set; }
+
+ /// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
string GetUserDataKey();
+
+ /// <summary>
+ /// Fills the user data dto values.
+ /// </summary>
+ /// <param name="dto">The dto.</param>
+ /// <param name="userData">The user data.</param>
+ /// <param name="user">The user.</param>
+ void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user);
}
}
diff --git a/MediaBrowser.Controller/Entities/IThemeMedia.cs b/MediaBrowser.Controller/Entities/IThemeMedia.cs
new file mode 100644
index 000000000..b2eff230f
--- /dev/null
+++ b/MediaBrowser.Controller/Entities/IThemeMedia.cs
@@ -0,0 +1,8 @@
+
+namespace MediaBrowser.Controller.Entities
+{
+ public interface IThemeMedia
+ {
+ bool IsThemeMedia { get; }
+ }
+}
diff --git a/MediaBrowser.Controller/Entities/LinkedChild.cs b/MediaBrowser.Controller/Entities/LinkedChild.cs
index 1ae04e40f..78e8e4959 100644
--- a/MediaBrowser.Controller/Entities/LinkedChild.cs
+++ b/MediaBrowser.Controller/Entities/LinkedChild.cs
@@ -13,11 +13,27 @@ namespace MediaBrowser.Controller.Entities
public string ItemType { get; set; }
public int? ItemYear { get; set; }
+ [IgnoreDataMember]
+ public string Id { get; set; }
+
/// <summary>
/// Serves as a cache
/// </summary>
- [IgnoreDataMember]
public Guid? ItemId { get; set; }
+
+ public static LinkedChild Create(BaseItem item)
+ {
+ return new LinkedChild
+ {
+ Path = item.Path,
+ Type = LinkedChildType.Manual
+ };
+ }
+
+ public LinkedChild()
+ {
+ Id = Guid.NewGuid().ToString("N");
+ }
}
public enum LinkedChildType
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index b0cb549f4..705cf9057 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -6,6 +6,7 @@ using MediaBrowser.Model.Querying;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
@@ -14,18 +15,25 @@ namespace MediaBrowser.Controller.Entities.Movies
/// <summary>
/// Class BoxSet
/// </summary>
- public class BoxSet : Folder, IHasTrailers, IHasTags, IHasKeywords, IHasPreferredMetadataLanguage, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IMetadataContainer
+ public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasPreferredMetadataLanguage, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IMetadataContainer
{
public BoxSet()
{
RemoteTrailers = new List<MediaUrl>();
LocalTrailerIds = new List<Guid>();
- Tags = new List<string>();
DisplayOrder = ItemSortBy.PremiereDate;
Keywords = new List<string>();
}
+ protected override bool FilterLinkedChildrenPerUser
+ {
+ get
+ {
+ return true;
+ }
+ }
+
public List<Guid> LocalTrailerIds { get; set; }
/// <summary>
@@ -38,7 +46,6 @@ namespace MediaBrowser.Controller.Entities.Movies
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
- public List<string> Tags { get; set; }
public List<string> Keywords { get; set; }
public string PreferredMetadataLanguage { get; set; }
@@ -60,6 +67,15 @@ namespace MediaBrowser.Controller.Entities.Movies
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
}
+ [IgnoreDataMember]
+ public override bool IsPreSorted
+ {
+ get
+ {
+ return true;
+ }
+ }
+
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
{
var children = base.GetChildren(user, includeLinkedChildren);
@@ -75,7 +91,7 @@ namespace MediaBrowser.Controller.Entities.Movies
// Sort by release date
return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending);
}
-
+
// Default sorting
return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending);
}
@@ -94,17 +110,9 @@ namespace MediaBrowser.Controller.Entities.Movies
var totalItems = items.Count;
var percentages = new Dictionary<Guid, double>(totalItems);
- var tasks = new List<Task>();
-
// Refresh songs
foreach (var item in items)
{
- if (tasks.Count >= 3)
- {
- await Task.WhenAll(tasks).ConfigureAwait(false);
- tasks.Clear();
- }
-
cancellationToken.ThrowIfCancellationRequested();
var innerProgress = new ActionableProgress<double>();
@@ -124,13 +132,9 @@ namespace MediaBrowser.Controller.Entities.Movies
});
// Avoid implicitly captured closure
- var taskChild = item;
- tasks.Add(Task.Run(async () => await RefreshItem(taskChild, refreshOptions, innerProgress, cancellationToken).ConfigureAwait(false), cancellationToken));
+ await RefreshItem(item, refreshOptions, innerProgress, cancellationToken).ConfigureAwait(false);
}
- await Task.WhenAll(tasks).ConfigureAwait(false);
- tasks.Clear();
-
// Refresh current item
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs
index 54cb3fcc9..5510c795a 100644
--- a/MediaBrowser.Controller/Entities/Movies/Movie.cs
+++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs
@@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Entities.Movies
/// <summary>
/// Class Movie
/// </summary>
- public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasPreferredMetadataLanguage, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping, IHasShortOverview
+ public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasPreferredMetadataLanguage, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping
{
public List<Guid> SpecialFeatureIds { get; set; }
@@ -52,7 +52,6 @@ namespace MediaBrowser.Controller.Entities.Movies
ProductionLocations = new List<string>();
}
- public string ShortOverview { get; set; }
public string AwardSummary { get; set; }
public float? Metascore { get; set; }
diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs
index 1def47391..fe8d61836 100644
--- a/MediaBrowser.Controller/Entities/Person.cs
+++ b/MediaBrowser.Controller/Entities/Person.cs
@@ -96,5 +96,10 @@ namespace MediaBrowser.Controller.Entities
{
return Name;
}
+
+ public bool IsType(string type)
+ {
+ return string.Equals(Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(Role, type, StringComparison.OrdinalIgnoreCase);
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs
index 96995c315..367db5dcb 100644
--- a/MediaBrowser.Controller/Entities/Photo.cs
+++ b/MediaBrowser.Controller/Entities/Photo.cs
@@ -1,4 +1,8 @@
-using System.Collections.Generic;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Drawing;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities
{
@@ -13,6 +17,16 @@ namespace MediaBrowser.Controller.Entities
Taglines = new List<string>();
}
+ [IgnoreDataMember]
+ public override bool SupportsLocalMetadata
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ [IgnoreDataMember]
public override string MediaType
{
get
@@ -20,5 +34,45 @@ namespace MediaBrowser.Controller.Entities
return Model.Entities.MediaType.Photo;
}
}
+
+ [IgnoreDataMember]
+ public override Folder LatestItemsIndexContainer
+ {
+ get
+ {
+ return Album;
+ }
+ }
+
+
+ [IgnoreDataMember]
+ public PhotoAlbum Album
+ {
+ get
+ {
+ return Parents.OfType<PhotoAlbum>().FirstOrDefault();
+ }
+ }
+
+ public int? Width { get; set; }
+ public int? Height { get; set; }
+ public string CameraMake { get; set; }
+ public string CameraModel { get; set; }
+ public string Software { get; set; }
+ public double? ExposureTime { get; set; }
+ public double? FocalLength { get; set; }
+ public ImageOrientation? Orientation { get; set; }
+ public double? Aperture { get; set; }
+ public double? ShutterSpeed { get; set; }
+
+ public double? Latitude { get; set; }
+ public double? Longitude { get; set; }
+ public double? Altitude { get; set; }
+ public int? IsoSpeedRating { get; set; }
+
+ protected override bool GetBlockUnratedValue(UserConfiguration config)
+ {
+ return config.BlockUnratedItems.Contains(UnratedItem.Other);
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/PhotoAlbum.cs b/MediaBrowser.Controller/Entities/PhotoAlbum.cs
new file mode 100644
index 000000000..7af4109f3
--- /dev/null
+++ b/MediaBrowser.Controller/Entities/PhotoAlbum.cs
@@ -0,0 +1,21 @@
+using MediaBrowser.Model.Configuration;
+using System.Linq;
+
+namespace MediaBrowser.Controller.Entities
+{
+ public class PhotoAlbum : Folder
+ {
+ public override bool SupportsLocalMetadata
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ protected override bool GetBlockUnratedValue(UserConfiguration config)
+ {
+ return config.BlockUnratedItems.Contains(UnratedItem.Other);
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs
index 8271a3df2..0d934ad0a 100644
--- a/MediaBrowser.Controller/Entities/Studio.cs
+++ b/MediaBrowser.Controller/Entities/Studio.cs
@@ -7,8 +7,15 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Class Studio
/// </summary>
- public class Studio : BaseItem, IItemByName
+ public class Studio : BaseItem, IItemByName, IHasTags
{
+ public List<string> Tags { get; set; }
+
+ public Studio()
+ {
+ Tags = new List<string>();
+ }
+
/// <summary>
/// Gets the user data key.
/// </summary>
diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs
index b9630a66f..b95c7df9c 100644
--- a/MediaBrowser.Controller/Entities/TV/Episode.cs
+++ b/MediaBrowser.Controller/Entities/TV/Episode.cs
@@ -91,7 +91,16 @@ namespace MediaBrowser.Controller.Entities.TV
{
get
{
- return FindParent<Season>();
+ return Season;
+ }
+ }
+
+ [IgnoreDataMember]
+ public override Folder LatestItemsIndexContainer
+ {
+ get
+ {
+ return Series;
}
}
@@ -181,6 +190,20 @@ namespace MediaBrowser.Controller.Entities.TV
}
[IgnoreDataMember]
+ public override bool SupportsRemoteImageDownloading
+ {
+ get
+ {
+ if (IsMissingEpisode)
+ {
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ [IgnoreDataMember]
public bool IsMissingEpisode
{
get
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs
index cf39cda89..6804b29b7 100644
--- a/MediaBrowser.Controller/Entities/TV/Season.cs
+++ b/MediaBrowser.Controller/Entities/TV/Season.cs
@@ -29,6 +29,21 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
+ [IgnoreDataMember]
+ public override bool SupportsAddingToPlaylist
+ {
+ get { return true; }
+ }
+
+ [IgnoreDataMember]
+ public override bool IsPreSorted
+ {
+ get
+ {
+ return true;
+ }
+ }
+
/// <summary>
/// We want to group into our Series
/// </summary>
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs
index a9a2b024f..d3b95eb0c 100644
--- a/MediaBrowser.Controller/Entities/TV/Series.cs
+++ b/MediaBrowser.Controller/Entities/TV/Series.cs
@@ -13,7 +13,7 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// Class Series
/// </summary>
- public class Series : Folder, IHasSoundtracks, IHasTrailers, IHasTags, IHasPreferredMetadataLanguage, IHasDisplayOrder, IHasLookupInfo<SeriesInfo>
+ public class Series : Folder, IHasSoundtracks, IHasTrailers, IHasPreferredMetadataLanguage, IHasDisplayOrder, IHasLookupInfo<SeriesInfo>
{
public List<Guid> SpecialFeatureIds { get; set; }
public List<Guid> SoundtrackIds { get; set; }
@@ -36,10 +36,24 @@ namespace MediaBrowser.Controller.Entities.TV
SoundtrackIds = new List<Guid>();
RemoteTrailers = new List<MediaUrl>();
LocalTrailerIds = new List<Guid>();
- Tags = new List<string>();
DisplaySpecialsWithSeasons = true;
}
+ [IgnoreDataMember]
+ public override bool SupportsAddingToPlaylist
+ {
+ get { return true; }
+ }
+
+ [IgnoreDataMember]
+ public override bool IsPreSorted
+ {
+ get
+ {
+ return true;
+ }
+ }
+
public bool DisplaySpecialsWithSeasons { get; set; }
public List<Guid> LocalTrailerIds { get; set; }
@@ -52,12 +66,6 @@ namespace MediaBrowser.Controller.Entities.TV
public string DisplayOrder { get; set; }
/// <summary>
- /// Gets or sets the tags.
- /// </summary>
- /// <value>The tags.</value>
- public List<string> Tags { get; set; }
-
- /// <summary>
/// Gets or sets the status.
/// </summary>
/// <value>The status.</value>
diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs
index b9c419722..e4fd929ff 100644
--- a/MediaBrowser.Controller/Entities/User.cs
+++ b/MediaBrowser.Controller/Entities/User.cs
@@ -24,6 +24,7 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value>The password.</value>
public string Password { get; set; }
+ public string LocalPassword { get; set; }
/// <summary>
/// Gets or sets the path.
diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs
index e5a8135c2..6404e71ec 100644
--- a/MediaBrowser.Controller/Entities/UserRootFolder.cs
+++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -51,5 +52,10 @@ namespace MediaBrowser.Controller.Entities
LibraryManager.RegisterItem(item);
}
}
+
+ public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
+ {
+ // Nothing meaninful here and will only waste resources
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index ce188554c..2abc71752 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -1,15 +1,20 @@
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.LiveTv;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
namespace MediaBrowser.Controller.Entities
{
public class UserView : Folder
{
public string ViewType { get; set; }
+ public static IUserViewManager UserViewManager { get; set; }
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
{
@@ -17,17 +22,50 @@ namespace MediaBrowser.Controller.Entities
switch (ViewType)
{
+ case CollectionType.LiveTvChannels:
+ return LiveTvManager.GetInternalChannels(new LiveTvChannelQuery
+ {
+ UserId = user.Id.ToString("N")
+
+ }, CancellationToken.None).Result.Items;
+ case CollectionType.LiveTvRecordingGroups:
+ return LiveTvManager.GetInternalRecordings(new RecordingQuery
+ {
+ UserId = user.Id.ToString("N"),
+ Status = RecordingStatus.Completed
+
+ }, CancellationToken.None).Result.Items;
+ case CollectionType.LiveTv:
+ return GetLiveTvFolders(user).Result;
+ case CollectionType.Folders:
+ return user.RootFolder.GetChildren(user, includeLinkedChildren);
case CollectionType.Games:
- return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren)).OfType<GameSystem>();
+ return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren))
+ .OfType<GameSystem>();
case CollectionType.BoxSets:
- return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren)).OfType<BoxSet>();
+ return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren))
+ .OfType<BoxSet>();
case CollectionType.TvShows:
- return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren)).OfType<Series>();
+ return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren))
+ .OfType<Series>();
+ case CollectionType.Trailers:
+ return mediaFolders.SelectMany(i => i.GetRecursiveChildren(user, includeLinkedChildren))
+ .OfType<Trailer>();
default:
return mediaFolders.SelectMany(i => i.GetChildren(user, includeLinkedChildren));
}
}
+ private async Task<IEnumerable<BaseItem>> GetLiveTvFolders(User user)
+ {
+ var list = new List<BaseItem>();
+
+ list.Add(await UserViewManager.GetUserView(CollectionType.LiveTvChannels, user, string.Empty, CancellationToken.None).ConfigureAwait(false));
+ list.Add(await UserViewManager.GetUserView(CollectionType.LiveTvRecordingGroups, user, string.Empty, CancellationToken.None).ConfigureAwait(false));
+
+ return list;
+ }
+
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
{
return GetChildren(user, false);
@@ -38,7 +76,7 @@ namespace MediaBrowser.Controller.Entities
var excludeFolderIds = user.Configuration.ExcludeFoldersFromGrouping.Select(i => new Guid(i)).ToList();
return user.RootFolder
- .GetChildren(user, true)
+ .GetChildren(user, true, true)
.OfType<Folder>()
.Where(i => !excludeFolderIds.Contains(i.Id) && !IsExcludedFromGrouping(i));
}
@@ -64,4 +102,30 @@ namespace MediaBrowser.Controller.Entities
return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty);
}
}
+
+ public class SpecialFolder : Folder
+ {
+ public SpecialFolderType SpecialFolderType { get; set; }
+ public string ItemTypeName { get; set; }
+ public string ParentId { get; set; }
+
+ public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
+ {
+ var parent = (Folder)LibraryManager.GetItemById(new Guid(ParentId));
+
+ if (SpecialFolderType == SpecialFolderType.ItemsByType)
+ {
+ var items = parent.GetRecursiveChildren(user, includeLinkedChildren);
+
+ return items.Where(i => string.Equals(i.GetType().Name, ItemTypeName, StringComparison.OrdinalIgnoreCase));
+ }
+
+ return new List<BaseItem>();
+ }
+ }
+
+ public enum SpecialFolderType
+ {
+ ItemsByType = 1
+ }
}
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index 61404949e..492a4a02f 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -23,7 +23,9 @@ namespace MediaBrowser.Controller.Entities
IHasAspectRatio,
IHasTags,
ISupportsPlaceHolders,
- IHasMediaSources
+ IHasMediaSources,
+ IHasShortOverview,
+ IThemeMedia
{
public bool IsMultiPart { get; set; }
public bool HasLocalAlternateVersions { get; set; }
@@ -32,10 +34,13 @@ namespace MediaBrowser.Controller.Entities
public List<Guid> AdditionalPartIds { get; set; }
public List<Guid> LocalAlternateVersionIds { get; set; }
+ public bool IsThemeMedia { get; set; }
+
public string FormatName { get; set; }
public long? Size { get; set; }
public string Container { get; set; }
public int? TotalBitrate { get; set; }
+ public string ShortOverview { get; set; }
/// <summary>
/// Gets or sets the timestamp.
@@ -54,6 +59,12 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
+ public override bool SupportsAddingToPlaylist
+ {
+ get { return LocationType == LocationType.FileSystem && RunTimeTicks.HasValue; }
+ }
+
+ [IgnoreDataMember]
public int MediaSourceCount
{
get
@@ -228,6 +239,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets the type of the media.
/// </summary>
/// <value>The type of the media.</value>
+ [IgnoreDataMember]
public override string MediaType
{
get
@@ -324,7 +336,7 @@ namespace MediaBrowser.Controller.Entities
{
if ((i.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
{
- return !string.Equals(i.FullName, path, StringComparison.OrdinalIgnoreCase) && EntityResolutionHelper.IsMultiPartFolder(i.FullName) && EntityResolutionHelper.IsMultiPartFile(i.Name);
+ return !string.Equals(i.FullName, path, StringComparison.OrdinalIgnoreCase) && EntityResolutionHelper.IsMultiPartFolder(i.FullName);
}
return false;
diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs
index 21f5fa87a..2af37e84d 100644
--- a/MediaBrowser.Controller/IServerApplicationHost.cs
+++ b/MediaBrowser.Controller/IServerApplicationHost.cs
@@ -40,5 +40,17 @@ namespace MediaBrowser.Controller
/// </summary>
/// <value><c>true</c> if this instance has update available; otherwise, <c>false</c>.</value>
bool HasUpdateAvailable { get; }
+
+ /// <summary>
+ /// Gets or sets the server identifier.
+ /// </summary>
+ /// <value>The server identifier.</value>
+ string ServerId { get; }
+
+ /// <summary>
+ /// Gets the name of the friendly.
+ /// </summary>
+ /// <value>The name of the friendly.</value>
+ string FriendlyName { get; }
}
}
diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs
index 2bec9e3de..9db91e7f2 100644
--- a/MediaBrowser.Controller/Library/IUserDataManager.cs
+++ b/MediaBrowser.Controller/Library/IUserDataManager.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using System;
using System.Threading;
@@ -34,5 +35,13 @@ namespace MediaBrowser.Controller.Library
/// <param name="key">The key.</param>
/// <returns>Task{UserItemData}.</returns>
UserItemData GetUserData(Guid userId, string key);
+
+ /// <summary>
+ /// Gets the user data dto.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="user">The user.</param>
+ /// <returns>UserItemDataDto.</returns>
+ UserItemDataDto GetUserDataDto(IHasUserData item, User user);
}
}
diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs
index 010caa233..a5d949c8a 100644
--- a/MediaBrowser.Controller/Library/IUserManager.cs
+++ b/MediaBrowser.Controller/Library/IUserManager.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Events;
using System;
using System.Collections.Generic;
@@ -31,6 +32,7 @@ namespace MediaBrowser.Controller.Library
event EventHandler<GenericEventArgs<User>> UserCreated;
event EventHandler<GenericEventArgs<User>> UserConfigurationUpdated;
+ event EventHandler<GenericEventArgs<User>> UserPasswordChanged;
/// <summary>
/// Updates the configuration.
@@ -50,12 +52,13 @@ namespace MediaBrowser.Controller.Library
/// <summary>
/// Authenticates a User and returns a result indicating whether or not it succeeded
/// </summary>
- /// <param name="user">The user.</param>
+ /// <param name="username">The username.</param>
/// <param name="password">The password.</param>
+ /// <param name="remoteEndPoint">The remote end point.</param>
/// <returns>Task{System.Boolean}.</returns>
/// <exception cref="System.ArgumentNullException">user</exception>
- Task<bool> AuthenticateUser(User user, string password);
-
+ Task<bool> AuthenticateUser(string username, string password, string remoteEndPoint);
+
/// <summary>
/// Refreshes metadata for each user
/// </summary>
@@ -113,5 +116,13 @@ namespace MediaBrowser.Controller.Library
/// <param name="newPassword">The new password.</param>
/// <returns>Task.</returns>
Task ChangePassword(User user, string newPassword);
+
+ /// <summary>
+ /// Gets the user dto.
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <param name="remoteEndPoint">The remote end point.</param>
+ /// <returns>UserDto.</returns>
+ UserDto GetUserDto(User user, string remoteEndPoint = null);
}
}
diff --git a/MediaBrowser.Controller/Library/IUserViewManager.cs b/MediaBrowser.Controller/Library/IUserViewManager.cs
index 7c352d97a..908525a2f 100644
--- a/MediaBrowser.Controller/Library/IUserViewManager.cs
+++ b/MediaBrowser.Controller/Library/IUserViewManager.cs
@@ -9,5 +9,7 @@ namespace MediaBrowser.Controller.Library
public interface IUserViewManager
{
Task<IEnumerable<Folder>> GetUserViews(UserViewQuery query, CancellationToken cancellationToken);
+
+ Task<UserView> GetUserView(string type, User user, string sortName, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs
index 64f3a3b4b..34486182b 100644
--- a/MediaBrowser.Controller/Library/TVUtils.cs
+++ b/MediaBrowser.Controller/Library/TVUtils.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using System;
@@ -7,6 +8,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
+using MediaBrowser.Model.Logging;
namespace MediaBrowser.Controller.Library
{
@@ -98,19 +100,19 @@ namespace MediaBrowser.Controller.Library
private static readonly Regex[] EpisodeExpressionsWithoutSeason =
{
new Regex(
- @".*[\\\/](?<epnumber>\d{1,3})\.\w+$",
+ @".*[\\\/](?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\.\w+$",
RegexOptions.Compiled),
// "01.avi"
new Regex(
- @".*(\\|\/)(?<epnumber>\d{1,2})\s?-\s?[^\\\/]*$",
+ @".*(\\|\/)(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\s?-\s?[^\\\/]*$",
RegexOptions.Compiled),
// "01 - blah.avi", "01-blah.avi"
new Regex(
- @".*(\\|\/)(?<epnumber>\d{1,2})\.[^\\\/]+$",
+ @".*(\\|\/)(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\.[^\\\/]+$",
RegexOptions.Compiled),
// "01.blah.avi"
new Regex(
- @".*[\\\/][^\\\/]* - (?<epnumber>\d{1,3})[^\\\/]*$",
+ @".*[\\\/][^\\\/]* - (?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*[^\\\/]*$",
RegexOptions.Compiled),
// "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi", "blah 2 - 01 - blah"
};
@@ -124,11 +126,27 @@ namespace MediaBrowser.Controller.Library
{
var filename = Path.GetFileName(path);
- if (string.Equals(path, "specials", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(filename, "specials", StringComparison.OrdinalIgnoreCase))
{
return 0;
}
+ int val;
+ if (int.TryParse(filename, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
+ {
+ return val;
+ }
+
+ if (filename.StartsWith("s", StringComparison.OrdinalIgnoreCase))
+ {
+ var testFilename = filename.Substring(1);
+
+ if (int.TryParse(testFilename, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
+ {
+ return val;
+ }
+ }
+
// Look for one of the season folder names
foreach (var name in SeasonFolderNames)
{
@@ -175,7 +193,7 @@ namespace MediaBrowser.Controller.Library
return null;
}
- return int.Parse(path.Substring(numericStart, length));
+ return int.Parse(path.Substring(numericStart, length), CultureInfo.InvariantCulture);
}
/// <summary>
@@ -183,20 +201,64 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="path">The path.</param>
/// <param name="directoryService">The directory service.</param>
+ /// <param name="fileSystem">The file system.</param>
/// <returns><c>true</c> if [is season folder] [the specified path]; otherwise, <c>false</c>.</returns>
- private static bool IsSeasonFolder(string path, IDirectoryService directoryService)
+ private static bool IsSeasonFolder(string path, IDirectoryService directoryService, IFileSystem fileSystem)
{
+ var seasonNumber = GetSeasonNumberFromPath(path);
+ var hasSeasonNumber = seasonNumber != null;
+
+ if (!hasSeasonNumber)
+ {
+ return false;
+ }
+
// It's a season folder if it's named as such and does not contain any audio files, apart from theme.mp3
- return GetSeasonNumberFromPath(path) != null && !directoryService.GetFiles(path).Any(i => EntityResolutionHelper.IsAudioFile(i.FullName) && !string.Equals(Path.GetFileNameWithoutExtension(i.FullName), BaseItem.ThemeSongFilename));
+ foreach (var fileSystemInfo in directoryService.GetFileSystemEntries(path))
+ {
+ var attributes = fileSystemInfo.Attributes;
+
+ if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
+ {
+ continue;
+ }
+
+ // Can't enforce this because files saved by Bitcasa are always marked System
+ //if ((attributes & FileAttributes.System) == FileAttributes.System)
+ //{
+ // continue;
+ //}
+
+ if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
+ {
+ //if (IsBadFolder(fileSystemInfo.Name))
+ //{
+ // return false;
+ //}
+ }
+ else
+ {
+ if (EntityResolutionHelper.IsAudioFile(fileSystemInfo.FullName) &&
+ !string.Equals(fileSystem.GetFileNameWithoutExtension(fileSystemInfo), BaseItem.ThemeSongFilename))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
/// <summary>
/// Determines whether [is series folder] [the specified path].
/// </summary>
/// <param name="path">The path.</param>
+ /// <param name="considerSeasonlessEntries">if set to <c>true</c> [consider seasonless entries].</param>
/// <param name="fileSystemChildren">The file system children.</param>
+ /// <param name="directoryService">The directory service.</param>
+ /// <param name="fileSystem">The file system.</param>
/// <returns><c>true</c> if [is series folder] [the specified path]; otherwise, <c>false</c>.</returns>
- public static bool IsSeriesFolder(string path, bool considerSeasonlessSeries, IEnumerable<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService)
+ public static bool IsSeriesFolder(string path, bool considerSeasonlessEntries, IEnumerable<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService, IFileSystem fileSystem, ILogger logger)
{
// A folder with more than 3 non-season folders in will not becounted as a series
var nonSeriesFolders = 0;
@@ -207,25 +269,35 @@ namespace MediaBrowser.Controller.Library
if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
{
+ //logger.Debug("Igoring series file or folder marked hidden: {0}", child.FullName);
continue;
}
- if ((attributes & FileAttributes.System) == FileAttributes.System)
- {
- continue;
- }
+ // Can't enforce this because files saved by Bitcasa are always marked System
+ //if ((attributes & FileAttributes.System) == FileAttributes.System)
+ //{
+ // logger.Debug("Igoring series subfolder marked system: {0}", child.FullName);
+ // continue;
+ //}
if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
{
- if (IsSeasonFolder(child.FullName, directoryService))
+ if (IsSeasonFolder(child.FullName, directoryService, fileSystem))
{
+ logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName);
return true;
}
- nonSeriesFolders++;
+ if (IsBadFolder(child.Name))
+ {
+ logger.Debug("Invalid folder under series: {0}", child.FullName);
+
+ nonSeriesFolders++;
+ }
if (nonSeriesFolders >= 3)
{
+ logger.Debug("{0} not a series due to 3 or more invalid folders.", path);
return false;
}
}
@@ -235,7 +307,7 @@ namespace MediaBrowser.Controller.Library
if (EntityResolutionHelper.IsVideoFile(fullName) || EntityResolutionHelper.IsVideoPlaceHolder(fullName))
{
- if (GetEpisodeNumberFromFile(fullName, considerSeasonlessSeries).HasValue)
+ if (GetEpisodeNumberFromFile(fullName, considerSeasonlessEntries).HasValue)
{
return true;
}
@@ -243,9 +315,28 @@ namespace MediaBrowser.Controller.Library
}
}
+ logger.Debug("{0} is not a series folder.", path);
return false;
}
+ private static bool IsBadFolder(string name)
+ {
+ if (string.Equals(name, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+ if (string.Equals(name, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+ if (string.Equals(name, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+
+ return !EntityResolutionHelper.IgnoreFolders.Contains(name, StringComparer.OrdinalIgnoreCase);
+ }
+
/// <summary>
/// Episodes the number from file.
/// </summary>
@@ -284,6 +375,12 @@ namespace MediaBrowser.Controller.Library
if (m.Success && !string.IsNullOrEmpty(m.Groups["endingepnumber"].Value))
return ParseEpisodeNumber(m.Groups["endingepnumber"].Value);
}
+ foreach (var r in EpisodeExpressionsWithoutSeason)
+ {
+ var m = r.Match(fl);
+ if (m.Success && !string.IsNullOrEmpty(m.Groups["endingepnumber"].Value))
+ return ParseEpisodeNumber(m.Groups["endingepnumber"].Value);
+ }
return null;
}
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index d40ecb463..b1c6ebffc 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -280,5 +280,22 @@ namespace MediaBrowser.Controller.LiveTv
/// </summary>
/// <returns>IEnumerable{User}.</returns>
IEnumerable<User> GetEnabledUsers();
+
+ /// <summary>
+ /// Gets the internal channels.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task&lt;QueryResult&lt;LiveTvChannel&gt;&gt;.</returns>
+ Task<QueryResult<LiveTvChannel>> GetInternalChannels(LiveTvChannelQuery query,
+ CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the internal recordings.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task&lt;QueryResult&lt;BaseItem&gt;&gt;.</returns>
+ Task<QueryResult<BaseItem>> GetInternalRecordings(RecordingQuery query, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
index 23610351e..ba1cb3043 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Controller.LiveTv
{
- public interface ILiveTvRecording : IHasImages, IHasMediaSources
+ public interface ILiveTvRecording : IHasImages, IHasMediaSources, IHasUserData
{
string ServiceName { get; set; }
@@ -20,8 +20,6 @@ namespace MediaBrowser.Controller.LiveTv
string GetClientTypeName();
- string GetUserDataKey();
-
bool IsParentalAllowed(User user);
Task RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken);
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
index 01fed68c8..f2fa912ca 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
@@ -3,13 +3,13 @@ using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;
+using MediaBrowser.Model.MediaInfo;
using System.Collections.Generic;
using System.Linq;
-using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Controller.LiveTv
{
- public class LiveTvChannel : BaseItem, IItemByName, IHasMediaSources
+ public class LiveTvChannel : BaseItem, IHasMediaSources
{
/// <summary>
/// Gets the user data key.
diff --git a/MediaBrowser.Controller/LiveTv/RecordingGroup.cs b/MediaBrowser.Controller/LiveTv/RecordingGroup.cs
new file mode 100644
index 000000000..7bd810b8d
--- /dev/null
+++ b/MediaBrowser.Controller/LiveTv/RecordingGroup.cs
@@ -0,0 +1,22 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Configuration;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+ public class RecordingGroup : Folder
+ {
+ protected override bool GetBlockUnratedValue(UserConfiguration config)
+ {
+ // Don't block.
+ return false;
+ }
+
+ public override bool SupportsLocalMetadata
+ {
+ get
+ {
+ return false;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 1310e7797..6a78fa5d9 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -48,6 +48,9 @@
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
@@ -57,9 +60,6 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
- <Reference Include="MoreLinq">
- <HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
- </Reference>
<Reference Include="ServiceStack.Interfaces">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
</Reference>
@@ -68,6 +68,8 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
+ <Compile Include="Activity\IActivityManager.cs" />
+ <Compile Include="Activity\IActivityRepository.cs" />
<Compile Include="Channels\ChannelFolderItem.cs" />
<Compile Include="Channels\ChannelItemInfo.cs" />
<Compile Include="Channels\ChannelItemResult.cs" />
@@ -95,7 +97,9 @@
<Compile Include="Chapters\IChapterProvider.cs" />
<Compile Include="Chapters\ChapterResponse.cs" />
<Compile Include="Collections\CollectionCreationOptions.cs" />
+ <Compile Include="Collections\CollectionEvents.cs" />
<Compile Include="Collections\ICollectionManager.cs" />
+ <Compile Include="Connect\IConnectManager.cs" />
<Compile Include="Dlna\ControlRequest.cs" />
<Compile Include="Dlna\ControlResponse.cs" />
<Compile Include="Dlna\DlnaIconResponse.cs" />
@@ -147,10 +151,12 @@
<Compile Include="Entities\ISupportsBoxSetGrouping.cs" />
<Compile Include="Entities\ISupportsPlaceHolders.cs" />
<Compile Include="Entities\ItemImageInfo.cs" />
+ <Compile Include="Entities\IThemeMedia.cs" />
<Compile Include="Entities\LinkedChild.cs" />
<Compile Include="Entities\MusicVideo.cs" />
<Compile Include="Entities\IHasAwards.cs" />
<Compile Include="Entities\Photo.cs" />
+ <Compile Include="Entities\PhotoAlbum.cs" />
<Compile Include="Entities\UserView.cs" />
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
<Compile Include="Library\DeleteOptions.cs" />
@@ -165,6 +171,7 @@
<Compile Include="Library\LibraryManagerExtensions.cs" />
<Compile Include="Library\PlaybackStopEventArgs.cs" />
<Compile Include="Library\UserDataSaveEventArgs.cs" />
+ <Compile Include="LiveTv\RecordingGroup.cs" />
<Compile Include="LiveTv\RecordingStatusChangedEventArgs.cs" />
<Compile Include="LiveTv\ILiveTvRecording.cs" />
<Compile Include="LiveTv\LiveStreamInfo.cs" />
@@ -195,10 +202,19 @@
<Compile Include="MediaEncoding\ISubtitleEncoder.cs" />
<Compile Include="MediaEncoding\MediaStreamSelector.cs" />
<Compile Include="MediaEncoding\VideoEncodingOptions.cs" />
+ <Compile Include="Net\AuthenticatedAttribute.cs" />
+ <Compile Include="Net\AuthorizationInfo.cs" />
+ <Compile Include="Net\IAuthorizationContext.cs" />
+ <Compile Include="Net\IAuthService.cs" />
+ <Compile Include="Net\IHasAuthorization.cs" />
<Compile Include="Net\IHasResultFactory.cs" />
+ <Compile Include="Net\IHasSession.cs" />
<Compile Include="Net\IHttpResultFactory.cs" />
<Compile Include="Net\IHttpServer.cs" />
<Compile Include="Net\IRestfulService.cs" />
+ <Compile Include="Net\ISessionContext.cs" />
+ <Compile Include="Net\LoggedAttribute.cs" />
+ <Compile Include="Net\StaticResultOptions.cs" />
<Compile Include="News\INewsService.cs" />
<Compile Include="Notifications\INotificationManager.cs" />
<Compile Include="Notifications\INotificationService.cs" />
@@ -208,6 +224,8 @@
<Compile Include="Notifications\UserNotification.cs" />
<Compile Include="Persistence\IFileOrganizationRepository.cs" />
<Compile Include="Persistence\MediaStreamQuery.cs" />
+ <Compile Include="Playlists\IPlaylistManager.cs" />
+ <Compile Include="Playlists\Playlist.cs" />
<Compile Include="Providers\DirectoryService.cs" />
<Compile Include="Providers\ICustomMetadataProvider.cs" />
<Compile Include="Providers\IExternalId.cs" />
@@ -224,7 +242,12 @@
<Compile Include="Providers\IMetadataService.cs" />
<Compile Include="Providers\IRemoteMetadataProvider.cs" />
<Compile Include="Providers\VideoContentType.cs" />
+ <Compile Include="RelatedMedia\IRelatedMediaProvider.cs" />
+ <Compile Include="Security\AuthenticationInfo.cs" />
+ <Compile Include="Security\AuthenticationInfoQuery.cs" />
+ <Compile Include="Security\IAuthenticationRepository.cs" />
<Compile Include="Security\IEncryptionManager.cs" />
+ <Compile Include="Session\AuthenticationRequest.cs" />
<Compile Include="Subtitles\ISubtitleManager.cs" />
<Compile Include="Subtitles\ISubtitleProvider.cs" />
<Compile Include="Providers\ItemIdentifier.cs" />
@@ -304,8 +327,13 @@
<Compile Include="Sorting\IUserBaseItemComparer.cs" />
<Compile Include="Providers\BaseItemXmlParser.cs" />
<Compile Include="Sorting\SortExtensions.cs" />
+ <Compile Include="Subtitles\SubtitleDownloadEventArgs.cs" />
<Compile Include="Subtitles\SubtitleResponse.cs" />
<Compile Include="Subtitles\SubtitleSearchRequest.cs" />
+ <Compile Include="Sync\ICloudSyncProvider.cs" />
+ <Compile Include="Sync\ISyncManager.cs" />
+ <Compile Include="Sync\ISyncProvider.cs" />
+ <Compile Include="Sync\ISyncRepository.cs" />
<Compile Include="Themes\IAppThemeManager.cs" />
<Compile Include="Themes\InternalThemeImage.cs" />
</ItemGroup>
@@ -332,7 +360,7 @@ xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\" /y /d /r /i
<PreBuildEvent>
</PreBuildEvent>
</PropertyGroup>
- <Import Project="$(SolutionDir)\.nuget\nuget.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.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">
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index f7e8554d1..38c2c83c4 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -44,6 +44,27 @@ namespace MediaBrowser.Controller.MediaEncoding
Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
/// <summary>
+ /// Extracts the video images on interval.
+ /// </summary>
+ /// <param name="inputFiles">The input files.</param>
+ /// <param name="protocol">The protocol.</param>
+ /// <param name="threedFormat">The threed format.</param>
+ /// <param name="interval">The interval.</param>
+ /// <param name="targetDirectory">The target directory.</param>
+ /// <param name="filenamePrefix">The filename prefix.</param>
+ /// <param name="maxWidth">The maximum width.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task ExtractVideoImagesOnInterval(string[] inputFiles,
+ MediaProtocol protocol,
+ Video3DFormat? threedFormat,
+ TimeSpan interval,
+ string targetDirectory,
+ string filenamePrefix,
+ int? maxWidth,
+ CancellationToken cancellationToken);
+
+ /// <summary>
/// Gets the media info.
/// </summary>
/// <param name="inputFiles">The input files.</param>
@@ -68,5 +89,12 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="protocol">The protocol.</param>
/// <returns>System.String.</returns>
string GetInputArgument(string[] inputFiles, MediaProtocol protocol);
+
+ /// <summary>
+ /// Gets the time parameter.
+ /// </summary>
+ /// <param name="ticks">The ticks.</param>
+ /// <returns>System.String.</returns>
+ string GetTimeParameter(long ticks);
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
index 6e9bcef2e..9e32fc32b 100644
--- a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
@@ -13,6 +13,7 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="inputFormat">The input format.</param>
/// <param name="outputFormat">The output format.</param>
/// <param name="startTimeTicks">The start time ticks.</param>
+ /// <param name="endTimeTicks">The end time ticks.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
Task<Stream> ConvertSubtitles(
@@ -20,6 +21,7 @@ namespace MediaBrowser.Controller.MediaEncoding
string inputFormat,
string outputFormat,
long startTimeTicks,
+ long? endTimeTicks,
CancellationToken cancellationToken);
/// <summary>
@@ -30,6 +32,7 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="subtitleStreamIndex">Index of the subtitle stream.</param>
/// <param name="outputFormat">The output format.</param>
/// <param name="startTimeTicks">The start time ticks.</param>
+ /// <param name="endTimeTicks">The end time ticks.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
Task<Stream> GetSubtitles(string itemId,
@@ -37,6 +40,7 @@ namespace MediaBrowser.Controller.MediaEncoding
int subtitleStreamIndex,
string outputFormat,
long startTimeTicks,
+ long? endTimeTicks,
CancellationToken cancellationToken);
/// <summary>
diff --git a/MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs b/MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs
index 39d1c3220..796fdb723 100644
--- a/MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs
+++ b/MediaBrowser.Controller/MediaEncoding/InternalMediaInfoResult.cs
@@ -313,6 +313,12 @@ namespace MediaBrowser.Controller.MediaEncoding
public string bit_rate { get; set; }
/// <summary>
+ /// Gets or sets the probe_score.
+ /// </summary>
+ /// <value>The probe_score.</value>
+ public int probe_score { get; set; }
+
+ /// <summary>
/// Gets or sets the tags.
/// </summary>
/// <value>The tags.</value>
diff --git a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
index 17ab0f31c..50a1c4e4f 100644
--- a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
+++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
@@ -127,8 +127,9 @@ namespace MediaBrowser.Controller.MediaEncoding
stream.BitDepth = GetBitDepth(stream.PixelFormat);
- stream.IsAnamorphic = string.Equals(streamInfo.sample_aspect_ratio, "0:1",
- StringComparison.OrdinalIgnoreCase);
+ 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);
}
else
{
diff --git a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs
new file mode 100644
index 000000000..567d20f39
--- /dev/null
+++ b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs
@@ -0,0 +1,41 @@
+using ServiceStack.Web;
+using System;
+
+namespace MediaBrowser.Controller.Net
+{
+ public class AuthenticatedAttribute : Attribute, IHasRequestFilter
+ {
+ public IAuthService AuthService { get; set; }
+
+ /// <summary>
+ /// The request filter is executed before the service.
+ /// </summary>
+ /// <param name="request">The http request wrapper</param>
+ /// <param name="response">The http response wrapper</param>
+ /// <param name="requestDto">The request DTO</param>
+ public void RequestFilter(IRequest request, IResponse response, object requestDto)
+ {
+ AuthService.Authenticate(request, response, requestDto);
+ }
+
+ /// <summary>
+ /// A new shallow copy of this filter is used on every request.
+ /// </summary>
+ /// <returns>IHasRequestFilter.</returns>
+ public IHasRequestFilter Copy()
+ {
+ return this;
+ }
+
+ /// <summary>
+ /// Order in which Request Filters are executed.
+ /// &lt;0 Executed before global request filters
+ /// &gt;0 Executed after global request filters
+ /// </summary>
+ /// <value>The priority.</value>
+ public int Priority
+ {
+ get { return 0; }
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/Net/AuthorizationInfo.cs b/MediaBrowser.Controller/Net/AuthorizationInfo.cs
new file mode 100644
index 000000000..d7dcb60f0
--- /dev/null
+++ b/MediaBrowser.Controller/Net/AuthorizationInfo.cs
@@ -0,0 +1,37 @@
+
+namespace MediaBrowser.Controller.Net
+{
+ public class AuthorizationInfo
+ {
+ /// <summary>
+ /// Gets or sets the user identifier.
+ /// </summary>
+ /// <value>The user identifier.</value>
+ public string UserId { get; set; }
+ /// <summary>
+ /// Gets or sets the device identifier.
+ /// </summary>
+ /// <value>The device identifier.</value>
+ public string DeviceId { get; set; }
+ /// <summary>
+ /// Gets or sets the device.
+ /// </summary>
+ /// <value>The device.</value>
+ public string Device { get; set; }
+ /// <summary>
+ /// Gets or sets the client.
+ /// </summary>
+ /// <value>The client.</value>
+ public string Client { get; set; }
+ /// <summary>
+ /// Gets or sets the version.
+ /// </summary>
+ /// <value>The version.</value>
+ public string Version { get; set; }
+ /// <summary>
+ /// Gets or sets the token.
+ /// </summary>
+ /// <value>The token.</value>
+ public string Token { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Net/IAuthService.cs b/MediaBrowser.Controller/Net/IAuthService.cs
new file mode 100644
index 000000000..41859395b
--- /dev/null
+++ b/MediaBrowser.Controller/Net/IAuthService.cs
@@ -0,0 +1,9 @@
+using ServiceStack.Web;
+
+namespace MediaBrowser.Controller.Net
+{
+ public interface IAuthService
+ {
+ void Authenticate(IRequest request, IResponse response, object requestDto);
+ }
+}
diff --git a/MediaBrowser.Controller/Net/IAuthorizationContext.cs b/MediaBrowser.Controller/Net/IAuthorizationContext.cs
new file mode 100644
index 000000000..9cf562370
--- /dev/null
+++ b/MediaBrowser.Controller/Net/IAuthorizationContext.cs
@@ -0,0 +1,14 @@
+using ServiceStack.Web;
+
+namespace MediaBrowser.Controller.Net
+{
+ public interface IAuthorizationContext
+ {
+ /// <summary>
+ /// Gets the authorization information.
+ /// </summary>
+ /// <param name="requestContext">The request context.</param>
+ /// <returns>AuthorizationInfo.</returns>
+ AuthorizationInfo GetAuthorizationInfo(IRequest requestContext);
+ }
+}
diff --git a/MediaBrowser.Controller/Net/IHasAuthorization.cs b/MediaBrowser.Controller/Net/IHasAuthorization.cs
new file mode 100644
index 000000000..6fc70159d
--- /dev/null
+++ b/MediaBrowser.Controller/Net/IHasAuthorization.cs
@@ -0,0 +1,12 @@
+
+namespace MediaBrowser.Controller.Net
+{
+ public interface IHasAuthorization
+ {
+ /// <summary>
+ /// Gets or sets the authorization context.
+ /// </summary>
+ /// <value>The authorization context.</value>
+ IAuthorizationContext AuthorizationContext { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Net/IHasResultFactory.cs b/MediaBrowser.Controller/Net/IHasResultFactory.cs
index a87113d1f..3988b8d61 100644
--- a/MediaBrowser.Controller/Net/IHasResultFactory.cs
+++ b/MediaBrowser.Controller/Net/IHasResultFactory.cs
@@ -1,5 +1,4 @@
-using MediaBrowser.Common.Net;
-using ServiceStack.Web;
+using ServiceStack.Web;
namespace MediaBrowser.Controller.Net
{
diff --git a/MediaBrowser.Controller/Net/IHasSession.cs b/MediaBrowser.Controller/Net/IHasSession.cs
new file mode 100644
index 000000000..e762c1e84
--- /dev/null
+++ b/MediaBrowser.Controller/Net/IHasSession.cs
@@ -0,0 +1,12 @@
+
+namespace MediaBrowser.Controller.Net
+{
+ public interface IHasSession
+ {
+ /// <summary>
+ /// Gets or sets the session context.
+ /// </summary>
+ /// <value>The session context.</value>
+ ISessionContext SessionContext { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Net/IHttpResultFactory.cs b/MediaBrowser.Controller/Net/IHttpResultFactory.cs
index f7984c32c..526bf4be2 100644
--- a/MediaBrowser.Controller/Net/IHttpResultFactory.cs
+++ b/MediaBrowser.Controller/Net/IHttpResultFactory.cs
@@ -1,8 +1,8 @@
-using System;
+using ServiceStack.Web;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
-using ServiceStack.Web;
namespace MediaBrowser.Controller.Net
{
@@ -80,41 +80,38 @@ namespace MediaBrowser.Controller.Net
/// <param name="responseHeaders">The response headers.</param>
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
/// <returns>System.Object.</returns>
- object GetStaticResult(IRequest requestContext, Guid cacheKey, DateTime? lastDateModified,
- TimeSpan? cacheDuration, string contentType, Func<Task<Stream>> factoryFn,
- IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false);
+ object GetStaticResult(IRequest requestContext,
+ Guid cacheKey,
+ DateTime? lastDateModified,
+ TimeSpan? cacheDuration,
+ string contentType, Func<Task<Stream>> factoryFn,
+ IDictionary<string, string> responseHeaders = null,
+ bool isHeadRequest = false);
/// <summary>
- /// Gets the static file result.
+ /// Gets the static result.
/// </summary>
/// <param name="requestContext">The request context.</param>
- /// <param name="path">The path.</param>
- /// <param name="fileShare">The file share.</param>
- /// <param name="responseHeaders">The response headers.</param>
- /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
+ /// <param name="options">The options.</param>
/// <returns>System.Object.</returns>
- object GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false);
+ object GetStaticResult(IRequest requestContext, StaticResultOptions options);
/// <summary>
/// Gets the static file result.
/// </summary>
/// <param name="requestContext">The request context.</param>
/// <param name="path">The path.</param>
- /// <param name="contentType">Type of the content.</param>
/// <param name="fileShare">The file share.</param>
- /// <param name="responseHeaders">The response headers.</param>
- /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
/// <returns>System.Object.</returns>
- object GetStaticFileResult(IRequest requestContext, string path, string contentType, FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false);
-
+ object GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read);
+
/// <summary>
- /// Gets the optimized serialized result using cache.
+ /// Gets the static file result.
/// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="request">The request.</param>
- /// <param name="result">The result.</param>
+ /// <param name="requestContext">The request context.</param>
+ /// <param name="options">The options.</param>
/// <returns>System.Object.</returns>
- object GetOptimizedSerializedResultUsingCache<T>(IRequest request, T result)
- where T : class;
+ object GetStaticFileResult(IRequest requestContext,
+ StaticFileResultOptions options);
}
}
diff --git a/MediaBrowser.Controller/Net/IHttpServer.cs b/MediaBrowser.Controller/Net/IHttpServer.cs
index 20f07c74d..5b179d479 100644
--- a/MediaBrowser.Controller/Net/IHttpServer.cs
+++ b/MediaBrowser.Controller/Net/IHttpServer.cs
@@ -22,12 +22,6 @@ namespace MediaBrowser.Controller.Net
void StartServer(IEnumerable<string> urlPrefixes);
/// <summary>
- /// Gets a value indicating whether [supports web sockets].
- /// </summary>
- /// <value><c>true</c> if [supports web sockets]; otherwise, <c>false</c>.</value>
- bool SupportsWebSockets { get; }
-
- /// <summary>
/// Gets the local end points.
/// </summary>
/// <value>The local end points.</value>
@@ -39,12 +33,6 @@ namespace MediaBrowser.Controller.Net
void Stop();
/// <summary>
- /// Gets or sets a value indicating whether [enable HTTP request logging].
- /// </summary>
- /// <value><c>true</c> if [enable HTTP request logging]; otherwise, <c>false</c>.</value>
- bool EnableHttpRequestLogging { get; set; }
-
- /// <summary>
/// Occurs when [web socket connected].
/// </summary>
event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
diff --git a/MediaBrowser.Controller/Net/IRestfulService.cs b/MediaBrowser.Controller/Net/IRestfulService.cs
index f55012b73..7d07bb094 100644
--- a/MediaBrowser.Controller/Net/IRestfulService.cs
+++ b/MediaBrowser.Controller/Net/IRestfulService.cs
@@ -5,6 +5,7 @@ namespace MediaBrowser.Controller.Net
/// <summary>
/// Interface IRestfulService
/// </summary>
+ [Logged]
public interface IRestfulService : IService
{
}
diff --git a/MediaBrowser.Controller/Net/ISessionContext.cs b/MediaBrowser.Controller/Net/ISessionContext.cs
new file mode 100644
index 000000000..31ccd5373
--- /dev/null
+++ b/MediaBrowser.Controller/Net/ISessionContext.cs
@@ -0,0 +1,13 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Session;
+using ServiceStack.Web;
+
+namespace MediaBrowser.Controller.Net
+{
+ public interface ISessionContext
+ {
+ SessionInfo GetSession(IRequest requestContext);
+
+ User GetUser(IRequest requestContext);
+ }
+}
diff --git a/MediaBrowser.Controller/Net/LoggedAttribute.cs b/MediaBrowser.Controller/Net/LoggedAttribute.cs
new file mode 100644
index 000000000..6df72f7a7
--- /dev/null
+++ b/MediaBrowser.Controller/Net/LoggedAttribute.cs
@@ -0,0 +1,73 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Logging;
+using ServiceStack.Web;
+using System;
+
+namespace MediaBrowser.Controller.Net
+{
+ public class LoggedAttribute : Attribute, IHasRequestFilter
+ {
+ public ILogger Logger { get; set; }
+ public IUserManager UserManager { get; set; }
+ public ISessionManager SessionManager { get; set; }
+ public IAuthorizationContext AuthorizationContext { get; set; }
+
+ /// <summary>
+ /// The request filter is executed before the service.
+ /// </summary>
+ /// <param name="request">The http request wrapper</param>
+ /// <param name="response">The http response wrapper</param>
+ /// <param name="requestDto">The request DTO</param>
+ public void RequestFilter(IRequest request, IResponse response, object requestDto)
+ {
+ //This code is executed before the service
+ var auth = AuthorizationContext.GetAuthorizationInfo(request);
+
+ if (auth != null)
+ {
+ User user = null;
+
+ if (!string.IsNullOrWhiteSpace(auth.UserId))
+ {
+ var userId = auth.UserId;
+
+ user = UserManager.GetUserById(new Guid(userId));
+ }
+
+ string deviceId = auth.DeviceId;
+ string device = auth.Device;
+ string client = auth.Client;
+ string version = auth.Version;
+
+ if (!string.IsNullOrEmpty(client) && !string.IsNullOrEmpty(deviceId) && !string.IsNullOrEmpty(device) && !string.IsNullOrEmpty(version))
+ {
+ var remoteEndPoint = request.RemoteIp;
+
+ SessionManager.LogSessionActivity(client, version, deviceId, device, remoteEndPoint, user);
+ }
+ }
+ }
+
+ /// <summary>
+ /// A new shallow copy of this filter is used on every request.
+ /// </summary>
+ /// <returns>IHasRequestFilter.</returns>
+ public IHasRequestFilter Copy()
+ {
+ return this;
+ }
+
+ /// <summary>
+ /// Order in which Request Filters are executed.
+ /// &lt;0 Executed before global request filters
+ /// &gt;0 Executed after global request filters
+ /// </summary>
+ /// <value>The priority.</value>
+ public int Priority
+ {
+ get { return 0; }
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/Net/StaticResultOptions.cs b/MediaBrowser.Controller/Net/StaticResultOptions.cs
new file mode 100644
index 000000000..fde08c269
--- /dev/null
+++ b/MediaBrowser.Controller/Net/StaticResultOptions.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Net
+{
+ public class StaticResultOptions
+ {
+ public string ContentType { get; set; }
+ public TimeSpan? CacheDuration { get; set; }
+ public DateTime? DateLastModified { get; set; }
+ public Guid CacheKey { get; set; }
+
+ public Func<Task<Stream>> ContentFactory { get; set; }
+
+ public bool IsHeadRequest { get; set; }
+
+ public IDictionary<string, string> ResponseHeaders { get; set; }
+
+ public bool Throttle { get; set; }
+ public long ThrottleLimit { get; set; }
+ public long MinThrottlePosition { get; set; }
+
+ public StaticResultOptions()
+ {
+ ResponseHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ }
+ }
+
+ public class StaticFileResultOptions : StaticResultOptions
+ {
+ public string Path { get; set; }
+
+ public FileShare FileShare { get; set; }
+
+ public StaticFileResultOptions()
+ {
+ FileShare = FileShare.Read;
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/Notifications/INotificationsRepository.cs b/MediaBrowser.Controller/Notifications/INotificationsRepository.cs
index 87b89e79c..254e56e05 100644
--- a/MediaBrowser.Controller/Notifications/INotificationsRepository.cs
+++ b/MediaBrowser.Controller/Notifications/INotificationsRepository.cs
@@ -16,10 +16,6 @@ namespace MediaBrowser.Controller.Notifications
/// </summary>
event EventHandler<NotificationUpdateEventArgs> NotificationAdded;
/// <summary>
- /// Occurs when [notification updated].
- /// </summary>
- event EventHandler<NotificationUpdateEventArgs> NotificationUpdated;
- /// <summary>
/// Occurs when [notifications marked read].
/// </summary>
event EventHandler<NotificationReadEventArgs> NotificationsMarkedRead;
@@ -38,14 +34,6 @@ namespace MediaBrowser.Controller.Notifications
NotificationResult GetNotifications(NotificationQuery query);
/// <summary>
- /// Gets the notification.
- /// </summary>
- /// <param name="id">The id.</param>
- /// <param name="userId">The user id.</param>
- /// <returns>Notification.</returns>
- Notification GetNotification(string id, string userId);
-
- /// <summary>
/// Adds the notification.
/// </summary>
/// <param name="notification">The notification.</param>
diff --git a/MediaBrowser.Controller/Playlists/IPlaylistManager.cs b/MediaBrowser.Controller/Playlists/IPlaylistManager.cs
new file mode 100644
index 000000000..cbe0b97a4
--- /dev/null
+++ b/MediaBrowser.Controller/Playlists/IPlaylistManager.cs
@@ -0,0 +1,49 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Playlists;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Playlists
+{
+ public interface IPlaylistManager
+ {
+ /// <summary>
+ /// Gets the playlists.
+ /// </summary>
+ /// <param name="userId">The user identifier.</param>
+ /// <returns>IEnumerable&lt;Playlist&gt;.</returns>
+ IEnumerable<Playlist> GetPlaylists(string userId);
+
+ /// <summary>
+ /// Creates the playlist.
+ /// </summary>
+ /// <param name="options">The options.</param>
+ /// <returns>Task&lt;Playlist&gt;.</returns>
+ Task<PlaylistCreationResult> CreatePlaylist(PlaylistCreationRequest options);
+
+ /// <summary>
+ /// Adds to playlist.
+ /// </summary>
+ /// <param name="playlistId">The playlist identifier.</param>
+ /// <param name="itemIds">The item ids.</param>
+ /// <param name="userId">The user identifier.</param>
+ /// <returns>Task.</returns>
+ Task AddToPlaylist(string playlistId, IEnumerable<string> itemIds, string userId);
+
+ /// <summary>
+ /// Removes from playlist.
+ /// </summary>
+ /// <param name="playlistId">The playlist identifier.</param>
+ /// <param name="entryIds">The entry ids.</param>
+ /// <returns>Task.</returns>
+ Task RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds);
+
+ /// <summary>
+ /// Gets the playlists folder.
+ /// </summary>
+ /// <param name="userId">The user identifier.</param>
+ /// <returns>Folder.</returns>
+ Folder GetPlaylistsFolder(string userId);
+
+ }
+}
diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs
new file mode 100644
index 000000000..5da810a91
--- /dev/null
+++ b/MediaBrowser.Controller/Playlists/Playlist.cs
@@ -0,0 +1,157 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Querying;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+
+namespace MediaBrowser.Controller.Playlists
+{
+ public class Playlist : Folder
+ {
+ public string OwnerUserId { get; set; }
+
+ protected override bool FilterLinkedChildrenPerUser
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
+ {
+ return GetPlayableItems(user);
+ }
+
+ public override IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true)
+ {
+ return GetPlayableItems(user);
+ }
+
+ public IEnumerable<Tuple<LinkedChild, BaseItem>> GetManageableItems()
+ {
+ return GetLinkedChildrenInfos();
+ }
+
+ private IEnumerable<BaseItem> GetPlayableItems(User user)
+ {
+ return GetPlaylistItems(MediaType, base.GetChildren(user, true), user);
+ }
+
+ public static IEnumerable<BaseItem> GetPlaylistItems(string playlistMediaType, IEnumerable<BaseItem> inputItems, User user)
+ {
+ if (user != null)
+ {
+ inputItems = inputItems.Where(i => i.IsVisible(user));
+ }
+
+ return inputItems.SelectMany(i => GetPlaylistItems(i, user))
+ .Where(m => string.Equals(m.MediaType, playlistMediaType, StringComparison.OrdinalIgnoreCase));
+ }
+
+ private static IEnumerable<BaseItem> GetPlaylistItems(BaseItem i, User user)
+ {
+ var musicGenre = i as MusicGenre;
+ if (musicGenre != null)
+ {
+ var items = user == null
+ ? LibraryManager.RootFolder.GetRecursiveChildren()
+ : user.RootFolder.GetRecursiveChildren(user, true);
+
+ var songs = items
+ .OfType<Audio>()
+ .Where(a => a.Genres.Contains(musicGenre.Name, StringComparer.OrdinalIgnoreCase));
+
+ return LibraryManager.Sort(songs, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending);
+ }
+
+ var musicArtist = i as MusicArtist;
+ if (musicArtist != null)
+ {
+ var items = user == null
+ ? LibraryManager.RootFolder.GetRecursiveChildren()
+ : user.RootFolder.GetRecursiveChildren(user, true);
+
+ var songs = items
+ .OfType<Audio>()
+ .Where(a => a.HasArtist(musicArtist.Name));
+
+ return LibraryManager.Sort(songs, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending);
+ }
+
+ // Grab these explicitly to avoid the sorting that will happen below
+ var collection = i as BoxSet;
+ if (collection != null)
+ {
+ var items = user == null
+ ? collection.Children
+ : collection.GetChildren(user, true);
+
+ return items
+ .Where(m => !m.IsFolder);
+ }
+
+ // Grab these explicitly to avoid the sorting that will happen below
+ var season = i as Season;
+ if (season != null)
+ {
+ var items = user == null
+ ? season.Children
+ : season.GetChildren(user, true);
+
+ return items
+ .Where(m => !m.IsFolder);
+ }
+
+ var folder = i as Folder;
+
+ if (folder != null)
+ {
+ var items = user == null
+ ? folder.GetRecursiveChildren()
+ : folder.GetRecursiveChildren(user, true);
+
+ items = items
+ .Where(m => !m.IsFolder);
+
+ return LibraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending);
+ }
+
+ return new[] { i };
+ }
+
+ [IgnoreDataMember]
+ public override bool IsPreSorted
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public string PlaylistMediaType { get; set; }
+
+ public override string MediaType
+ {
+ get
+ {
+ return PlaylistMediaType;
+ }
+ }
+
+ public void SetMediaType(string value)
+ {
+ PlaylistMediaType = value;
+ }
+
+ public override bool IsVisible(User user)
+ {
+ return base.IsVisible(user) && string.Equals(user.Id.ToString("N"), OwnerUserId);
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
index 3cb90d360..06d738297 100644
--- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
+++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
@@ -1283,6 +1283,67 @@ namespace MediaBrowser.Controller.Providers
return new[] { personInfo };
}
+ protected LinkedChild GetLinkedChild(XmlReader reader)
+ {
+ reader.MoveToContent();
+
+ var linkedItem = new LinkedChild
+ {
+ Type = LinkedChildType.Manual
+ };
+
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "Name":
+ {
+ linkedItem.ItemName = reader.ReadElementContentAsString();
+ break;
+ }
+
+ case "Path":
+ {
+ linkedItem.Path = reader.ReadElementContentAsString();
+ break;
+ }
+
+ case "Type":
+ {
+ linkedItem.ItemType = reader.ReadElementContentAsString();
+ break;
+ }
+
+ case "Year":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int rval;
+
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
+ {
+ linkedItem.ItemYear = rval;
+ }
+ }
+
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+
+ return string.IsNullOrWhiteSpace(linkedItem.ItemName) || string.IsNullOrWhiteSpace(linkedItem.ItemType) ? null : linkedItem;
+ }
+
+
/// <summary>
/// Used to split names of comma or pipe delimeted genres and people
/// </summary>
diff --git a/MediaBrowser.Controller/Providers/IMetadataProvider.cs b/MediaBrowser.Controller/Providers/IMetadataProvider.cs
index d33b2c9eb..52cd6fcea 100644
--- a/MediaBrowser.Controller/Providers/IMetadataProvider.cs
+++ b/MediaBrowser.Controller/Providers/IMetadataProvider.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities;
+using System.Collections.Generic;
namespace MediaBrowser.Controller.Providers
{
diff --git a/MediaBrowser.Controller/Providers/ItemIdentities.cs b/MediaBrowser.Controller/Providers/ItemIdentities.cs
index 93d468af0..8d24f6c1f 100644
--- a/MediaBrowser.Controller/Providers/ItemIdentities.cs
+++ b/MediaBrowser.Controller/Providers/ItemIdentities.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
+using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
index 692d6db90..dd07979d3 100644
--- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
+++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
@@ -1,6 +1,7 @@
-using System;
+using MediaBrowser.Model.Entities;
+using System;
using System.Collections.Generic;
-using MediaBrowser.Model.Entities;
+using System.Linq;
namespace MediaBrowser.Controller.Providers
{
@@ -18,6 +19,23 @@ namespace MediaBrowser.Controller.Providers
/// </summary>
[Obsolete]
public bool ForceSave { get; set; }
+
+ public MetadataRefreshOptions()
+ {
+ MetadataRefreshMode = MetadataRefreshMode.Default;
+ }
+
+ public MetadataRefreshOptions(MetadataRefreshOptions copy)
+ {
+ MetadataRefreshMode = copy.MetadataRefreshMode;
+ ForceSave = copy.ForceSave;
+ ReplaceAllMetadata = copy.ReplaceAllMetadata;
+
+ ImageRefreshMode = copy.ImageRefreshMode;
+ DirectoryService = copy.DirectoryService;
+ ReplaceAllImages = copy.ReplaceAllImages;
+ ReplaceImages = copy.ReplaceImages.ToList();
+ }
}
public class ImageRefreshOptions
@@ -38,48 +56,54 @@ namespace MediaBrowser.Controller.Providers
public bool IsReplacingImage(ImageType type)
{
- return ReplaceAllImages || ReplaceImages.Contains(type);
+ return ImageRefreshMode == ImageRefreshMode.FullRefresh &&
+ (ReplaceAllImages || ReplaceImages.Contains(type));
}
}
public enum MetadataRefreshMode
{
/// <summary>
- /// Providers will be executed based on default rules
+ /// The none
/// </summary>
- EnsureMetadata = 0,
+ None = 0,
/// <summary>
- /// No providers will be executed
+ /// The validation only
/// </summary>
- None = 1,
+ ValidationOnly = 1,
/// <summary>
- /// All providers will be executed to search for new metadata
+ /// Providers will be executed based on default rules
/// </summary>
- FullRefresh = 2,
+ Default = 2,
/// <summary>
- /// The validation only
+ /// All providers will be executed to search for new metadata
/// </summary>
- ValidationOnly = 3
+ FullRefresh = 3
}
public enum ImageRefreshMode
{
/// <summary>
+ /// The none
+ /// </summary>
+ None = 0,
+
+ /// <summary>
/// The default
/// </summary>
- Default = 0,
+ Default = 1,
/// <summary>
/// Existing images will be validated
/// </summary>
- ValidationOnly = 1,
+ ValidationOnly = 2,
/// <summary>
/// All providers will be executed to search for new metadata
/// </summary>
- FullRefresh = 2
+ FullRefresh = 3
}
}
diff --git a/MediaBrowser.Controller/Providers/NameParser.cs b/MediaBrowser.Controller/Providers/NameParser.cs
index 726f0e60e..cdd0974ea 100644
--- a/MediaBrowser.Controller/Providers/NameParser.cs
+++ b/MediaBrowser.Controller/Providers/NameParser.cs
@@ -5,13 +5,13 @@ namespace MediaBrowser.Controller.Providers
{
public static class NameParser
{
- static readonly Regex[] NameMatches = new[] {
+ static readonly Regex[] NameMatches =
+ {
new Regex(@"(?<name>.*)\((?<year>\d{4})\)"), // matches "My Movie (2001)" and gives us the name and the year
new Regex(@"(?<name>.*)(\.(?<year>\d{4})(\.|$)).*$"),
new Regex(@"(?<name>.*)") // last resort matches the whole string as the name
};
-
/// <summary>
/// Parses the name.
/// </summary>
diff --git a/MediaBrowser.Controller/RelatedMedia/IRelatedMediaProvider.cs b/MediaBrowser.Controller/RelatedMedia/IRelatedMediaProvider.cs
new file mode 100644
index 000000000..1cf5742b2
--- /dev/null
+++ b/MediaBrowser.Controller/RelatedMedia/IRelatedMediaProvider.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.RelatedMedia
+{
+ public interface IRelatedMediaProvider
+ {
+ /// <summary>
+ /// Gets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ string Name { get; }
+ }
+}
diff --git a/MediaBrowser.Controller/Resolvers/BaseVideoResolver.cs b/MediaBrowser.Controller/Resolvers/BaseVideoResolver.cs
index 06bee2ad1..038d8d48b 100644
--- a/MediaBrowser.Controller/Resolvers/BaseVideoResolver.cs
+++ b/MediaBrowser.Controller/Resolvers/BaseVideoResolver.cs
@@ -108,6 +108,25 @@ namespace MediaBrowser.Controller.Resolvers
{
item.Video3DFormat = Video3DFormat.HalfTopAndBottom;
}
+ else
+ {
+ // Support Xbmc conventions:
+ // http://wiki.xbmc.org/index.php?title=3D
+ var name = Path.GetFileName(item.Path);
+
+ name = name.Replace('.', ' ').Replace('_', ' ').Replace('-', ' ');
+
+ if (name.IndexOf(" 3d hsbs ", StringComparison.OrdinalIgnoreCase) != -1 ||
+ name.IndexOf(" 3d sbs ", StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ item.Video3DFormat = Video3DFormat.HalfSideBySide;
+ }
+ else if (name.IndexOf(" 3d htab ", StringComparison.OrdinalIgnoreCase) != -1 ||
+ name.IndexOf(" 3d tab ", StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ item.Video3DFormat = Video3DFormat.HalfTopAndBottom;
+ }
+ }
}
}
}
diff --git a/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs b/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs
index 42178c44c..7c68448e5 100644
--- a/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs
+++ b/MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using System.Globalization;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using System;
@@ -15,6 +16,21 @@ namespace MediaBrowser.Controller.Resolvers
public static class EntityResolutionHelper
{
/// <summary>
+ /// Any folder named in this list will be ignored - can be added to at runtime for extensibility
+ /// </summary>
+ public static readonly List<string> IgnoreFolders = new List<string>
+ {
+ "metadata",
+ "ps3_update",
+ "ps3_vprm",
+ "extrafanart",
+ "extrathumbs",
+ ".actors",
+ ".wd_tv"
+
+ };
+
+ /// <summary>
/// Any extension in this list is considered a video file - can be added to at runtime for extensibility
/// </summary>
public static List<string> VideoFileExtensions = new List<string>
@@ -174,6 +190,44 @@ namespace MediaBrowser.Controller.Resolvers
}
/// <summary>
+ /// Determines whether [is multi disc album folder] [the specified path].
+ /// </summary>
+ /// <param name="path">The path.</param>
+ /// <returns><c>true</c> if [is multi disc album folder] [the specified path]; otherwise, <c>false</c>.</returns>
+ public static bool IsMultiDiscAlbumFolder(string path)
+ {
+ var filename = Path.GetFileName(path);
+
+ if (string.IsNullOrWhiteSpace(filename))
+ {
+ return false;
+ }
+
+ // Normalize
+ // Remove whitespace
+ filename = filename.Replace("-", string.Empty);
+ filename = Regex.Replace(filename, @"\s+", "");
+
+ var prefixes = new[] { "disc", "cd", "disk" };
+
+ foreach (var prefix in prefixes)
+ {
+ if (filename.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ var tmp = filename.Substring(prefix.Length);
+
+ int val;
+ if (int.TryParse(tmp, NumberStyles.Any, CultureInfo.InvariantCulture, out val))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
/// Ensures DateCreated and DateModified have values
/// </summary>
/// <param name="fileSystem">The file system.</param>
diff --git a/MediaBrowser.Controller/Security/AuthenticationInfo.cs b/MediaBrowser.Controller/Security/AuthenticationInfo.cs
new file mode 100644
index 000000000..dd5eec1f9
--- /dev/null
+++ b/MediaBrowser.Controller/Security/AuthenticationInfo.cs
@@ -0,0 +1,61 @@
+using System;
+
+namespace MediaBrowser.Controller.Security
+{
+ public class AuthenticationInfo
+ {
+ /// <summary>
+ /// Gets or sets the identifier.
+ /// </summary>
+ /// <value>The identifier.</value>
+ public string Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the access token.
+ /// </summary>
+ /// <value>The access token.</value>
+ public string AccessToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the device identifier.
+ /// </summary>
+ /// <value>The device identifier.</value>
+ public string DeviceId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the application.
+ /// </summary>
+ /// <value>The name of the application.</value>
+ public string AppName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the device.
+ /// </summary>
+ /// <value>The name of the device.</value>
+ public string DeviceName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the user identifier.
+ /// </summary>
+ /// <value>The user identifier.</value>
+ public string UserId { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is active.
+ /// </summary>
+ /// <value><c>true</c> if this instance is active; otherwise, <c>false</c>.</value>
+ public bool IsActive { get; set; }
+
+ /// <summary>
+ /// Gets or sets the date created.
+ /// </summary>
+ /// <value>The date created.</value>
+ public DateTime DateCreated { get; set; }
+
+ /// <summary>
+ /// Gets or sets the date revoked.
+ /// </summary>
+ /// <value>The date revoked.</value>
+ public DateTime? DateRevoked { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Security/AuthenticationInfoQuery.cs b/MediaBrowser.Controller/Security/AuthenticationInfoQuery.cs
new file mode 100644
index 000000000..3234b0350
--- /dev/null
+++ b/MediaBrowser.Controller/Security/AuthenticationInfoQuery.cs
@@ -0,0 +1,42 @@
+
+namespace MediaBrowser.Controller.Security
+{
+ public class AuthenticationInfoQuery
+ {
+ /// <summary>
+ /// Gets or sets the device identifier.
+ /// </summary>
+ /// <value>The device identifier.</value>
+ public string DeviceId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the user identifier.
+ /// </summary>
+ /// <value>The user identifier.</value>
+ public string UserId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the access token.
+ /// </summary>
+ /// <value>The access token.</value>
+ public string AccessToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is active.
+ /// </summary>
+ /// <value><c>null</c> if [is active] contains no value, <c>true</c> if [is active]; otherwise, <c>false</c>.</value>
+ public bool? IsActive { get; set; }
+
+ /// <summary>
+ /// Gets or sets the start index.
+ /// </summary>
+ /// <value>The start index.</value>
+ public int? StartIndex { get; set; }
+
+ /// <summary>
+ /// Gets or sets the limit.
+ /// </summary>
+ /// <value>The limit.</value>
+ public int? Limit { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Security/IAuthenticationRepository.cs b/MediaBrowser.Controller/Security/IAuthenticationRepository.cs
new file mode 100644
index 000000000..219b07028
--- /dev/null
+++ b/MediaBrowser.Controller/Security/IAuthenticationRepository.cs
@@ -0,0 +1,39 @@
+using MediaBrowser.Model.Querying;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Security
+{
+ public interface IAuthenticationRepository
+ {
+ /// <summary>
+ /// Creates the specified information.
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task Create(AuthenticationInfo info, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Updates the specified information.
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task Update(AuthenticationInfo info, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the specified query.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <returns>QueryResult{AuthenticationInfo}.</returns>
+ QueryResult<AuthenticationInfo> Get(AuthenticationInfoQuery query);
+
+ /// <summary>
+ /// Gets the specified identifier.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <returns>AuthenticationInfo.</returns>
+ AuthenticationInfo Get(string id);
+ }
+}
diff --git a/MediaBrowser.Controller/Session/AuthenticationRequest.cs b/MediaBrowser.Controller/Session/AuthenticationRequest.cs
new file mode 100644
index 000000000..38871e814
--- /dev/null
+++ b/MediaBrowser.Controller/Session/AuthenticationRequest.cs
@@ -0,0 +1,14 @@
+
+namespace MediaBrowser.Controller.Session
+{
+ public class AuthenticationRequest
+ {
+ public string Username { get; set; }
+ public string Password { get; set; }
+ public string App { get; set; }
+ public string AppVersion { get; set; }
+ public string DeviceId { get; set; }
+ public string DeviceName { get; set; }
+ public string RemoteEndPoint { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs
index 8c2ece131..f715ce770 100644
--- a/MediaBrowser.Controller/Session/ISessionManager.cs
+++ b/MediaBrowser.Controller/Session/ISessionManager.cs
@@ -1,7 +1,9 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Session;
+using MediaBrowser.Model.Users;
using System;
using System.Collections.Generic;
using System.Threading;
@@ -45,6 +47,16 @@ namespace MediaBrowser.Controller.Session
/// Occurs when [capabilities changed].
/// </summary>
event EventHandler<SessionEventArgs> CapabilitiesChanged;
+
+ /// <summary>
+ /// Occurs when [authentication failed].
+ /// </summary>
+ event EventHandler<GenericEventArgs<AuthenticationRequest>> AuthenticationFailed;
+
+ /// <summary>
+ /// Occurs when [authentication succeeded].
+ /// </summary>
+ event EventHandler<GenericEventArgs<AuthenticationRequest>> AuthenticationSucceeded;
/// <summary>
/// Gets the sessions.
@@ -206,19 +218,14 @@ namespace MediaBrowser.Controller.Session
/// <param name="sessionId">The session identifier.</param>
/// <param name="item">The item.</param>
void ReportNowViewingItem(string sessionId, BaseItemInfo item);
-
+
/// <summary>
/// Authenticates the new session.
/// </summary>
- /// <param name="user">The user.</param>
- /// <param name="password">The password.</param>
- /// <param name="clientType">Type of the client.</param>
- /// <param name="appVersion">The application version.</param>
- /// <param name="deviceId">The device identifier.</param>
- /// <param name="deviceName">Name of the device.</param>
- /// <param name="remoteEndPoint">The remote end point.</param>
+ /// <param name="request">The request.</param>
+ /// <param name="isLocal">if set to <c>true</c> [is local].</param>
/// <returns>Task{SessionInfo}.</returns>
- Task<SessionInfo> AuthenticateNewSession(User user, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint);
+ Task<AuthenticationResult> AuthenticateNewSession(AuthenticationRequest request, bool isLocal);
/// <summary>
/// Reports the capabilities.
@@ -239,5 +246,41 @@ namespace MediaBrowser.Controller.Session
/// </summary>
/// <param name="deviceId">The device identifier.</param>
void ClearTranscodingInfo(string deviceId);
+
+ /// <summary>
+ /// Gets the session.
+ /// </summary>
+ /// <param name="deviceId">The device identifier.</param>
+ /// <param name="client">The client.</param>
+ /// <param name="version">The version.</param>
+ /// <returns>SessionInfo.</returns>
+ SessionInfo GetSession(string deviceId, string client, string version);
+
+ /// <summary>
+ /// Validates the security token.
+ /// </summary>
+ /// <param name="accessToken">The access token.</param>
+ void ValidateSecurityToken(string accessToken);
+
+ /// <summary>
+ /// Logouts the specified access token.
+ /// </summary>
+ /// <param name="accessToken">The access token.</param>
+ /// <returns>Task.</returns>
+ Task Logout(string accessToken);
+
+ /// <summary>
+ /// Revokes the user tokens.
+ /// </summary>
+ /// <param name="userId">The user identifier.</param>
+ /// <returns>Task.</returns>
+ Task RevokeUserTokens(string userId);
+
+ /// <summary>
+ /// Revokes the token.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <returns>Task.</returns>
+ Task RevokeToken(string id);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs
index 6f27f6cb2..53a8d5a7c 100644
--- a/MediaBrowser.Controller/Session/SessionInfo.cs
+++ b/MediaBrowser.Controller/Session/SessionInfo.cs
@@ -123,7 +123,7 @@ namespace MediaBrowser.Controller.Session
public List<string> SupportedCommands { get; set; }
public TranscodingInfo TranscodingInfo { get; set; }
-
+
/// <summary>
/// Gets a value indicating whether this instance is active.
/// </summary>
@@ -156,7 +156,7 @@ namespace MediaBrowser.Controller.Session
public bool ContainsUser(Guid userId)
{
- return (UserId ?? Guid.Empty) == UserId || AdditionalUsers.Any(i => userId == new Guid(i.UserId));
+ return (UserId ?? Guid.Empty) == userId || AdditionalUsers.Any(i => userId == new Guid(i.UserId));
}
}
}
diff --git a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs
index 1d66d1505..0c814c0d4 100644
--- a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs
+++ b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Providers;
+using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -9,6 +10,16 @@ namespace MediaBrowser.Controller.Subtitles
public interface ISubtitleManager
{
/// <summary>
+ /// Occurs when [subtitle download failure].
+ /// </summary>
+ event EventHandler<SubtitleDownloadFailureEventArgs> SubtitleDownloadFailure;
+
+ /// <summary>
+ /// Occurs when [subtitles downloaded].
+ /// </summary>
+ event EventHandler<SubtitleDownloadEventArgs> SubtitlesDownloaded;
+
+ /// <summary>
/// Adds the parts.
/// </summary>
/// <param name="subtitleProviders">The subtitle providers.</param>
@@ -31,7 +42,7 @@ namespace MediaBrowser.Controller.Subtitles
/// <param name="request">The request.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{RemoteSubtitleInfo}}.</returns>
- Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(SubtitleSearchRequest request,
+ Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(SubtitleSearchRequest request,
CancellationToken cancellationToken);
/// <summary>
@@ -41,8 +52,8 @@ namespace MediaBrowser.Controller.Subtitles
/// <param name="subtitleId">The subtitle identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task DownloadSubtitles(Video video,
- string subtitleId,
+ Task DownloadSubtitles(Video video,
+ string subtitleId,
CancellationToken cancellationToken);
/// <summary>
diff --git a/MediaBrowser.Controller/Subtitles/SubtitleDownloadEventArgs.cs b/MediaBrowser.Controller/Subtitles/SubtitleDownloadEventArgs.cs
new file mode 100644
index 000000000..1d204f2cb
--- /dev/null
+++ b/MediaBrowser.Controller/Subtitles/SubtitleDownloadEventArgs.cs
@@ -0,0 +1,27 @@
+using System;
+using MediaBrowser.Controller.Entities;
+
+namespace MediaBrowser.Controller.Subtitles
+{
+ public class SubtitleDownloadEventArgs
+ {
+ public BaseItem Item { get; set; }
+
+ public string Format { get; set; }
+
+ public string Language { get; set; }
+
+ public bool IsForced { get; set; }
+
+ public string Provider { get; set; }
+ }
+
+ public class SubtitleDownloadFailureEventArgs
+ {
+ public BaseItem Item { get; set; }
+
+ public string Provider { get; set; }
+
+ public Exception Exception { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/Sync/ICloudSyncProvider.cs b/MediaBrowser.Controller/Sync/ICloudSyncProvider.cs
new file mode 100644
index 000000000..f93360c64
--- /dev/null
+++ b/MediaBrowser.Controller/Sync/ICloudSyncProvider.cs
@@ -0,0 +1,12 @@
+
+namespace MediaBrowser.Controller.Sync
+{
+ public interface ICloudSyncProvider
+ {
+ /// <summary>
+ /// Gets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ string Name { get; }
+ }
+}
diff --git a/MediaBrowser.Controller/Sync/ISyncManager.cs b/MediaBrowser.Controller/Sync/ISyncManager.cs
new file mode 100644
index 000000000..1d5ab7d3e
--- /dev/null
+++ b/MediaBrowser.Controller/Sync/ISyncManager.cs
@@ -0,0 +1,55 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Querying;
+using MediaBrowser.Model.Sync;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Sync
+{
+ public interface ISyncManager
+ {
+ /// <summary>
+ /// Creates the job.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ /// <returns>Task.</returns>
+ Task<SyncJobCreationResult> CreateJob(SyncJobRequest request);
+
+ /// <summary>
+ /// Gets the jobs.
+ /// </summary>
+ /// <returns>QueryResult&lt;SyncJob&gt;.</returns>
+ QueryResult<SyncJob> GetJobs(SyncJobQuery query);
+
+ /// <summary>
+ /// Gets the job.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <returns>SyncJob.</returns>
+ SyncJob GetJob(string id);
+
+ /// <summary>
+ /// Cancels the job.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <returns>Task.</returns>
+ Task CancelJob(string id);
+
+ /// <summary>
+ /// Adds the parts.
+ /// </summary>
+ void AddParts(IEnumerable<ISyncProvider> providers);
+
+ /// <summary>
+ /// Gets the synchronize targets.
+ /// </summary>
+ IEnumerable<SyncTarget> GetSyncTargets(string userId);
+
+ /// <summary>
+ /// Supportses the synchronize.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
+ bool SupportsSync(BaseItem item);
+ }
+}
diff --git a/MediaBrowser.Controller/Sync/ISyncProvider.cs b/MediaBrowser.Controller/Sync/ISyncProvider.cs
new file mode 100644
index 000000000..89f61b80e
--- /dev/null
+++ b/MediaBrowser.Controller/Sync/ISyncProvider.cs
@@ -0,0 +1,28 @@
+using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Sync;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Sync
+{
+ public interface ISyncProvider
+ {
+ /// <summary>
+ /// Gets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ string Name { get; }
+
+ /// <summary>
+ /// Gets the synchronize targets.
+ /// </summary>
+ /// <returns>IEnumerable&lt;SyncTarget&gt;.</returns>
+ IEnumerable<SyncTarget> GetSyncTargets();
+
+ /// <summary>
+ /// Gets the device profile.
+ /// </summary>
+ /// <param name="target">The target.</param>
+ /// <returns>DeviceProfile.</returns>
+ DeviceProfile GetDeviceProfile(SyncTarget target);
+ }
+}
diff --git a/MediaBrowser.Controller/Sync/ISyncRepository.cs b/MediaBrowser.Controller/Sync/ISyncRepository.cs
new file mode 100644
index 000000000..9cce69bdc
--- /dev/null
+++ b/MediaBrowser.Controller/Sync/ISyncRepository.cs
@@ -0,0 +1,58 @@
+using MediaBrowser.Model.Querying;
+using MediaBrowser.Model.Sync;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Sync
+{
+ public interface ISyncRepository
+ {
+ /// <summary>
+ /// Gets the job.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <returns>SyncJob.</returns>
+ SyncJob GetJob(string id);
+
+ /// <summary>
+ /// Creates the specified job.
+ /// </summary>
+ /// <param name="job">The job.</param>
+ /// <returns>Task.</returns>
+ Task Create(SyncJob job);
+
+ /// <summary>
+ /// Updates the specified job.
+ /// </summary>
+ /// <param name="job">The job.</param>
+ /// <returns>Task.</returns>
+ Task Update(SyncJob job);
+
+ /// <summary>
+ /// Gets the jobs.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <returns>QueryResult&lt;SyncJob&gt;.</returns>
+ QueryResult<SyncJob> GetJobs(SyncJobQuery query);
+
+ /// <summary>
+ /// Gets the job item.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <returns>SyncJobItem.</returns>
+ SyncJobItem GetJobItem(string id);
+
+ /// <summary>
+ /// Creates the specified job item.
+ /// </summary>
+ /// <param name="jobItem">The job item.</param>
+ /// <returns>Task.</returns>
+ Task Create(SyncJobItem jobItem);
+
+ /// <summary>
+ /// Updates the specified job item.
+ /// </summary>
+ /// <param name="jobItem">The job item.</param>
+ /// <returns>Task.</returns>
+ Task Update(SyncJobItem jobItem);
+ }
+}
diff --git a/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs
new file mode 100644
index 000000000..78db68f63
--- /dev/null
+++ b/MediaBrowser.Dlna/Channels/DlnaChannelFactory.cs
@@ -0,0 +1,341 @@
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Dlna.ContentDirectory;
+using MediaBrowser.Dlna.PlayTo;
+using MediaBrowser.Dlna.Ssdp;
+using MediaBrowser.Model.Channels;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Dlna.Channels
+{
+ public class DlnaChannelFactory : IChannelFactory, IDisposable
+ {
+ private readonly IServerConfigurationManager _config;
+ private readonly ILogger _logger;
+ private readonly IHttpClient _httpClient;
+
+ private DeviceDiscovery _deviceDiscovery;
+
+ private readonly SemaphoreSlim _syncLock = new SemaphoreSlim(1, 1);
+ private List<Device> _servers = new List<Device>();
+
+ public static DlnaChannelFactory Instance;
+
+ private Func<List<string>> _localServersLookup;
+
+ public DlnaChannelFactory(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger)
+ {
+ _config = config;
+ _httpClient = httpClient;
+ _logger = logger;
+ Instance = this;
+ }
+
+ internal void Start(DeviceDiscovery deviceDiscovery, Func<List<string>> localServersLookup)
+ {
+ _localServersLookup = localServersLookup;
+
+ _deviceDiscovery = deviceDiscovery;
+ //deviceDiscovery.DeviceDiscovered += deviceDiscovery_DeviceDiscovered;
+ deviceDiscovery.DeviceLeft += deviceDiscovery_DeviceLeft;
+ }
+
+ async void deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e)
+ {
+ string usn;
+ if (!e.Headers.TryGetValue("USN", out usn)) usn = string.Empty;
+
+ string nt;
+ if (!e.Headers.TryGetValue("NT", out nt)) nt = string.Empty;
+
+ string location;
+ if (!e.Headers.TryGetValue("Location", out location)) location = string.Empty;
+
+ if (!IsValid(nt, usn))
+ {
+ return;
+ }
+
+ if (_localServersLookup != null)
+ {
+ if (_localServersLookup().Any(i => usn.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1))
+ {
+ // Don't add the local Dlna server to this
+ return;
+ }
+ }
+
+ if (GetExistingServers(usn).Any())
+ {
+ return;
+ }
+
+ await _syncLock.WaitAsync().ConfigureAwait(false);
+
+ try
+ {
+ if (GetExistingServers(usn).Any())
+ {
+ return;
+ }
+
+ var device = await Device.CreateuPnpDeviceAsync(new Uri(location), _httpClient, _config, _logger)
+ .ConfigureAwait(false);
+
+ if (!_servers.Any(i => string.Equals(i.Properties.UUID, device.Properties.UUID, StringComparison.OrdinalIgnoreCase)))
+ {
+ _servers.Add(device);
+ }
+ }
+ catch (Exception ex)
+ {
+
+ }
+ finally
+ {
+ _syncLock.Release();
+ }
+ }
+
+ async void deviceDiscovery_DeviceLeft(object sender, SsdpMessageEventArgs e)
+ {
+ string usn;
+ if (!e.Headers.TryGetValue("USN", out usn)) usn = String.Empty;
+
+ string nt;
+ if (!e.Headers.TryGetValue("NT", out nt)) nt = String.Empty;
+
+ if (!IsValid(nt, usn))
+ {
+ return;
+ }
+
+ if (!GetExistingServers(usn).Any())
+ {
+ return;
+ }
+
+ await _syncLock.WaitAsync().ConfigureAwait(false);
+
+ try
+ {
+ var list = _servers.ToList();
+
+ foreach (var device in GetExistingServers(usn).ToList())
+ {
+ list.Remove(device);
+ }
+
+ _servers = list;
+ }
+ finally
+ {
+ _syncLock.Release();
+ }
+ }
+
+ private bool IsValid(string nt, string usn)
+ {
+ // It has to report that it's a media renderer
+ if (usn.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 &&
+ nt.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 &&
+ usn.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1 &&
+ nt.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private IEnumerable<Device> GetExistingServers(string usn)
+ {
+ return _servers
+ .Where(i => usn.IndexOf(i.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1);
+ }
+
+ public IEnumerable<IChannel> GetChannels()
+ {
+ //if (_servers.Count > 0)
+ //{
+ // var service = _servers[0].Properties.Services
+ // .FirstOrDefault(i => string.Equals(i.ServiceType, "urn:schemas-upnp-org:service:ContentDirectory:1", StringComparison.OrdinalIgnoreCase));
+
+ // var controlUrl = service == null ? null : (_servers[0].Properties.BaseUrl.TrimEnd('/') + "/" + service.ControlUrl.TrimStart('/'));
+
+ // if (!string.IsNullOrEmpty(controlUrl))
+ // {
+ // return new List<IChannel>
+ // {
+ // new ServerChannel(_servers.ToList(), _httpClient, _logger, controlUrl)
+ // };
+ // }
+ //}
+
+ return new List<IChannel>();
+ }
+
+ public void Dispose()
+ {
+ if (_deviceDiscovery != null)
+ {
+ _deviceDiscovery.DeviceDiscovered -= deviceDiscovery_DeviceDiscovered;
+ _deviceDiscovery.DeviceLeft -= deviceDiscovery_DeviceLeft;
+ }
+ }
+ }
+
+ public class ServerChannel : IChannel, IFactoryChannel
+ {
+ private readonly IHttpClient _httpClient;
+ private readonly ILogger _logger;
+ public string ControlUrl { get; set; }
+ public List<Device> Servers { get; set; }
+
+ public ServerChannel(IHttpClient httpClient, ILogger logger)
+ {
+ _httpClient = httpClient;
+ _logger = logger;
+ Servers = new List<Device>();
+ }
+
+ public string Name
+ {
+ get { return "Devices"; }
+ }
+
+ public string Description
+ {
+ get { return string.Empty; }
+ }
+
+ public string DataVersion
+ {
+ get { return DateTime.UtcNow.Ticks.ToString(); }
+ }
+
+ public string HomePageUrl
+ {
+ get { return string.Empty; }
+ }
+
+ public ChannelParentalRating ParentalRating
+ {
+ get { return ChannelParentalRating.GeneralAudience; }
+ }
+
+ public InternalChannelFeatures GetChannelFeatures()
+ {
+ return new InternalChannelFeatures
+ {
+ ContentTypes = new List<ChannelMediaContentType>
+ {
+ ChannelMediaContentType.Song,
+ ChannelMediaContentType.Clip
+ },
+
+ MediaTypes = new List<ChannelMediaType>
+ {
+ ChannelMediaType.Audio,
+ ChannelMediaType.Video,
+ ChannelMediaType.Photo
+ }
+ };
+ }
+
+ public bool IsEnabledFor(string userId)
+ {
+ return true;
+ }
+
+ public async Task<ChannelItemResult> GetChannelItems(InternalChannelItemQuery query, CancellationToken cancellationToken)
+ {
+ IEnumerable<ChannelItemInfo> items;
+
+ if (string.IsNullOrWhiteSpace(query.FolderId))
+ {
+ items = Servers.Select(i => new ChannelItemInfo
+ {
+ FolderType = ChannelFolderType.Container,
+ Id = GetServerId(i),
+ Name = i.Properties.Name,
+ Overview = i.Properties.ModelDescription,
+ Type = ChannelItemType.Folder
+ });
+ }
+ else
+ {
+ var idParts = query.FolderId.Split('|');
+ var folderId = idParts.Length == 2 ? idParts[1] : null;
+
+ var result = await new ContentDirectoryBrowser(_httpClient, _logger).Browse(new ContentDirectoryBrowseRequest
+ {
+ Limit = query.Limit,
+ StartIndex = query.StartIndex,
+ ParentId = folderId,
+ ContentDirectoryUrl = ControlUrl
+
+ }, cancellationToken).ConfigureAwait(false);
+
+ items = result.Items.ToList();
+ }
+
+ var list = items.ToList();
+ var count = list.Count;
+
+ list = ApplyPaging(list, query).ToList();
+
+ return new ChannelItemResult
+ {
+ Items = list,
+ TotalRecordCount = count
+ };
+ }
+
+ private string GetServerId(Device device)
+ {
+ return device.Properties.UUID.GetMD5().ToString("N");
+ }
+
+ private IEnumerable<T> ApplyPaging<T>(IEnumerable<T> items, InternalChannelItemQuery query)
+ {
+ if (query.StartIndex.HasValue)
+ {
+ items = items.Skip(query.StartIndex.Value);
+ }
+
+ if (query.Limit.HasValue)
+ {
+ items = items.Take(query.Limit.Value);
+ }
+
+ return items;
+ }
+
+ public Task<DynamicImageResponse> GetChannelImage(ImageType type, CancellationToken cancellationToken)
+ {
+ // TODO: Implement
+ return Task.FromResult(new DynamicImageResponse
+ {
+ HasImage = false
+ });
+ }
+
+ public IEnumerable<ImageType> GetSupportedChannelImages()
+ {
+ return new List<ImageType>
+ {
+ ImageType.Primary
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/ConfigurationExtension.cs b/MediaBrowser.Dlna/ConfigurationExtension.cs
new file mode 100644
index 000000000..821e21ccf
--- /dev/null
+++ b/MediaBrowser.Dlna/ConfigurationExtension.cs
@@ -0,0 +1,29 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Configuration;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Dlna
+{
+ public static class ConfigurationExtension
+ {
+ public static DlnaOptions GetDlnaConfiguration(this IConfigurationManager manager)
+ {
+ return manager.GetConfiguration<DlnaOptions>("dlna");
+ }
+ }
+
+ public class DlnaConfigurationFactory : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new List<ConfigurationStore>
+ {
+ new ConfigurationStore
+ {
+ Key = "dlna",
+ ConfigurationType = typeof (DlnaOptions)
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs
index bb65f422c..f5731b893 100644
--- a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs
+++ b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
@@ -21,6 +22,8 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly IDlnaManager _dlna;
private readonly IServerConfigurationManager _config;
private readonly IUserManager _userManager;
+ private readonly IUserViewManager _userViewManager;
+ private readonly IChannelManager _channelManager;
public ContentDirectory(IDlnaManager dlna,
IUserDataManager userDataManager,
@@ -29,7 +32,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
IServerConfigurationManager config,
IUserManager userManager,
ILogger logger,
- IHttpClient httpClient)
+ IHttpClient httpClient, IUserViewManager userViewManager, IChannelManager channelManager)
: base(logger, httpClient)
{
_dlna = dlna;
@@ -38,6 +41,8 @@ namespace MediaBrowser.Dlna.ContentDirectory
_libraryManager = libraryManager;
_config = config;
_userManager = userManager;
+ _userViewManager = userViewManager;
+ _channelManager = channelManager;
}
private int SystemUpdateId
@@ -73,7 +78,9 @@ namespace MediaBrowser.Dlna.ContentDirectory
_userDataManager,
user,
SystemUpdateId,
- _config)
+ _config,
+ _userViewManager,
+ _channelManager)
.ProcessControlRequest(request);
}
@@ -89,9 +96,11 @@ namespace MediaBrowser.Dlna.ContentDirectory
}
}
- if (!string.IsNullOrEmpty(_config.Configuration.DlnaOptions.DefaultUserId))
+ var userId = _config.GetDlnaConfiguration().DefaultUserId;
+
+ if (!string.IsNullOrEmpty(userId))
{
- var user = _userManager.GetUserById(new Guid(_config.Configuration.DlnaOptions.DefaultUserId));
+ var user = _userManager.GetUserById(new Guid(userId));
if (user != null)
{
diff --git a/MediaBrowser.Dlna/ContentDirectory/ContentDirectoryBrowser.cs b/MediaBrowser.Dlna/ContentDirectory/ContentDirectoryBrowser.cs
new file mode 100644
index 000000000..0c62ada80
--- /dev/null
+++ b/MediaBrowser.Dlna/ContentDirectory/ContentDirectoryBrowser.cs
@@ -0,0 +1,126 @@
+using System.Linq;
+using System.Xml.Linq;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Channels;
+using MediaBrowser.Dlna.PlayTo;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Querying;
+using System;
+using System.Globalization;
+using System.IO;
+using System.Security;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Dlna.ContentDirectory
+{
+ public class ContentDirectoryBrowser
+ {
+ private readonly IHttpClient _httpClient;
+ private readonly ILogger _logger;
+
+ public ContentDirectoryBrowser(IHttpClient httpClient, ILogger logger)
+ {
+ _httpClient = httpClient;
+ _logger = logger;
+ }
+
+ private static XNamespace UNamespace = "u";
+
+ public async Task<QueryResult<ChannelItemInfo>> Browse(ContentDirectoryBrowseRequest request, CancellationToken cancellationToken)
+ {
+ var options = new HttpRequestOptions
+ {
+ CancellationToken = cancellationToken,
+ UserAgent = "Media Browser",
+ RequestContentType = "text/xml; charset=\"utf-8\"",
+ LogErrorResponseBody = true,
+ Url = request.ContentDirectoryUrl
+ };
+
+ options.RequestHeaders["SOAPACTION"] = "urn:schemas-upnp-org:service:ContentDirectory:1#Browse";
+
+ options.RequestContent = GetRequestBody(request);
+
+ var response = await _httpClient.SendAsync(options, "POST");
+
+ using (var reader = new StreamReader(response.Content))
+ {
+ var doc = XDocument.Parse(reader.ReadToEnd(), LoadOptions.PreserveWhitespace);
+
+ var queryResult = new QueryResult<ChannelItemInfo>();
+
+ if (doc.Document == null)
+ return queryResult;
+
+ var responseElement = doc.Document.Descendants(UNamespace + "BrowseResponse").ToList();
+
+ var countElement = responseElement.Select(i => i.Element("TotalMatches")).FirstOrDefault(i => i != null);
+ var countValue = countElement == null ? null : countElement.Value;
+
+ int count;
+ if (!string.IsNullOrWhiteSpace(countValue) && int.TryParse(countValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out count))
+ {
+ queryResult.TotalRecordCount = count;
+
+ var resultElement = responseElement.Select(i => i.Element("Result")).FirstOrDefault(i => i != null);
+ var resultString = (string)resultElement;
+
+ if (resultElement != null)
+ {
+ var xElement = XElement.Parse(resultString);
+ }
+ }
+
+ return queryResult;
+ }
+ }
+
+ private string GetRequestBody(ContentDirectoryBrowseRequest request)
+ {
+ var builder = new StringBuilder();
+
+ builder.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+
+ builder.Append("<s:Envelope s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body>");
+ builder.Append("<u:Browse xmlns:u=\"urn:schemas-upnp-org:service:ContentDirectory:1\">");
+
+ if (string.IsNullOrWhiteSpace(request.ParentId))
+ {
+ request.ParentId = "1";
+ }
+
+ builder.AppendFormat("<ObjectID>{0}</ObjectID>", SecurityElement.Escape(request.ParentId));
+ builder.Append("<BrowseFlag>BrowseDirectChildren</BrowseFlag>");
+
+ //builder.Append("<BrowseFlag>BrowseMetadata</BrowseFlag>");
+
+ builder.Append("<Filter>*</Filter>");
+
+ request.StartIndex = request.StartIndex ?? 0;
+ builder.AppendFormat("<StartingIndex>{0}</StartingIndex>", SecurityElement.Escape(request.StartIndex.Value.ToString(CultureInfo.InvariantCulture)));
+
+ request.Limit = request.Limit ?? 20;
+ if (request.Limit.HasValue)
+ {
+ builder.AppendFormat("<RequestedCount>{0}</RequestedCount>", SecurityElement.Escape(request.Limit.Value.ToString(CultureInfo.InvariantCulture)));
+ }
+
+ builder.Append("<SortCriteria></SortCriteria>");
+
+ builder.Append("</u:Browse>");
+ builder.Append("</s:Body></s:Envelope>");
+
+ return builder.ToString();
+ }
+ }
+
+ public class ContentDirectoryBrowseRequest
+ {
+ public int? StartIndex { get; set; }
+ public int? Limit { get; set; }
+ public string ParentId { get; set; }
+ public string ContentDirectoryUrl { get; set; }
+ }
+}
diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
index b4f918e68..6d5ed9eb8 100644
--- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
+++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
@@ -6,11 +7,14 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Playlists;
using MediaBrowser.Dlna.Didl;
using MediaBrowser.Dlna.Server;
using MediaBrowser.Dlna.Service;
+using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using System;
@@ -19,6 +23,7 @@ using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading;
+using System.Threading.Tasks;
using System.Xml;
namespace MediaBrowser.Dlna.ContentDirectory
@@ -40,14 +45,18 @@ namespace MediaBrowser.Dlna.ContentDirectory
private readonly DidlBuilder _didlBuilder;
private readonly DeviceProfile _profile;
+ private readonly IUserViewManager _userViewManager;
+ private readonly IChannelManager _channelManager;
- public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config)
+ public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, IUserViewManager userViewManager, IChannelManager channelManager)
: base(config, logger)
{
_libraryManager = libraryManager;
_userDataManager = userDataManager;
_user = user;
_systemUpdateId = systemUpdateId;
+ _userViewManager = userViewManager;
+ _channelManager = channelManager;
_profile = profile;
_didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress);
@@ -69,7 +78,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
return HandleGetSystemUpdateID();
if (string.Equals(methodName, "Browse", StringComparison.OrdinalIgnoreCase))
- return HandleBrowse(methodParams, user, deviceId);
+ return HandleBrowse(methodParams, user, deviceId).Result;
if (string.Equals(methodName, "X_GetFeatureList", StringComparison.OrdinalIgnoreCase))
return HandleXGetFeatureList();
@@ -78,7 +87,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
return HandleXSetBookmark(methodParams, user);
if (string.Equals(methodName, "Search", StringComparison.OrdinalIgnoreCase))
- return HandleSearch(methodParams, user, deviceId);
+ return HandleSearch(methodParams, user, deviceId).Result;
throw new ResourceNotFoundException("Unexpected control request name: " + methodName);
}
@@ -103,12 +112,12 @@ namespace MediaBrowser.Dlna.ContentDirectory
private IEnumerable<KeyValuePair<string, string>> HandleGetSearchCapabilities()
{
- return new Headers(true) { { "SearchCaps", "upnp:class,dc:title,upnp:artist" } };
+ return new Headers(true) { { "SearchCaps", "res@resolution,res@size,res@duration,dc:title,dc:creator,upnp:actor,upnp:artist,upnp:genre,upnp:album,dc:date,upnp:class,@id,@refID,@protocolInfo,upnp:author,dc:description,pv:avKeywords" } };
}
private IEnumerable<KeyValuePair<string, string>> HandleGetSortCapabilities()
{
- return new Headers(true) { { "SortCaps", string.Empty } };
+ return new Headers(true) { { "SortCaps", "res@duration,res@size,res@bitrate,dc:date,dc:title,dc:size,upnp:album,upnp:artist,upnp:albumArtist,upnp:episodeNumber,upnp:genre,upnp:originalTrackNumber,upnp:rating" } };
}
private IEnumerable<KeyValuePair<string, string>> HandleGetSystemUpdateID()
@@ -141,7 +150,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
return builder.ToString();
}
- private IEnumerable<KeyValuePair<string, string>> HandleBrowse(Headers sparams, User user, string deviceId)
+ private async Task<IEnumerable<KeyValuePair<string, string>>> HandleBrowse(Headers sparams, User user, string deviceId)
{
var id = sparams["ObjectID"];
var flag = sparams["BrowseFlag"];
@@ -149,16 +158,20 @@ namespace MediaBrowser.Dlna.ContentDirectory
var sortCriteria = new SortCriteria(sparams.GetValueOrDefault("SortCriteria", ""));
var provided = 0;
- var requested = 0;
- var start = 0;
- if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requested) && requested <= 0)
+ int? requested = 0;
+ int? start = 0;
+
+ int requestedVal;
+ if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requestedVal) && requestedVal > 0)
{
- requested = 0;
+ requested = requestedVal;
}
- if (sparams.ContainsKey("StartingIndex") && int.TryParse(sparams["StartingIndex"], out start) && start <= 0)
+
+ int startVal;
+ if (sparams.ContainsKey("StartingIndex") && int.TryParse(sparams["StartingIndex"], out startVal) && startVal > 0)
{
- start = 0;
+ start = startVal;
}
//var root = GetItem(id) as IMediaFolder;
@@ -171,36 +184,43 @@ namespace MediaBrowser.Dlna.ContentDirectory
//didl.SetAttribute("xmlns:sec", NS_SEC);
result.AppendChild(didl);
- var folder = (Folder)GetItemFromObjectId(id, user);
-
- var children = GetChildrenSorted(folder, user, sortCriteria).ToList();
+ var item = GetItemFromObjectId(id, user);
- var totalCount = children.Count;
+ var totalCount = 0;
if (string.Equals(flag, "BrowseMetadata"))
{
- result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, folder, children.Count, filter));
- provided++;
- }
- else
- {
- if (start > 0)
+ var folder = item as Folder;
+
+ if (folder == null)
{
- children = children.Skip(start).ToList();
+ result.DocumentElement.AppendChild(_didlBuilder.GetItemElement(result, item, deviceId, filter));
}
- if (requested > 0)
+ else
{
- children = children.Take(requested).ToList();
+ var childrenResult = (await GetChildrenSorted(folder, user, sortCriteria, start, requested).ConfigureAwait(false));
+ totalCount = childrenResult.TotalRecordCount;
+
+ result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, folder, totalCount, filter));
}
+ provided++;
+ }
+ else
+ {
+ var folder = (Folder)item;
+
+ var childrenResult = (await GetChildrenSorted(folder, user, sortCriteria, start, requested).ConfigureAwait(false));
+ totalCount = childrenResult.TotalRecordCount;
- provided = children.Count;
+ provided = childrenResult.Items.Length;
- foreach (var i in children)
+ foreach (var i in childrenResult.Items)
{
if (i.IsFolder)
{
var f = (Folder)i;
- var childCount = GetChildrenSorted(f, user, sortCriteria).Count();
+ var childCount = (await GetChildrenSorted(f, user, sortCriteria, null, 0).ConfigureAwait(false))
+ .TotalRecordCount;
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, f, childCount, filter));
}
@@ -222,7 +242,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
};
}
- private IEnumerable<KeyValuePair<string, string>> HandleSearch(Headers sparams, User user, string deviceId)
+ private async Task<IEnumerable<KeyValuePair<string, string>>> HandleSearch(Headers sparams, User user, string deviceId)
{
var searchCriteria = new SearchCriteria(sparams.GetValueOrDefault("SearchCriteria", ""));
var sortCriteria = new SortCriteria(sparams.GetValueOrDefault("SortCriteria", ""));
@@ -230,16 +250,19 @@ namespace MediaBrowser.Dlna.ContentDirectory
// sort example: dc:title, dc:date
- var requested = 0;
- var start = 0;
+ int? requested = 0;
+ int? start = 0;
- if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requested) && requested <= 0)
+ int requestedVal;
+ if (sparams.ContainsKey("RequestedCount") && int.TryParse(sparams["RequestedCount"], out requestedVal) && requestedVal > 0)
{
- requested = 0;
+ requested = requestedVal;
}
- if (sparams.ContainsKey("StartingIndex") && int.TryParse(sparams["StartingIndex"], out start) && start <= 0)
+
+ int startVal;
+ if (sparams.ContainsKey("StartingIndex") && int.TryParse(sparams["StartingIndex"], out startVal) && startVal > 0)
{
- start = 0;
+ start = startVal;
}
//var root = GetItem(id) as IMediaFolder;
@@ -259,27 +282,19 @@ namespace MediaBrowser.Dlna.ContentDirectory
var folder = (Folder)GetItemFromObjectId(sparams["ContainerID"], user);
- var children = GetChildrenSorted(folder, user, searchCriteria, sortCriteria).ToList();
-
- var totalCount = children.Count;
+ var childrenResult = (await GetChildrenSorted(folder, user, searchCriteria, sortCriteria, start, requested).ConfigureAwait(false));
- if (start > 0)
- {
- children = children.Skip(start).ToList();
- }
- if (requested > 0)
- {
- children = children.Take(requested).ToList();
- }
+ var totalCount = childrenResult.TotalRecordCount;
- var provided = children.Count;
+ var provided = childrenResult.Items.Length;
- foreach (var i in children)
+ foreach (var i in childrenResult.Items)
{
if (i.IsFolder)
{
var f = (Folder)i;
- var childCount = GetChildrenSorted(f, user, searchCriteria, sortCriteria).Count();
+ var childCount = (await GetChildrenSorted(f, user, searchCriteria, sortCriteria, null, 0).ConfigureAwait(false))
+ .TotalRecordCount;
result.DocumentElement.AppendChild(_didlBuilder.GetFolderElement(result, f, childCount, filter));
}
@@ -300,15 +315,12 @@ namespace MediaBrowser.Dlna.ContentDirectory
};
}
- private IEnumerable<BaseItem> GetChildrenSorted(Folder folder, User user, SearchCriteria search, SortCriteria sort)
+ private async Task<QueryResult<BaseItem>> GetChildrenSorted(Folder folder, User user, SearchCriteria search, SortCriteria sort, int? startIndex, int? limit)
{
- if (search.SearchType == SearchType.Unknown)
- {
- return GetChildrenSorted(folder, user, sort);
- }
+ // TODO: Make a recursive version of GetChildrenSorted (although sorting isn't needed)
+ var result = folder.GetRecursiveChildren(user, true);
- var items = folder.GetRecursiveChildren(user);
- items = FilterUnsupportedContent(items);
+ var items = FilterUnsupportedContent(result);
if (search.SearchType == SearchType.Audio)
{
@@ -324,18 +336,161 @@ namespace MediaBrowser.Dlna.ContentDirectory
}
else if (search.SearchType == SearchType.Playlist)
{
+ items = items.OfType<Playlist>();
+ }
+ else if (search.SearchType == SearchType.MusicAlbum)
+ {
+ items = items.OfType<MusicAlbum>();
}
- return SortItems(items, user, sort);
+ items = SortItems(items, user, sort);
+
+ return ToResult(items, startIndex, limit);
+ }
+
+ private async Task<QueryResult<BaseItem>> GetChildrenSorted(Folder folder, User user, SortCriteria sort, int? startIndex, int? limit)
+ {
+ if (folder is UserRootFolder)
+ {
+ var result = await _userViewManager.GetUserViews(new UserViewQuery
+ {
+ UserId = user.Id.ToString("N")
+
+ }, CancellationToken.None).ConfigureAwait(false);
+
+ return ToResult(result, startIndex, limit);
+ }
+
+ var view = folder as UserView;
+
+ if (view != null)
+ {
+ var result = await GetUserViewChildren(view, user, sort).ConfigureAwait(false);
+
+ return ToResult(result, startIndex, limit);
+ }
+
+ var channel = folder as Channel;
+
+ if (channel != null)
+ {
+ try
+ {
+ // Don't blow up here because it could cause parent screens with other content to fail
+ return await _channelManager.GetChannelItemsInternal(new ChannelItemQuery
+ {
+ ChannelId = channel.Id.ToString("N"),
+ Limit = limit,
+ StartIndex = startIndex,
+ UserId = user.Id.ToString("N")
+
+ }, CancellationToken.None);
+ }
+ catch
+ {
+ // Already logged at lower levels
+ }
+ }
+
+ var channelFolderItem = folder as ChannelFolderItem;
+
+ if (channelFolderItem != null)
+ {
+ try
+ {
+ // Don't blow up here because it could cause parent screens with other content to fail
+ return await _channelManager.GetChannelItemsInternal(new ChannelItemQuery
+ {
+ ChannelId = channelFolderItem.ChannelId,
+ FolderId = channelFolderItem.Id.ToString("N"),
+ Limit = limit,
+ StartIndex = startIndex,
+ UserId = user.Id.ToString("N")
+
+ }, CancellationToken.None);
+ }
+ catch
+ {
+ // Already logged at lower levels
+ }
+ }
+
+ return ToResult(GetPlainFolderChildrenSorted(folder, user, sort), startIndex, limit);
+ }
+
+ private QueryResult<BaseItem> ToResult(IEnumerable<BaseItem> items, int? startIndex, int? limit)
+ {
+ var list = items.ToArray();
+ var totalCount = list.Length;
+
+ if (startIndex.HasValue)
+ {
+ list = list.Skip(startIndex.Value).ToArray();
+ }
+
+ if (limit.HasValue)
+ {
+ list = list.Take(limit.Value).ToArray();
+ }
+
+ return new QueryResult<BaseItem>
+ {
+ Items = list,
+ TotalRecordCount = totalCount
+ };
+ }
+
+ private async Task<IEnumerable<BaseItem>> GetUserViewChildren(UserView folder, User user, SortCriteria sort)
+ {
+ if (string.Equals(folder.ViewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase))
+ {
+ var result = await _channelManager.GetChannelsInternal(new ChannelQuery()
+ {
+ UserId = user.Id.ToString("N")
+
+ }, CancellationToken.None).ConfigureAwait(false);
+
+ return result.Items;
+ }
+ if (string.Equals(folder.ViewType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
+ {
+ return SortItems(folder.GetChildren(user, true).OfType<Series>(), user, sort);
+ }
+ if (string.Equals(folder.ViewType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
+ {
+ return SortItems(folder.GetRecursiveChildren(user, true).OfType<Movie>(), user, sort);
+ }
+ if (string.Equals(folder.ViewType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
+ {
+ return SortItems(folder.GetChildren(user, true).OfType<MusicArtist>(), user, sort);
+ }
+ if (string.Equals(folder.ViewType, CollectionType.Folders, StringComparison.OrdinalIgnoreCase))
+ {
+ return SortItems(folder.GetChildren(user, true), user, sort);
+ }
+ if (string.Equals(folder.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase))
+ {
+ return SortItems(folder.GetChildren(user, true), user, sort);
+ }
+ if (string.Equals(folder.ViewType, CollectionType.LiveTvRecordingGroups, StringComparison.OrdinalIgnoreCase))
+ {
+ return SortItems(folder.GetChildren(user, true), user, sort);
+ }
+ if (string.Equals(folder.ViewType, CollectionType.LiveTvChannels, StringComparison.OrdinalIgnoreCase))
+ {
+ return SortItems(folder.GetChildren(user, true), user, sort);
+ }
+
+ return GetPlainFolderChildrenSorted(folder, user, sort);
}
- private IEnumerable<BaseItem> GetChildrenSorted(Folder folder, User user, SortCriteria sort)
+ private IEnumerable<BaseItem> GetPlainFolderChildrenSorted(Folder folder, User user, SortCriteria sort)
{
var items = folder.GetChildren(user, true);
items = FilterUnsupportedContent(items);
- if (folder is Series || folder is Season || folder is BoxSet)
+ if (folder.IsPreSorted)
{
return items;
}
@@ -345,7 +500,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
private IEnumerable<BaseItem> SortItems(IEnumerable<BaseItem> items, User user, SortCriteria sort)
{
- return _libraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending);
+ return _libraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, sort.SortOrder);
}
private IEnumerable<BaseItem> FilterUnsupportedContent(IEnumerable<BaseItem> items)
@@ -353,22 +508,18 @@ namespace MediaBrowser.Dlna.ContentDirectory
return items.Where(i =>
{
// Unplayable
- // TODO: Display and prevent playback with restricted flag?
- if (i.LocationType == LocationType.Virtual)
+ if (i.LocationType == LocationType.Virtual && !i.IsFolder)
{
return false;
}
// Unplayable
- // TODO: Display and prevent playback with restricted flag?
var supportsPlaceHolder = i as ISupportsPlaceHolders;
if (supportsPlaceHolder != null && supportsPlaceHolder.IsPlaceHolder)
{
return false;
}
- // Upnp renderers won't understand these
- // TODO: Display and prevent playback with restricted flag?
if (i is Game || i is Book)
{
return false;
diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
index 746931b68..69fec1e44 100644
--- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs
+++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
@@ -1,9 +1,12 @@
-using MediaBrowser.Common.Net;
+using System.IO;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
@@ -12,6 +15,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Xml;
+using MediaBrowser.Common.Extensions;
namespace MediaBrowser.Dlna.Didl
{
@@ -77,16 +81,18 @@ namespace MediaBrowser.Dlna.Didl
// refID?
// storeAttribute(itemNode, object, ClassProperties.REF_ID, false);
- var audio = item as Audio;
- if (audio != null)
- {
- AddAudioResource(element, audio, deviceId, filter, streamInfo);
- }
+ var hasMediaSources = item as IHasMediaSources;
- var video = item as Video;
- if (video != null)
+ if (hasMediaSources != null)
{
- AddVideoResource(element, video, deviceId, filter, streamInfo);
+ if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
+ {
+ AddAudioResource(element, hasMediaSources, deviceId, filter, streamInfo);
+ }
+ else if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
+ {
+ AddVideoResource(element, hasMediaSources, deviceId, filter, streamInfo);
+ }
}
AddCover(item, element);
@@ -94,24 +100,94 @@ namespace MediaBrowser.Dlna.Didl
return element;
}
- private void AddVideoResource(XmlElement container, Video video, string deviceId, Filter filter, StreamInfo streamInfo = null)
+ private void AddVideoResource(XmlElement container, IHasMediaSources video, string deviceId, Filter filter, StreamInfo streamInfo = null)
{
- var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);
-
if (streamInfo == null)
{
var sources = _user == null ? video.GetMediaSources(true).ToList() : video.GetMediaSources(true, _user).ToList();
- streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
+ streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
{
ItemId = video.Id.ToString("N"),
MediaSources = sources,
Profile = _profile,
DeviceId = deviceId,
- MaxBitrate = _profile.MaxBitrate
+ MaxBitrate = _profile.MaxStreamingBitrate
});
}
+ var targetWidth = streamInfo.TargetWidth;
+ var targetHeight = streamInfo.TargetHeight;
+
+ var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container,
+ streamInfo.VideoCodec,
+ streamInfo.AudioCodec,
+ targetWidth,
+ targetHeight,
+ streamInfo.TargetVideoBitDepth,
+ streamInfo.TargetVideoBitrate,
+ streamInfo.TargetAudioChannels,
+ streamInfo.TargetAudioBitrate,
+ streamInfo.TargetTimestamp,
+ streamInfo.IsDirectStream,
+ streamInfo.RunTimeTicks,
+ streamInfo.TargetVideoProfile,
+ streamInfo.TargetVideoLevel,
+ streamInfo.TargetFramerate,
+ streamInfo.TargetPacketLength,
+ streamInfo.TranscodeSeekInfo,
+ streamInfo.IsTargetAnamorphic);
+
+ foreach (var contentFeature in contentFeatureList)
+ {
+ AddVideoResource(container, video, deviceId, filter, contentFeature, streamInfo);
+ }
+
+ foreach (var subtitle in streamInfo.GetExternalSubtitles(_serverAddress))
+ {
+ AddSubtitleElement(container, subtitle);
+ }
+ }
+
+ private void AddSubtitleElement(XmlElement container, SubtitleStreamInfo info)
+ {
+ var subtitleProfile = _profile.SubtitleProfiles
+ .FirstOrDefault(i => string.Equals(info.Format, i.Format, StringComparison.OrdinalIgnoreCase) && i.Method == SubtitleDeliveryMethod.External);
+
+ if (subtitleProfile == null)
+ {
+ return;
+ }
+
+ var subtitleMode = subtitleProfile.DidlMode;
+
+ if (string.Equals(subtitleMode, "CaptionInfoEx", StringComparison.OrdinalIgnoreCase))
+ {
+ //var res = container.OwnerDocument.CreateElement("SEC", "CaptionInfoEx");
+
+ //res.InnerText = info.Url;
+
+ //// TODO: attribute needs SEC:
+ //res.SetAttribute("type", info.Format.ToLower());
+ //container.AppendChild(res);
+ }
+ else
+ {
+ var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);
+
+ res.InnerText = info.Url;
+
+ var protocolInfo = string.Format("http-get:*:text/{0}:*", info.Format.ToLower());
+ res.SetAttribute("protocolInfo", protocolInfo);
+
+ container.AppendChild(res);
+ }
+ }
+
+ private void AddVideoResource(XmlElement container, IHasMediaSources video, string deviceId, Filter filter, string contentFeatures, StreamInfo streamInfo)
+ {
+ var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);
+
var url = streamInfo.ToDlnaUrl(_serverAddress);
res.InnerText = url;
@@ -188,25 +264,6 @@ namespace MediaBrowser.Dlna.Didl
? MimeTypes.GetMimeType(filename)
: mediaProfile.MimeType;
- var contentFeatures = new ContentFeatureBuilder(_profile).BuildVideoHeader(streamInfo.Container,
- streamInfo.VideoCodec,
- streamInfo.AudioCodec,
- targetWidth,
- targetHeight,
- streamInfo.TargetVideoBitDepth,
- streamInfo.TargetVideoBitrate,
- streamInfo.TargetAudioChannels,
- streamInfo.TargetAudioBitrate,
- streamInfo.TargetTimestamp,
- streamInfo.IsDirectStream,
- streamInfo.RunTimeTicks,
- streamInfo.TargetVideoProfile,
- streamInfo.TargetVideoLevel,
- streamInfo.TargetFramerate,
- streamInfo.TargetPacketLength,
- streamInfo.TranscodeSeekInfo,
- streamInfo.IsTargetAnamorphic);
-
res.SetAttribute("protocolInfo", String.Format(
"http-get:*:{0}:{1}",
mimeType,
@@ -215,8 +272,8 @@ namespace MediaBrowser.Dlna.Didl
container.AppendChild(res);
}
-
- private void AddAudioResource(XmlElement container, Audio audio, string deviceId, Filter filter, StreamInfo streamInfo = null)
+
+ private void AddAudioResource(XmlElement container, IHasMediaSources audio, string deviceId, Filter filter, StreamInfo streamInfo = null)
{
var res = container.OwnerDocument.CreateElement(string.Empty, "res", NS_DIDL);
@@ -382,9 +439,17 @@ namespace MediaBrowser.Dlna.Didl
if (filter.Contains("dc:description"))
{
- if (!string.IsNullOrWhiteSpace(item.Overview))
+ var desc = item.Overview;
+
+ var hasShortOverview = item as IHasShortOverview;
+ if (hasShortOverview != null && !string.IsNullOrEmpty(hasShortOverview.ShortOverview))
{
- AddValue(element, "dc", "description", item.Overview, NS_DC);
+ desc = hasShortOverview.ShortOverview;
+ }
+
+ if (!string.IsNullOrWhiteSpace(desc))
+ {
+ AddValue(element, "dc", "description", desc, NS_DC);
}
}
if (filter.Contains("upnp:longDescription"))
@@ -432,6 +497,10 @@ namespace MediaBrowser.Dlna.Didl
{
classType = "object.container.album.videoAlbum";
}
+ else if (item is Playlist)
+ {
+ classType = "object.container.playlistContainer";
+ }
}
objectClass.InnerText = classType ?? "object.container.storageFolder";
@@ -457,7 +526,7 @@ namespace MediaBrowser.Dlna.Didl
}
else
{
- throw new NotSupportedException();
+ objectClass.InnerText = "object.item";
}
return objectClass;
@@ -496,7 +565,7 @@ namespace MediaBrowser.Dlna.Didl
foreach (var artist in audio.AlbumArtists)
{
- AddValue(element, "upnp", "albumArtist", artist, NS_UPNP);
+ AddAlbumArtist(element, artist);
}
}
@@ -506,8 +575,12 @@ namespace MediaBrowser.Dlna.Didl
{
foreach (var artist in album.AlbumArtists)
{
+ AddAlbumArtist(element, artist);
+ AddValue(element, "upnp", "artist", artist, NS_UPNP);
+ }
+ foreach (var artist in album.Artists)
+ {
AddValue(element, "upnp", "artist", artist, NS_UPNP);
- AddValue(element, "upnp", "albumArtist", artist, NS_UPNP);
}
}
@@ -518,6 +591,7 @@ namespace MediaBrowser.Dlna.Didl
if (!string.IsNullOrEmpty(musicVideo.Artist))
{
AddValue(element, "upnp", "artist", musicVideo.Artist, NS_UPNP);
+ AddAlbumArtist(element, musicVideo.Artist);
}
if (!string.IsNullOrEmpty(musicVideo.Album))
@@ -529,6 +603,28 @@ namespace MediaBrowser.Dlna.Didl
if (item.IndexNumber.HasValue)
{
AddValue(element, "upnp", "originalTrackNumber", item.IndexNumber.Value.ToString(_usCulture), NS_UPNP);
+
+ if (item is Episode)
+ {
+ AddValue(element, "upnp", "episodeNumber", item.IndexNumber.Value.ToString(_usCulture), NS_UPNP);
+ }
+ }
+ }
+
+ private void AddAlbumArtist(XmlElement elem, string name)
+ {
+ try
+ {
+ var newNode = elem.OwnerDocument.CreateElement("upnp", "artist", NS_UPNP);
+ newNode.InnerText = name;
+
+ newNode.SetAttribute("role", "AlbumArtist");
+
+ elem.AppendChild(newNode);
+ }
+ catch (XmlException)
+ {
+ //_logger.Error("Error adding xml value: " + value);
}
}
@@ -557,7 +653,7 @@ namespace MediaBrowser.Dlna.Didl
var result = element.OwnerDocument;
- var albumartUrlInfo = GetImageUrl(imageInfo, _profile.MaxAlbumArtWidth, _profile.MaxAlbumArtHeight);
+ var albumartUrlInfo = GetImageUrl(imageInfo, _profile.MaxAlbumArtWidth, _profile.MaxAlbumArtHeight, "jpg");
var icon = result.CreateElement("upnp", "albumArtURI", NS_UPNP);
var profile = result.CreateAttribute("dlna", "profileID", NS_DLNA);
@@ -566,19 +662,49 @@ namespace MediaBrowser.Dlna.Didl
icon.InnerText = albumartUrlInfo.Url;
element.AppendChild(icon);
- var iconUrlInfo = GetImageUrl(imageInfo, _profile.MaxIconWidth, _profile.MaxIconHeight);
+ // TOOD: Remove these default values
+ var iconUrlInfo = GetImageUrl(imageInfo, _profile.MaxIconWidth ?? 48, _profile.MaxIconHeight ?? 48, "jpg");
icon = result.CreateElement("upnp", "icon", NS_UPNP);
- profile = result.CreateAttribute("dlna", "profileID", NS_DLNA);
- profile.InnerText = _profile.AlbumArtPn;
- icon.SetAttributeNode(profile);
icon.InnerText = iconUrlInfo.Url;
element.AppendChild(icon);
if (!_profile.EnableAlbumArtInDidl)
{
+ if (!string.Equals(item.MediaType, MediaType.Photo, StringComparison.OrdinalIgnoreCase) && !string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
+ {
+ if (!item.IsFolder)
+ {
+ return;
+ }
+ }
+ }
+
+ AddImageResElement(item, element, 4096, 4096, "jpg", "JPEG_LRG");
+ AddImageResElement(item, element, 4096, 4096, "png", "PNG_LRG");
+ AddImageResElement(item, element, 1024, 768, "jpg", "JPEG_MED");
+ AddImageResElement(item, element, 640, 480, "jpg", "JPEG_SM");
+ AddImageResElement(item, element, 160, 160, "jpg", "JPEG_TN");
+ AddImageResElement(item, element, 160, 160, "png", "PNG_TN");
+ }
+
+ private void AddImageResElement(BaseItem item,
+ XmlElement element,
+ int maxWidth,
+ int maxHeight,
+ string format,
+ string org_Pn)
+ {
+ var imageInfo = GetImageInfo(item);
+
+ if (imageInfo == null)
+ {
return;
}
+ var result = element.OwnerDocument;
+
+ var albumartUrlInfo = GetImageUrl(imageInfo, maxWidth, maxHeight, format);
+
var res = result.CreateElement(string.Empty, "res", NS_DIDL);
res.InnerText = albumartUrlInfo.Url;
@@ -586,11 +712,12 @@ namespace MediaBrowser.Dlna.Didl
var width = albumartUrlInfo.Width;
var height = albumartUrlInfo.Height;
- var contentFeatures = new ContentFeatureBuilder(_profile).BuildImageHeader("jpg", width, height);
+ var contentFeatures = new ContentFeatureBuilder(_profile)
+ .BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn);
res.SetAttribute("protocolInfo", String.Format(
"http-get:*:{0}:{1}",
- "image/jpeg",
+ MimeTypes.GetMimeType("file." + format),
contentFeatures
));
@@ -612,6 +739,13 @@ namespace MediaBrowser.Dlna.Didl
{
return GetImageInfo(item, ImageType.Thumb);
}
+ if (item.HasImage(ImageType.Backdrop))
+ {
+ if (item is Channel)
+ {
+ return GetImageInfo(item, ImageType.Backdrop);
+ }
+ }
if (item is Audio || item is Episode)
{
@@ -633,7 +767,7 @@ namespace MediaBrowser.Dlna.Didl
try
{
- tag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
+ tag = _imageProcessor.GetImageCacheTag(item, type);
}
catch
{
@@ -658,10 +792,12 @@ namespace MediaBrowser.Dlna.Didl
return new ImageDownloadInfo
{
ItemId = item.Id.ToString("N"),
- Type = ImageType.Primary,
+ Type = type,
ImageTag = tag,
Width = width,
- Height = height
+ Height = height,
+ File = imageInfo.Path,
+ ItemImageInfo = imageInfo
};
}
@@ -673,6 +809,12 @@ namespace MediaBrowser.Dlna.Didl
internal int? Width;
internal int? Height;
+
+ internal bool IsDirectStream;
+
+ internal string File;
+
+ internal ItemImageInfo ItemImageInfo;
}
class ImageUrlInfo
@@ -683,47 +825,44 @@ namespace MediaBrowser.Dlna.Didl
internal int? Height;
}
- private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int? maxWidth, int? maxHeight)
+ private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, string format)
{
- var url = string.Format("{0}/Items/{1}/Images/{2}?params=",
+ var url = string.Format("{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}",
_serverAddress,
info.ItemId,
- info.Type);
-
- var options = new List<string>
- {
+ info.Type,
info.ImageTag,
- "jpg"
- };
-
- if (maxWidth.HasValue)
- {
- options.Add(maxWidth.Value.ToString(_usCulture));
- }
-
- if (maxHeight.HasValue)
- {
- options.Add(maxHeight.Value.ToString(_usCulture));
- }
-
- url += string.Join(";", options.ToArray());
+ format,
+ maxWidth,
+ maxHeight);
var width = info.Width;
var height = info.Height;
+ info.IsDirectStream = false;
+
if (width.HasValue && height.HasValue)
{
- if (maxWidth.HasValue || maxHeight.HasValue)
+ var newSize = DrawingUtils.Resize(new ImageSize
{
- var newSize = DrawingUtils.Resize(new ImageSize
- {
- Height = height.Value,
- Width = width.Value
+ Height = height.Value,
+ Width = width.Value
- }, null, null, maxWidth, maxHeight);
+ }, null, null, maxWidth, maxHeight);
- width = Convert.ToInt32(newSize.Width);
- height = Convert.ToInt32(newSize.Height);
+ width = Convert.ToInt32(newSize.Width);
+ height = Convert.ToInt32(newSize.Height);
+
+ var inputFormat = (Path.GetExtension(info.File) ?? string.Empty)
+ .TrimStart('.')
+ .Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase);
+
+ var normalizedFormat = format
+ .Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase);
+
+ if (string.Equals(inputFormat, normalizedFormat, StringComparison.OrdinalIgnoreCase))
+ {
+ info.IsDirectStream = maxWidth >= width.Value && maxHeight >= height.Value;
}
}
diff --git a/MediaBrowser.Model/Dlna/Filter.cs b/MediaBrowser.Dlna/Didl/Filter.cs
index a41997010..c980a2a2e 100644
--- a/MediaBrowser.Model/Dlna/Filter.cs
+++ b/MediaBrowser.Dlna/Didl/Filter.cs
@@ -1,8 +1,9 @@
using MediaBrowser.Model.Extensions;
using System;
using System.Collections.Generic;
+using System.Linq;
-namespace MediaBrowser.Model.Dlna
+namespace MediaBrowser.Dlna.Didl
{
public class Filter
{
@@ -19,9 +20,8 @@ namespace MediaBrowser.Model.Dlna
{
_all = StringHelper.EqualsIgnoreCase(filter, "*");
- List<string> list = new List<string>();
- foreach (string s in (filter ?? string.Empty).Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries))
- list.Add(s);
+ var list = (filter ?? string.Empty).Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries).ToList();
+
_fields = list;
}
diff --git a/MediaBrowser.Dlna/DlnaManager.cs b/MediaBrowser.Dlna/DlnaManager.cs
index 21476c5d9..2dd863c80 100644
--- a/MediaBrowser.Dlna/DlnaManager.cs
+++ b/MediaBrowser.Dlna/DlnaManager.cs
@@ -75,6 +75,11 @@ namespace MediaBrowser.Dlna
new LgTvProfile(),
new Foobar2000Profile(),
new MediaMonkeyProfile(),
+ new Windows81Profile(),
+ //new WindowsMediaCenterProfile(),
+ new WindowsPhoneProfile(),
+ new AndroidProfile(),
+ new DirectTvProfile(),
new DefaultProfile()
};
@@ -368,7 +373,7 @@ namespace MediaBrowser.Dlna
Info = new DeviceProfileInfo
{
Id = i.FullName.ToLower().GetMD5().ToString("N"),
- Name = Path.GetFileNameWithoutExtension(i.FullName),
+ Name = _fileSystem.GetFileNameWithoutExtension(i),
Type = type
}
})
diff --git a/MediaBrowser.Model/Dlna/EventSubscription.cs b/MediaBrowser.Dlna/Eventing/EventSubscription.cs
index 863ea508a..bd4cbdd55 100644
--- a/MediaBrowser.Model/Dlna/EventSubscription.cs
+++ b/MediaBrowser.Dlna/Eventing/EventSubscription.cs
@@ -1,6 +1,6 @@
using System;
-namespace MediaBrowser.Model.Dlna
+namespace MediaBrowser.Dlna.Eventing
{
public class EventSubscription
{
diff --git a/MediaBrowser.Dlna/Images/logo120.jpg b/MediaBrowser.Dlna/Images/logo120.jpg
index 1de803c8f..394c8e137 100644
--- a/MediaBrowser.Dlna/Images/logo120.jpg
+++ b/MediaBrowser.Dlna/Images/logo120.jpg
Binary files differ
diff --git a/MediaBrowser.Dlna/Images/logo120.png b/MediaBrowser.Dlna/Images/logo120.png
index 2dd04d468..97bdef818 100644
--- a/MediaBrowser.Dlna/Images/logo120.png
+++ b/MediaBrowser.Dlna/Images/logo120.png
Binary files differ
diff --git a/MediaBrowser.Dlna/Images/logo240.jpg b/MediaBrowser.Dlna/Images/logo240.jpg
new file mode 100644
index 000000000..c80552351
--- /dev/null
+++ b/MediaBrowser.Dlna/Images/logo240.jpg
Binary files differ
diff --git a/MediaBrowser.Dlna/Images/logo240.png b/MediaBrowser.Dlna/Images/logo240.png
new file mode 100644
index 000000000..532f12317
--- /dev/null
+++ b/MediaBrowser.Dlna/Images/logo240.png
Binary files differ
diff --git a/MediaBrowser.Dlna/Images/logo48.jpg b/MediaBrowser.Dlna/Images/logo48.jpg
index f1e7302aa..52b985354 100644
--- a/MediaBrowser.Dlna/Images/logo48.jpg
+++ b/MediaBrowser.Dlna/Images/logo48.jpg
Binary files differ
diff --git a/MediaBrowser.Dlna/Images/logo48.png b/MediaBrowser.Dlna/Images/logo48.png
index 3b13d141c..29d4a0528 100644
--- a/MediaBrowser.Dlna/Images/logo48.png
+++ b/MediaBrowser.Dlna/Images/logo48.png
Binary files differ
diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
index 048525588..8914ae8bf 100644
--- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
+++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
@@ -8,6 +9,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
+using MediaBrowser.Dlna.Channels;
using MediaBrowser.Dlna.PlayTo;
using MediaBrowser.Dlna.Ssdp;
using MediaBrowser.Model.Logging;
@@ -34,8 +36,9 @@ namespace MediaBrowser.Dlna.Main
private readonly IImageProcessor _imageProcessor;
private SsdpHandler _ssdpHandler;
+ private DeviceDiscovery _deviceDiscovery;
- private readonly List<Guid> _registeredServerIds = new List<Guid>();
+ private readonly List<string> _registeredServerIds = new List<string>();
private bool _dlnaServerStarted;
public DlnaEntryPoint(IServerConfigurationManager config, ILogManager logManager, IServerApplicationHost appHost, INetworkManager network, ISessionManager sessionManager, IHttpClient httpClient, IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IImageProcessor imageProcessor)
@@ -58,34 +61,41 @@ namespace MediaBrowser.Dlna.Main
StartSsdpHandler();
ReloadComponents();
- _config.ConfigurationUpdated += ConfigurationUpdated;
+ _config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
+
+ DlnaChannelFactory.Instance.Start(_deviceDiscovery, () => _registeredServerIds);
}
- void ConfigurationUpdated(object sender, EventArgs e)
+ void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
{
- ReloadComponents();
+ if (string.Equals(e.Key, "dlna", StringComparison.OrdinalIgnoreCase))
+ {
+ ReloadComponents();
+ }
}
private void ReloadComponents()
{
var isServerStarted = _dlnaServerStarted;
- if (_config.Configuration.DlnaOptions.EnableServer && !isServerStarted)
+ var options = _config.GetDlnaConfiguration();
+
+ if (options.EnableServer && !isServerStarted)
{
StartDlnaServer();
}
- else if (!_config.Configuration.DlnaOptions.EnableServer && isServerStarted)
+ else if (!options.EnableServer && isServerStarted)
{
DisposeDlnaServer();
}
var isPlayToStarted = _manager != null;
- if (_config.Configuration.DlnaOptions.EnablePlayTo && !isPlayToStarted)
+ if (options.EnablePlayTo && !isPlayToStarted)
{
StartPlayToManager();
}
- else if (!_config.Configuration.DlnaOptions.EnablePlayTo && isPlayToStarted)
+ else if (!options.EnablePlayTo && isPlayToStarted)
{
DisposePlayToManager();
}
@@ -98,10 +108,14 @@ namespace MediaBrowser.Dlna.Main
_ssdpHandler = new SsdpHandler(_logger, _config, GenerateServerSignature());
_ssdpHandler.Start();
+
+ _deviceDiscovery = new DeviceDiscovery(_logger, _config, _httpClient, _ssdpHandler, _network);
+
+ _deviceDiscovery.Start();
}
catch (Exception ex)
{
- _logger.ErrorException("Error starting Dlna server", ex);
+ _logger.ErrorException("Error starting ssdp handlers", ex);
}
}
@@ -109,6 +123,15 @@ namespace MediaBrowser.Dlna.Main
{
try
{
+ _deviceDiscovery.Dispose();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error disposing device discovery", ex);
+ }
+
+ try
+ {
_ssdpHandler.Dispose();
}
catch (Exception ex)
@@ -151,7 +174,7 @@ namespace MediaBrowser.Dlna.Main
_ssdpHandler.RegisterNotification(guid, uri, IPAddress.Parse(address), services);
- _registeredServerIds.Add(guid);
+ _registeredServerIds.Add(guid.ToString("N"));
}
}
@@ -186,16 +209,16 @@ namespace MediaBrowser.Dlna.Main
try
{
_manager = new PlayToManager(_logger,
- _config,
_sessionManager,
- _httpClient,
_itemRepo,
_libraryManager,
_userManager,
_dlnaManager,
_appHost,
_imageProcessor,
- _ssdpHandler);
+ _deviceDiscovery,
+ _httpClient,
+ _config);
_manager.Start();
}
@@ -238,7 +261,7 @@ namespace MediaBrowser.Dlna.Main
{
try
{
- _ssdpHandler.UnregisterNotification(id);
+ _ssdpHandler.UnregisterNotification(new Guid(id));
}
catch (Exception ex)
{
diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
index 10da21e52..466c99009 100644
--- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
+++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
@@ -51,13 +51,18 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
+ <Compile Include="Channels\DlnaChannelFactory.cs" />
+ <Compile Include="ConfigurationExtension.cs" />
<Compile Include="ConnectionManager\ConnectionManager.cs" />
<Compile Include="ConnectionManager\ConnectionManagerXmlBuilder.cs" />
<Compile Include="ConnectionManager\ControlHandler.cs" />
<Compile Include="ConnectionManager\ServiceActionListBuilder.cs" />
+ <Compile Include="ContentDirectory\ContentDirectoryBrowser.cs" />
+ <Compile Include="Didl\Filter.cs" />
<Compile Include="DlnaManager.cs" />
<Compile Include="Common\Argument.cs" />
<Compile Include="Eventing\EventManager.cs" />
+ <Compile Include="Eventing\EventSubscription.cs" />
<Compile Include="Main\DlnaEntryPoint.cs" />
<Compile Include="PlayTo\CurrentIdEventArgs.cs" />
<Compile Include="PlayTo\Device.cs">
@@ -68,7 +73,9 @@
<Compile Include="Common\DeviceService.cs" />
<Compile Include="Didl\DidlBuilder.cs" />
<Compile Include="PlayTo\PlayToController.cs" />
- <Compile Include="PlayTo\Extensions.cs" />
+ <Compile Include="Profiles\DirectTvProfile.cs" />
+ <Compile Include="Ssdp\DeviceDiscoveryInfo.cs" />
+ <Compile Include="Ssdp\Extensions.cs" />
<Compile Include="PlayTo\PlaybackProgressEventArgs.cs" />
<Compile Include="PlayTo\PlaybackStoppedEventArgs.cs" />
<Compile Include="PlayTo\PlaylistItem.cs">
@@ -79,6 +86,7 @@
<Compile Include="Common\ServiceAction.cs" />
<Compile Include="PlayTo\TRANSPORTSTATE.cs" />
<Compile Include="PlayTo\uParserObject.cs" />
+ <Compile Include="Profiles\AndroidProfile.cs" />
<Compile Include="Profiles\Foobar2000Profile.cs" />
<Compile Include="Profiles\MediaMonkeyProfile.cs" />
<Compile Include="Profiles\Windows81Profile.cs" />
@@ -94,6 +102,7 @@
<Compile Include="Service\ServiceXmlBuilder.cs" />
<Compile Include="Ssdp\Datagram.cs" />
<Compile Include="Server\DescriptionXmlBuilder.cs" />
+ <Compile Include="Ssdp\DeviceDiscovery.cs" />
<Compile Include="Ssdp\SsdpHelper.cs" />
<Compile Include="PlayTo\SsdpHttpClient.cs" />
<Compile Include="Common\StateVariable.cs" />
@@ -171,6 +180,18 @@
<ItemGroup>
<EmbeddedResource Include="Profiles\Xml\MediaMonkey.xml" />
</ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Profiles\Xml\Android.xml" />
+ <EmbeddedResource Include="Profiles\Xml\Windows 8 RT.xml" />
+ <EmbeddedResource Include="Profiles\Xml\Windows Phone.xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Images\logo240.jpg" />
+ <EmbeddedResource Include="Images\logo240.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Profiles\Xml\DirecTV HD-DVR.xml" />
+ </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.Dlna/PlayTo/Device.cs b/MediaBrowser.Dlna/PlayTo/Device.cs
index a5c3a6038..f67094554 100644
--- a/MediaBrowser.Dlna/PlayTo/Device.cs
+++ b/MediaBrowser.Dlna/PlayTo/Device.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Dlna.Common;
+using MediaBrowser.Dlna.Ssdp;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
@@ -289,7 +290,8 @@ namespace MediaBrowser.Dlna.PlayTo
throw new InvalidOperationException("Unable to find service");
}
- await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, url, dictionary), header)
+ var post = AvCommands.BuildPost(command, service.ServiceType, url, dictionary);
+ await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, post, header)
.ConfigureAwait(false);
await Task.Delay(50).ConfigureAwait(false);
@@ -315,31 +317,6 @@ namespace MediaBrowser.Dlna.PlayTo
return SecurityElement.Escape(value);
}
- public async Task SetNextAvTransport(string value, string header, string metaData)
- {
- var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetNextAVTransportURI");
- if (command == null)
- return;
-
- var dictionary = new Dictionary<string, string>
- {
- {"NextURI", value},
- {"NextURIMetaData", CreateDidlMeta(metaData)}
- };
-
- var service = Properties.Services.FirstOrDefault(s => s.ServiceType == ServiceAvtransportType);
-
- if (service == null)
- {
- throw new InvalidOperationException("Unable to find service");
- }
-
- await new SsdpHttpClient(_httpClient, _config).SendCommandAsync(Properties.BaseUrl, service, command.Name, AvCommands.BuildPost(command, service.ServiceType, value, dictionary), header)
- .ConfigureAwait(false);
-
- RestartTimer();
- }
-
public async Task SetPlay()
{
var command = AvCommands.ServiceActions.FirstOrDefault(c => c.Name == "Play");
@@ -393,6 +370,8 @@ namespace MediaBrowser.Dlna.PlayTo
if (_disposed)
return;
+ const int maxSuccessiveStopReturns = 5;
+
try
{
var transportState = await GetTransportInfo().ConfigureAwait(false);
@@ -431,7 +410,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
_successiveStopCount++;
- if (_successiveStopCount >= 10)
+ if (_successiveStopCount >= maxSuccessiveStopReturns)
{
RestartTimerInactive();
}
@@ -445,7 +424,14 @@ namespace MediaBrowser.Dlna.PlayTo
}
catch (Exception ex)
{
- _logger.ErrorException("Error updating device info", ex);
+ _logger.ErrorException("Error updating device info for {0}", ex, Properties.Name);
+
+ _successiveStopCount++;
+
+ if (_successiveStopCount >= maxSuccessiveStopReturns)
+ {
+ RestartTimerInactive();
+ }
}
}
@@ -458,7 +444,7 @@ namespace MediaBrowser.Dlna.PlayTo
}
catch (Exception ex)
{
- _logger.ErrorException("Error updating device info", ex);
+ _logger.ErrorException("Error updating device volume info for {0}", ex, Properties.Name);
}
}
@@ -771,13 +757,17 @@ namespace MediaBrowser.Dlna.PlayTo
var deviceProperties = new DeviceInfo();
+ var friendlyNames = new List<string>();
+
var name = document.Descendants(uPnpNamespaces.ud.GetName("friendlyName")).FirstOrDefault();
- if (name != null)
- deviceProperties.Name = name.Value;
+ if (name != null && !string.IsNullOrWhiteSpace(name.Value))
+ friendlyNames.Add(name.Value);
- var name2 = document.Descendants(uPnpNamespaces.ud.GetName("roomName")).FirstOrDefault();
- if (name2 != null)
- deviceProperties.Name = name2.Value;
+ var room = document.Descendants(uPnpNamespaces.ud.GetName("roomName")).FirstOrDefault();
+ if (room != null && !string.IsNullOrWhiteSpace(room.Value))
+ friendlyNames.Add(room.Value);
+
+ deviceProperties.Name = string.Join(" ", friendlyNames.ToArray());
var model = document.Descendants(uPnpNamespaces.ud.GetName("modelName")).FirstOrDefault();
if (model != null)
@@ -829,12 +819,12 @@ namespace MediaBrowser.Dlna.PlayTo
foreach (var services in document.Descendants(uPnpNamespaces.ud.GetName("serviceList")))
{
if (services == null)
- return null;
+ continue;
var servicesList = services.Descendants(uPnpNamespaces.ud.GetName("service"));
if (servicesList == null)
- return null;
+ continue;
foreach (var element in servicesList)
{
@@ -851,17 +841,15 @@ namespace MediaBrowser.Dlna.PlayTo
}
}
+ var device = new Device(deviceProperties, httpClient, logger, config);
+
if (isRenderer)
{
- var device = new Device(deviceProperties, httpClient, logger, config);
-
await device.GetRenderingProtocolAsync().ConfigureAwait(false);
await device.GetAVProtocolAsync().ConfigureAwait(false);
-
- return device;
}
- return null;
+ return device;
}
#endregion
diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
index 89d61bb21..9e8d8213f 100644
--- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Session;
@@ -34,7 +33,7 @@ namespace MediaBrowser.Dlna.PlayTo
private readonly IUserManager _userManager;
private readonly IImageProcessor _imageProcessor;
- private readonly SsdpHandler _ssdpHandler;
+ private readonly DeviceDiscovery _deviceDiscovery;
private readonly string _serverAddress;
public bool IsSessionActive
@@ -52,7 +51,7 @@ namespace MediaBrowser.Dlna.PlayTo
private Timer _updateTimer;
- public PlayToController(SessionInfo session, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, SsdpHandler ssdpHandler, string serverAddress)
+ public PlayToController(SessionInfo session, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, DeviceDiscovery deviceDiscovery)
{
_session = session;
_itemRepository = itemRepository;
@@ -61,8 +60,8 @@ namespace MediaBrowser.Dlna.PlayTo
_dlnaManager = dlnaManager;
_userManager = userManager;
_imageProcessor = imageProcessor;
- _ssdpHandler = ssdpHandler;
_serverAddress = serverAddress;
+ _deviceDiscovery = deviceDiscovery;
_logger = logger;
}
@@ -75,33 +74,12 @@ namespace MediaBrowser.Dlna.PlayTo
_device.MediaChanged += _device_MediaChanged;
_device.Start();
- _ssdpHandler.MessageReceived += _SsdpHandler_MessageReceived;
+ _deviceDiscovery.DeviceLeft += _deviceDiscovery_DeviceLeft;
_updateTimer = new Timer(updateTimer_Elapsed, null, 60000, 60000);
}
- private async void updateTimer_Elapsed(object state)
- {
- if (DateTime.UtcNow >= _device.DateLastActivity.AddSeconds(120))
- {
- try
- {
- // Session is inactive, mark it for Disposal and don't start the elapsed timer.
- _sessionManager.ReportSessionEnded(_session.Id);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error in ReportSessionEnded", ex);
- }
- }
- }
-
- private string GetServerAddress()
- {
- return _serverAddress;
- }
-
- void _SsdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e)
+ void _deviceDiscovery_DeviceLeft(object sender, SsdpMessageEventArgs e)
{
string nts;
e.Headers.TryGetValue("NTS", out nts);
@@ -112,9 +90,7 @@ namespace MediaBrowser.Dlna.PlayTo
string nt;
if (!e.Headers.TryGetValue("NT", out nt)) nt = String.Empty;
- if (String.Equals(e.Method, "NOTIFY", StringComparison.OrdinalIgnoreCase) &&
- String.Equals(nts, "ssdp:byebye", StringComparison.OrdinalIgnoreCase) &&
- usn.IndexOf(_device.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1 &&
+ if ( usn.IndexOf(_device.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1 &&
!_disposed)
{
if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) != -1 ||
@@ -132,6 +108,27 @@ namespace MediaBrowser.Dlna.PlayTo
}
}
+ private void updateTimer_Elapsed(object state)
+ {
+ if (DateTime.UtcNow >= _device.DateLastActivity.AddSeconds(120))
+ {
+ try
+ {
+ // Session is inactive, mark it for Disposal and don't start the elapsed timer.
+ _sessionManager.ReportSessionEnded(_session.Id);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error in ReportSessionEnded", ex);
+ }
+ }
+ }
+
+ private string GetServerAddress()
+ {
+ return _serverAddress;
+ }
+
async void _device_MediaChanged(object sender, MediaChangedEventArgs e)
{
try
@@ -504,7 +501,7 @@ namespace MediaBrowser.Dlna.PlayTo
if (streamInfo.MediaType == DlnaProfileType.Video)
{
- return new ContentFeatureBuilder(profile)
+ var list = new ContentFeatureBuilder(profile)
.BuildVideoHeader(streamInfo.Container,
streamInfo.VideoCodec,
streamInfo.AudioCodec,
@@ -523,6 +520,8 @@ namespace MediaBrowser.Dlna.PlayTo
streamInfo.TargetPacketLength,
streamInfo.TranscodeSeekInfo,
streamInfo.IsTargetAnamorphic);
+
+ return list.FirstOrDefault();
}
return null;
@@ -540,7 +539,7 @@ namespace MediaBrowser.Dlna.PlayTo
MediaSources = mediaSources,
Profile = profile,
DeviceId = deviceId,
- MaxBitrate = profile.MaxBitrate,
+ MaxBitrate = profile.MaxStreamingBitrate,
MediaSourceId = mediaSourceId,
AudioStreamIndex = audioStreamIndex,
SubtitleStreamIndex = subtitleStreamIndex
@@ -560,7 +559,7 @@ namespace MediaBrowser.Dlna.PlayTo
MediaSources = mediaSources,
Profile = profile,
DeviceId = deviceId,
- MaxBitrate = profile.MaxBitrate,
+ MaxBitrate = profile.MaxStreamingBitrate,
MediaSourceId = mediaSourceId
}),
@@ -603,9 +602,7 @@ namespace MediaBrowser.Dlna.PlayTo
_currentPlaylistIndex = index;
var currentitem = Playlist[index];
- var dlnaheaders = GetDlnaHeaders(currentitem);
-
- await _device.SetAvTransport(currentitem.StreamUrl, dlnaheaders, currentitem.Didl);
+ await _device.SetAvTransport(currentitem.StreamUrl, GetDlnaHeaders(currentitem), currentitem.Didl);
var streamInfo = currentitem.StreamInfo;
if (streamInfo.StartPositionTicks > 0 && streamInfo.IsDirectStream)
@@ -626,7 +623,7 @@ namespace MediaBrowser.Dlna.PlayTo
_device.PlaybackProgress -= _device_PlaybackProgress;
_device.PlaybackStopped -= _device_PlaybackStopped;
_device.MediaChanged -= _device_MediaChanged;
- _ssdpHandler.MessageReceived -= _SsdpHandler_MessageReceived;
+ _deviceDiscovery.DeviceLeft -= _deviceDiscovery_DeviceLeft;
DisposeUpdateTimer();
@@ -734,7 +731,7 @@ namespace MediaBrowser.Dlna.PlayTo
var info = StreamParams.ParseFromUrl(media.Url, _libraryManager);
var progress = GetProgressInfo(media, info);
- if (info.Item != null && !info.IsDirectStream)
+ if (info.Item != null)
{
var newPosition = progress.PositionTicks ?? 0;
@@ -760,7 +757,7 @@ namespace MediaBrowser.Dlna.PlayTo
var info = StreamParams.ParseFromUrl(media.Url, _libraryManager);
var progress = GetProgressInfo(media, info);
- if (info.Item != null && !info.IsDirectStream)
+ if (info.Item != null)
{
var newPosition = progress.PositionTicks ?? 0;
diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs
index 095c6a893..a52c38086 100644
--- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs
@@ -13,315 +13,108 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
-using System.Net.NetworkInformation;
-using System.Net.Sockets;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
namespace MediaBrowser.Dlna.PlayTo
{
class PlayToManager : IDisposable
{
- private bool _disposed;
private readonly ILogger _logger;
private readonly ISessionManager _sessionManager;
- private readonly IHttpClient _httpClient;
- private readonly CancellationTokenSource _tokenSource;
private readonly IItemRepository _itemRepository;
private readonly ILibraryManager _libraryManager;
private readonly IUserManager _userManager;
private readonly IDlnaManager _dlnaManager;
- private readonly IServerConfigurationManager _config;
private readonly IServerApplicationHost _appHost;
private readonly IImageProcessor _imageProcessor;
+ private readonly IHttpClient _httpClient;
+ private readonly IServerConfigurationManager _config;
- private readonly SsdpHandler _ssdpHandler;
+ private readonly DeviceDiscovery _deviceDiscovery;
- public PlayToManager(ILogger logger, IServerConfigurationManager config, ISessionManager sessionManager, IHttpClient httpClient, IItemRepository itemRepository, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, SsdpHandler ssdpHandler)
+ public PlayToManager(ILogger logger, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, DeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config)
{
- _tokenSource = new CancellationTokenSource();
-
_logger = logger;
_sessionManager = sessionManager;
- _httpClient = httpClient;
_itemRepository = itemRepository;
_libraryManager = libraryManager;
_userManager = userManager;
_dlnaManager = dlnaManager;
_appHost = appHost;
_imageProcessor = imageProcessor;
- _ssdpHandler = ssdpHandler;
+ _deviceDiscovery = deviceDiscovery;
+ _httpClient = httpClient;
_config = config;
}
public void Start()
{
- foreach (var network in GetNetworkInterfaces())
- {
- _logger.Debug("Found interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
-
- if (!network.SupportsMulticast || OperationalStatus.Up != network.OperationalStatus || !network.GetIPProperties().MulticastAddresses.Any())
- continue;
-
- var ipV4 = network.GetIPProperties().GetIPv4Properties();
- if (null == ipV4)
- continue;
-
- var localIp = network.GetIPProperties().UnicastAddresses
- .Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork)
- .Select(i => i.Address)
- .FirstOrDefault();
-
- if (localIp != null)
- {
- try
- {
- CreateListener(localIp, ipV4.Index);
- }
- catch (Exception e)
- {
- _logger.ErrorException("Failed to Initilize Socket", e);
- }
- }
- }
- }
-
- private IEnumerable<NetworkInterface> GetNetworkInterfaces()
- {
- try
- {
- return NetworkInterface.GetAllNetworkInterfaces();
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
- return new List<NetworkInterface>();
- }
- }
-
- /// <summary>
- /// Creates a socket for the interface and listends for data.
- /// </summary>
- /// <param name="localIp">The local ip.</param>
- /// <param name="networkInterfaceIndex">Index of the network interface.</param>
- private void CreateListener(IPAddress localIp, int networkInterfaceIndex)
- {
- Task.Factory.StartNew(async (o) =>
- {
- try
- {
- var socket = GetMulticastSocket(networkInterfaceIndex);
-
- var endPoint = new IPEndPoint(localIp, 1900);
-
- socket.Bind(endPoint);
-
- _logger.Info("Creating SSDP listener on {0}, network interface index {1}", localIp, networkInterfaceIndex);
-
- var receiveBuffer = new byte[64000];
-
- CreateNotifier(socket);
-
- while (!_tokenSource.IsCancellationRequested)
- {
- var receivedBytes = await socket.ReceiveAsync(receiveBuffer, 0, 64000);
-
- if (receivedBytes > 0)
- {
- var args = SsdpHelper.ParseSsdpResponse(receiveBuffer, endPoint);
-
- TryCreateController(args, localIp);
- }
- }
-
- _logger.Info("SSDP listener - Task completed");
- }
- catch (OperationCanceledException)
- {
- }
- catch (Exception e)
- {
- _logger.ErrorException("Error in listener", e);
- }
-
- }, _tokenSource.Token, TaskCreationOptions.LongRunning);
+ _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered;
}
- private void TryCreateController(SsdpMessageEventArgs args, IPAddress localIp)
+ async void _deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e)
{
- string nts;
- args.Headers.TryGetValue("NTS", out nts);
+ var localIp = e.LocalIp;
string usn;
- if (!args.Headers.TryGetValue("USN", out usn)) usn = string.Empty;
+ if (!e.Headers.TryGetValue("USN", out usn)) usn = string.Empty;
string nt;
- if (!args.Headers.TryGetValue("NT", out nt)) nt = string.Empty;
-
- // Don't create a new controller when a device is indicating it's shutting down
- if (string.Equals(nts, "ssdp:byebye", StringComparison.OrdinalIgnoreCase))
- {
- return;
- }
+ if (!e.Headers.TryGetValue("NT", out nt)) nt = string.Empty;
+ string location;
+ if (!e.Headers.TryGetValue("Location", out location)) location = string.Empty;
+
// It has to report that it's a media renderer
if (usn.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1 &&
nt.IndexOf("MediaRenderer:", StringComparison.OrdinalIgnoreCase) == -1)
{
return;
}
-
- // Need to be able to download device description
- string location;
- if (!args.Headers.TryGetValue("Location", out location) ||
- string.IsNullOrEmpty(location))
- {
- return;
- }
-
- if (_config.Configuration.DlnaOptions.EnableDebugLogging)
- {
- var headerTexts = args.Headers.Select(i => string.Format("{0}={1}", i.Key, i.Value));
- var headerText = string.Join(",", headerTexts.ToArray());
-
- _logger.Debug("{0} PlayTo message received from {1}. Headers: {2}", args.Method, args.EndPoint, headerText);
- }
if (_sessionManager.Sessions.Any(i => usn.IndexOf(i.DeviceId, StringComparison.OrdinalIgnoreCase) != -1))
{
return;
}
- Task.Run(async () =>
- {
- try
- {
- await CreateController(new Uri(location), localIp).ConfigureAwait(false);
- }
- catch (OperationCanceledException)
- {
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error creating play to controller", ex);
- }
- });
- }
-
- private void CreateNotifier(IPAddress localIp)
- {
- Task.Factory.StartNew(async (o) =>
+ try
{
- try
- {
- while (true)
- {
- _ssdpHandler.SendRendererSearchMessage(new IPEndPoint(localIp, 1900));
+ var uri = new Uri(location);
- var delay = _config.Configuration.DlnaOptions.ClientDiscoveryIntervalSeconds * 1000;
+ var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger).ConfigureAwait(false);
- await Task.Delay(delay, _tokenSource.Token).ConfigureAwait(false);
- }
- }
- catch (OperationCanceledException)
- {
- }
- catch (Exception ex)
+ if (device.RendererCommands != null)
{
- _logger.ErrorException("Error in notifier", ex);
- }
-
- }, _tokenSource.Token, TaskCreationOptions.LongRunning);
-
- }
+ var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null)
+ .ConfigureAwait(false);
- private void CreateNotifier(Socket socket)
- {
- Task.Factory.StartNew(async (o) =>
- {
- try
- {
- var msg = new SsdpMessageBuilder().BuildRendererDiscoveryMessage();
- var request = Encoding.UTF8.GetBytes(msg);
+ var controller = sessionInfo.SessionController as PlayToController;
- while (true)
+ if (controller == null)
{
- socket.SendTo(request, new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900));
+ var serverAddress = GetServerAddress(localIp);
- var delay = _config.Configuration.DlnaOptions.ClientDiscoveryIntervalSeconds * 1000;
+ sessionInfo.SessionController = controller = new PlayToController(sessionInfo,
+ _sessionManager,
+ _itemRepository,
+ _libraryManager,
+ _logger,
+ _dlnaManager,
+ _userManager,
+ _imageProcessor,
+ serverAddress,
+ _deviceDiscovery);
- await Task.Delay(delay).ConfigureAwait(false);
- }
- }
- catch (OperationCanceledException)
- {
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error in notifier", ex);
- }
+ controller.Init(device);
- }, _tokenSource.Token, TaskCreationOptions.LongRunning);
-
- }
-
- /// <summary>
- /// Gets a socket configured for SDDP multicasting.
- /// </summary>
- /// <returns></returns>
- private Socket GetMulticastSocket(int networkInterfaceIndex)
- {
- var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
- socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
- socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), networkInterfaceIndex));
- socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4);
- return socket;
- }
-
- /// <summary>
- /// Creates a new DlnaSessionController.
- /// and logs the session in SessionManager
- /// </summary>
- /// <param name="uri">The URI.</param>
- /// <returns></returns>
- private async Task CreateController(Uri uri, IPAddress localIp)
- {
- var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger).ConfigureAwait(false);
-
- if (device != null && device.RendererCommands != null)
- {
- var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, _appHost.ApplicationVersion.ToString(), device.Properties.UUID, device.Properties.Name, uri.OriginalString, null)
- .ConfigureAwait(false);
+ var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ??
+ _dlnaManager.GetDefaultProfile();
- var controller = sessionInfo.SessionController as PlayToController;
-
- if (controller == null)
- {
- var serverAddress = GetServerAddress(localIp);
-
- sessionInfo.SessionController = controller = new PlayToController(sessionInfo,
- _sessionManager,
- _itemRepository,
- _libraryManager,
- _logger,
- _dlnaManager,
- _userManager,
- _imageProcessor,
- _ssdpHandler,
- serverAddress);
-
- controller.Init(device);
-
- var profile = _dlnaManager.GetProfile(device.Properties.ToDeviceIdentification()) ??
- _dlnaManager.GetDefaultProfile();
-
- _sessionManager.ReportCapabilities(sessionInfo.Id, new SessionCapabilities
- {
- PlayableMediaTypes = profile.GetSupportedMediaTypes(),
+ _sessionManager.ReportCapabilities(sessionInfo.Id, new SessionCapabilities
+ {
+ PlayableMediaTypes = profile.GetSupportedMediaTypes(),
- SupportedCommands = new List<string>
+ SupportedCommands = new List<string>
{
GeneralCommandType.VolumeDown.ToString(),
GeneralCommandType.VolumeUp.ToString(),
@@ -333,12 +126,17 @@ namespace MediaBrowser.Dlna.PlayTo
GeneralCommandType.SetSubtitleStreamIndex.ToString()
},
- SupportsMediaControl = true
- });
+ SupportsMediaControl = true
+ });
- _logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
+ _logger.Info("DLNA Session created for {0} - {1}", device.Properties.Name, device.Properties.ModelName);
+ }
}
}
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error creating PlayTo device.", ex);
+ }
}
private string GetServerAddress(IPAddress localIp)
@@ -353,11 +151,7 @@ namespace MediaBrowser.Dlna.PlayTo
public void Dispose()
{
- if (!_disposed)
- {
- _disposed = true;
- _tokenSource.Cancel();
- }
+ _deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered;
}
}
}
diff --git a/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs b/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs
index 796ccb004..83d7f322d 100644
--- a/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlaylistItemFactory.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Session;
using System;
using System.Globalization;
using System.IO;
@@ -29,7 +30,7 @@ namespace MediaBrowser.Dlna.PlayTo
if (directPlay != null)
{
- playlistItem.StreamInfo.IsDirectStream = true;
+ playlistItem.StreamInfo.PlayMethod = PlayMethod.DirectStream;
playlistItem.StreamInfo.Container = Path.GetExtension(item.Path);
return playlistItem;
@@ -40,7 +41,7 @@ namespace MediaBrowser.Dlna.PlayTo
if (transcodingProfile != null)
{
- playlistItem.StreamInfo.IsDirectStream = true;
+ playlistItem.StreamInfo.PlayMethod = PlayMethod.Transcode;
playlistItem.StreamInfo.Container = "." + transcodingProfile.Container.TrimStart('.');
}
diff --git a/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs b/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs
index 22d4797a3..ccc7d46e6 100644
--- a/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs
+++ b/MediaBrowser.Dlna/PlayTo/SsdpHttpClient.cs
@@ -58,7 +58,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
Url = url,
UserAgent = USERAGENT,
- LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging,
+ LogRequest = _config.GetDlnaConfiguration().EnableDebugLogging,
LogErrorResponseBody = true
};
@@ -76,7 +76,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
Url = url,
UserAgent = USERAGENT,
- LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging,
+ LogRequest = _config.GetDlnaConfiguration().EnableDebugLogging,
LogErrorResponseBody = true
};
@@ -103,7 +103,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
Url = url,
UserAgent = USERAGENT,
- LogRequest = _config.Configuration.DlnaOptions.EnableDebugLogging,
+ LogRequest = _config.GetDlnaConfiguration().EnableDebugLogging,
LogErrorResponseBody = true
};
diff --git a/MediaBrowser.Dlna/PlayTo/TransportCommands.cs b/MediaBrowser.Dlna/PlayTo/TransportCommands.cs
index 2f2276a87..c49767cfb 100644
--- a/MediaBrowser.Dlna/PlayTo/TransportCommands.cs
+++ b/MediaBrowser.Dlna/PlayTo/TransportCommands.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Dlna.Common;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
+using MediaBrowser.Dlna.Ssdp;
namespace MediaBrowser.Dlna.PlayTo
{
@@ -146,34 +147,6 @@ namespace MediaBrowser.Dlna.PlayTo
return string.Format(CommandBase, action.Name, xmlNamesapce, stateString);
}
- public string BuildSearchPost(ServiceAction action, string xmlNamesapce, object value, string commandParameter = "")
- {
- var stateString = string.Empty;
-
- foreach (var arg in action.ArgumentList)
- {
- if (arg.Direction == "out")
- continue;
-
- if (arg.Name == "ObjectID")
- stateString += BuildArgumentXml(arg, value.ToString());
- else if (arg.Name == "Filter")
- stateString += BuildArgumentXml(arg, "*");
- else if (arg.Name == "StartingIndex")
- stateString += BuildArgumentXml(arg, "0");
- else if (arg.Name == "RequestedCount")
- stateString += BuildArgumentXml(arg, "200");
- else if (arg.Name == "BrowseFlag")
- stateString += BuildArgumentXml(arg, null, "BrowseDirectChildren");
- else if (arg.Name == "SortCriteria")
- stateString += BuildArgumentXml(arg, "");
- else
- stateString += BuildArgumentXml(arg, value.ToString(), commandParameter);
- }
-
- return string.Format(CommandBase, action.Name, xmlNamesapce, stateString);
- }
-
public string BuildPost(ServiceAction action, string xmlNamesapce, object value, Dictionary<string, string> dictionary)
{
var stateString = string.Empty;
@@ -193,12 +166,12 @@ namespace MediaBrowser.Dlna.PlayTo
private string BuildArgumentXml(Argument argument, string value, string commandParameter = "")
{
- var state = StateVariables.FirstOrDefault(a => a.Name == argument.RelatedStateVariable);
+ var state = StateVariables.FirstOrDefault(a => string.Equals(a.Name, argument.RelatedStateVariable, StringComparison.OrdinalIgnoreCase));
if (state != null)
{
- var sendValue = (state.AllowedValues.FirstOrDefault(a => a == commandParameter) ??
- state.AllowedValues.FirstOrDefault()) ??
+ var sendValue = state.AllowedValues.FirstOrDefault(a => string.Equals(a, commandParameter, StringComparison.OrdinalIgnoreCase)) ??
+ state.AllowedValues.FirstOrDefault() ??
value;
return string.Format("<{0} xmlns:dt=\"urn:schemas-microsoft-com:datatypes\" dt:dt=\"{1}\">{2}</{0}>", argument.Name, state.DataType ?? "string", sendValue);
diff --git a/MediaBrowser.Dlna/PlayTo/UpnpContainer.cs b/MediaBrowser.Dlna/PlayTo/UpnpContainer.cs
index 95bafc1fb..e044d6b30 100644
--- a/MediaBrowser.Dlna/PlayTo/UpnpContainer.cs
+++ b/MediaBrowser.Dlna/PlayTo/UpnpContainer.cs
@@ -1,5 +1,6 @@
using System;
using System.Xml.Linq;
+using MediaBrowser.Dlna.Ssdp;
namespace MediaBrowser.Dlna.PlayTo
{
diff --git a/MediaBrowser.Dlna/Profiles/AndroidProfile.cs b/MediaBrowser.Dlna/Profiles/AndroidProfile.cs
new file mode 100644
index 000000000..c9dc1aa2c
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/AndroidProfile.cs
@@ -0,0 +1,178 @@
+using MediaBrowser.Model.Dlna;
+using System.Xml.Serialization;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ [XmlRoot("Profile")]
+ public class AndroidProfile : DefaultProfile
+ {
+ public AndroidProfile()
+ {
+ Name = "Android";
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+ new TranscodingProfile
+ {
+ Protocol = "hls",
+ Container = "ts",
+ VideoCodec = "h264",
+ AudioCodec = "aac",
+ Type = DlnaProfileType.Video,
+ VideoProfile = "Baseline",
+ Context = EncodingContext.Streaming
+ },
+ new TranscodingProfile
+ {
+ Container = "mp4",
+ VideoCodec = "h264",
+ AudioCodec = "aac",
+ Type = DlnaProfileType.Video,
+ VideoProfile = "Baseline",
+ Context = EncodingContext.Static
+ }
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "mp4",
+ VideoCodec = "h264,mpeg4",
+ AudioCodec = "aac",
+ Type = DlnaProfileType.Video
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "mp4,aac",
+ AudioCodec = "aac",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "mp3",
+ AudioCodec = "mp3",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "flac",
+ AudioCodec = "flac",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "ogg",
+ AudioCodec = "vorbis",
+ Type = DlnaProfileType.Audio
+ },
+
+ new DirectPlayProfile
+ {
+ Container = "jpeg,png,gif,bmp",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Type = CodecType.Video,
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.NotEquals,
+ Property = ProfileConditionValue.IsAnamorphic,
+ Value = "true",
+ IsRequired = false
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitDepth,
+ Value = "8",
+ IsRequired = false
+ },
+ // TODO: Add HasScalingMatrix != true, IsRequired false
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.VideoAudio,
+ Codec = "aac",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "2"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.Audio,
+ Codec = "aac",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "2"
+ }
+ }
+ },
+
+ new CodecProfile
+ {
+ Type = CodecType.Audio,
+ Codec = "mp3",
+ Conditions = new []
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "2"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioBitrate,
+ Value = "320000"
+ }
+ }
+ }
+ };
+
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
index 8885eddfc..5c317d94d 100644
--- a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
@@ -24,8 +24,18 @@ namespace MediaBrowser.Dlna.Profiles
AlbumArtPn = "JPEG_SM";
- MaxAlbumArtHeight = 512;
- MaxAlbumArtWidth = 512;
+ MaxAlbumArtHeight = 480;
+ MaxAlbumArtWidth = 480;
+
+ MaxIconWidth = 48;
+ MaxIconHeight = 48;
+
+ MaxStreamingBitrate = 8000000;
+ MaxStaticBitrate = 8000000;
+ MusicStreamingTranscodingBitrate = 128000;
+ MusicSyncBitrate = 128000;
+
+ EnableAlbumArtInDidl = false;
TranscodingProfiles = new[]
{
diff --git a/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs b/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs
index 2f2d4f3ce..f8451bdfd 100644
--- a/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/DenonAvrProfile.cs
@@ -1,6 +1,5 @@
-using System.Xml.Serialization;
-using MediaBrowser.Controller.Dlna;
-using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Dlna;
+using System.Xml.Serialization;
namespace MediaBrowser.Dlna.Profiles
{
diff --git a/MediaBrowser.Dlna/Profiles/DirectTvProfile.cs b/MediaBrowser.Dlna/Profiles/DirectTvProfile.cs
new file mode 100644
index 000000000..585f8652e
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/DirectTvProfile.cs
@@ -0,0 +1,117 @@
+using MediaBrowser.Model.Dlna;
+using System.Xml.Serialization;
+
+namespace MediaBrowser.Dlna.Profiles
+{
+ [XmlRoot("Profile")]
+ public class DirectTvProfile : DefaultProfile
+ {
+ public DirectTvProfile()
+ {
+ Name = "DirecTV HD-DVR";
+
+ TimelineOffsetSeconds = 10;
+ RequiresPlainFolders = true;
+ RequiresPlainVideoItems = true;
+
+ Identification = new DeviceIdentification
+ {
+ Headers = new[]
+ {
+ new HttpHeaderInfo
+ {
+ Match = HeaderMatchType.Substring,
+ Name = "User-Agent",
+ Value = "DIRECTV"
+ }
+ },
+
+ FriendlyName = "^DIRECTV.*$"
+ };
+
+ DirectPlayProfiles = new[]
+ {
+ new DirectPlayProfile
+ {
+ Container = "mpeg",
+ VideoCodec = "mpeg2video",
+ AudioCodec = "mp2",
+ Type = DlnaProfileType.Video
+ },
+ new DirectPlayProfile
+ {
+ Container = "jpeg,jpg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ TranscodingProfiles = new[]
+ {
+ new TranscodingProfile
+ {
+ Container = "mpeg",
+ VideoCodec = "mpeg2video",
+ AudioCodec = "mp2",
+ Type = DlnaProfileType.Video
+ },
+ new TranscodingProfile
+ {
+ Container = "jpeg",
+ Type = DlnaProfileType.Photo
+ }
+ };
+
+ CodecProfiles = new[]
+ {
+ new CodecProfile
+ {
+ Codec = "mpeg2video",
+ Type = CodecType.Video,
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Width,
+ Value = "1920"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.Height,
+ Value = "1080"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoFramerate,
+ Value = "30"
+ },
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.VideoBitrate,
+ Value = "8192000"
+ }
+ }
+ },
+ new CodecProfile
+ {
+ Codec = "mp2",
+ Type = CodecType.Audio,
+
+ Conditions = new[]
+ {
+ new ProfileCondition
+ {
+ Condition = ProfileConditionType.LessThanEqual,
+ Property = ProfileConditionValue.AudioChannels,
+ Value = "2"
+ }
+ }
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs b/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs
index 26229b62b..533f4ecf4 100644
--- a/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/PanasonicVieraProfile.cs
@@ -192,6 +192,15 @@ namespace MediaBrowser.Dlna.Profiles
}
}
};
+
+ SubtitleProfiles = new[]
+ {
+ new SubtitleProfile
+ {
+ Format = "srt",
+ Method = SubtitleDeliveryMethod.External
+ }
+ };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs b/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs
index d9581ff2c..b0eef109d 100644
--- a/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/SamsungSmartTvProfile.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Model.Dlna;
using System.Xml.Serialization;
+using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Dlna.Profiles
{
@@ -338,6 +339,21 @@ namespace MediaBrowser.Dlna.Profiles
}
};
+ SubtitleProfiles = new[]
+ {
+ new SubtitleProfile
+ {
+ Format = "smi",
+ Method = SubtitleDeliveryMethod.External,
+ DidlMode = "CaptionInfoEx"
+ },
+ new SubtitleProfile
+ {
+ Format = "srt",
+ Method = SubtitleDeliveryMethod.External,
+ DidlMode = "CaptionInfoEx"
+ }
+ };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/Windows81Profile.cs b/MediaBrowser.Dlna/Profiles/Windows81Profile.cs
index 5e74884a2..3f74a0e88 100644
--- a/MediaBrowser.Dlna/Profiles/Windows81Profile.cs
+++ b/MediaBrowser.Dlna/Profiles/Windows81Profile.cs
@@ -30,7 +30,8 @@ namespace MediaBrowser.Dlna.Profiles
VideoCodec = "h264",
AudioCodec = "aac",
Type = DlnaProfileType.Video,
- VideoProfile = "Baseline"
+ VideoProfile = "Baseline",
+ Context = EncodingContext.Streaming
},
new TranscodingProfile
{
@@ -38,7 +39,16 @@ namespace MediaBrowser.Dlna.Profiles
VideoCodec = "h264",
AudioCodec = "aac",
Type = DlnaProfileType.Video,
- VideoProfile = "Baseline"
+ VideoProfile = "Baseline",
+ Context = EncodingContext.Streaming
+ },
+ new TranscodingProfile
+ {
+ Container = "mp4",
+ VideoCodec = "h264",
+ AudioCodec = "aac,ac3,eac3",
+ Type = DlnaProfileType.Video,
+ Context = EncodingContext.Static
}
};
@@ -145,6 +155,14 @@ namespace MediaBrowser.Dlna.Profiles
}
};
+ SubtitleProfiles = new[]
+ {
+ new SubtitleProfile
+ {
+ Format = "vtt",
+ Method = SubtitleDeliveryMethod.External
+ }
+ };
}
}
}
diff --git a/MediaBrowser.Dlna/Profiles/WindowsPhoneProfile.cs b/MediaBrowser.Dlna/Profiles/WindowsPhoneProfile.cs
index 66949c533..49e6319dc 100644
--- a/MediaBrowser.Dlna/Profiles/WindowsPhoneProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/WindowsPhoneProfile.cs
@@ -25,7 +25,8 @@ namespace MediaBrowser.Dlna.Profiles
VideoCodec = "h264",
AudioCodec = "aac",
Type = DlnaProfileType.Video,
- VideoProfile = "Baseline"
+ VideoProfile = "Baseline",
+ Context = EncodingContext.Streaming
},
new TranscodingProfile
{
@@ -33,7 +34,17 @@ namespace MediaBrowser.Dlna.Profiles
VideoCodec = "h264",
AudioCodec = "aac",
Type = DlnaProfileType.Video,
- VideoProfile = "Baseline"
+ VideoProfile = "Baseline",
+ Context = EncodingContext.Streaming
+ },
+ new TranscodingProfile
+ {
+ Container = "mp4",
+ VideoCodec = "h264",
+ AudioCodec = "aac",
+ Type = DlnaProfileType.Video,
+ VideoProfile = "Baseline",
+ Context = EncodingContext.Static
}
};
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Android.xml b/MediaBrowser.Dlna/Profiles/Xml/Android.xml
new file mode 100644
index 000000000..642f93c14
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/Xml/Android.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <Name>Android</Name>
+ <FriendlyName>Media Browser</FriendlyName>
+ <Manufacturer>Media Browser</Manufacturer>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
+ <ModelName>Media Browser</ModelName>
+ <ModelDescription>Media Browser</ModelDescription>
+ <ModelNumber>Media Browser</ModelNumber>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
+ <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+ <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+ <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+ <AlbumArtPn>JPEG_SM</AlbumArtPn>
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
+ <XDlnaDoc>DMS-1.50</XDlnaDoc>
+ <ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
+ <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+ <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+ <RequiresPlainFolders>false</RequiresPlainFolders>
+ <XmlRootAttributes />
+ <DirectPlayProfiles>
+ <DirectPlayProfile container="mp4" audioCodec="aac" videoCodec="h264,mpeg4" type="Video" />
+ <DirectPlayProfile container="mp4,aac" audioCodec="aac" type="Audio" />
+ <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
+ <DirectPlayProfile container="flac" audioCodec="flac" type="Audio" />
+ <DirectPlayProfile container="ogg" audioCodec="vorbis" type="Audio" />
+ <DirectPlayProfile container="jpeg,png,gif,bmp" type="Photo" />
+ </DirectPlayProfiles>
+ <TranscodingProfiles>
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" protocol="hls" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="Baseline" context="Streaming" />
+ <TranscodingProfile container="mp4" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="Baseline" context="Static" />
+ </TranscodingProfiles>
+ <ContainerProfiles />
+ <CodecProfiles>
+ <CodecProfile type="Video">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+ <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+ <ProfileCondition condition="NotEquals" property="IsAnamorphic" value="true" isRequired="false" />
+ <ProfileCondition condition="LessThanEqual" property="VideoBitDepth" value="8" isRequired="false" />
+ </Conditions>
+ </CodecProfile>
+ <CodecProfile type="VideoAudio" codec="aac">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
+ </Conditions>
+ </CodecProfile>
+ <CodecProfile type="Audio" codec="aac">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
+ </Conditions>
+ </CodecProfile>
+ <CodecProfile type="Audio" codec="mp3">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
+ <ProfileCondition condition="LessThanEqual" property="AudioBitrate" value="320000" isRequired="true" />
+ </Conditions>
+ </CodecProfile>
+ </CodecProfiles>
+ <ResponseProfiles />
+ <SubtitleProfiles />
+</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Default.xml b/MediaBrowser.Dlna/Profiles/Xml/Default.xml
index a94938ecd..61aebdb89 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Default.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Default.xml
@@ -12,11 +12,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
@@ -28,10 +31,11 @@
<DirectPlayProfile container="avi,mp4" type="Video" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles />
<CodecProfiles />
<ResponseProfiles />
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
index 7c6ba70de..b9b7b6e8e 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
@@ -17,11 +17,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
@@ -32,10 +35,11 @@
<DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles />
<CodecProfiles />
<ResponseProfiles />
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml b/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml
new file mode 100644
index 000000000..c6ca13e04
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <Name>DirecTV HD-DVR</Name>
+ <Identification>
+ <FriendlyName>^DIRECTV.*$</FriendlyName>
+ <Headers>
+ <HttpHeaderInfo name="User-Agent" value="DIRECTV" match="Substring" />
+ </Headers>
+ </Identification>
+ <FriendlyName>Media Browser</FriendlyName>
+ <Manufacturer>Media Browser</Manufacturer>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
+ <ModelName>Media Browser</ModelName>
+ <ModelDescription>Media Browser</ModelDescription>
+ <ModelNumber>Media Browser</ModelNumber>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
+ <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+ <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+ <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+ <AlbumArtPn>JPEG_SM</AlbumArtPn>
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
+ <XDlnaDoc>DMS-1.50</XDlnaDoc>
+ <ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
+ <TimelineOffsetSeconds>10</TimelineOffsetSeconds>
+ <RequiresPlainVideoItems>true</RequiresPlainVideoItems>
+ <RequiresPlainFolders>true</RequiresPlainFolders>
+ <XmlRootAttributes />
+ <DirectPlayProfiles>
+ <DirectPlayProfile container="mpeg" audioCodec="mp2" videoCodec="mpeg2video" type="Video" />
+ <DirectPlayProfile container="jpeg,jpg" type="Photo" />
+ </DirectPlayProfiles>
+ <TranscodingProfiles>
+ <TranscodingProfile container="mpeg" type="Video" videoCodec="mpeg2video" audioCodec="mp2" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ </TranscodingProfiles>
+ <ContainerProfiles />
+ <CodecProfiles>
+ <CodecProfile type="Video" codec="mpeg2video">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="Width" value="1920" isRequired="true" />
+ <ProfileCondition condition="LessThanEqual" property="Height" value="1080" isRequired="true" />
+ <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="30" isRequired="true" />
+ <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="8192000" isRequired="true" />
+ </Conditions>
+ </CodecProfile>
+ <CodecProfile type="Audio" codec="mp2">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
+ </Conditions>
+ </CodecProfile>
+ </CodecProfiles>
+ <ResponseProfiles />
+ <SubtitleProfiles />
+</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
index fe1e945b7..fd5363529 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
@@ -18,11 +18,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>10</TimelineOffsetSeconds>
@@ -37,9 +40,9 @@
<DirectPlayProfile container="jpeg" type="Photo" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Photo">
@@ -72,4 +75,5 @@
</CodecProfile>
</CodecProfiles>
<ResponseProfiles />
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
index f14417168..d2cfae46b 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
@@ -16,11 +16,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
@@ -32,10 +35,11 @@
<DirectPlayProfile container="avi,mp4,mkv,ts" type="Video" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles />
<CodecProfiles />
<ResponseProfiles />
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml b/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml
index 902d749f0..b8360d95c 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml
@@ -18,11 +18,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
@@ -38,10 +41,11 @@
<DirectPlayProfile container="ogg" audioCodec="vorbis" type="Audio" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles />
<CodecProfiles />
<ResponseProfiles />
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
index 2bc2bf4c4..de767b932 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
@@ -19,11 +19,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>10</TimelineOffsetSeconds>
@@ -45,9 +48,9 @@
<DirectPlayProfile container="jpeg" type="Photo" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Photo">
@@ -67,4 +70,7 @@
</CodecProfile>
</CodecProfiles>
<ResponseProfiles />
+ <SubtitleProfiles>
+ <SubtitleProfile format="srt" method="External" />
+ </SubtitleProfiles>
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
index 964e49ed6..25dac2f84 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
@@ -18,11 +18,14 @@
<EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
@@ -45,9 +48,9 @@
<DirectPlayProfile container="jpeg" type="Photo" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Photo">
@@ -105,4 +108,8 @@
<Conditions />
</ResponseProfile>
</ResponseProfiles>
+ <SubtitleProfiles>
+ <SubtitleProfile format="smi" method="External" didlMode="CaptionInfoEx" />
+ <SubtitleProfile format="srt" method="External" didlMode="CaptionInfoEx" />
+ </SubtitleProfiles>
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
index 3a7e99eaa..65f3393ff 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
@@ -18,11 +18,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/divx:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/flac:DLNA.ORG_PN=FLAC;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/ogg:DLNA.ORG_PN=OGG;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/gif:DLNA.ORG_PN=GIF_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_JP_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-flv:DLNA.ORG_PN=FLV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-dvr:DLNA.ORG_PN=DVR_MS;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/wtv:DLNA.ORG_PN=WTV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/ogg:DLNA.ORG_PN=OGV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.rn-realvideo:DLNA.ORG_PN=REAL_VIDEO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_3GPP_P0_L10_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_MP4_P0_L10_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
@@ -43,9 +46,9 @@
<DirectPlayProfile container="jpeg" type="Photo" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Photo">
@@ -70,4 +73,5 @@
</CodecProfile>
</CodecProfiles>
<ResponseProfiles />
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
index 61b5d1a05..c47e5045e 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
@@ -20,11 +20,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/divx:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMABASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMAFULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/mp4:DLNA.ORG_PN=AAC_ISO_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/vnd.dlna.adts:DLNA.ORG_PN=AAC_ADTS_320;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/flac:DLNA.ORG_PN=FLAC;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:audio/ogg:DLNA.ORG_PN=OGG;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/png:DLNA.ORG_PN=PNG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/gif:DLNA.ORG_PN=GIF_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_JP_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-flv:DLNA.ORG_PN=FLV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-dvr:DLNA.ORG_PN=DVR_MS;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/wtv:DLNA.ORG_PN=WTV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/ogg:DLNA.ORG_PN=OGV;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/vnd.rn-realvideo:DLNA.ORG_PN=REAL_VIDEO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_P2_3GPP_SP_L0B_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_3GPP_P0_L10_AMR;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:video/3gpp:DLNA.ORG_PN=MPEG4_H263_MP4_P0_L10_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
@@ -42,9 +45,9 @@
<DirectPlayProfile container="jpeg" type="Photo" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="mpeg2video" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="mpeg2video" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Photo">
@@ -98,4 +101,5 @@
<Conditions />
</ResponseProfile>
</ResponseProfiles>
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml
index a50fdb68e..c0164ae53 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml
@@ -19,11 +19,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_TN</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<SonyAggregationFlags>10</SonyAggregationFlags>
<ProtocolInfo>http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000</ProtocolInfo>
@@ -40,9 +43,9 @@
<DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac" estimateContentLength="false" enableMpegtsM2TsMode="true" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac" estimateContentLength="false" enableMpegtsM2TsMode="true" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Photo">
@@ -106,4 +109,5 @@
<Conditions />
</ResponseProfile>
</ResponseProfiles>
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml
index dd381a5b6..454c7b794 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml
@@ -19,11 +19,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_TN</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<SonyAggregationFlags>10</SonyAggregationFlags>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
@@ -43,9 +46,9 @@
<DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac" estimateContentLength="false" enableMpegtsM2TsMode="true" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac" estimateContentLength="false" enableMpegtsM2TsMode="true" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Photo">
@@ -109,4 +112,5 @@
<Conditions />
</ResponseProfile>
</ResponseProfiles>
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml
index 57d822d41..f9e20531a 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml
@@ -19,11 +19,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_TN</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<SonyAggregationFlags>10</SonyAggregationFlags>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
@@ -45,9 +48,9 @@
<DirectPlayProfile container="jpeg" type="Photo" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac" estimateContentLength="false" enableMpegtsM2TsMode="true" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac" estimateContentLength="false" enableMpegtsM2TsMode="true" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Photo">
@@ -92,4 +95,5 @@
<Conditions />
</ResponseProfile>
</ResponseProfiles>
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml
index 6f5679fee..68e35184c 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml
@@ -19,11 +19,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_TN</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<SonyAggregationFlags>10</SonyAggregationFlags>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
@@ -50,9 +53,9 @@
<DirectPlayProfile container="jpeg" type="Photo" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac" estimateContentLength="false" enableMpegtsM2TsMode="true" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3,aac" estimateContentLength="false" enableMpegtsM2TsMode="true" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Photo">
@@ -92,4 +95,5 @@
<Conditions />
</ResponseProfile>
</ResponseProfiles>
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
index 494cedff7..103c8ad27 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
@@ -19,11 +19,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_TN</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<SonyAggregationFlags>10</SonyAggregationFlags>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
@@ -36,9 +39,9 @@
<DirectPlayProfile container="avi,mp4" type="Video" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Photo">
@@ -92,4 +95,5 @@
<Conditions />
</ResponseProfile>
</ResponseProfiles>
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
index 5f57fa9ed..3717b07c4 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
@@ -19,11 +19,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>5</TimelineOffsetSeconds>
@@ -46,9 +49,9 @@
<DirectPlayProfile container="jpeg,png,gif,bmp,tiff" type="Photo" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Photo">
@@ -77,4 +80,5 @@
<Conditions />
</ResponseProfile>
</ResponseProfiles>
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Windows 8 RT.xml b/MediaBrowser.Dlna/Profiles/Xml/Windows 8 RT.xml
new file mode 100644
index 000000000..284166fa3
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/Xml/Windows 8 RT.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <Name>Windows 8/RT</Name>
+ <Identification>
+ <Manufacturer>Microsoft SDK Customer</Manufacturer>
+ <Headers />
+ </Identification>
+ <FriendlyName>Media Browser</FriendlyName>
+ <Manufacturer>Media Browser</Manufacturer>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
+ <ModelName>Media Browser</ModelName>
+ <ModelDescription>Media Browser</ModelDescription>
+ <ModelNumber>Media Browser</ModelNumber>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
+ <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+ <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+ <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+ <AlbumArtPn>JPEG_SM</AlbumArtPn>
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
+ <XDlnaDoc>DMS-1.50</XDlnaDoc>
+ <ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
+ <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+ <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+ <RequiresPlainFolders>false</RequiresPlainFolders>
+ <XmlRootAttributes />
+ <DirectPlayProfiles>
+ <DirectPlayProfile container="mp4,mov" audioCodec="aac,ac3,eac3,mp3,pcm" videoCodec="h264,mpeg4" type="Video" />
+ <DirectPlayProfile container="ts" audioCodec="aac,ac3,eac3,mp3,mp2,pcm" videoCodec="h264" type="Video" />
+ <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" videoCodec="wmv2,wmv3,vc1" type="Video" />
+ <DirectPlayProfile container="avi" audioCodec="mp3,ac3,eac3,mp2,pcm" videoCodec="mpeg4,msmpeg4,mjpeg" type="Video" />
+ <DirectPlayProfile container="mp4" audioCodec="aac" type="Audio" />
+ <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
+ <DirectPlayProfile container="jpeg" type="Photo" />
+ </DirectPlayProfiles>
+ <TranscodingProfiles>
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" protocol="hls" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="Baseline" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="Baseline" context="Streaming" />
+ <TranscodingProfile container="mp4" type="Video" videoCodec="h264" audioCodec="aac,ac3,eac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Static" />
+ </TranscodingProfiles>
+ <ContainerProfiles />
+ <CodecProfiles>
+ <CodecProfile type="Video">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="VideoBitDepth" value="8" isRequired="false" />
+ </Conditions>
+ </CodecProfile>
+ <CodecProfile type="VideoAudio" codec="aac,eac3">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="8" isRequired="true" />
+ </Conditions>
+ </CodecProfile>
+ <CodecProfile type="VideoAudio" codec="ac3">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="6" isRequired="true" />
+ </Conditions>
+ </CodecProfile>
+ </CodecProfiles>
+ <ResponseProfiles />
+ <SubtitleProfiles>
+ <SubtitleProfile format="ttml" method="External" />
+ </SubtitleProfiles>
+</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Windows Phone.xml b/MediaBrowser.Dlna/Profiles/Xml/Windows Phone.xml
new file mode 100644
index 000000000..d1f415291
--- /dev/null
+++ b/MediaBrowser.Dlna/Profiles/Xml/Windows Phone.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+<Profile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+ <Name>Windows Phone</Name>
+ <FriendlyName>Media Browser</FriendlyName>
+ <Manufacturer>Media Browser</Manufacturer>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
+ <ModelName>Media Browser</ModelName>
+ <ModelDescription>Media Browser</ModelDescription>
+ <ModelNumber>Media Browser</ModelNumber>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
+ <IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
+ <EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
+ <SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
+ <AlbumArtPn>JPEG_SM</AlbumArtPn>
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
+ <XDlnaDoc>DMS-1.50</XDlnaDoc>
+ <ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
+ <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
+ <RequiresPlainVideoItems>false</RequiresPlainVideoItems>
+ <RequiresPlainFolders>false</RequiresPlainFolders>
+ <XmlRootAttributes />
+ <DirectPlayProfiles>
+ <DirectPlayProfile container="mp4,mov" audioCodec="aac,mp3" videoCodec="h264" type="Video" />
+ <DirectPlayProfile container="mp4,avi" audioCodec="aac,mp3" videoCodec="mpeg4,msmpeg4" type="Video" />
+ <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" videoCodec="wmv2,wmv3,vc1" type="Video" />
+ <DirectPlayProfile container="asf" audioCodec="wmav2,wmapro,wmavoice" type="Audio" />
+ <DirectPlayProfile container="mp4,aac" audioCodec="aac" type="Audio" />
+ <DirectPlayProfile container="mp3" audioCodec="mp3" type="Audio" />
+ <DirectPlayProfile container="jpeg,png,gif,bmp" type="Photo" />
+ </DirectPlayProfiles>
+ <TranscodingProfiles>
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" protocol="hls" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="Baseline" context="Streaming" />
+ <TranscodingProfile container="mp4" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="Baseline" context="Streaming" />
+ <TranscodingProfile container="mp4" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="Baseline" context="Static" />
+ </TranscodingProfiles>
+ <ContainerProfiles />
+ <CodecProfiles>
+ <CodecProfile type="Video">
+ <Conditions>
+ <ProfileCondition condition="NotEquals" property="IsAnamorphic" value="true" isRequired="true" />
+ </Conditions>
+ </CodecProfile>
+ <CodecProfile type="Video" codec="h264">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="Width" value="800" isRequired="true" />
+ <ProfileCondition condition="LessThanEqual" property="Height" value="480" isRequired="true" />
+ <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="1000000" isRequired="false" />
+ <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="24" isRequired="false" />
+ <ProfileCondition condition="LessThanEqual" property="VideoLevel" value="3" isRequired="true" />
+ </Conditions>
+ </CodecProfile>
+ <CodecProfile type="Video">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="Width" value="800" isRequired="true" />
+ <ProfileCondition condition="LessThanEqual" property="Height" value="480" isRequired="true" />
+ <ProfileCondition condition="LessThanEqual" property="VideoBitrate" value="1000000" isRequired="false" />
+ <ProfileCondition condition="LessThanEqual" property="VideoFramerate" value="24" isRequired="false" />
+ </Conditions>
+ </CodecProfile>
+ <CodecProfile type="VideoAudio">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="AudioBitrate" value="128000" isRequired="true" />
+ <ProfileCondition condition="LessThanEqual" property="AudioChannels" value="2" isRequired="true" />
+ </Conditions>
+ </CodecProfile>
+ <CodecProfile type="Audio">
+ <Conditions>
+ <ProfileCondition condition="LessThanEqual" property="AudioBitrate" value="128000" isRequired="true" />
+ </Conditions>
+ </CodecProfile>
+ </CodecProfiles>
+ <ResponseProfiles />
+ <SubtitleProfiles />
+</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
index 27dcef1e4..3a7eddc1f 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
@@ -19,11 +19,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>40</TimelineOffsetSeconds>
@@ -40,9 +43,9 @@
<DirectPlayProfile container="jpeg" type="Photo" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="asf" type="Video" videoCodec="wmv2" audioCodec="wmav2" estimateContentLength="true" enableMpegtsM2TsMode="false" transcodeSeekInfo="Bytes" />
- <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="asf" type="Video" videoCodec="wmv2" audioCodec="wmav2" estimateContentLength="true" enableMpegtsM2TsMode="false" transcodeSeekInfo="Bytes" context="Streaming" />
+ <TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Video" container="mp4,mov">
@@ -99,4 +102,5 @@
<Conditions />
</ResponseProfile>
</ResponseProfiles>
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
index 1de77c64f..13c368328 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
@@ -17,11 +17,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
@@ -39,8 +42,8 @@
<DirectPlayProfile container="jpeg" type="Photo" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="true" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="true" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles>
<ContainerProfile type="Video" container="mp4,mov">
@@ -89,4 +92,5 @@
<Conditions />
</ResponseProfile>
</ResponseProfiles>
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
index 60fb7cba6..09886210c 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
@@ -18,11 +18,14 @@
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio</SupportedMediaTypes>
<AlbumArtPn>JPEG_SM</AlbumArtPn>
- <MaxAlbumArtWidth>512</MaxAlbumArtWidth>
- <MaxAlbumArtHeight>512</MaxAlbumArtHeight>
- <MaxIconWidth xsi:nil="true" />
- <MaxIconHeight xsi:nil="true" />
- <MaxBitrate xsi:nil="true" />
+ <MaxAlbumArtWidth>480</MaxAlbumArtWidth>
+ <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
+ <MaxIconWidth>48</MaxIconWidth>
+ <MaxIconHeight>48</MaxIconHeight>
+ <MaxStreamingBitrate>8000000</MaxStreamingBitrate>
+ <MaxStaticBitrate>8000000</MaxStaticBitrate>
+ <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
+ <MusicSyncBitrate>128000</MusicSyncBitrate>
<XDlnaDoc>DMS-1.50</XDlnaDoc>
<ProtocolInfo>http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000</ProtocolInfo>
<TimelineOffsetSeconds>0</TimelineOffsetSeconds>
@@ -38,10 +41,11 @@
<DirectPlayProfile container="ogg" audioCodec="vorbis" type="Audio" />
</DirectPlayProfiles>
<TranscodingProfiles>
- <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" />
- <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" />
+ <TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" context="Streaming" />
+ <TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" videoProfile="baseline" context="Streaming" />
</TranscodingProfiles>
<ContainerProfiles />
<CodecProfiles />
<ResponseProfiles />
+ <SubtitleProfiles />
</Profile> \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs b/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs
index 9efce5bb3..f4f724d07 100644
--- a/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs
+++ b/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs
@@ -137,6 +137,24 @@ namespace MediaBrowser.Dlna.Server
{
MimeType = "image/png",
Depth = "24",
+ Width = 240,
+ Height = 240,
+ Url = "/mediabrowser/dlna/icons/logo240.png"
+ });
+
+ list.Add(new DeviceIcon
+ {
+ MimeType = "image/jpeg",
+ Depth = "24",
+ Width = 240,
+ Height = 240,
+ Url = "/mediabrowser/dlna/icons/logo240.jpg"
+ });
+
+ list.Add(new DeviceIcon
+ {
+ MimeType = "image/png",
+ Depth = "24",
Width = 120,
Height = 120,
Url = "/mediabrowser/dlna/icons/logo120.png"
diff --git a/MediaBrowser.Dlna/Service/BaseControlHandler.cs b/MediaBrowser.Dlna/Service/BaseControlHandler.cs
index 9f7e87088..a17182a7e 100644
--- a/MediaBrowser.Dlna/Service/BaseControlHandler.cs
+++ b/MediaBrowser.Dlna/Service/BaseControlHandler.cs
@@ -1,5 +1,4 @@
-using System.Security;
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Dlna.Server;
using MediaBrowser.Model.Logging;
@@ -28,12 +27,19 @@ namespace MediaBrowser.Dlna.Service
{
try
{
- if (Config.Configuration.DlnaOptions.EnableDebugLogging)
+ if (Config.GetDlnaConfiguration().EnableDebugLogging)
{
LogRequest(request);
}
- return ProcessControlRequestInternal(request);
+ var response = ProcessControlRequestInternal(request);
+
+ if (Config.GetDlnaConfiguration().EnableDebugLogging)
+ {
+ LogResponse(response);
+ }
+
+ return response;
}
catch (Exception ex)
{
@@ -113,5 +119,17 @@ namespace MediaBrowser.Dlna.Service
Logger.LogMultiline("Control request", LogSeverity.Debug, builder);
}
+
+ private void LogResponse(ControlResponse response)
+ {
+ var builder = new StringBuilder();
+
+ var headers = string.Join(", ", response.Headers.Select(i => string.Format("{0}={1}", i.Key, i.Value)).ToArray());
+ builder.AppendFormat("Headers: {0}", headers);
+ builder.AppendLine();
+ builder.Append(response.Xml);
+
+ Logger.LogMultiline("Control response", LogSeverity.Debug, builder);
+ }
}
}
diff --git a/MediaBrowser.Dlna/Ssdp/Datagram.cs b/MediaBrowser.Dlna/Ssdp/Datagram.cs
index 9df7502e7..2554d33c6 100644
--- a/MediaBrowser.Dlna/Ssdp/Datagram.cs
+++ b/MediaBrowser.Dlna/Ssdp/Datagram.cs
@@ -69,7 +69,7 @@ namespace MediaBrowser.Dlna.Ssdp
}
catch (Exception ex)
{
- _logger.ErrorException("Error sending Datagram: " + Message, ex);
+ _logger.ErrorException("Error sending Datagram to {0} from {1}: " + Message, ex, ToEndPoint, FromEndPoint == null ? "" : FromEndPoint.ToString());
}
++SendCount;
}
diff --git a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs
new file mode 100644
index 000000000..cc9b80d75
--- /dev/null
+++ b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs
@@ -0,0 +1,246 @@
+using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Net.Sockets;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Dlna.Ssdp
+{
+ public class DeviceDiscovery : IDisposable
+ {
+ private bool _disposed;
+
+ private readonly ILogger _logger;
+ private readonly IServerConfigurationManager _config;
+ private readonly SsdpHandler _ssdpHandler;
+ private readonly CancellationTokenSource _tokenSource;
+ private readonly IHttpClient _httpClient;
+ private readonly INetworkManager _networkManager;
+
+ public event EventHandler<SsdpMessageEventArgs> DeviceDiscovered;
+ public event EventHandler<SsdpMessageEventArgs> DeviceLeft;
+
+ public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, IHttpClient httpClient, SsdpHandler ssdpHandler, INetworkManager networkManager)
+ {
+ _tokenSource = new CancellationTokenSource();
+
+ _logger = logger;
+ _config = config;
+ _httpClient = httpClient;
+ _ssdpHandler = ssdpHandler;
+ _networkManager = networkManager;
+ }
+
+ public void Start()
+ {
+ _ssdpHandler.MessageReceived += _ssdpHandler_MessageReceived;
+
+ foreach (var network in GetNetworkInterfaces())
+ {
+ _logger.Debug("Found interface: {0}. Type: {1}. Status: {2}", network.Name, network.NetworkInterfaceType, network.OperationalStatus);
+
+ if (!network.SupportsMulticast || OperationalStatus.Up != network.OperationalStatus || !network.GetIPProperties().MulticastAddresses.Any())
+ continue;
+
+ var ipV4 = network.GetIPProperties().GetIPv4Properties();
+ if (null == ipV4)
+ continue;
+
+ var localIp = network.GetIPProperties().UnicastAddresses
+ .Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork)
+ .Select(i => i.Address)
+ .FirstOrDefault();
+
+ if (localIp != null)
+ {
+ try
+ {
+ CreateListener(localIp, ipV4.Index);
+ }
+ catch (Exception e)
+ {
+ _logger.ErrorException("Failed to Initilize Socket", e);
+ }
+ }
+ }
+ }
+
+ void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e)
+ {
+ string nts;
+ e.Headers.TryGetValue("NTS", out nts);
+
+ if (String.Equals(e.Method, "NOTIFY", StringComparison.OrdinalIgnoreCase) &&
+ String.Equals(nts, "ssdp:byebye", StringComparison.OrdinalIgnoreCase) &&
+ !_disposed)
+ {
+ EventHelper.FireEventIfNotNull(DeviceLeft, this, e, _logger);
+ return;
+ }
+
+ try
+ {
+ //var ip = _networkManager.GetLocalIpAddresses().FirstOrDefault();
+
+ //if (ip != null)
+ //{
+ // e.LocalIp = IPAddress.Parse(ip);
+ // TryCreateDevice(e);
+ //}
+ }
+ catch (OperationCanceledException)
+ {
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error creating play to controller", ex);
+ }
+ }
+
+ private IEnumerable<NetworkInterface> GetNetworkInterfaces()
+ {
+ try
+ {
+ return NetworkInterface.GetAllNetworkInterfaces();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error in GetAllNetworkInterfaces", ex);
+ return new List<NetworkInterface>();
+ }
+ }
+ private void CreateListener(IPAddress localIp, int networkInterfaceIndex)
+ {
+ Task.Factory.StartNew(async (o) =>
+ {
+ try
+ {
+ var socket = GetMulticastSocket(networkInterfaceIndex);
+
+ var endPoint = new IPEndPoint(localIp, 1900);
+
+ socket.Bind(endPoint);
+
+ _logger.Info("Creating SSDP listener on {0}, network interface index {1}", localIp, networkInterfaceIndex);
+
+ var receiveBuffer = new byte[64000];
+
+ CreateNotifier(localIp);
+
+ while (!_tokenSource.IsCancellationRequested)
+ {
+ var receivedBytes = await socket.ReceiveAsync(receiveBuffer, 0, 64000);
+
+ if (receivedBytes > 0)
+ {
+ var args = SsdpHelper.ParseSsdpResponse(receiveBuffer, endPoint);
+ args.LocalIp = localIp;
+
+ TryCreateDevice(args);
+ }
+ }
+
+ _logger.Info("SSDP listener - Task completed");
+ }
+ catch (OperationCanceledException)
+ {
+ }
+ catch (Exception e)
+ {
+ _logger.ErrorException("Error in listener", e);
+ }
+
+ }, _tokenSource.Token, TaskCreationOptions.LongRunning);
+ }
+
+ private void CreateNotifier(IPAddress localIp)
+ {
+ Task.Factory.StartNew(async (o) =>
+ {
+ try
+ {
+ while (true)
+ {
+ _ssdpHandler.SendSearchMessage(new IPEndPoint(localIp, 1900));
+
+ var delay = _config.GetDlnaConfiguration().ClientDiscoveryIntervalSeconds * 1000;
+
+ await Task.Delay(delay, _tokenSource.Token).ConfigureAwait(false);
+ }
+ }
+ catch (OperationCanceledException)
+ {
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error in notifier", ex);
+ }
+
+ }, _tokenSource.Token, TaskCreationOptions.LongRunning);
+
+ }
+
+ private Socket GetMulticastSocket(int networkInterfaceIndex)
+ {
+ var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
+ socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), networkInterfaceIndex));
+ socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4);
+ return socket;
+ }
+
+ private void TryCreateDevice(SsdpMessageEventArgs args)
+ {
+ string nts;
+ args.Headers.TryGetValue("NTS", out nts);
+
+ string usn;
+ if (!args.Headers.TryGetValue("USN", out usn)) usn = string.Empty;
+
+ string nt;
+ if (!args.Headers.TryGetValue("NT", out nt)) nt = string.Empty;
+
+ // Ignore when a device is indicating it's shutting down
+ if (string.Equals(nts, "ssdp:byebye", StringComparison.OrdinalIgnoreCase))
+ {
+ return;
+ }
+
+ // Need to be able to download device description
+ string location;
+ if (!args.Headers.TryGetValue("Location", out location) ||
+ string.IsNullOrEmpty(location))
+ {
+ return;
+ }
+
+ if (_config.GetDlnaConfiguration().EnableDebugLogging)
+ {
+ var headerTexts = args.Headers.Select(i => string.Format("{0}={1}", i.Key, i.Value));
+ var headerText = string.Join(",", headerTexts.ToArray());
+
+ _logger.Debug("{0} Device message received from {1}. Headers: {2}", args.Method, args.EndPoint, headerText);
+ }
+
+ EventHelper.FireEventIfNotNull(DeviceDiscovered, this, args, _logger);
+ }
+
+ public void Dispose()
+ {
+ _ssdpHandler.MessageReceived -= _ssdpHandler_MessageReceived;
+
+ if (!_disposed)
+ {
+ _disposed = true;
+ _tokenSource.Cancel();
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Dlna/Ssdp/DeviceDiscoveryInfo.cs b/MediaBrowser.Dlna/Ssdp/DeviceDiscoveryInfo.cs
new file mode 100644
index 000000000..e9de45522
--- /dev/null
+++ b/MediaBrowser.Dlna/Ssdp/DeviceDiscoveryInfo.cs
@@ -0,0 +1,21 @@
+using MediaBrowser.Dlna.PlayTo;
+using System;
+using System.Net;
+
+namespace MediaBrowser.Dlna.Ssdp
+{
+ public class DeviceDiscoveryInfo
+ {
+ public Device Device { get; set; }
+
+ /// <summary>
+ /// The server's ip address that the device responded to
+ /// </summary>
+ public IPAddress LocalIpAddress { get; set; }
+
+ public Uri Uri { get; set; }
+
+ public string Usn { get; set; }
+ public string Nt { get; set; }
+ }
+}
diff --git a/MediaBrowser.Dlna/PlayTo/Extensions.cs b/MediaBrowser.Dlna/Ssdp/Extensions.cs
index 05003a65b..12589e80f 100644
--- a/MediaBrowser.Dlna/PlayTo/Extensions.cs
+++ b/MediaBrowser.Dlna/Ssdp/Extensions.cs
@@ -5,7 +5,7 @@ using System.Net.Sockets;
using System.Threading.Tasks;
using System.Xml.Linq;
-namespace MediaBrowser.Dlna.PlayTo
+namespace MediaBrowser.Dlna.Ssdp
{
public static class Extensions
{
diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
index 0fc7c579b..b8c64a787 100644
--- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
+++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
@@ -1,4 +1,6 @@
-using System.Text;
+using System.Globalization;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Events;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Dlna.Server;
@@ -9,6 +11,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
+using System.Text;
using System.Threading;
namespace MediaBrowser.Dlna.Ssdp
@@ -42,20 +45,38 @@ namespace MediaBrowser.Dlna.Ssdp
_config = config;
_serverSignature = serverSignature;
- _config.ConfigurationUpdated += _config_ConfigurationUpdated;
+ _config.NamedConfigurationUpdated += _config_ConfigurationUpdated;
}
- void _config_ConfigurationUpdated(object sender, EventArgs e)
+ void _config_ConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
{
- ReloadAliveNotifier();
+ if (string.Equals(e.Key, "dlna", StringComparison.OrdinalIgnoreCase))
+ {
+ ReloadAliveNotifier();
+ }
}
public event EventHandler<SsdpMessageEventArgs> MessageReceived;
- private void OnMessageReceived(SsdpMessageEventArgs args)
+ private async void OnMessageReceived(SsdpMessageEventArgs args)
{
if (string.Equals(args.Method, "M-SEARCH", StringComparison.OrdinalIgnoreCase))
{
+ string mx = null;
+ args.Headers.TryGetValue("mx", out mx);
+ int delaySeconds;
+ if (!string.IsNullOrWhiteSpace(mx) &&
+ int.TryParse(mx, NumberStyles.Any, CultureInfo.InvariantCulture, out delaySeconds)
+ && delaySeconds > 0)
+ {
+ if (_config.GetDlnaConfiguration().EnableDebugLogging)
+ {
+ _logger.Debug("Delaying search response by {0} seconds", delaySeconds);
+ }
+
+ await Task.Delay(delaySeconds * 1000).ConfigureAwait(false);
+ }
+
RespondToSearch(args.EndPoint, args.Headers["st"]);
}
@@ -80,20 +101,20 @@ namespace MediaBrowser.Dlna.Ssdp
ReloadAliveNotifier();
}
- public void SendRendererSearchMessage(IPEndPoint localIp)
- {
- SendSearchMessage("urn:schemas-upnp-org:device:MediaRenderer:1", "3", localIp);
- }
-
- public void SendSearchMessage(string deviceSearchType, string mx, IPEndPoint localIp)
+ public void SendSearchMessage(IPEndPoint localIp)
{
var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
values["HOST"] = "239.255.255.250:1900";
values["USER-AGENT"] = "UPnP/1.0 DLNADOC/1.50 Platinum/1.0.4.2";
- values["ST"] = deviceSearchType;
+
values["MAN"] = "\"ssdp:discover\"";
- values["MX"] = mx;
+
+ // Search target
+ values["ST"] = "ssdp:all";
+
+ // Seconds to delay response
+ values["MX"] = "3";
SendDatagram("M-SEARCH * HTTP/1.1", values, localIp);
}
@@ -125,24 +146,9 @@ namespace MediaBrowser.Dlna.Ssdp
StartQueueTimer();
}
- public void SendDatagramFromDevices(string header,
- Dictionary<string, string> values,
- IPEndPoint endpoint,
- string deviceType)
- {
- foreach (var d in RegisteredDevices)
- {
- if (string.Equals(deviceType, "ssdp:all", StringComparison.OrdinalIgnoreCase) ||
- string.Equals(deviceType, d.Type, StringComparison.OrdinalIgnoreCase))
- {
- SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0));
- }
- }
- }
-
private void RespondToSearch(IPEndPoint endpoint, string deviceType)
{
- if (_config.Configuration.DlnaOptions.EnableDebugLogging)
+ if (_config.GetDlnaConfiguration().EnableDebugLogging)
{
_logger.Debug("RespondToSearch");
}
@@ -164,9 +170,9 @@ namespace MediaBrowser.Dlna.Ssdp
values["ST"] = d.Type;
values["USN"] = d.USN;
- SendDatagram(header, values, endpoint, null);
+ SendDatagram(header, values, endpoint, new IPEndPoint(d.Address, 0));
- if (_config.Configuration.DlnaOptions.EnableDebugLogging)
+ if (_config.GetDlnaConfiguration().EnableDebugLogging)
{
_logger.Debug("{1} - Responded to a {0} request to {2}", d.Type, endpoint, d.Address.ToString());
}
@@ -255,19 +261,19 @@ namespace MediaBrowser.Dlna.Ssdp
var received = (byte[])result.AsyncState;
- if (_config.Configuration.DlnaOptions.EnableDebugLogging)
+ if (_config.GetDlnaConfiguration().EnableDebugLogging)
{
_logger.Debug(Encoding.ASCII.GetString(received));
}
var args = SsdpHelper.ParseSsdpResponse(received, (IPEndPoint)endpoint);
- if (_config.Configuration.DlnaOptions.EnableDebugLogging)
+ if (_config.GetDlnaConfiguration().EnableDebugLogging)
{
var headerTexts = args.Headers.Select(i => string.Format("{0}={1}", i.Key, i.Value));
var headerText = string.Join(",", headerTexts.ToArray());
- _logger.Debug("{0} message received from {1}. Headers: {2}", args.Method, args.EndPoint, headerText);
+ _logger.Debug("{0} message received from {1} on {3}. Headers: {2}", args.Method, args.EndPoint, headerText, _socket.LocalEndPoint);
}
OnMessageReceived(args);
@@ -285,7 +291,7 @@ namespace MediaBrowser.Dlna.Ssdp
public void Dispose()
{
- _config.ConfigurationUpdated -= _config_ConfigurationUpdated;
+ _config.NamedConfigurationUpdated -= _config_ConfigurationUpdated;
_isDisposed = true;
while (_messageQueue.Count != 0)
@@ -337,7 +343,7 @@ namespace MediaBrowser.Dlna.Ssdp
private void NotifyAll()
{
- if (_config.Configuration.DlnaOptions.EnableDebugLogging)
+ if (_config.GetDlnaConfiguration().EnableDebugLogging)
{
_logger.Debug("Sending alive notifications");
}
@@ -362,7 +368,7 @@ namespace MediaBrowser.Dlna.Ssdp
values["NT"] = dev.Type;
values["USN"] = dev.USN;
- if (_config.Configuration.DlnaOptions.EnableDebugLogging)
+ if (_config.GetDlnaConfiguration().EnableDebugLogging)
{
_logger.Debug("{0} said {1}", dev.USN, type);
}
@@ -406,13 +412,13 @@ namespace MediaBrowser.Dlna.Ssdp
private int _aliveNotifierIntervalMs;
private void ReloadAliveNotifier()
{
- if (!_config.Configuration.DlnaOptions.BlastAliveMessages)
+ if (!_config.GetDlnaConfiguration().BlastAliveMessages)
{
DisposeNotificationTimer();
return;
}
- var intervalMs = _config.Configuration.DlnaOptions.BlastAliveMessageIntervalSeconds * 1000;
+ var intervalMs = _config.GetDlnaConfiguration().BlastAliveMessageIntervalSeconds * 1000;
if (_notificationTimer == null || _aliveNotifierIntervalMs != intervalMs)
{
diff --git a/MediaBrowser.Dlna/Ssdp/SsdpMessageBuilder.cs b/MediaBrowser.Dlna/Ssdp/SsdpMessageBuilder.cs
index 1ba8a50ec..e479ca19a 100644
--- a/MediaBrowser.Dlna/Ssdp/SsdpMessageBuilder.cs
+++ b/MediaBrowser.Dlna/Ssdp/SsdpMessageBuilder.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Text;
namespace MediaBrowser.Dlna.Ssdp
@@ -23,25 +22,5 @@ namespace MediaBrowser.Dlna.Ssdp
return builder.ToString();
}
-
- public string BuildDiscoveryMessage(string deviceSearchType, string mx)
- {
- const string header = "M-SEARCH * HTTP/1.1";
-
- var values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-
- values["HOST"] = "239.255.255.250:1900";
- values["USER-AGENT"] = "UPnP/1.0 DLNADOC/1.50 Platinum/1.0.4.2";
- values["ST"] = deviceSearchType;
- values["MAN"] = "\"ssdp:discover\"";
- values["MX"] = mx;
-
- return BuildMessage(header, values);
- }
-
- public string BuildRendererDiscoveryMessage()
- {
- return BuildDiscoveryMessage("urn:schemas-upnp-org:device:MediaRenderer:1", "3");
- }
}
}
diff --git a/MediaBrowser.Dlna/Ssdp/SsdpMessageEventArgs.cs b/MediaBrowser.Dlna/Ssdp/SsdpMessageEventArgs.cs
index d6368191b..189476830 100644
--- a/MediaBrowser.Dlna/Ssdp/SsdpMessageEventArgs.cs
+++ b/MediaBrowser.Dlna/Ssdp/SsdpMessageEventArgs.cs
@@ -12,6 +12,8 @@ namespace MediaBrowser.Dlna.Ssdp
public Dictionary<string, string> Headers { get; set; }
+ public IPAddress LocalIp { get; set; }
+
public SsdpMessageEventArgs()
{
Headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
diff --git a/MediaBrowser.Providers/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs
index a5a3ba146..25778d036 100644
--- a/MediaBrowser.Providers/BaseXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs
@@ -7,7 +7,7 @@ using System.IO;
using System.Threading;
using System.Threading.Tasks;
-namespace MediaBrowser.Providers
+namespace MediaBrowser.LocalMetadata
{
public abstract class BaseXmlProvider<T> : ILocalMetadataProvider<T>, IHasChangeMonitor
where T : IHasMetadata, new()
@@ -27,7 +27,7 @@ namespace MediaBrowser.Providers
var path = file.FullName;
- await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
+ //await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
@@ -46,7 +46,7 @@ namespace MediaBrowser.Providers
}
finally
{
- XmlProviderUtils.XmlParsingResourcePool.Release();
+ //XmlProviderUtils.XmlParsingResourcePool.Release();
}
return result;
diff --git a/MediaBrowser.Providers/Folders/CollectionFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs
index fa5946bd5..ccb2acd1d 100644
--- a/MediaBrowser.Providers/Folders/CollectionFolderImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/CollectionFolderImageProvider.cs
@@ -1,13 +1,19 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Providers.All;
using System.Collections.Generic;
-namespace MediaBrowser.Providers.Folders
+namespace MediaBrowser.LocalMetadata.Images
{
public class CollectionFolderLocalImageProvider : ILocalImageFileProvider, IHasOrder
{
+ private readonly IFileSystem _fileSystem;
+
+ public CollectionFolderLocalImageProvider(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
public string Name
{
get { return "Collection Folder Images"; }
@@ -31,7 +37,7 @@ namespace MediaBrowser.Providers.Folders
{
var collectionFolder = (CollectionFolder)item;
- return new LocalImageProvider().GetImages(item, collectionFolder.PhysicalLocations, directoryService);
+ return new LocalImageProvider(_fileSystem).GetImages(item, collectionFolder.PhysicalLocations, directoryService);
}
}
}
diff --git a/MediaBrowser.Providers/TV/EpisodeLocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs
index 1ec0e0f48..cd9b78201 100644
--- a/MediaBrowser.Providers/TV/EpisodeLocalImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/EpisodeLocalImageProvider.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
@@ -7,10 +8,17 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
-namespace MediaBrowser.Providers.TV
+namespace MediaBrowser.LocalMetadata.Images
{
public class EpisodeLocalLocalImageProvider : ILocalImageFileProvider
{
+ private readonly IFileSystem _fileSystem;
+
+ public EpisodeLocalLocalImageProvider(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
public string Name
{
get { return "Local Images"; }
@@ -27,7 +35,7 @@ namespace MediaBrowser.Providers.TV
var parentPathFiles = directoryService.GetFileSystemEntries(parentPath);
- var nameWithoutExtension = Path.GetFileNameWithoutExtension(item.Path);
+ var nameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(item.Path);
var files = GetFilesFromParentFolder(nameWithoutExtension, parentPathFiles);
@@ -53,9 +61,14 @@ namespace MediaBrowser.Providers.TV
return parentPathFiles
.Where(i =>
{
- if (BaseItem.SupportedImageExtensions.Contains(i.Extension))
+ if ((i.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
+ {
+ return false;
+ }
+
+ if (BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
{
- var currentNameWithoutExtension = Path.GetFileNameWithoutExtension(i.Name);
+ var currentNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(i);
if (string.Equals(filenameWithoutExtension, currentNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
{
diff --git a/MediaBrowser.Providers/Folders/ImagesByNameImageProvider.cs b/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs
index 5dcf3bc59..d992e2026 100644
--- a/MediaBrowser.Providers/Folders/ImagesByNameImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/ImagesByNameImageProvider.cs
@@ -1,12 +1,11 @@
-using MediaBrowser.Common.IO;
+using System.Collections.Generic;
+using System.IO;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Providers.All;
-using System.Collections.Generic;
-using System.IO;
-namespace MediaBrowser.Providers.Folders
+namespace MediaBrowser.LocalMetadata.Images
{
public class ImagesByNameImageProvider : ILocalImageFileProvider, IHasOrder
{
@@ -46,7 +45,7 @@ namespace MediaBrowser.Providers.Folders
try
{
- return new LocalImageProvider().GetImages(item, path, directoryService);
+ return new LocalImageProvider(_fileSystem).GetImages(item, path, directoryService);
}
catch (DirectoryNotFoundException)
{
diff --git a/MediaBrowser.Providers/All/InternalMetadataFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs
index edaa5edaf..c126af884 100644
--- a/MediaBrowser.Providers/All/InternalMetadataFolderImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs
@@ -1,19 +1,22 @@
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using System.Collections.Generic;
using System.IO;
-namespace MediaBrowser.Providers.All
+namespace MediaBrowser.LocalMetadata.Images
{
public class InternalMetadataFolderImageProvider : ILocalImageFileProvider, IHasOrder
{
private readonly IServerConfigurationManager _config;
+ private readonly IFileSystem _fileSystem;
- public InternalMetadataFolderImageProvider(IServerConfigurationManager config)
+ public InternalMetadataFolderImageProvider(IServerConfigurationManager config, IFileSystem fileSystem)
{
_config = config;
+ _fileSystem = fileSystem;
}
public string Name
@@ -57,7 +60,7 @@ namespace MediaBrowser.Providers.All
try
{
- return new LocalImageProvider().GetImages(item, path, directoryService);
+ return new LocalImageProvider(_fileSystem).GetImages(item, path, directoryService);
}
catch (DirectoryNotFoundException)
{
diff --git a/MediaBrowser.Providers/All/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
index 1d10fcfa3..f69c261d8 100644
--- a/MediaBrowser.Providers/All/LocalImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@@ -10,10 +11,17 @@ using System.Globalization;
using System.IO;
using System.Linq;
-namespace MediaBrowser.Providers.All
+namespace MediaBrowser.LocalMetadata.Images
{
public class LocalImageProvider : ILocalImageFileProvider
{
+ private readonly IFileSystem _fileSystem;
+
+ public LocalImageProvider(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
public string Name
{
get { return "Local Images"; }
@@ -29,7 +37,7 @@ namespace MediaBrowser.Providers.All
if (item.SupportsLocalMetadata)
{
// Episode has it's own provider
- if (item.IsOwnedItem || item is Episode || item is Audio)
+ if (item.IsOwnedItem || item is Episode || item is Audio || item is Photo)
{
return false;
}
@@ -117,7 +125,7 @@ namespace MediaBrowser.Providers.All
var baseItem = item as BaseItem;
if (baseItem != null && baseItem.IsInMixedFolder)
{
- imagePrefix = Path.GetFileNameWithoutExtension(item.Path) + "-";
+ imagePrefix = _fileSystem.GetFileNameWithoutExtension(item.Path) + "-";
}
PopulatePrimaryImages(item, images, files, imagePrefix);
@@ -172,7 +180,7 @@ namespace MediaBrowser.Providers.All
if (!string.IsNullOrEmpty(item.Path))
{
- var name = Path.GetFileNameWithoutExtension(item.Path);
+ var name = _fileSystem.GetFileNameWithoutExtension(item.Path);
if (!string.IsNullOrEmpty(name))
{
@@ -188,7 +196,7 @@ namespace MediaBrowser.Providers.All
if (!string.IsNullOrEmpty(item.Path))
{
- var name = Path.GetFileNameWithoutExtension(item.Path);
+ var name = _fileSystem.GetFileNameWithoutExtension(item.Path);
if (!string.IsNullOrEmpty(name))
{
@@ -259,6 +267,7 @@ namespace MediaBrowser.Providers.All
}
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
private void PopulateSeasonImagesFromSeriesFolder(Season season, List<LocalImageInfo> images, IDirectoryService directoryService)
{
var seasonNumber = season.IndexNumber;
@@ -316,7 +325,7 @@ namespace MediaBrowser.Providers.All
private FileSystemInfo GetImage(IEnumerable<FileSystemInfo> files, string name)
{
var candidates = files
- .Where(i => string.Equals(name, Path.GetFileNameWithoutExtension(i.Name), StringComparison.OrdinalIgnoreCase))
+ .Where(i => string.Equals(name, _fileSystem.GetFileNameWithoutExtension(i), StringComparison.OrdinalIgnoreCase))
.ToList();
return BaseItem.SupportedImageExtensions
diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
new file mode 100644
index 000000000..6f8cf31d1
--- /dev/null
+++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.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>{7EF9F3E0-697D-42F3-A08F-19DEB5F84392}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>MediaBrowser.LocalMetadata</RootNamespace>
+ <AssemblyName>MediaBrowser.LocalMetadata</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </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="System" />
+ <Reference Include="System.Core" />
+ <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="BaseXmlProvider.cs" />
+ <Compile Include="Images\CollectionFolderImageProvider.cs" />
+ <Compile Include="Images\EpisodeLocalImageProvider.cs" />
+ <Compile Include="Images\ImagesByNameImageProvider.cs" />
+ <Compile Include="Images\InternalMetadataFolderImageProvider.cs" />
+ <Compile Include="Images\LocalImageProvider.cs" />
+ <Compile Include="Parsers\BoxSetXmlParser.cs" />
+ <Compile Include="Parsers\EpisodeXmlParser.cs" />
+ <Compile Include="Parsers\GameSystemXmlParser.cs" />
+ <Compile Include="Parsers\GameXmlParser.cs" />
+ <Compile Include="Parsers\MovieXmlParser.cs" />
+ <Compile Include="Parsers\MusicVideoXmlParser.cs" />
+ <Compile Include="Parsers\PlaylistXmlParser.cs" />
+ <Compile Include="Parsers\SeasonXmlParser.cs" />
+ <Compile Include="Parsers\SeriesXmlParser.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Providers\AdultVideoXmlProvider.cs" />
+ <Compile Include="Providers\AlbumXmlProvider.cs" />
+ <Compile Include="Providers\ArtistXmlProvider.cs" />
+ <Compile Include="Providers\BoxSetXmlProvider.cs" />
+ <Compile Include="Providers\ChannelXmlProvider.cs" />
+ <Compile Include="Providers\EpisodeXmlProvider.cs" />
+ <Compile Include="Providers\FolderXmlProvider.cs" />
+ <Compile Include="Providers\GameSystemXmlProvider.cs" />
+ <Compile Include="Providers\GameXmlProvider.cs" />
+ <Compile Include="Providers\MovieXmlProvider.cs" />
+ <Compile Include="Providers\MusicVideoXmlProvider.cs" />
+ <Compile Include="Providers\PersonXmlProvider.cs" />
+ <Compile Include="Providers\PlaylistXmlProvider.cs" />
+ <Compile Include="Providers\SeasonXmlProvider.cs" />
+ <Compile Include="Providers\SeriesXmlProvider.cs" />
+ <Compile Include="Providers\TrailerXmlProvider.cs" />
+ <Compile Include="Providers\VideoXmlProvider.cs" />
+ <Compile Include="Savers\AlbumXmlSaver.cs" />
+ <Compile Include="Savers\ArtistXmlSaver.cs" />
+ <Compile Include="Savers\BoxSetXmlSaver.cs" />
+ <Compile Include="Savers\ChannelXmlSaver.cs" />
+ <Compile Include="Savers\EpisodeXmlSaver.cs" />
+ <Compile Include="Savers\FolderXmlSaver.cs" />
+ <Compile Include="Savers\GameSystemXmlSaver.cs" />
+ <Compile Include="Savers\GameXmlSaver.cs" />
+ <Compile Include="Savers\MovieXmlSaver.cs" />
+ <Compile Include="Savers\PersonXmlSaver.cs" />
+ <Compile Include="Savers\PlaylistXmlSaver.cs" />
+ <Compile Include="Savers\SeasonXmlSaver.cs" />
+ <Compile Include="Savers\SeriesXmlSaver.cs" />
+ <Compile Include="Savers\XmlSaverHelpers.cs" />
+ </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>
+ <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/MediaBrowser.Providers/BoxSets/BoxSetXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs
index eb3c99cef..f89e29d54 100644
--- a/MediaBrowser.Providers/BoxSets/BoxSetXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/BoxSetXmlParser.cs
@@ -3,15 +3,12 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using System.Collections.Generic;
-using System.Globalization;
using System.Xml;
-namespace MediaBrowser.Providers.BoxSets
+namespace MediaBrowser.LocalMetadata.Parsers
{
public class BoxSetXmlParser : BaseItemXmlParser<BoxSet>
{
- private readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
public BoxSetXmlParser(ILogger logger)
: base(logger)
{
@@ -71,59 +68,5 @@ namespace MediaBrowser.Providers.BoxSets
item.LinkedChildren = list;
}
-
- private LinkedChild GetLinkedChild(XmlReader reader)
- {
- reader.MoveToContent();
-
- var linkedItem = new LinkedChild
- {
- Type = LinkedChildType.Manual
- };
-
- while (reader.Read())
- {
- if (reader.NodeType == XmlNodeType.Element)
- {
- switch (reader.Name)
- {
- case "Name":
- {
- linkedItem.ItemName = reader.ReadElementContentAsString();
- break;
- }
-
- case "Type":
- {
- linkedItem.ItemType = reader.ReadElementContentAsString();
- break;
- }
-
- case "Year":
- {
- var val = reader.ReadElementContentAsString();
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- int rval;
-
- if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
- {
- linkedItem.ItemYear = rval;
- }
- }
-
- break;
- }
-
- default:
- reader.Skip();
- break;
- }
- }
- }
-
- return string.IsNullOrWhiteSpace(linkedItem.ItemName) || string.IsNullOrWhiteSpace(linkedItem.ItemType) ? null : linkedItem;
- }
}
}
diff --git a/MediaBrowser.Providers/TV/EpisodeXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs
index 20f267885..8430f3b3c 100644
--- a/MediaBrowser.Providers/TV/EpisodeXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/EpisodeXmlParser.cs
@@ -1,15 +1,15 @@
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using System;
+using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Xml;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
-namespace MediaBrowser.Providers.TV
+namespace MediaBrowser.LocalMetadata.Parsers
{
/// <summary>
/// Class EpisodeXmlParser
diff --git a/MediaBrowser.Providers/Games/GameSystemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/GameSystemXmlParser.cs
index 85ee509ca..d449108c4 100644
--- a/MediaBrowser.Providers/Games/GameSystemXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/GameSystemXmlParser.cs
@@ -1,12 +1,12 @@
-using MediaBrowser.Controller.Entities;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Xml;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Xml;
-namespace MediaBrowser.Providers.Games
+namespace MediaBrowser.LocalMetadata.Parsers
{
public class GameSystemXmlParser : BaseItemXmlParser<GameSystem>
{
diff --git a/MediaBrowser.Providers/Games/GameXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs
index dfa71e5f4..2caced8a9 100644
--- a/MediaBrowser.Providers/Games/GameXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/GameXmlParser.cs
@@ -1,13 +1,13 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using System.Globalization;
+using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
-namespace MediaBrowser.Providers.Games
+namespace MediaBrowser.LocalMetadata.Parsers
{
/// <summary>
/// Class EpisodeXmlParser
diff --git a/MediaBrowser.Providers/Movies/MovieXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs
index 52795ac2d..388a0d20d 100644
--- a/MediaBrowser.Providers/Movies/MovieXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/MovieXmlParser.cs
@@ -1,13 +1,13 @@
-using MediaBrowser.Controller.Entities;
+using System.Collections.Generic;
+using System.Threading;
+using System.Xml;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
-using System.Collections.Generic;
-using System.Threading;
-using System.Xml;
-namespace MediaBrowser.Providers.Movies
+namespace MediaBrowser.LocalMetadata.Parsers
{
/// <summary>
/// Class EpisodeXmlParser
diff --git a/MediaBrowser.Providers/Music/MusicVideoXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/MusicVideoXmlParser.cs
index 0c160ff66..b88ff6c3a 100644
--- a/MediaBrowser.Providers/Music/MusicVideoXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/MusicVideoXmlParser.cs
@@ -1,10 +1,9 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
+using System.Xml;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
-using System.Xml;
-namespace MediaBrowser.Providers.Music
+namespace MediaBrowser.LocalMetadata.Parsers
{
public class MusicVideoXmlParser : BaseItemXmlParser<MusicVideo>
{
diff --git a/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs
new file mode 100644
index 000000000..c7f974200
--- /dev/null
+++ b/MediaBrowser.LocalMetadata/Parsers/PlaylistXmlParser.cs
@@ -0,0 +1,86 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Playlists;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Logging;
+using System.Collections.Generic;
+using System.Xml;
+
+namespace MediaBrowser.LocalMetadata.Parsers
+{
+ public class PlaylistXmlParser : BaseItemXmlParser<Playlist>
+ {
+ public PlaylistXmlParser(ILogger logger)
+ : base(logger)
+ {
+ }
+
+ protected override void FetchDataFromXmlNode(XmlReader reader, Playlist item)
+ {
+ switch (reader.Name)
+ {
+ case "OwnerUserId":
+ {
+ item.OwnerUserId = reader.ReadElementContentAsString();
+
+ break;
+ }
+
+ case "PlaylistMediaType":
+ {
+ item.PlaylistMediaType = reader.ReadElementContentAsString();
+
+ break;
+ }
+
+ case "PlaylistItems":
+
+ using (var subReader = reader.ReadSubtree())
+ {
+ FetchFromCollectionItemsNode(subReader, item);
+ }
+ break;
+
+ default:
+ base.FetchDataFromXmlNode(reader, item);
+ break;
+ }
+ }
+
+ private void FetchFromCollectionItemsNode(XmlReader reader, Playlist item)
+ {
+ reader.MoveToContent();
+
+ var list = new List<LinkedChild>();
+
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "PlaylistItem":
+ {
+ using (var subReader = reader.ReadSubtree())
+ {
+ var child = GetLinkedChild(subReader);
+
+ if (child != null)
+ {
+ list.Add(child);
+ }
+ }
+
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+
+ item.LinkedChildren = list;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/TV/SeasonXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/SeasonXmlParser.cs
index 44b73e8e1..62a7d37cf 100644
--- a/MediaBrowser.Providers/TV/SeasonXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/SeasonXmlParser.cs
@@ -1,9 +1,9 @@
-using MediaBrowser.Controller.Entities.TV;
+using System.Xml;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
-using System.Xml;
-namespace MediaBrowser.Providers.TV
+namespace MediaBrowser.LocalMetadata.Parsers
{
public class SeasonXmlParser : BaseItemXmlParser<Season>
{
diff --git a/MediaBrowser.Providers/TV/SeriesXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/SeriesXmlParser.cs
index 237fcf73a..a3d45034e 100644
--- a/MediaBrowser.Providers/TV/SeriesXmlParser.cs
+++ b/MediaBrowser.LocalMetadata/Parsers/SeriesXmlParser.cs
@@ -1,12 +1,12 @@
-using MediaBrowser.Controller.Entities.TV;
+using System;
+using System.Xml;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
-using System;
-using System.Xml;
-namespace MediaBrowser.Providers.TV
+namespace MediaBrowser.LocalMetadata.Parsers
{
/// <summary>
/// Class SeriesXmlParser
diff --git a/MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs b/MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..a26bfd954
--- /dev/null
+++ b/MediaBrowser.LocalMetadata/Properties/AssemblyInfo.cs
@@ -0,0 +1,34 @@
+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("MediaBrowser.LocalMetadata")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MediaBrowser.LocalMetadata")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[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("1c669501-2113-493a-b0ed-f8fd26311941")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")] \ No newline at end of file
diff --git a/MediaBrowser.Providers/AdultVideos/AdultVideoXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/AdultVideoXmlProvider.cs
index 07b24c57d..fa17d597d 100644
--- a/MediaBrowser.Providers/AdultVideos/AdultVideoXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/AdultVideoXmlProvider.cs
@@ -1,14 +1,14 @@
-using MediaBrowser.Common.IO;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
-using MediaBrowser.Providers.Movies;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.AdultVideos
+namespace MediaBrowser.LocalMetadata.Providers
{
class AdultVideoXmlProvider : BaseXmlProvider<AdultVideo>
{
diff --git a/MediaBrowser.Providers/Music/AlbumXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/AlbumXmlProvider.cs
index 73b914090..646922769 100644
--- a/MediaBrowser.Providers/Music/AlbumXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/AlbumXmlProvider.cs
@@ -1,13 +1,13 @@
-using MediaBrowser.Common.IO;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.Music
+namespace MediaBrowser.LocalMetadata.Providers
{
- class AlbumXmlProvider : BaseXmlProvider<MusicAlbum>
+ public class AlbumXmlProvider : BaseXmlProvider<MusicAlbum>
{
private readonly ILogger _logger;
diff --git a/MediaBrowser.Providers/Music/ArtistXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/ArtistXmlProvider.cs
index b221fde1e..0b5ebfb11 100644
--- a/MediaBrowser.Providers/Music/ArtistXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/ArtistXmlProvider.cs
@@ -1,11 +1,11 @@
-using MediaBrowser.Common.IO;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.Music
+namespace MediaBrowser.LocalMetadata.Providers
{
class ArtistXmlProvider : BaseXmlProvider<MusicArtist>
{
diff --git a/MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs
index 1d4d893ed..6e40c3594 100644
--- a/MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/BoxSetXmlProvider.cs
@@ -1,11 +1,12 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
using System.IO;
using System.Threading;
-namespace MediaBrowser.Providers.BoxSets
+namespace MediaBrowser.LocalMetadata.Providers
{
/// <summary>
/// Class BoxSetXmlProvider.
diff --git a/MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/ChannelXmlProvider.cs
index 44a312e24..78845487a 100644
--- a/MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/ChannelXmlProvider.cs
@@ -1,11 +1,11 @@
-using MediaBrowser.Common.IO;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.LiveTv
+namespace MediaBrowser.LocalMetadata.Providers
{
public class ChannelXmlProvider : BaseXmlProvider<LiveTvChannel>
{
diff --git a/MediaBrowser.Providers/TV/EpisodeXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs
index 3def06bfe..dff3c1c07 100644
--- a/MediaBrowser.Providers/TV/EpisodeXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/EpisodeXmlProvider.cs
@@ -1,15 +1,16 @@
-using MediaBrowser.Common.IO;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.TV
+namespace MediaBrowser.LocalMetadata.Providers
{
- public class EpisodeXmlProvider : BaseXmlProvider<Episode>
+ public class EpisodeXmlProvider : BaseXmlProvider<Episode>, IHasOrder
{
private readonly ILogger _logger;
@@ -39,5 +40,14 @@ namespace MediaBrowser.Providers.TV
return directoryService.GetFile(metadataFile);
}
+
+ public int Order
+ {
+ get
+ {
+ // After Xbmc
+ return 1;
+ }
+ }
}
}
diff --git a/MediaBrowser.Providers/Folders/FolderXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs
index 144d1b752..0a2b33744 100644
--- a/MediaBrowser.Providers/Folders/FolderXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/FolderXmlProvider.cs
@@ -1,11 +1,11 @@
-using MediaBrowser.Common.IO;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.Folders
+namespace MediaBrowser.LocalMetadata.Providers
{
/// <summary>
/// Provides metadata for Folders and all subclasses by parsing folder.xml
diff --git a/MediaBrowser.Providers/Games/GameSystemXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs
index db9c8f063..dd486da1d 100644
--- a/MediaBrowser.Providers/Games/GameSystemXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/GameSystemXmlProvider.cs
@@ -1,11 +1,12 @@
-using MediaBrowser.Common.IO;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.Games
+namespace MediaBrowser.LocalMetadata.Providers
{
public class GameSystemXmlProvider : BaseXmlProvider<GameSystem>
{
diff --git a/MediaBrowser.Providers/Games/GameXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs
index 6609f9d5e..83ef6e424 100644
--- a/MediaBrowser.Providers/Games/GameXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/GameXmlProvider.cs
@@ -1,11 +1,12 @@
-using MediaBrowser.Common.IO;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.Games
+namespace MediaBrowser.LocalMetadata.Providers
{
public class GameXmlProvider : BaseXmlProvider<Game>
{
@@ -35,7 +36,7 @@ namespace MediaBrowser.Providers.Games
var directoryPath = directoryInfo.FullName;
- var specificFile = Path.Combine(directoryPath, Path.GetFileNameWithoutExtension(info.Path) + ".xml");
+ var specificFile = Path.Combine(directoryPath, FileSystem.GetFileNameWithoutExtension(info.Path) + ".xml");
var file = new FileInfo(specificFile);
diff --git a/MediaBrowser.Providers/Movies/MovieXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs
index cc7293f53..fb3a01bf2 100644
--- a/MediaBrowser.Providers/Movies/MovieXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/MovieXmlProvider.cs
@@ -1,13 +1,14 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System.Collections.Generic;
using System.IO;
using System.Threading;
-namespace MediaBrowser.Providers.Movies
+namespace MediaBrowser.LocalMetadata.Providers
{
public class MovieXmlProvider : BaseXmlProvider<Movie>
{
@@ -46,7 +47,7 @@ namespace MediaBrowser.Providers.Movies
var directoryPath = directoryInfo.FullName;
- var specificFile = Path.Combine(directoryPath, Path.GetFileNameWithoutExtension(info.Path) + ".xml");
+ var specificFile = Path.Combine(directoryPath, fileSystem.GetFileNameWithoutExtension(info.Path) + ".xml");
var file = new FileInfo(specificFile);
diff --git a/MediaBrowser.Providers/Music/MusicVideoXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs
index 93d9031c3..6289dcb56 100644
--- a/MediaBrowser.Providers/Music/MusicVideoXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/MusicVideoXmlProvider.cs
@@ -1,13 +1,12 @@
-using MediaBrowser.Common.IO;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
-using MediaBrowser.Providers.Movies;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.Music
+namespace MediaBrowser.LocalMetadata.Providers
{
class MusicVideoXmlProvider : BaseXmlProvider<MusicVideo>
{
diff --git a/MediaBrowser.Providers/People/PersonXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs
index b120c4830..9f27d6c7d 100644
--- a/MediaBrowser.Providers/People/PersonXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/PersonXmlProvider.cs
@@ -1,11 +1,11 @@
-using MediaBrowser.Common.IO;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.People
+namespace MediaBrowser.LocalMetadata.Providers
{
public class PersonXmlProvider : BaseXmlProvider<Person>
{
diff --git a/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs
new file mode 100644
index 000000000..2279ae052
--- /dev/null
+++ b/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs
@@ -0,0 +1,31 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Playlists;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
+using MediaBrowser.Model.Logging;
+using System.IO;
+using System.Threading;
+
+namespace MediaBrowser.LocalMetadata.Providers
+{
+ class PlaylistXmlProvider : BaseXmlProvider<Playlist>
+ {
+ private readonly ILogger _logger;
+
+ public PlaylistXmlProvider(IFileSystem fileSystem, ILogger logger)
+ : base(fileSystem)
+ {
+ _logger = logger;
+ }
+
+ protected override void Fetch(LocalMetadataResult<Playlist> result, string path, CancellationToken cancellationToken)
+ {
+ new PlaylistXmlParser(_logger).Fetch(result.Item, path, cancellationToken);
+ }
+
+ protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+ {
+ return directoryService.GetFile(Path.Combine(info.Path, "playlist.xml"));
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/TV/SeasonXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/SeasonXmlProvider.cs
index 6a41988de..2320982c3 100644
--- a/MediaBrowser.Providers/TV/SeasonXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/SeasonXmlProvider.cs
@@ -1,16 +1,17 @@
-using MediaBrowser.Common.IO;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.TV
+namespace MediaBrowser.LocalMetadata.Providers
{
/// <summary>
/// Class SeriesProviderFromXml
/// </summary>
- public class SeasonXmlProvider : BaseXmlProvider<Season>
+ public class SeasonXmlProvider : BaseXmlProvider<Season>, IHasOrder
{
private readonly ILogger _logger;
@@ -29,6 +30,15 @@ namespace MediaBrowser.Providers.TV
{
return directoryService.GetFile(Path.Combine(info.Path, "season.xml"));
}
+
+ public int Order
+ {
+ get
+ {
+ // After Xbmc
+ return 1;
+ }
+ }
}
}
diff --git a/MediaBrowser.Providers/TV/SeriesXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs
index f32afbd96..311c10287 100644
--- a/MediaBrowser.Providers/TV/SeriesXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/SeriesXmlProvider.cs
@@ -1,16 +1,17 @@
-using MediaBrowser.Common.IO;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Logging;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.TV
+namespace MediaBrowser.LocalMetadata.Providers
{
/// <summary>
/// Class SeriesProviderFromXml
/// </summary>
- public class SeriesXmlProvider : BaseXmlProvider<Series>
+ public class SeriesXmlProvider : BaseXmlProvider<Series>, IHasOrder
{
private readonly ILogger _logger;
@@ -29,5 +30,14 @@ namespace MediaBrowser.Providers.TV
{
return directoryService.GetFile(Path.Combine(info.Path, "series.xml"));
}
+
+ public int Order
+ {
+ get
+ {
+ // After Xbmc
+ return 1;
+ }
+ }
}
}
diff --git a/MediaBrowser.Providers/Movies/TrailerXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/TrailerXmlProvider.cs
index d24bdb431..7f96f7d96 100644
--- a/MediaBrowser.Providers/Movies/TrailerXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/TrailerXmlProvider.cs
@@ -1,13 +1,14 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System.Collections.Generic;
using System.IO;
using System.Threading;
-namespace MediaBrowser.Providers.Movies
+namespace MediaBrowser.LocalMetadata.Providers
{
public class TrailerXmlProvider : BaseXmlProvider<Trailer>
{
diff --git a/MediaBrowser.Providers/Videos/VideoXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs
index 779f3faa7..25aa61baf 100644
--- a/MediaBrowser.Providers/Videos/VideoXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/Providers/VideoXmlProvider.cs
@@ -1,14 +1,14 @@
-using MediaBrowser.Common.IO;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.LocalMetadata.Parsers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
-using MediaBrowser.Providers.Movies;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
-namespace MediaBrowser.Providers.Videos
+namespace MediaBrowser.LocalMetadata.Providers
{
class VideoXmlProvider : BaseXmlProvider<Video>
{
diff --git a/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/AlbumXmlSaver.cs
index 4f08f0d82..05022464d 100644
--- a/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/AlbumXmlSaver.cs
@@ -1,12 +1,12 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Library;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Library;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
class AlbumXmlSaver : IMetadataFileSaver
{
diff --git a/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/ArtistXmlSaver.cs
index 5f9c06d25..b932c5c7c 100644
--- a/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/ArtistXmlSaver.cs
@@ -1,12 +1,12 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Library;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Library;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
class ArtistXmlSaver : IMetadataFileSaver
{
diff --git a/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs
index dcf789b30..db7b40c7d 100644
--- a/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs
@@ -1,13 +1,12 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Library;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
public class BoxSetXmlSaver : IMetadataFileSaver
{
diff --git a/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/ChannelXmlSaver.cs
index 2d4221bda..3b7783012 100644
--- a/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/ChannelXmlSaver.cs
@@ -1,13 +1,12 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.LiveTv;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
/// <summary>
/// Class PersonXmlSaver
diff --git a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs
index 98a298620..275ec2fe8 100644
--- a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs
@@ -1,15 +1,15 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Persistence;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Persistence;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
public class EpisodeXmlSaver : IMetadataFileSaver
{
diff --git a/MediaBrowser.Providers/Savers/FolderXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs
index db08eafe3..c38a33c40 100644
--- a/MediaBrowser.Providers/Savers/FolderXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs
@@ -3,13 +3,13 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Controller.Playlists;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
public class FolderXmlSaver : IMetadataFileSaver
{
@@ -38,7 +38,8 @@ namespace MediaBrowser.Providers.Savers
{
if (!(item is Series) && !(item is BoxSet) && !(item is MusicArtist) && !(item is MusicAlbum) &&
!(item is Season) &&
- !(item is GameSystem))
+ !(item is GameSystem) &&
+ !(item is Playlist))
{
return updateType >= ItemUpdateType.MetadataDownload;
}
diff --git a/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs
index 98a2d03be..163c79ce2 100644
--- a/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/GameSystemXmlSaver.cs
@@ -1,12 +1,12 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
public class GameSystemXmlSaver : IMetadataFileSaver
{
diff --git a/MediaBrowser.Providers/Savers/GameXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs
index 959041a8c..7eeaa211f 100644
--- a/MediaBrowser.Providers/Savers/GameXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/GameXmlSaver.cs
@@ -1,14 +1,14 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
/// <summary>
/// Saves game.xml for games
diff --git a/MediaBrowser.Providers/Savers/MovieXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs
index cd5f2faec..ef81790a6 100644
--- a/MediaBrowser.Providers/Savers/MovieXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs
@@ -1,16 +1,15 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Persistence;
-using System.Collections.Generic;
-using System.Globalization;
+using System.Collections.Generic;
using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Persistence;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
/// <summary>
/// Saves movie.xml for movies, trailers and music videos
diff --git a/MediaBrowser.Providers/Savers/PersonXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs
index 9bbe5b5dc..2ea60f47c 100644
--- a/MediaBrowser.Providers/Savers/PersonXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/PersonXmlSaver.cs
@@ -1,14 +1,12 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Providers;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.IO;
using System.Security;
using System.Text;
using System.Threading;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
/// <summary>
/// Class PersonXmlSaver
diff --git a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs
new file mode 100644
index 000000000..1541c2176
--- /dev/null
+++ b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs
@@ -0,0 +1,86 @@
+using System.Security;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Playlists;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading;
+
+namespace MediaBrowser.LocalMetadata.Savers
+{
+ public class PlaylistXmlSaver : IMetadataFileSaver
+ {
+ public string Name
+ {
+ get
+ {
+ return "Media Browser Xml";
+ }
+ }
+
+ /// <summary>
+ /// Determines whether [is enabled for] [the specified item].
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="updateType">Type of the update.</param>
+ /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
+ public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ {
+ if (!item.SupportsLocalMetadata)
+ {
+ return false;
+ }
+
+ return item is Playlist && updateType >= ItemUpdateType.MetadataImport;
+ }
+
+ /// <summary>
+ /// Saves the specified item.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ public void Save(IHasMetadata item, CancellationToken cancellationToken)
+ {
+ var playlist = (Playlist)item;
+
+ var builder = new StringBuilder();
+
+ builder.Append("<Item>");
+
+ if (!string.IsNullOrEmpty(playlist.OwnerUserId))
+ {
+ builder.Append("<OwnerUserId>" + SecurityElement.Escape(playlist.OwnerUserId) + "</OwnerUserId>");
+ }
+
+ if (!string.IsNullOrEmpty(playlist.PlaylistMediaType))
+ {
+ builder.Append("<PlaylistMediaType>" + SecurityElement.Escape(playlist.PlaylistMediaType) + "</PlaylistMediaType>");
+ }
+
+ XmlSaverHelpers.AddCommonNodes(playlist, builder);
+
+ builder.Append("</Item>");
+
+ var xmlFilePath = GetSavePath(item);
+
+ XmlSaverHelpers.Save(builder, xmlFilePath, new List<string>
+ {
+ "OwnerUserId",
+ "PlaylistMediaType"
+
+ });
+ }
+
+ /// <summary>
+ /// Gets the save path.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>System.String.</returns>
+ public string GetSavePath(IHasMetadata item)
+ {
+ return Path.Combine(item.Path, "playlist.xml");
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/SeasonXmlSaver.cs
index ee3e18fd7..b9908875d 100644
--- a/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/SeasonXmlSaver.cs
@@ -1,14 +1,14 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
public class SeasonXmlSaver : IMetadataFileSaver
{
diff --git a/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs
index a7ed55e5d..23ea52820 100644
--- a/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs
@@ -1,15 +1,15 @@
-using System.Globalization;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
+using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using System.Security;
using System.Text;
using System.Threading;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
public class SeriesXmlSaver : IMetadataFileSaver
{
diff --git a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
index 6b9ebbfe9..0801b7358 100644
--- a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs
+++ b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
@@ -1,9 +1,4 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Model.Entities;
-using System;
+using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@@ -11,8 +6,14 @@ using System.Linq;
using System.Security;
using System.Text;
using System.Xml;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Playlists;
+using MediaBrowser.Model.Entities;
-namespace MediaBrowser.Providers.Savers
+namespace MediaBrowser.LocalMetadata.Savers
{
/// <summary>
/// Class XmlHelpers
@@ -63,6 +64,8 @@ namespace MediaBrowser.Providers.Savers
// Deprecated. No longer saving in this field.
"MPAARating",
+ "MPAADescription",
+
"MusicBrainzArtistId",
"MusicBrainzAlbumArtistId",
"MusicBrainzAlbumId",
@@ -72,6 +75,7 @@ namespace MediaBrowser.Providers.Savers
"MusicbrainzId",
"Overview",
+ "ShortOverview",
"Persons",
"PlotKeywords",
"PremiereDate",
@@ -106,7 +110,8 @@ namespace MediaBrowser.Providers.Savers
"VoteCount",
"Website",
"Zap2ItId",
- "CollectionItems"
+ "CollectionItems",
+ "PlaylistItems"
}.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
@@ -229,6 +234,11 @@ namespace MediaBrowser.Providers.Savers
builder.Append("<ContentRating>" + SecurityElement.Escape(item.OfficialRating) + "</ContentRating>");
}
+ if (!string.IsNullOrEmpty(item.OfficialRatingDescription))
+ {
+ builder.Append("<MPAADescription>" + SecurityElement.Escape(item.OfficialRatingDescription) + "</MPAADescription>");
+ }
+
builder.Append("<Added>" + SecurityElement.Escape(item.DateCreated.ToLocalTime().ToString("G")) + "</Added>");
builder.Append("<LockData>" + item.IsLocked.ToString().ToLower() + "</LockData>");
@@ -257,6 +267,11 @@ namespace MediaBrowser.Providers.Savers
}
}
+ if (!string.IsNullOrEmpty(item.Overview))
+ {
+ builder.Append("<Overview><![CDATA[" + item.Overview + "]]></Overview>");
+ }
+
var hasShortOverview = item as IHasShortOverview;
if (hasShortOverview != null)
{
@@ -618,10 +633,16 @@ namespace MediaBrowser.Providers.Savers
builder.Append("</Persons>");
}
- var folder = item as BoxSet;
- if (folder != null)
+ var boxset = item as BoxSet;
+ if (boxset != null)
+ {
+ AddLinkedChildren(boxset, builder, "CollectionItems", "CollectionItem");
+ }
+
+ var playlist = item as Playlist;
+ if (playlist != null)
{
- AddCollectionItems(folder, builder);
+ AddLinkedChildren(playlist, builder, "PlaylistItems", "PlaylistItem");
}
}
@@ -680,10 +701,10 @@ namespace MediaBrowser.Providers.Savers
}
}
- public static void AddCollectionItems(Folder item, StringBuilder builder)
+ public static void AddLinkedChildren(Folder item, StringBuilder builder, string pluralNodeName, string singularNodeName)
{
var items = item.LinkedChildren
- .Where(i => i.Type == LinkedChildType.Manual && !string.IsNullOrWhiteSpace(i.ItemName))
+ .Where(i => i.Type == LinkedChildType.Manual)
.ToList();
if (items.Count == 0)
@@ -691,22 +712,29 @@ namespace MediaBrowser.Providers.Savers
return;
}
- builder.Append("<CollectionItems>");
+ builder.Append("<" + pluralNodeName + ">");
foreach (var link in items)
{
- builder.Append("<CollectionItem>");
+ builder.Append("<" + singularNodeName + ">");
- builder.Append("<Name>" + SecurityElement.Escape(link.ItemName) + "</Name>");
- builder.Append("<Type>" + SecurityElement.Escape(link.ItemType) + "</Type>");
+ if (!string.IsNullOrWhiteSpace(link.ItemType))
+ {
+ builder.Append("<Type>" + SecurityElement.Escape(link.ItemType) + "</Type>");
+ }
if (link.ItemYear.HasValue)
{
builder.Append("<Year>" + SecurityElement.Escape(link.ItemYear.Value.ToString(UsCulture)) + "</Year>");
}
- builder.Append("</CollectionItem>");
+ if (!string.IsNullOrWhiteSpace(link.Path))
+ {
+ builder.Append("<Path>" + SecurityElement.Escape((link.Path)) + "</Path>");
+ }
+
+ builder.Append("</" + singularNodeName + ">");
}
- builder.Append("</CollectionItems>");
+ builder.Append("</" + pluralNodeName + ">");
}
}
}
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index 5ee119e13..82d5e0344 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -1,5 +1,3 @@
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.IO;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -11,7 +9,6 @@ using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
-using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -28,11 +25,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
private readonly ILogger _logger;
/// <summary>
- /// The _app paths
- /// </summary>
- private readonly IApplicationPaths _appPaths;
-
- /// <summary>
/// Gets the json serializer.
/// </summary>
/// <value>The json serializer.</value>
@@ -53,23 +45,17 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// </summary>
private readonly SemaphoreSlim _ffProbeResourcePool = new SemaphoreSlim(2, 2);
- private readonly IFileSystem _fileSystem;
-
public string FFMpegPath { get; private set; }
public string FFProbePath { get; private set; }
public string Version { get; private set; }
- public MediaEncoder(ILogger logger, IApplicationPaths appPaths,
- IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version,
- IFileSystem fileSystem)
+ public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, string version)
{
_logger = logger;
- _appPaths = appPaths;
_jsonSerializer = jsonSerializer;
Version = version;
- _fileSystem = fileSystem;
FFProbePath = ffProbePath;
FFMpegPath = ffMpegPath;
}
@@ -84,22 +70,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
}
/// <summary>
- /// The _semaphoreLocks
- /// </summary>
- private readonly ConcurrentDictionary<string, SemaphoreSlim> _semaphoreLocks =
- new ConcurrentDictionary<string, SemaphoreSlim>();
-
- /// <summary>
- /// Gets the lock.
- /// </summary>
- /// <param name="filename">The filename.</param>
- /// <returns>System.Object.</returns>
- private SemaphoreSlim GetLock(string filename)
- {
- return _semaphoreLocks.GetOrAdd(filename, key => new SemaphoreSlim(1, 1));
- }
-
- /// <summary>
/// Gets the media info.
/// </summary>
/// <param name="inputFiles">The input files.</param>
@@ -166,7 +136,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
RedirectStandardError = true,
FileName = FFProbePath,
Arguments = string.Format(args,
- probeSizeArgument, inputPath).Trim(),
+ probeSizeArgument, inputPath).Trim(),
WindowStyle = ProcessWindowStyle.Hidden,
ErrorDialog = false
@@ -200,8 +170,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
process.BeginErrorReadLine();
- result =
- _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream);
+ result = _jsonSerializer.DeserializeFromStream<InternalMediaInfoResult>(process.StandardOutput.BaseStream);
}
catch
{
@@ -263,30 +232,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
((Process)sender).Dispose();
}
- private const int FastSeekOffsetSeconds = 1;
-
- protected string GetFastSeekCommandLineParameter(TimeSpan offset)
- {
- var seconds = offset.TotalSeconds - FastSeekOffsetSeconds;
-
- if (seconds > 0)
- {
- return string.Format("-ss {0} ", seconds.ToString(UsCulture));
- }
-
- return string.Empty;
- }
-
- protected string GetSlowSeekCommandLineParameter(TimeSpan offset)
- {
- if (offset.TotalSeconds - FastSeekOffsetSeconds > 0)
- {
- return string.Format(" -ss {0}", FastSeekOffsetSeconds.ToString(UsCulture));
- }
-
- return string.Empty;
- }
-
public Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken)
{
return ExtractImage(new[] { path }, MediaProtocol.File, true, null, null, cancellationToken);
@@ -330,7 +275,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
// apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar then scale to width 600.
// This filter chain may have adverse effects on recorded tv thumbnails if ar changes during presentation ex. commercials @ diff ar
var vf = "scale=600:trunc(600/dar/2)*2";
- //crop=min(iw\,ih*dar):min(ih\,iw/dar):(iw-min(iw\,iw*sar))/2:(ih - min (ih\,ih/sar))/2,scale=600:(600/dar),thumbnail" -f image2
if (threedFormat.HasValue)
{
@@ -368,7 +312,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (offset.HasValue)
{
- args = string.Format("-ss {0} ", Convert.ToInt32(offset.Value.TotalSeconds)).ToString(UsCulture) + args;
+ args = string.Format("-ss {0} ", GetTimeParameter(offset.Value)) + args;
}
var process = new Process
@@ -382,7 +326,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
WindowStyle = ProcessWindowStyle.Hidden,
ErrorDialog = false,
RedirectStandardOutput = true,
- RedirectStandardError = true
+ RedirectStandardError = true,
+ RedirectStandardInput = true
}
};
@@ -408,7 +353,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
{
_logger.Info("Killing ffmpeg process");
- process.Kill();
+ process.StandardInput.WriteLine("q");
process.WaitForExit(1000);
}
@@ -463,5 +408,105 @@ namespace MediaBrowser.MediaEncoding.Encoder
_videoImageResourcePool.Dispose();
}
}
+
+ public string GetTimeParameter(long ticks)
+ {
+ var time = TimeSpan.FromTicks(ticks);
+
+ return GetTimeParameter(time);
+ }
+
+ public string GetTimeParameter(TimeSpan time)
+ {
+ return time.ToString(@"hh\:mm\:ss\.fff", UsCulture);
+ }
+
+ public async Task ExtractVideoImagesOnInterval(string[] inputFiles,
+ MediaProtocol protocol,
+ Video3DFormat? threedFormat,
+ TimeSpan interval,
+ string targetDirectory,
+ string filenamePrefix,
+ int? maxWidth,
+ CancellationToken cancellationToken)
+ {
+ var resourcePool = _videoImageResourcePool;
+
+ var inputArgument = GetInputArgument(inputFiles, protocol);
+
+ var vf = "fps=fps=1/" + interval.TotalSeconds.ToString(UsCulture);
+
+ if (maxWidth.HasValue)
+ {
+ var maxWidthParam = maxWidth.Value.ToString(UsCulture);
+
+ vf += string.Format(",scale=min(iw\\,{0}):trunc(ow/dar/2)*2", maxWidthParam);
+ }
+
+ Directory.CreateDirectory(targetDirectory);
+ var outputPath = Path.Combine(targetDirectory, filenamePrefix + "%05d.jpg");
+
+ var args = string.Format("-i {0} -threads 0 -v quiet -vf \"{2}\" -f image2 \"{1}\"", inputArgument, outputPath, vf);
+
+ var probeSize = GetProbeSizeArgument(new[] { inputArgument }, protocol);
+
+ if (!string.IsNullOrEmpty(probeSize))
+ {
+ args = probeSize + " " + args;
+ }
+
+ var process = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ CreateNoWindow = true,
+ UseShellExecute = false,
+ FileName = FFMpegPath,
+ Arguments = args,
+ WindowStyle = ProcessWindowStyle.Hidden,
+ ErrorDialog = false,
+ RedirectStandardInput = true
+ }
+ };
+
+ _logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments);
+
+ await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+ process.Start();
+
+ var ranToCompletion = process.WaitForExit(120000);
+
+ if (!ranToCompletion)
+ {
+ try
+ {
+ _logger.Info("Killing ffmpeg process");
+
+ process.StandardInput.WriteLine("q");
+
+ process.WaitForExit(1000);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error killing process", ex);
+ }
+ }
+
+ resourcePool.Release();
+
+ var exitCode = ranToCompletion ? process.ExitCode : -1;
+
+ process.Dispose();
+
+ if (exitCode == -1)
+ {
+ var msg = string.Format("ffmpeg image extraction failed for {0}", inputArgument);
+
+ _logger.Error(msg);
+
+ throw new ApplicationException(msg);
+ }
+ }
}
}
diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
index d2c21639c..9263a3187 100644
--- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
+++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
@@ -52,17 +52,23 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\SharedVersion.cs">
+ <Link>Properties\SharedVersion.cs</Link>
+ </Compile>
<Compile Include="BdInfo\BdInfoExaminer.cs" />
<Compile Include="Encoder\EncodingUtils.cs" />
<Compile Include="Encoder\MediaEncoder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Subtitles\ISubtitleParser.cs" />
<Compile Include="Subtitles\ISubtitleWriter.cs" />
+ <Compile Include="Subtitles\JsonWriter.cs" />
<Compile Include="Subtitles\SrtParser.cs" />
<Compile Include="Subtitles\SrtWriter.cs" />
+ <Compile Include="Subtitles\AssParser.cs" />
<Compile Include="Subtitles\SsaParser.cs" />
<Compile Include="Subtitles\SubtitleEncoder.cs" />
<Compile Include="Subtitles\SubtitleTrackInfo.cs" />
+ <Compile Include="Subtitles\TtmlWriter.cs" />
<Compile Include="Subtitles\VttWriter.cs" />
</ItemGroup>
<ItemGroup>
@@ -84,7 +90,7 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.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">
diff --git a/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs b/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs
index 6616e46ac..6b456b98d 100644
--- a/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs
+++ b/MediaBrowser.MediaEncoding/Properties/AssemblyInfo.cs
@@ -31,6 +31,4 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+// [assembly: AssemblyVersion("1.0.*")] \ No newline at end of file
diff --git a/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs
new file mode 100644
index 000000000..e5a727428
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Subtitles/AssParser.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+
+namespace MediaBrowser.MediaEncoding.Subtitles
+{
+ public class AssParser : ISubtitleParser
+ {
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
+ public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken)
+ {
+ var trackInfo = new SubtitleTrackInfo();
+ var eventIndex = 1;
+ using (var reader = new StreamReader(stream))
+ {
+ string line;
+ while (reader.ReadLine() != "[Events]")
+ {}
+ var headers = ParseFieldHeaders(reader.ReadLine());
+
+ while ((line = reader.ReadLine()) != null)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (string.IsNullOrWhiteSpace(line))
+ {
+ continue;
+ }
+ if(line.StartsWith("["))
+ break;
+ if(string.IsNullOrEmpty(line))
+ continue;
+ var subEvent = new SubtitleTrackEvent { Id = eventIndex.ToString(_usCulture) };
+ eventIndex++;
+ var sections = line.Substring(10).Split(',');
+
+ subEvent.StartPositionTicks = GetTicks(sections[headers["Start"]]);
+ subEvent.EndPositionTicks = GetTicks(sections[headers["End"]]);
+ subEvent.Text = string.Join(",", sections.Skip(headers["Text"]));
+ subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase);
+
+ trackInfo.TrackEvents.Add(subEvent);
+ }
+ }
+ return trackInfo;
+ }
+
+ long GetTicks(string time)
+ {
+ TimeSpan span;
+ return TimeSpan.TryParseExact(time, @"h\:mm\:ss\.ff", _usCulture, out span)
+ ? span.Ticks: 0;
+ }
+
+ private Dictionary<string,int> ParseFieldHeaders(string line) {
+ var fields = line.Substring(8).Split(',').Select(x=>x.Trim()).ToList();
+
+ var result = new Dictionary<string, int> {
+ {"Start", fields.IndexOf("Start")},
+ {"End", fields.IndexOf("End")},
+ {"Text", fields.IndexOf("Text")}
+ };
+ return result;
+ }
+ }
+}
diff --git a/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs
new file mode 100644
index 000000000..a4fc5d795
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Subtitles/JsonWriter.cs
@@ -0,0 +1,27 @@
+using MediaBrowser.Model.Serialization;
+using System.IO;
+using System.Text;
+using System.Threading;
+
+namespace MediaBrowser.MediaEncoding.Subtitles
+{
+ public class JsonWriter : ISubtitleWriter
+ {
+ private readonly IJsonSerializer _json;
+
+ public JsonWriter(IJsonSerializer json)
+ {
+ _json = json;
+ }
+
+ public void Write(SubtitleTrackInfo info, Stream stream, CancellationToken cancellationToken)
+ {
+ using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true))
+ {
+ var json = _json.SerializeToString(info);
+
+ writer.Write(json);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs
index f94fae9e9..84cd1eb2d 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs
@@ -48,7 +48,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
multiline.Add(line);
}
- subEvent.Text = string.Join(@"\N", multiline);
+ subEvent.Text = string.Join(@"\n", multiline);
subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase);
subEvent.Text = Regex.Replace(subEvent.Text, "<", "&lt;", RegexOptions.IgnoreCase);
subEvent.Text = Regex.Replace(subEvent.Text, ">", "&gt;", RegexOptions.IgnoreCase);
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs
index d0d0819dd..3e574f931 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SrtWriter.cs
@@ -25,7 +25,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
var text = trackEvent.Text;
// TODO: Not sure how to handle these
- text = Regex.Replace(text, @"\\N", " ", RegexOptions.IgnoreCase);
+ text = Regex.Replace(text, @"\\n", " ", RegexOptions.IgnoreCase);
writer.WriteLine(text);
writer.WriteLine(string.Empty);
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs
index e21804f6c..559a05bc8 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs
@@ -1,71 +1,391 @@
using System;
-using System.Collections.Generic;
-using System.Globalization;
using System.IO;
-using System.Linq;
-using System.Text.RegularExpressions;
+using System.Text;
using System.Threading;
namespace MediaBrowser.MediaEncoding.Subtitles
{
+ /// <summary>
+ /// Credit to https://github.com/SubtitleEdit/subtitleedit/blob/a299dc4407a31796364cc6ad83f0d3786194ba22/src/Logic/SubtitleFormats/SubStationAlpha.cs
+ /// </summary>
public class SsaParser : ISubtitleParser
{
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
-
public SubtitleTrackInfo Parse(Stream stream, CancellationToken cancellationToken)
{
var trackInfo = new SubtitleTrackInfo();
- var eventIndex = 1;
+
using (var reader = new StreamReader(stream))
{
+ bool eventsStarted = false;
+
+ string[] format = "Marked, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text".Split(',');
+ int indexLayer = 0;
+ int indexStart = 1;
+ int indexEnd = 2;
+ int indexStyle = 3;
+ int indexName = 4;
+ int indexEffect = 8;
+ int indexText = 9;
+ int lineNumber = 0;
+
+ var header = new StringBuilder();
+
string line;
- while (reader.ReadLine() != "[Events]")
- {}
- var headers = ParseFieldHeaders(reader.ReadLine());
while ((line = reader.ReadLine()) != null)
{
cancellationToken.ThrowIfCancellationRequested();
-
- if (string.IsNullOrWhiteSpace(line))
+
+ lineNumber++;
+ if (!eventsStarted)
+ header.AppendLine(line);
+
+ if (line.Trim().ToLower() == "[events]")
{
- continue;
+ eventsStarted = true;
}
- if(line.StartsWith("["))
- break;
- if(string.IsNullOrEmpty(line))
- continue;
- var subEvent = new SubtitleTrackEvent { Id = eventIndex.ToString(_usCulture) };
- eventIndex++;
- var sections = line.Substring(10).Split(',');
-
- subEvent.StartPositionTicks = GetTicks(sections[headers["Start"]]);
- subEvent.EndPositionTicks = GetTicks(sections[headers["End"]]);
- subEvent.Text = string.Join(",", sections.Skip(headers["Text"]));
- subEvent.Text = Regex.Replace(subEvent.Text, @"\{(\\[\w]+\(?([\w\d]+,?)+\)?)+\}", string.Empty, RegexOptions.IgnoreCase);
-
- trackInfo.TrackEvents.Add(subEvent);
- }
+ else if (!string.IsNullOrEmpty(line) && line.Trim().StartsWith(";"))
+ {
+ // skip comment lines
+ }
+ else if (eventsStarted && line.Trim().Length > 0)
+ {
+ string s = line.Trim().ToLower();
+ if (s.StartsWith("format:"))
+ {
+ if (line.Length > 10)
+ {
+ format = line.ToLower().Substring(8).Split(',');
+ for (int i = 0; i < format.Length; i++)
+ {
+ if (format[i].Trim().ToLower() == "layer")
+ indexLayer = i;
+ else if (format[i].Trim().ToLower() == "start")
+ indexStart = i;
+ else if (format[i].Trim().ToLower() == "end")
+ indexEnd = i;
+ else if (format[i].Trim().ToLower() == "text")
+ indexText = i;
+ else if (format[i].Trim().ToLower() == "effect")
+ indexEffect = i;
+ else if (format[i].Trim().ToLower() == "style")
+ indexStyle = i;
+ }
+ }
+ }
+ else if (!string.IsNullOrEmpty(s))
+ {
+ string text = string.Empty;
+ string start = string.Empty;
+ string end = string.Empty;
+ string style = string.Empty;
+ string layer = string.Empty;
+ string effect = string.Empty;
+ string name = string.Empty;
+
+ string[] splittedLine;
+
+ if (s.StartsWith("dialogue:"))
+ splittedLine = line.Substring(10).Split(',');
+ else
+ splittedLine = line.Split(',');
+
+ for (int i = 0; i < splittedLine.Length; i++)
+ {
+ if (i == indexStart)
+ start = splittedLine[i].Trim();
+ else if (i == indexEnd)
+ end = splittedLine[i].Trim();
+ else if (i == indexLayer)
+ layer = splittedLine[i];
+ else if (i == indexEffect)
+ effect = splittedLine[i];
+ else if (i == indexText)
+ text = splittedLine[i];
+ else if (i == indexStyle)
+ style = splittedLine[i];
+ else if (i == indexName)
+ name = splittedLine[i];
+ else if (i > indexText)
+ text += "," + splittedLine[i];
+ }
+
+ try
+ {
+ var p = new SubtitleTrackEvent();
+
+ p.StartPositionTicks = GetTimeCodeFromString(start);
+ p.EndPositionTicks = GetTimeCodeFromString(end);
+ p.Text = GetFormattedText(text);
+
+ trackInfo.TrackEvents.Add(p);
+ }
+ catch
+ {
+ }
+ }
+ }
+ }
+
+ //if (header.Length > 0)
+ //subtitle.Header = header.ToString();
+
+ //subtitle.Renumber(1);
}
return trackInfo;
}
- long GetTicks(string time)
+ private static long GetTimeCodeFromString(string time)
+ {
+ // h:mm:ss.cc
+ string[] timeCode = time.Split(':', '.');
+ return new TimeSpan(0, int.Parse(timeCode[0]),
+ int.Parse(timeCode[1]),
+ int.Parse(timeCode[2]),
+ int.Parse(timeCode[3]) * 10).Ticks;
+ }
+
+ public static string GetFormattedText(string text)
+ {
+ text = text.Replace("\\n", Environment.NewLine).Replace("\\n", Environment.NewLine);
+ bool italic = false;
+
+ for (int i = 0; i < 10; i++) // just look ten times...
+ {
+ if (text.Contains(@"{\fn"))
+ {
+ int start = text.IndexOf(@"{\fn");
+ int end = text.IndexOf('}', start);
+ if (end > 0 && !text.Substring(start).StartsWith("{\\fn}"))
+ {
+ string fontName = text.Substring(start + 4, end - (start + 4));
+ string extraTags = string.Empty;
+ CheckAndAddSubTags(ref fontName, ref extraTags, out italic);
+ text = text.Remove(start, end - start + 1);
+ if (italic)
+ text = text.Insert(start, "<font face=\"" + fontName + "\"" + extraTags + "><i>");
+ else
+ text = text.Insert(start, "<font face=\"" + fontName + "\"" + extraTags + ">");
+
+ int indexOfEndTag = text.IndexOf("{\\fn}", start);
+ if (indexOfEndTag > 0)
+ text = text.Remove(indexOfEndTag, "{\\fn}".Length).Insert(indexOfEndTag, "</font>");
+ else
+ text += "</font>";
+ }
+ }
+
+ if (text.Contains(@"{\fs"))
+ {
+ int start = text.IndexOf(@"{\fs");
+ int end = text.IndexOf('}', start);
+ if (end > 0 && !text.Substring(start).StartsWith("{\\fs}"))
+ {
+ string fontSize = text.Substring(start + 4, end - (start + 4));
+ string extraTags = string.Empty;
+ CheckAndAddSubTags(ref fontSize, ref extraTags, out italic);
+ if (IsInteger(fontSize))
+ {
+ text = text.Remove(start, end - start + 1);
+ if (italic)
+ text = text.Insert(start, "<font size=\"" + fontSize + "\"" + extraTags + "><i>");
+ else
+ text = text.Insert(start, "<font size=\"" + fontSize + "\"" + extraTags + ">");
+
+ int indexOfEndTag = text.IndexOf("{\\fs}", start);
+ if (indexOfEndTag > 0)
+ text = text.Remove(indexOfEndTag, "{\\fs}".Length).Insert(indexOfEndTag, "</font>");
+ else
+ text += "</font>";
+ }
+ }
+ }
+
+ if (text.Contains(@"{\c"))
+ {
+ int start = text.IndexOf(@"{\c");
+ int end = text.IndexOf('}', start);
+ if (end > 0 && !text.Substring(start).StartsWith("{\\c}"))
+ {
+ string color = text.Substring(start + 4, end - (start + 4));
+ string extraTags = string.Empty;
+ CheckAndAddSubTags(ref color, ref extraTags, out italic);
+
+ color = color.Replace("&", string.Empty).TrimStart('H');
+ color = color.PadLeft(6, '0');
+
+ // switch to rrggbb from bbggrr
+ color = "#" + color.Remove(color.Length - 6) + color.Substring(color.Length - 2, 2) + color.Substring(color.Length - 4, 2) + color.Substring(color.Length - 6, 2);
+ color = color.ToLower();
+
+ text = text.Remove(start, end - start + 1);
+ if (italic)
+ text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + "><i>");
+ else
+ text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">");
+ int indexOfEndTag = text.IndexOf("{\\c}", start);
+ if (indexOfEndTag > 0)
+ text = text.Remove(indexOfEndTag, "{\\c}".Length).Insert(indexOfEndTag, "</font>");
+ else
+ text += "</font>";
+ }
+ }
+
+ if (text.Contains(@"{\1c")) // "1" specifices primary color
+ {
+ int start = text.IndexOf(@"{\1c");
+ int end = text.IndexOf('}', start);
+ if (end > 0 && !text.Substring(start).StartsWith("{\\1c}"))
+ {
+ string color = text.Substring(start + 5, end - (start + 5));
+ string extraTags = string.Empty;
+ CheckAndAddSubTags(ref color, ref extraTags, out italic);
+
+ color = color.Replace("&", string.Empty).TrimStart('H');
+ color = color.PadLeft(6, '0');
+
+ // switch to rrggbb from bbggrr
+ color = "#" + color.Remove(color.Length - 6) + color.Substring(color.Length - 2, 2) + color.Substring(color.Length - 4, 2) + color.Substring(color.Length - 6, 2);
+ color = color.ToLower();
+
+ text = text.Remove(start, end - start + 1);
+ if (italic)
+ text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + "><i>");
+ else
+ text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">");
+ text += "</font>";
+ }
+ }
+
+ }
+
+ text = text.Replace(@"{\i1}", "<i>");
+ text = text.Replace(@"{\i0}", "</i>");
+ text = text.Replace(@"{\i}", "</i>");
+ if (CountTagInText(text, "<i>") > CountTagInText(text, "</i>"))
+ text += "</i>";
+
+ text = text.Replace(@"{\u1}", "<u>");
+ text = text.Replace(@"{\u0}", "</u>");
+ text = text.Replace(@"{\u}", "</u>");
+ if (CountTagInText(text, "<u>") > CountTagInText(text, "</u>"))
+ text += "</u>";
+
+ text = text.Replace(@"{\b1}", "<b>");
+ text = text.Replace(@"{\b0}", "</b>");
+ text = text.Replace(@"{\b}", "</b>");
+ if (CountTagInText(text, "<b>") > CountTagInText(text, "</b>"))
+ text += "</b>";
+
+ return text;
+ }
+
+ private static bool IsInteger(string s)
{
- TimeSpan span;
- return TimeSpan.TryParseExact(time, @"h\:mm\:ss\.ff", _usCulture, out span)
- ? span.Ticks: 0;
+ int i;
+ if (int.TryParse(s, out i))
+ return true;
+ return false;
}
- private Dictionary<string,int> ParseFieldHeaders(string line) {
- var fields = line.Substring(8).Split(',').Select(x=>x.Trim()).ToList();
+ private static int CountTagInText(string text, string tag)
+ {
+ int count = 0;
+ int index = text.IndexOf(tag);
+ while (index >= 0)
+ {
+ count++;
+ if (index == text.Length)
+ return count;
+ index = text.IndexOf(tag, index + 1);
+ }
+ return count;
+ }
+
+ private static void CheckAndAddSubTags(ref string tagName, ref string extraTags, out bool italic)
+ {
+ italic = false;
+ int indexOfSPlit = tagName.IndexOf(@"\");
+ if (indexOfSPlit > 0)
+ {
+ string rest = tagName.Substring(indexOfSPlit).TrimStart('\\');
+ tagName = tagName.Remove(indexOfSPlit);
+
+ for (int i = 0; i < 10; i++)
+ {
+ if (rest.StartsWith("fs") && rest.Length > 2)
+ {
+ indexOfSPlit = rest.IndexOf(@"\");
+ string fontSize = rest;
+ if (indexOfSPlit > 0)
+ {
+ fontSize = rest.Substring(0, indexOfSPlit);
+ rest = rest.Substring(indexOfSPlit).TrimStart('\\');
+ }
+ else
+ {
+ rest = string.Empty;
+ }
+ extraTags += " size=\"" + fontSize.Substring(2) + "\"";
+ }
+ else if (rest.StartsWith("fn") && rest.Length > 2)
+ {
+ indexOfSPlit = rest.IndexOf(@"\");
+ string fontName = rest;
+ if (indexOfSPlit > 0)
+ {
+ fontName = rest.Substring(0, indexOfSPlit);
+ rest = rest.Substring(indexOfSPlit).TrimStart('\\');
+ }
+ else
+ {
+ rest = string.Empty;
+ }
+ extraTags += " face=\"" + fontName.Substring(2) + "\"";
+ }
+ else if (rest.StartsWith("c") && rest.Length > 2)
+ {
+ indexOfSPlit = rest.IndexOf(@"\");
+ string fontColor = rest;
+ if (indexOfSPlit > 0)
+ {
+ fontColor = rest.Substring(0, indexOfSPlit);
+ rest = rest.Substring(indexOfSPlit).TrimStart('\\');
+ }
+ else
+ {
+ rest = string.Empty;
+ }
+
+ string color = fontColor.Substring(2);
+ color = color.Replace("&", string.Empty).TrimStart('H');
+ color = color.PadLeft(6, '0');
+ // switch to rrggbb from bbggrr
+ color = "#" + color.Remove(color.Length - 6) + color.Substring(color.Length - 2, 2) + color.Substring(color.Length - 4, 2) + color.Substring(color.Length - 6, 2);
+ color = color.ToLower();
- var result = new Dictionary<string, int> {
- {"Start", fields.IndexOf("Start")},
- {"End", fields.IndexOf("End")},
- {"Text", fields.IndexOf("Text")}
- };
- return result;
+ extraTags += " color=\"" + color + "\"";
+ }
+ else if (rest.StartsWith("i1") && rest.Length > 1)
+ {
+ indexOfSPlit = rest.IndexOf(@"\");
+ italic = true;
+ if (indexOfSPlit > 0)
+ {
+ rest = rest.Substring(indexOfSPlit).TrimStart('\\');
+ }
+ else
+ {
+ rest = string.Empty;
+ }
+ }
+ else if (rest.Length > 0 && rest.Contains("\\"))
+ {
+ indexOfSPlit = rest.IndexOf(@"\");
+ rest = rest.Substring(indexOfSPlit).TrimStart('\\');
+ }
+ }
+ }
}
}
}
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index 154541316..7a3a7d2d0 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -7,6 +7,7 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
+using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
@@ -26,14 +27,16 @@ namespace MediaBrowser.MediaEncoding.Subtitles
private readonly IApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem;
private readonly IMediaEncoder _mediaEncoder;
+ private readonly IJsonSerializer _json;
- public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder)
+ public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IJsonSerializer json)
{
_libraryManager = libraryManager;
_logger = logger;
_appPaths = appPaths;
_fileSystem = fileSystem;
_mediaEncoder = mediaEncoder;
+ _json = json;
}
private string SubtitleCachePath
@@ -48,6 +51,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
string inputFormat,
string outputFormat,
long startTimeTicks,
+ long? endTimeTicks,
CancellationToken cancellationToken)
{
var ms = new MemoryStream();
@@ -56,6 +60,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
// Return the original without any conversions, if possible
if (startTimeTicks == 0 &&
+ !endTimeTicks.HasValue &&
string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase))
{
await stream.CopyToAsync(ms, 81920, cancellationToken).ConfigureAwait(false);
@@ -64,7 +69,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
var trackInfo = await GetTrackInfo(stream, inputFormat, cancellationToken).ConfigureAwait(false);
- UpdateStartingPosition(trackInfo, startTimeTicks);
+ FilterEvents(trackInfo, startTimeTicks, endTimeTicks, false);
var writer = GetWriter(outputFormat);
@@ -81,19 +86,30 @@ namespace MediaBrowser.MediaEncoding.Subtitles
return ms;
}
- private void UpdateStartingPosition(SubtitleTrackInfo track, long startPositionTicks)
+ private void FilterEvents(SubtitleTrackInfo track, long startPositionTicks, long? endTimeTicks, bool preserveTimestamps)
{
- if (startPositionTicks == 0) return;
+ // Drop subs that are earlier than what we're looking for
+ track.TrackEvents = track.TrackEvents
+ .SkipWhile(i => (i.StartPositionTicks - startPositionTicks) < 0 || (i.EndPositionTicks - startPositionTicks) < 0)
+ .ToList();
- foreach (var trackEvent in track.TrackEvents)
+ if (endTimeTicks.HasValue)
{
- trackEvent.EndPositionTicks -= startPositionTicks;
- trackEvent.StartPositionTicks -= startPositionTicks;
+ var endTime = endTimeTicks.Value;
+
+ track.TrackEvents = track.TrackEvents
+ .TakeWhile(i => i.StartPositionTicks <= endTime)
+ .ToList();
}
- track.TrackEvents = track.TrackEvents
- .SkipWhile(i => i.StartPositionTicks < 0 || i.EndPositionTicks < 0)
- .ToList();
+ if (!preserveTimestamps)
+ {
+ foreach (var trackEvent in track.TrackEvents)
+ {
+ trackEvent.EndPositionTicks -= startPositionTicks;
+ trackEvent.StartPositionTicks -= startPositionTicks;
+ }
+ }
}
public async Task<Stream> GetSubtitles(string itemId,
@@ -101,6 +117,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
int subtitleStreamIndex,
string outputFormat,
long startTimeTicks,
+ long? endTimeTicks,
CancellationToken cancellationToken)
{
var subtitle = await GetSubtitleStream(itemId, mediaSourceId, subtitleStreamIndex, cancellationToken)
@@ -110,7 +127,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
var inputFormat = subtitle.Item2;
- return await ConvertSubtitles(stream, inputFormat, outputFormat, startTimeTicks, cancellationToken).ConfigureAwait(false);
+ return await ConvertSubtitles(stream, inputFormat, outputFormat, startTimeTicks, endTimeTicks, cancellationToken).ConfigureAwait(false);
}
}
@@ -179,13 +196,36 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
if (!subtitleStream.IsExternal)
{
+ string outputFormat;
+ string outputCodec;
+
+ if (string.Equals(subtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase))
+ {
+ // Extract
+ outputCodec = "copy";
+ outputFormat = "ass";
+ }
+ else if (string.Equals(subtitleStream.Codec, "subrip", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(subtitleStream.Codec, "srt", StringComparison.OrdinalIgnoreCase))
+ {
+ // Extract
+ outputCodec = "copy";
+ outputFormat = "srt";
+ }
+ else
+ {
+ // Extract
+ outputCodec = "srt";
+ outputFormat = "srt";
+ }
+
// Extract
- var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, ".ass");
+ var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, "." + outputFormat);
- await ExtractTextSubtitle(inputFiles, protocol, subtitleStream.Index, false, outputPath, cancellationToken)
+ await ExtractTextSubtitle(inputFiles, protocol, subtitleStream.Index, outputCodec, outputPath, cancellationToken)
.ConfigureAwait(false);
- return new Tuple<string, string>(outputPath, "ass");
+ return new Tuple<string, string>(outputPath, outputFormat);
}
var currentFormat = (Path.GetExtension(subtitleStream.Path) ?? subtitleStream.Codec)
@@ -194,12 +234,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles
if (GetReader(currentFormat, false) == null)
{
// Convert
- var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, ".ass");
+ var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, ".srt");
- await ConvertTextSubtitleToAss(subtitleStream.Path, outputPath, subtitleStream.Language, cancellationToken)
+ await ConvertTextSubtitleToSrt(subtitleStream.Path, outputPath, subtitleStream.Language, cancellationToken)
.ConfigureAwait(false);
- return new Tuple<string, string>(outputPath, "ass");
+ return new Tuple<string, string>(outputPath, "srt");
}
return new Tuple<string, string>(subtitleStream.Path, currentFormat);
@@ -225,11 +265,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
return new SrtParser();
}
- if (string.Equals(format, SubtitleFormat.SSA, StringComparison.OrdinalIgnoreCase) ||
- string.Equals(format, SubtitleFormat.ASS, StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(format, SubtitleFormat.SSA, StringComparison.OrdinalIgnoreCase))
{
return new SsaParser();
}
+ if (string.Equals(format, SubtitleFormat.ASS, StringComparison.OrdinalIgnoreCase))
+ {
+ return new AssParser();
+ }
if (throwIfMissing)
{
@@ -246,6 +289,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles
throw new ArgumentNullException("format");
}
+ if (string.Equals(format, "json", StringComparison.OrdinalIgnoreCase))
+ {
+ return new JsonWriter(_json);
+ }
if (string.Equals(format, SubtitleFormat.SRT, StringComparison.OrdinalIgnoreCase))
{
return new SrtWriter();
@@ -254,6 +301,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
return new VttWriter();
}
+ if (string.Equals(format, SubtitleFormat.TTML, StringComparison.OrdinalIgnoreCase))
+ {
+ return new TtmlWriter();
+ }
throw new ArgumentException("Unsupported format: " + format);
}
@@ -275,14 +326,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
/// <summary>
- /// Converts the text subtitle to ass.
+ /// Converts the text subtitle to SRT.
/// </summary>
/// <param name="inputPath">The input path.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="language">The language.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- public async Task ConvertTextSubtitleToAss(string inputPath, string outputPath, string language,
+ public async Task ConvertTextSubtitleToSrt(string inputPath, string outputPath, string language,
CancellationToken cancellationToken)
{
var semaphore = GetLock(outputPath);
@@ -293,7 +344,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
if (!File.Exists(outputPath))
{
- await ConvertTextSubtitleToAssInternal(inputPath, outputPath, language).ConfigureAwait(false);
+ await ConvertTextSubtitleToSrtInternal(inputPath, outputPath, language).ConfigureAwait(false);
}
}
finally
@@ -303,17 +354,19 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
/// <summary>
- /// Converts the text subtitle to ass.
+ /// Converts the text subtitle to SRT internal.
/// </summary>
/// <param name="inputPath">The input path.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="language">The language.</param>
/// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException">inputPath
+ /// <exception cref="System.ArgumentNullException">
+ /// inputPath
/// or
- /// outputPath</exception>
+ /// outputPath
+ /// </exception>
/// <exception cref="System.ApplicationException"></exception>
- private async Task ConvertTextSubtitleToAssInternal(string inputPath, string outputPath, string language)
+ private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string outputPath, string language)
{
if (string.IsNullOrEmpty(inputPath))
{
@@ -342,12 +395,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
RedirectStandardOutput = false,
RedirectStandardError = true,
+ RedirectStandardInput = true,
CreateNoWindow = true,
UseShellExecute = false,
FileName = _mediaEncoder.EncoderPath,
- Arguments =
- string.Format("{0} -i \"{1}\" -c:s ass \"{2}\"", encodingParam, inputPath, outputPath),
+ Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath),
WindowStyle = ProcessWindowStyle.Hidden,
ErrorDialog = false
@@ -385,8 +438,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
_logger.Info("Killing ffmpeg subtitle conversion process");
- process.Kill();
-
+ process.StandardInput.WriteLine("q");
process.WaitForExit(1000);
await logTask.ConfigureAwait(false);
@@ -446,13 +498,13 @@ namespace MediaBrowser.MediaEncoding.Subtitles
/// <param name="inputFiles">The input files.</param>
/// <param name="protocol">The protocol.</param>
/// <param name="subtitleStreamIndex">Index of the subtitle stream.</param>
- /// <param name="copySubtitleStream">if set to true, copy stream instead of converting.</param>
+ /// <param name="outputCodec">The output codec.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentException">Must use inputPath list overload</exception>
private async Task ExtractTextSubtitle(string[] inputFiles, MediaProtocol protocol, int subtitleStreamIndex,
- bool copySubtitleStream, string outputPath, CancellationToken cancellationToken)
+ string outputCodec, string outputPath, CancellationToken cancellationToken)
{
var semaphore = GetLock(outputPath);
@@ -463,7 +515,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
if (!File.Exists(outputPath))
{
await ExtractTextSubtitleInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), subtitleStreamIndex,
- copySubtitleStream, outputPath, cancellationToken).ConfigureAwait(false);
+ outputCodec, outputPath, cancellationToken).ConfigureAwait(false);
}
}
finally
@@ -472,23 +524,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
}
- /// <summary>
- /// Extracts the text subtitle.
- /// </summary>
- /// <param name="inputPath">The input path.</param>
- /// <param name="subtitleStreamIndex">Index of the subtitle stream.</param>
- /// <param name="copySubtitleStream">if set to true, copy stream instead of converting.</param>
- /// <param name="outputPath">The output path.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException">inputPath
- /// or
- /// outputPath
- /// or
- /// cancellationToken</exception>
- /// <exception cref="System.ApplicationException"></exception>
private async Task ExtractTextSubtitleInternal(string inputPath, int subtitleStreamIndex,
- bool copySubtitleStream, string outputPath, CancellationToken cancellationToken)
+ string outputCodec, string outputPath, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(inputPath))
{
@@ -502,14 +539,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles
Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
- var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s ass \"{2}\"", inputPath,
- subtitleStreamIndex, outputPath);
-
- if (copySubtitleStream)
- {
- processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s copy \"{2}\"", inputPath,
- subtitleStreamIndex, outputPath);
- }
+ var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", inputPath,
+ subtitleStreamIndex, outputCodec, outputPath);
var process = new Process
{
@@ -520,6 +551,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
RedirectStandardOutput = false,
RedirectStandardError = true,
+ RedirectStandardInput = true,
FileName = _mediaEncoder.EncoderPath,
Arguments = processArgs,
@@ -559,8 +591,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
_logger.Info("Killing ffmpeg subtitle extraction process");
- process.Kill();
-
+ process.StandardInput.WriteLine("q");
process.WaitForExit(1000);
}
catch (Exception ex)
diff --git a/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs
new file mode 100644
index 000000000..955b36ecd
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Subtitles/TtmlWriter.cs
@@ -0,0 +1,59 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+
+namespace MediaBrowser.MediaEncoding.Subtitles
+{
+ public class TtmlWriter : ISubtitleWriter
+ {
+ public void Write(SubtitleTrackInfo info, Stream stream, CancellationToken cancellationToken)
+ {
+ // Example: https://github.com/zmalltalker/ttml2vtt/blob/master/data/sample.xml
+ // Parser example: https://github.com/mozilla/popcorn-js/blob/master/parsers/parserTTML/popcorn.parserTTML.js
+
+ using (var writer = new StreamWriter(stream, Encoding.UTF8, 1024, true))
+ {
+ writer.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+ writer.WriteLine("<tt xmlns=\"http://www.w3.org/ns/ttml\" xmlns:tts=\"http://www.w3.org/2006/04/ttaf1#styling\" lang=\"no\">");
+
+ writer.WriteLine("<head>");
+ writer.WriteLine("<styling>");
+ writer.WriteLine("<style id=\"italic\" tts:fontStyle=\"italic\" />");
+ writer.WriteLine("<style id=\"left\" tts:textAlign=\"left\" />");
+ writer.WriteLine("<style id=\"center\" tts:textAlign=\"center\" />");
+ writer.WriteLine("<style id=\"right\" tts:textAlign=\"right\" />");
+ writer.WriteLine("</styling>");
+ writer.WriteLine("</head>");
+
+ writer.WriteLine("<body>");
+ writer.WriteLine("<div>");
+
+ foreach (var trackEvent in info.TrackEvents)
+ {
+ var text = trackEvent.Text;
+
+ text = Regex.Replace(text, @"\\n", "<br/>", RegexOptions.IgnoreCase);
+
+ writer.WriteLine("<p begin=\"{0}\" dur=\"{1}\">{2}</p>",
+ trackEvent.StartPositionTicks,
+ (trackEvent.EndPositionTicks - trackEvent.StartPositionTicks),
+ text);
+ }
+
+ writer.WriteLine("</div>");
+ writer.WriteLine("</body>");
+
+ writer.WriteLine("</tt>");
+ }
+ }
+
+ private string FormatTime(long ticks)
+ {
+ var time = TimeSpan.FromTicks(ticks);
+
+ return string.Format(@"{0:hh\:mm\:ss\,fff}", time);
+ }
+ }
+}
diff --git a/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs
index 09f45aa61..fa53e4d13 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs
@@ -18,12 +18,21 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
cancellationToken.ThrowIfCancellationRequested();
- writer.WriteLine(@"{0:hh\:mm\:ss\.fff} --> {1:hh\:mm\:ss\.fff}", TimeSpan.FromTicks(trackEvent.StartPositionTicks), TimeSpan.FromTicks(trackEvent.EndPositionTicks));
+ TimeSpan startTime = TimeSpan.FromTicks(trackEvent.StartPositionTicks);
+ TimeSpan endTime = TimeSpan.FromTicks(trackEvent.EndPositionTicks);
+
+ // make sure the start and end times are different and seqential
+ if (endTime.TotalMilliseconds <= startTime.TotalMilliseconds)
+ {
+ endTime = startTime.Add(TimeSpan.FromMilliseconds(1));
+ }
+
+ writer.WriteLine(@"{0:hh\:mm\:ss\.fff} --> {1:hh\:mm\:ss\.fff}", startTime, endTime);
var text = trackEvent.Text;
// TODO: Not sure how to handle these
- text = Regex.Replace(text, @"\\N", " ", RegexOptions.IgnoreCase);
+ text = Regex.Replace(text, @"\\n", " ", RegexOptions.IgnoreCase);
writer.WriteLine(text);
writer.WriteLine(string.Empty);
diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
index ee6f05cc1..62f2a7425 100644
--- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
+++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
@@ -11,12 +11,32 @@
<RootNamespace>MediaBrowser.Model</RootNamespace>
<AssemblyName>MediaBrowser.Model</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <TargetFrameworkProfile>Profile104</TargetFrameworkProfile>
+ <TargetFrameworkProfile>Profile158</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<FodyPath>..\packages\Fody.1.19.1.0</FodyPath>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ <OldToolsVersion>4.0</OldToolsVersion>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -37,28 +57,35 @@
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .NET Framework is automatically included -->
+ <None Include="app.config" />
<None Include="Fody.targets" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Threading.Tasks">
- <HintPath>..\packages\Microsoft.Bcl.Async.1.0.16\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.dll</HintPath>
+ <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\portable-net40+sl4+win8+wp71+wpa81\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
- <HintPath>..\packages\Microsoft.Bcl.Async.1.0.16\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
+ <HintPath>..\packages\Microsoft.Bcl.Async.1.0.168\lib\portable-net40+sl4+win8+wp71+wpa81\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="PropertyChanged">
<HintPath>..\packages\PropertyChanged.Fody.1.41.0.0\Lib\portable-net4+sl4+wp7+win8+MonoAndroid16+MonoTouch40\PropertyChanged.dll</HintPath>
<Private>False</Private>
</Reference>
+ <Reference Include="System.IO">
+ <HintPath>..\packages\Microsoft.Bcl.1.1.8\lib\portable-net40+sl5+win8+wp8+wpa81\System.IO.dll</HintPath>
+ </Reference>
<Reference Include="System.Runtime">
- <HintPath>..\packages\Microsoft.Bcl.1.0.19\lib\portable-net40+sl4+win8+wp71\System.Runtime.dll</HintPath>
+ <HintPath>..\packages\Microsoft.Bcl.1.1.8\lib\portable-net40+sl5+win8+wp8+wpa81\System.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks">
- <HintPath>..\packages\Microsoft.Bcl.1.0.19\lib\portable-net40+sl4+win8+wp71\System.Threading.Tasks.dll</HintPath>
+ <HintPath>..\packages\Microsoft.Bcl.1.1.8\lib\portable-net40+sl5+win8+wp8+wpa81\System.Threading.Tasks.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\MediaBrowser.Model\Activity\ActivityLogEntry.cs">
+ <Link>Activity\ActivityLogEntry.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\ApiClient\ApiClientExtensions.cs">
<Link>ApiClient\ApiClientExtensions.cs</Link>
</Compile>
@@ -74,9 +101,15 @@
<Compile Include="..\MediaBrowser.Model\ApiClient\IServerEvents.cs">
<Link>ApiClient\IServerEvents.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\ApiClient\ServerDiscoveryInfo.cs">
+ <Link>ApiClient\ServerDiscoveryInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\ApiClient\SessionUpdatesEventArgs.cs">
<Link>ApiClient\SessionUpdatesEventArgs.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Branding\BrandingOptions.cs">
+ <Link>Branding\BrandingOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Channels\ChannelFeatures.cs">
<Link>Channels\ChannelFeatures.cs</Link>
</Compile>
@@ -101,9 +134,18 @@
<Compile Include="..\MediaBrowser.Model\Chapters\RemoteChapterResult.cs">
<Link>Chapters\RemoteChapterResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Collections\CollectionCreationResult.cs">
+ <Link>Collections\CollectionCreationResult.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\BaseApplicationConfiguration.cs">
<Link>Configuration\BaseApplicationConfiguration.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\ChannelOptions.cs">
+ <Link>Configuration\ChannelOptions.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\ChapterOptions.cs">
+ <Link>Configuration\ChapterOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\DlnaOptions.cs">
<Link>Configuration\DlnaOptions.cs</Link>
</Compile>
@@ -116,9 +158,6 @@
<Compile Include="..\MediaBrowser.Model\Configuration\ImageSavingConvention.cs">
<Link>Configuration\ImageSavingConvention.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\LiveTvOptions.cs">
- <Link>Configuration\LiveTvOptions.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\MetadataOptions.cs">
<Link>Configuration\MetadataOptions.cs</Link>
</Compile>
@@ -131,29 +170,14 @@
<Compile Include="..\MediaBrowser.Model\Configuration\MetadataPluginType.cs">
<Link>Configuration\MetadataPluginType.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\NotificationOption.cs">
- <Link>Configuration\NotificationOption.cs</Link>
- </Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\NotificationOptions.cs">
- <Link>Configuration\NotificationOptions.cs</Link>
- </Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\NotificationType.cs">
- <Link>Configuration\NotificationType.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\PathSubstitution.cs">
<Link>Configuration\PathSubstitution.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\SendToUserType.cs">
- <Link>Configuration\SendToUserType.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\ServerConfiguration.cs">
<Link>Configuration\ServerConfiguration.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\SubtitleOptions.cs">
- <Link>Configuration\SubtitleOptions.cs</Link>
- </Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\TvFileOrganizationOptions.cs">
- <Link>Configuration\TvFileOrganizationOptions.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Configuration\SubtitlePlaybackMode.cs">
+ <Link>Configuration\SubtitlePlaybackMode.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\UnratedItem.cs">
<Link>Configuration\UnratedItem.cs</Link>
@@ -161,6 +185,9 @@
<Compile Include="..\MediaBrowser.Model\Configuration\UserConfiguration.cs">
<Link>Configuration\UserConfiguration.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\XbmcMetadataOptions.cs">
+ <Link>Configuration\XbmcMetadataOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\AudioOptions.cs">
<Link>Dlna\AudioOptions.cs</Link>
</Compile>
@@ -203,12 +230,6 @@
<Compile Include="..\MediaBrowser.Model\Dlna\DlnaProfileType.cs">
<Link>Dlna\DlnaProfileType.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Dlna\EventSubscription.cs">
- <Link>Dlna\EventSubscription.cs</Link>
- </Compile>
- <Compile Include="..\MediaBrowser.Model\Dlna\Filter.cs">
- <Link>Dlna\Filter.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\HeaderMatchType.cs">
<Link>Dlna\HeaderMatchType.cs</Link>
</Compile>
@@ -248,6 +269,9 @@
<Compile Include="..\MediaBrowser.Model\Dlna\StreamInfo.cs">
<Link>Dlna\StreamInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\SubtitleProfile.cs">
+ <Link>Dlna\SubtitleProfile.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\TranscodeSeekInfo.cs">
<Link>Dlna\TranscodeSeekInfo.cs</Link>
</Compile>
@@ -263,6 +287,9 @@
<Compile Include="..\MediaBrowser.Model\Drawing\DrawingUtils.cs">
<Link>Drawing\DrawingUtils.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Drawing\ImageOrientation.cs">
+ <Link>Drawing\ImageOrientation.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Drawing\ImageOutputFormat.cs">
<Link>Drawing\ImageOutputFormat.cs</Link>
</Compile>
@@ -314,9 +341,6 @@
<Compile Include="..\MediaBrowser.Model\Dto\RecommendationType.cs">
<Link>Dto\RecommendationType.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Dto\StreamOptions.cs">
- <Link>Dto\StreamOptions.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\StudioDto.cs">
<Link>Dto\StudioDto.cs</Link>
</Compile>
@@ -329,9 +353,6 @@
<Compile Include="..\MediaBrowser.Model\Dto\UserItemDataDto.cs">
<Link>Dto\UserItemDataDto.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Dto\VideoStreamOptions.cs">
- <Link>Dto\VideoStreamOptions.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\BaseItemInfo.cs">
<Link>Entities\BaseItemInfo.cs</Link>
</Compile>
@@ -434,6 +455,9 @@
<Compile Include="..\MediaBrowser.Model\Extensions\DoubleHelper.cs">
<Link>Extensions\DoubleHelper.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Extensions\IHasPropertyChangedEvent.cs">
+ <Link>Extensions\IHasPropertyChangedEvent.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Extensions\IntHelper.cs">
<Link>Extensions\IntHelper.cs</Link>
</Compile>
@@ -443,6 +467,9 @@
<Compile Include="..\MediaBrowser.Model\Extensions\StringHelper.cs">
<Link>Extensions\StringHelper.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\FileOrganization\AutoOrganizeOptions.cs">
+ <Link>FileOrganization\AutoOrganizeOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\FileOrganization\EpisodeFileOrganizationRequest.cs">
<Link>FileOrganization\EpisodeFileOrganizationRequest.cs</Link>
</Compile>
@@ -458,6 +485,9 @@
<Compile Include="..\MediaBrowser.Model\FileOrganization\FileSortingStatus.cs">
<Link>FileOrganization\FileSortingStatus.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\FileOrganization\TvFileOrganizationOptions.cs">
+ <Link>FileOrganization\TvFileOrganizationOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Games\GameSystem.cs">
<Link>Games\GameSystem.cs</Link>
</Compile>
@@ -512,6 +542,9 @@
<Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvInfo.cs">
<Link>LiveTv\LiveTvInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvOptions.cs">
+ <Link>LiveTv\LiveTvOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvServiceInfo.cs">
<Link>LiveTv\LiveTvServiceInfo.cs</Link>
</Compile>
@@ -629,6 +662,12 @@
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationLevel.cs">
<Link>Notifications\NotificationLevel.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\NotificationOption.cs">
+ <Link>Notifications\NotificationOption.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\NotificationOptions.cs">
+ <Link>Notifications\NotificationOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationQuery.cs">
<Link>Notifications\NotificationQuery.cs</Link>
</Compile>
@@ -644,9 +683,24 @@
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationsSummary.cs">
<Link>Notifications\NotificationsSummary.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\NotificationType.cs">
+ <Link>Notifications\NotificationType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationTypeInfo.cs">
<Link>Notifications\NotificationTypeInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\SendToUserType.cs">
+ <Link>Notifications\SendToUserType.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Playlists\PlaylistCreationRequest.cs">
+ <Link>Playlists\PlaylistCreationRequest.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Playlists\PlaylistCreationResult.cs">
+ <Link>Playlists\PlaylistCreationResult.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Playlists\PlaylistItemQuery.cs">
+ <Link>Playlists\PlaylistItemQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Plugins\BasePluginConfiguration.cs">
<Link>Plugins\BasePluginConfiguration.cs</Link>
</Compile>
@@ -677,6 +731,9 @@
<Compile Include="..\MediaBrowser.Model\Providers\RemoteSubtitleInfo.cs">
<Link>Providers\RemoteSubtitleInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Providers\SubtitleOptions.cs">
+ <Link>Providers\SubtitleOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Querying\AllThemeMediaResult.cs">
<Link>Querying\AllThemeMediaResult.cs</Link>
</Compile>
@@ -707,6 +764,9 @@
<Compile Include="..\MediaBrowser.Model\Querying\ItemsResult.cs">
<Link>Querying\ItemsResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Querying\LatestItemsQuery.cs">
+ <Link>Querying\LatestItemsQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Querying\NextUpQuery.cs">
<Link>Querying\NextUpQuery.cs</Link>
</Compile>
@@ -806,6 +866,33 @@
<Compile Include="..\MediaBrowser.Model\Session\UserDataChangeInfo.cs">
<Link>Session\UserDataChangeInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncJob.cs">
+ <Link>Sync\SyncJob.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncJobCreationResult.cs">
+ <Link>Sync\SyncJobCreationResult.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncJobItem.cs">
+ <Link>Sync\SyncJobItem.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncJobQuery.cs">
+ <Link>Sync\SyncJobQuery.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncJobRequest.cs">
+ <Link>Sync\SyncJobRequest.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncJobStatus.cs">
+ <Link>Sync\SyncJobStatus.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncQuality.cs">
+ <Link>Sync\SyncQuality.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncTarget.cs">
+ <Link>Sync\SyncTarget.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\System\LogFile.cs">
+ <Link>System\LogFile.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\System\SystemInfo.cs">
<Link>System\SystemInfo.cs</Link>
</Compile>
@@ -871,7 +958,18 @@
<ItemGroup>
<Content Include="FodyWeavers.xml" />
</ItemGroup>
- <ItemGroup />
+ <ItemGroup>
+ <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>if $(ConfigurationName) == Release (
@@ -879,8 +977,12 @@ xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\portable\" /y /d /r /i
)</PostBuildEvent>
</PropertyGroup>
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
- <Import Project="..\packages\Microsoft.Bcl.Build.1.0.8\tools\Microsoft.Bcl.Build.targets" />
<Import Project="Fody.targets" />
+ <Import Project="..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" />
+ <Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
+ <Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
+ <Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.14\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
+ </Target>
<!-- 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">
diff --git a/MediaBrowser.Model.Portable/app.config b/MediaBrowser.Model.Portable/app.config
new file mode 100644
index 000000000..3c7378292
--- /dev/null
+++ b/MediaBrowser.Model.Portable/app.config
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration> \ No newline at end of file
diff --git a/MediaBrowser.Model.Portable/packages.config b/MediaBrowser.Model.Portable/packages.config
index 2d74129b8..4d54d0baf 100644
--- a/MediaBrowser.Model.Portable/packages.config
+++ b/MediaBrowser.Model.Portable/packages.config
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Fody" version="1.19.1.0" targetFramework="portable-win+net45+sl40+wp71" developmentDependency="true" />
- <package id="Microsoft.Bcl" version="1.0.19" targetFramework="portable-win+net45+sl40+wp71" />
- <package id="Microsoft.Bcl.Async" version="1.0.16" targetFramework="portable-win+net45+sl40+wp71" />
- <package id="Microsoft.Bcl.Build" version="1.0.8" targetFramework="portable-win+net45+sl40+wp71" />
+ <package id="Microsoft.Bcl" version="1.1.8" targetFramework="portable-net45+sl50+win+wp80" />
+ <package id="Microsoft.Bcl.Async" version="1.0.168" targetFramework="portable-net45+sl50+win+wp80" />
+ <package id="Microsoft.Bcl.Build" version="1.0.14" targetFramework="portable-net45+sl50+win+wp80" />
<package id="PropertyChanged.Fody" version="1.41.0.0" targetFramework="portable-net45+sl40+wp71+win" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
index a2fa1aa94..715331436 100644
--- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
+++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
@@ -52,6 +52,9 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\mediabrowser.model\activity\ActivityLogEntry.cs">
+ <Link>Activity\ActivityLogEntry.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\ApiClient\GeneralCommandEventArgs.cs">
<Link>ApiClient\GeneralCommandEventArgs.cs</Link>
</Compile>
@@ -61,9 +64,15 @@
<Compile Include="..\MediaBrowser.Model\ApiClient\IServerEvents.cs">
<Link>ApiClient\IServerEvents.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\ApiClient\ServerDiscoveryInfo.cs">
+ <Link>ApiClient\ServerDiscoveryInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\ApiClient\SessionUpdatesEventArgs.cs">
<Link>ApiClient\SessionUpdatesEventArgs.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Branding\BrandingOptions.cs">
+ <Link>Branding\BrandingOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Channels\ChannelFeatures.cs">
<Link>Channels\ChannelFeatures.cs</Link>
</Compile>
@@ -88,9 +97,18 @@
<Compile Include="..\MediaBrowser.Model\Chapters\RemoteChapterResult.cs">
<Link>Chapters\RemoteChapterResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Collections\CollectionCreationResult.cs">
+ <Link>Collections\CollectionCreationResult.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\BaseApplicationConfiguration.cs">
<Link>Configuration\BaseApplicationConfiguration.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\ChannelOptions.cs">
+ <Link>Configuration\ChannelOptions.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\ChapterOptions.cs">
+ <Link>Configuration\ChapterOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\DlnaOptions.cs">
<Link>Configuration\DlnaOptions.cs</Link>
</Compile>
@@ -103,9 +121,6 @@
<Compile Include="..\MediaBrowser.Model\Configuration\ImageSavingConvention.cs">
<Link>Configuration\ImageSavingConvention.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\LiveTvOptions.cs">
- <Link>Configuration\LiveTvOptions.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\MetadataOptions.cs">
<Link>Configuration\MetadataOptions.cs</Link>
</Compile>
@@ -118,29 +133,14 @@
<Compile Include="..\MediaBrowser.Model\Configuration\MetadataPluginType.cs">
<Link>Configuration\MetadataPluginType.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\NotificationOption.cs">
- <Link>Configuration\NotificationOption.cs</Link>
- </Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\NotificationOptions.cs">
- <Link>Configuration\NotificationOptions.cs</Link>
- </Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\NotificationType.cs">
- <Link>Configuration\NotificationType.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\PathSubstitution.cs">
<Link>Configuration\PathSubstitution.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\SendToUserType.cs">
- <Link>Configuration\SendToUserType.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\ServerConfiguration.cs">
<Link>Configuration\ServerConfiguration.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\SubtitleOptions.cs">
- <Link>Configuration\SubtitleOptions.cs</Link>
- </Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\TvFileOrganizationOptions.cs">
- <Link>Configuration\TvFileOrganizationOptions.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Configuration\SubtitlePlaybackMode.cs">
+ <Link>Configuration\SubtitlePlaybackMode.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\UnratedItem.cs">
<Link>Configuration\UnratedItem.cs</Link>
@@ -148,6 +148,9 @@
<Compile Include="..\MediaBrowser.Model\Configuration\UserConfiguration.cs">
<Link>Configuration\UserConfiguration.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\XbmcMetadataOptions.cs">
+ <Link>Configuration\XbmcMetadataOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\AudioOptions.cs">
<Link>Dlna\AudioOptions.cs</Link>
</Compile>
@@ -190,12 +193,6 @@
<Compile Include="..\MediaBrowser.Model\Dlna\DlnaProfileType.cs">
<Link>Dlna\DlnaProfileType.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Dlna\EventSubscription.cs">
- <Link>Dlna\EventSubscription.cs</Link>
- </Compile>
- <Compile Include="..\MediaBrowser.Model\Dlna\Filter.cs">
- <Link>Dlna\Filter.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\HeaderMatchType.cs">
<Link>Dlna\HeaderMatchType.cs</Link>
</Compile>
@@ -235,6 +232,9 @@
<Compile Include="..\MediaBrowser.Model\Dlna\StreamInfo.cs">
<Link>Dlna\StreamInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\SubtitleProfile.cs">
+ <Link>Dlna\SubtitleProfile.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\TranscodeSeekInfo.cs">
<Link>Dlna\TranscodeSeekInfo.cs</Link>
</Compile>
@@ -250,6 +250,9 @@
<Compile Include="..\MediaBrowser.Model\Drawing\DrawingUtils.cs">
<Link>Drawing\DrawingUtils.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Drawing\ImageOrientation.cs">
+ <Link>Drawing\ImageOrientation.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Drawing\ImageOutputFormat.cs">
<Link>Drawing\ImageOutputFormat.cs</Link>
</Compile>
@@ -301,9 +304,6 @@
<Compile Include="..\MediaBrowser.Model\Dto\RecommendationType.cs">
<Link>Dto\RecommendationType.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Dto\StreamOptions.cs">
- <Link>Dto\StreamOptions.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\StudioDto.cs">
<Link>Dto\StudioDto.cs</Link>
</Compile>
@@ -316,9 +316,6 @@
<Compile Include="..\MediaBrowser.Model\Dto\UserItemDataDto.cs">
<Link>Dto\UserItemDataDto.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Dto\VideoStreamOptions.cs">
- <Link>Dto\VideoStreamOptions.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\BaseItemInfo.cs">
<Link>Entities\BaseItemInfo.cs</Link>
</Compile>
@@ -421,6 +418,9 @@
<Compile Include="..\MediaBrowser.Model\Extensions\DoubleHelper.cs">
<Link>Extensions\DoubleHelper.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Extensions\IHasPropertyChangedEvent.cs">
+ <Link>Extensions\IHasPropertyChangedEvent.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Extensions\IntHelper.cs">
<Link>Extensions\IntHelper.cs</Link>
</Compile>
@@ -430,6 +430,9 @@
<Compile Include="..\MediaBrowser.Model\Extensions\StringHelper.cs">
<Link>Extensions\StringHelper.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\FileOrganization\AutoOrganizeOptions.cs">
+ <Link>FileOrganization\AutoOrganizeOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\FileOrganization\EpisodeFileOrganizationRequest.cs">
<Link>FileOrganization\EpisodeFileOrganizationRequest.cs</Link>
</Compile>
@@ -445,6 +448,9 @@
<Compile Include="..\MediaBrowser.Model\FileOrganization\FileSortingStatus.cs">
<Link>FileOrganization\FileSortingStatus.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\FileOrganization\TvFileOrganizationOptions.cs">
+ <Link>FileOrganization\TvFileOrganizationOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Games\GameSystem.cs">
<Link>Games\GameSystem.cs</Link>
</Compile>
@@ -493,6 +499,9 @@
<Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvInfo.cs">
<Link>LiveTv\LiveTvInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvOptions.cs">
+ <Link>LiveTv\LiveTvOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvServiceInfo.cs">
<Link>LiveTv\LiveTvServiceInfo.cs</Link>
</Compile>
@@ -610,6 +619,12 @@
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationLevel.cs">
<Link>Notifications\NotificationLevel.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\NotificationOption.cs">
+ <Link>Notifications\NotificationOption.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\NotificationOptions.cs">
+ <Link>Notifications\NotificationOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationQuery.cs">
<Link>Notifications\NotificationQuery.cs</Link>
</Compile>
@@ -625,9 +640,24 @@
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationsSummary.cs">
<Link>Notifications\NotificationsSummary.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\NotificationType.cs">
+ <Link>Notifications\NotificationType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationTypeInfo.cs">
<Link>Notifications\NotificationTypeInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\SendToUserType.cs">
+ <Link>Notifications\SendToUserType.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Playlists\PlaylistCreationRequest.cs">
+ <Link>Playlists\PlaylistCreationRequest.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Playlists\PlaylistCreationResult.cs">
+ <Link>Playlists\PlaylistCreationResult.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Playlists\PlaylistItemQuery.cs">
+ <Link>Playlists\PlaylistItemQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Plugins\BasePluginConfiguration.cs">
<Link>Plugins\BasePluginConfiguration.cs</Link>
</Compile>
@@ -658,6 +688,9 @@
<Compile Include="..\MediaBrowser.Model\Providers\RemoteSubtitleInfo.cs">
<Link>Providers\RemoteSubtitleInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Providers\SubtitleOptions.cs">
+ <Link>Providers\SubtitleOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Querying\AllThemeMediaResult.cs">
<Link>Querying\AllThemeMediaResult.cs</Link>
</Compile>
@@ -688,6 +721,9 @@
<Compile Include="..\MediaBrowser.Model\Querying\ItemsResult.cs">
<Link>Querying\ItemsResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Querying\LatestItemsQuery.cs">
+ <Link>Querying\LatestItemsQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Querying\NextUpQuery.cs">
<Link>Querying\NextUpQuery.cs</Link>
</Compile>
@@ -787,6 +823,33 @@
<Compile Include="..\MediaBrowser.Model\Session\UserDataChangeInfo.cs">
<Link>Session\UserDataChangeInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncJob.cs">
+ <Link>Sync\SyncJob.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncJobCreationResult.cs">
+ <Link>Sync\SyncJobCreationResult.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncJobItem.cs">
+ <Link>Sync\SyncJobItem.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncJobQuery.cs">
+ <Link>Sync\SyncJobQuery.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncJobRequest.cs">
+ <Link>Sync\SyncJobRequest.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncJobStatus.cs">
+ <Link>Sync\SyncJobStatus.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncQuality.cs">
+ <Link>Sync\SyncQuality.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncTarget.cs">
+ <Link>Sync\SyncTarget.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\System\LogFile.cs">
+ <Link>System\LogFile.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\System\SystemInfo.cs">
<Link>System\SystemInfo.cs</Link>
</Compile>
diff --git a/MediaBrowser.Model/Activity/ActivityLogEntry.cs b/MediaBrowser.Model/Activity/ActivityLogEntry.cs
new file mode 100644
index 000000000..8fad57461
--- /dev/null
+++ b/MediaBrowser.Model/Activity/ActivityLogEntry.cs
@@ -0,0 +1,62 @@
+using MediaBrowser.Model.Logging;
+using System;
+
+namespace MediaBrowser.Model.Activity
+{
+ public class ActivityLogEntry
+ {
+ /// <summary>
+ /// Gets or sets the identifier.
+ /// </summary>
+ /// <value>The identifier.</value>
+ public string Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the overview.
+ /// </summary>
+ /// <value>The overview.</value>
+ public string Overview { get; set; }
+
+ /// <summary>
+ /// Gets or sets the short overview.
+ /// </summary>
+ /// <value>The short overview.</value>
+ public string ShortOverview { get; set; }
+
+ /// <summary>
+ /// Gets or sets the type.
+ /// </summary>
+ /// <value>The type.</value>
+ public string Type { get; set; }
+
+ /// <summary>
+ /// Gets or sets the item identifier.
+ /// </summary>
+ /// <value>The item identifier.</value>
+ public string ItemId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the date.
+ /// </summary>
+ /// <value>The date.</value>
+ public DateTime Date { get; set; }
+
+ /// <summary>
+ /// Gets or sets the user identifier.
+ /// </summary>
+ /// <value>The user identifier.</value>
+ public string UserId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the log severity.
+ /// </summary>
+ /// <value>The log severity.</value>
+ public LogSeverity Severity { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/ApiClient/ApiClientExtensions.cs b/MediaBrowser.Model/ApiClient/ApiClientExtensions.cs
index 98e99b1cc..4b0effa55 100644
--- a/MediaBrowser.Model/ApiClient/ApiClientExtensions.cs
+++ b/MediaBrowser.Model/ApiClient/ApiClientExtensions.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Querying;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -25,5 +26,10 @@ namespace MediaBrowser.Model.ApiClient
{
return apiClient.GetPublicUsersAsync(CancellationToken.None);
}
+
+ public static Task<ItemsResult> GetItemsAsync(this IApiClient apiClient, ItemQuery query)
+ {
+ return apiClient.GetItemsAsync(query, CancellationToken.None);
+ }
}
}
diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs
index 4f008571c..a9d0f480c 100644
--- a/MediaBrowser.Model/ApiClient/IApiClient.cs
+++ b/MediaBrowser.Model/ApiClient/IApiClient.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Notifications;
+using MediaBrowser.Model.Playlists;
using MediaBrowser.Model.Plugins;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Search;
@@ -48,7 +49,7 @@ namespace MediaBrowser.Model.ApiClient
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{List{GameSystemSummary}}.</returns>
- Task<List<GameSystemSummary>> GetGameSystemSummariesAsync(CancellationToken cancellationToken);
+ Task<List<GameSystemSummary>> GetGameSystemSummariesAsync(CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the async.
@@ -57,40 +58,22 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="url">The URL.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{``0}.</returns>
- Task<T> GetAsync<T>(string url, CancellationToken cancellationToken)
+ Task<T> GetAsync<T>(string url, CancellationToken cancellationToken = default(CancellationToken))
where T : class;
/// <summary>
- /// Gets the url needed to stream an audio file
- /// </summary>
- /// <param name="options">The options.</param>
- /// <returns>System.String.</returns>
- /// <exception cref="ArgumentNullException">options</exception>
- string GetAudioStreamUrl(StreamOptions options);
-
- /// <summary>
- /// Gets the url needed to stream a video file
- /// </summary>
- /// <param name="options">The options.</param>
- /// <returns>System.String.</returns>
- /// <exception cref="ArgumentNullException">options</exception>
- string GetVideoStreamUrl(VideoStreamOptions options);
-
- /// <summary>
- /// Formulates a url for streaming video using the HLS protocol
- /// </summary>
- /// <param name="options">The options.</param>
- /// <returns>System.String.</returns>
- /// <exception cref="ArgumentNullException">options</exception>
- string GetHlsVideoStreamUrl(VideoStreamOptions options);
-
- /// <summary>
/// Reports the capabilities.
/// </summary>
/// <param name="capabilities">The capabilities.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task ReportCapabilities(ClientCapabilities capabilities, CancellationToken cancellationToken);
+ Task ReportCapabilities(ClientCapabilities capabilities, CancellationToken cancellationToken = default(CancellationToken));
+
+ /// <summary>
+ /// Logouts this instance.
+ /// </summary>
+ /// <returns>Task.</returns>
+ Task Logout();
/// <summary>
/// Gets the index of the game players.
@@ -98,7 +81,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="userId">The user id.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{List{ItemIndex}}.</returns>
- Task<List<ItemIndex>> GetGamePlayerIndex(string userId, CancellationToken cancellationToken);
+ Task<List<ItemIndex>> GetGamePlayerIndex(string userId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the index of the year.
@@ -107,7 +90,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="includeItemTypes">The include item types.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{List{ItemIndex}}.</returns>
- Task<List<ItemIndex>> GetYearIndex(string userId, string[] includeItemTypes, CancellationToken cancellationToken);
+ Task<List<ItemIndex>> GetYearIndex(string userId, string[] includeItemTypes, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the critic reviews.
@@ -117,7 +100,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="startIndex">The start index.</param>
/// <param name="limit">The limit.</param>
/// <returns>Task{ItemReviewsResult}.</returns>
- Task<QueryResult<ItemReview>> GetCriticReviews(string itemId, CancellationToken cancellationToken, int? startIndex = null, int? limit = null);
+ Task<QueryResult<ItemReview>> GetCriticReviews(string itemId, CancellationToken cancellationToken = default(CancellationToken), int? startIndex = null, int? limit = null);
/// <summary>
/// Gets the theme songs async.
@@ -127,7 +110,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="inheritFromParents">if set to <c>true</c> [inherit from parents].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ThemeMediaResult}.</returns>
- Task<ThemeMediaResult> GetThemeSongsAsync(string userId, string itemId, bool inheritFromParents, CancellationToken cancellationToken);
+ Task<ThemeMediaResult> GetThemeSongsAsync(string userId, string itemId, bool inheritFromParents, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the search hints async.
@@ -144,7 +127,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="inheritFromParents">if set to <c>true</c> [inherit from parents].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ThemeMediaResult}.</returns>
- Task<ThemeMediaResult> GetThemeVideosAsync(string userId, string itemId, bool inheritFromParents, CancellationToken cancellationToken);
+ Task<ThemeMediaResult> GetThemeVideosAsync(string userId, string itemId, bool inheritFromParents, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets all theme media async.
@@ -154,7 +137,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="inheritFromParents">if set to <c>true</c> [inherit from parents].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{AllThemeMediaResult}.</returns>
- Task<AllThemeMediaResult> GetAllThemeMediaAsync(string userId, string itemId, bool inheritFromParents, CancellationToken cancellationToken);
+ Task<AllThemeMediaResult> GetAllThemeMediaAsync(string userId, string itemId, bool inheritFromParents, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Marks the notifications read.
@@ -186,7 +169,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
/// <exception cref="ArgumentNullException">url</exception>
- Task<Stream> GetImageStreamAsync(string url, CancellationToken cancellationToken);
+ Task<Stream> GetImageStreamAsync(string url, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets a BaseItem
@@ -198,6 +181,13 @@ namespace MediaBrowser.Model.ApiClient
Task<BaseItemDto> GetItemAsync(string id, string userId);
/// <summary>
+ /// Gets the latest items.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <returns>Task&lt;QueryResult&lt;BaseItemDto&gt;&gt;.</returns>
+ Task<BaseItemDto[]> GetLatestItems(LatestItemsQuery query);
+
+ /// <summary>
/// Gets the intros async.
/// </summary>
/// <param name="itemId">The item id.</param>
@@ -217,9 +207,10 @@ namespace MediaBrowser.Model.ApiClient
/// Gets the additional parts.
/// </summary>
/// <param name="itemId">The item identifier.</param>
+ /// <param name="userId">The user identifier.</param>
/// <returns>Task{BaseItemDto[]}.</returns>
Task<ItemsResult> GetAdditionalParts(string itemId, string userId);
-
+
/// <summary>
/// Gets the users async.
/// </summary>
@@ -232,7 +223,7 @@ namespace MediaBrowser.Model.ApiClient
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{UserDto[]}.</returns>
- Task<UserDto[]> GetPublicUsersAsync(CancellationToken cancellationToken);
+ Task<UserDto[]> GetPublicUsersAsync(CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets active client sessions.
@@ -242,6 +233,12 @@ namespace MediaBrowser.Model.ApiClient
Task<SessionInfoDto[]> GetClientSessionsAsync(SessionQuery query);
/// <summary>
+ /// Gets the client session asynchronous.
+ /// </summary>
+ /// <returns>Task{SessionInfoDto}.</returns>
+ Task<SessionInfoDto> GetCurrentSessionAsync(CancellationToken cancellationToken = default(CancellationToken));
+
+ /// <summary>
/// Gets the item counts async.
/// </summary>
/// <param name="query">The query.</param>
@@ -252,25 +249,36 @@ namespace MediaBrowser.Model.ApiClient
/// Gets the episodes asynchronous.
/// </summary>
/// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ItemsResult}.</returns>
- Task<ItemsResult> GetEpisodesAsync(EpisodeQuery query);
+ Task<ItemsResult> GetEpisodesAsync(EpisodeQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the seasons asynchronous.
/// </summary>
/// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ItemsResult}.</returns>
- Task<ItemsResult> GetSeasonsAsync(SeasonQuery query);
+ Task<ItemsResult> GetSeasonsAsync(SeasonQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Queries for items
/// </summary>
/// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ItemsResult}.</returns>
/// <exception cref="ArgumentNullException">query</exception>
- Task<ItemsResult> GetItemsAsync(ItemQuery query);
+ Task<ItemsResult> GetItemsAsync(ItemQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
+ /// Gets the user views.
+ /// </summary>
+ /// <param name="userId">The user identifier.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task&lt;ItemsResult&gt;.</returns>
+ Task<ItemsResult> GetUserViews(string userId, CancellationToken cancellationToken = default(CancellationToken));
+
+ /// <summary>
/// Gets the instant mix from song async.
/// </summary>
/// <param name="query">The query.</param>
@@ -302,44 +310,50 @@ namespace MediaBrowser.Model.ApiClient
/// Gets the similar movies async.
/// </summary>
/// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ItemsResult}.</returns>
- Task<ItemsResult> GetSimilarMoviesAsync(SimilarItemsQuery query);
+ Task<ItemsResult> GetSimilarMoviesAsync(SimilarItemsQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the similar trailers async.
/// </summary>
/// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ItemsResult}.</returns>
- Task<ItemsResult> GetSimilarTrailersAsync(SimilarItemsQuery query);
+ Task<ItemsResult> GetSimilarTrailersAsync(SimilarItemsQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the similar series async.
/// </summary>
/// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ItemsResult}.</returns>
- Task<ItemsResult> GetSimilarSeriesAsync(SimilarItemsQuery query);
+ Task<ItemsResult> GetSimilarSeriesAsync(SimilarItemsQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the similar albums async.
/// </summary>
/// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ItemsResult}.</returns>
- Task<ItemsResult> GetSimilarAlbumsAsync(SimilarItemsQuery query);
+ Task<ItemsResult> GetSimilarAlbumsAsync(SimilarItemsQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the similar games async.
/// </summary>
/// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ItemsResult}.</returns>
- Task<ItemsResult> GetSimilarGamesAsync(SimilarItemsQuery query);
+ Task<ItemsResult> GetSimilarGamesAsync(SimilarItemsQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the people async.
/// </summary>
/// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ItemsResult}.</returns>
/// <exception cref="ArgumentNullException">userId</exception>
- Task<ItemsResult> GetPeopleAsync(PersonsQuery query);
+ Task<ItemsResult> GetPeopleAsync(PersonsQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the artists.
@@ -355,7 +369,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <returns>Task{ItemsResult}.</returns>
Task<ItemsResult> GetAlbumArtistsAsync(ArtistsQuery query);
-
+
/// <summary>
/// Gets a studio
/// </summary>
@@ -369,8 +383,9 @@ namespace MediaBrowser.Model.ApiClient
/// Gets the next up async.
/// </summary>
/// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ItemsResult}.</returns>
- Task<ItemsResult> GetNextUpEpisodesAsync(NextUpQuery query);
+ Task<ItemsResult> GetNextUpEpisodesAsync(NextUpQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the upcoming episodes asynchronous.
@@ -452,9 +467,16 @@ namespace MediaBrowser.Model.ApiClient
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{SystemInfo}.</returns>
- Task<SystemInfo> GetSystemInfoAsync(CancellationToken cancellationToken);
+ Task<SystemInfo> GetSystemInfoAsync(CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
+ /// Gets the public system information asynchronous.
+ /// </summary>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task&lt;PublicSystemInfo&gt;.</returns>
+ Task<PublicSystemInfo> GetPublicSystemInfoAsync(CancellationToken cancellationToken = default(CancellationToken));
+
+ /// <summary>
/// Gets a person
/// </summary>
/// <param name="name">The name.</param>
@@ -585,7 +607,7 @@ namespace MediaBrowser.Model.ApiClient
Task ReportPlaybackStoppedAsync(PlaybackStopInfo info);
/// <summary>
- /// Instructs antoher client to browse to a library item.
+ /// Instructs another client to browse to a library item.
/// </summary>
/// <param name="sessionId">The session id.</param>
/// <param name="itemId">The id of the item to browse to.</param>
@@ -638,6 +660,13 @@ namespace MediaBrowser.Model.ApiClient
Task SetVolume(string sessionId, int volume);
/// <summary>
+ /// Stops the transcoding processes.
+ /// </summary>
+ /// <param name="deviceId">The device identifier.</param>
+ /// <returns>Task.</returns>
+ Task StopTranscodingProcesses(string deviceId);
+
+ /// <summary>
/// Sets the index of the audio stream.
/// </summary>
/// <param name="sessionId">The session identifier.</param>
@@ -652,7 +681,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="index">The index.</param>
/// <returns>Task.</returns>
Task SetSubtitleStreamIndex(string sessionId, int? index);
-
+
/// <summary>
/// Instructs the client to display a message to the user
/// </summary>
@@ -714,7 +743,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="client">The client.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{BaseItemDto}.</returns>
- Task<DisplayPreferences> GetDisplayPreferencesAsync(string id, string userId, string client, CancellationToken cancellationToken);
+ Task<DisplayPreferences> GetDisplayPreferencesAsync(string id, string userId, string client, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Updates display preferences for a user
@@ -725,7 +754,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{DisplayPreferences}.</returns>
/// <exception cref="System.ArgumentNullException">userId</exception>
- Task UpdateDisplayPreferencesAsync(DisplayPreferences displayPreferences, string userId, string client, CancellationToken cancellationToken);
+ Task UpdateDisplayPreferencesAsync(DisplayPreferences displayPreferences, string userId, string client, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Posts a set of data to a url, and deserializes the return stream into T
@@ -735,7 +764,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="args">The args.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{``0}.</returns>
- Task<T> PostAsync<T>(string url, Dictionary<string, string> args, CancellationToken cancellationToken)
+ Task<T> PostAsync<T>(string url, Dictionary<string, string> args, CancellationToken cancellationToken = default(CancellationToken))
where T : class;
/// <summary>
@@ -752,23 +781,16 @@ namespace MediaBrowser.Model.ApiClient
IJsonSerializer JsonSerializer { get; set; }
/// <summary>
- /// Gets or sets the server host name (myserver or 192.168.x.x)
- /// </summary>
- /// <value>The name of the server host.</value>
- string ServerHostName { get; }
-
- /// <summary>
- /// Gets or sets the port number used by the API
+ /// Gets or sets the server address
/// </summary>
- /// <value>The server API port.</value>
- int ServerApiPort { get; }
+ /// <value>The server address.</value>
+ string ServerAddress { get; }
/// <summary>
/// Changes the server location.
/// </summary>
- /// <param name="hostName">Name of the host.</param>
- /// <param name="apiPort">The API port.</param>
- void ChangeServerLocation(string hostName, int apiPort);
+ /// <param name="address">The address.</param>
+ void ChangeServerLocation(string address);
/// <summary>
/// Gets or sets the type of the client.
@@ -792,7 +814,31 @@ namespace MediaBrowser.Model.ApiClient
/// Gets or sets the current user id.
/// </summary>
/// <value>The current user id.</value>
- string CurrentUserId { get; set; }
+ string CurrentUserId { get; }
+
+ /// <summary>
+ /// Gets the access token.
+ /// </summary>
+ /// <value>The access token.</value>
+ string AccessToken { get; }
+
+ /// <summary>
+ /// Sets the authentication information.
+ /// </summary>
+ /// <param name="accessToken">The access token.</param>
+ /// <param name="userId">The user identifier.</param>
+ void SetAuthenticationInfo(string accessToken, string userId);
+
+ /// <summary>
+ /// Sets the authentication information.
+ /// </summary>
+ /// <param name="accessToken">The access token.</param>
+ void SetAuthenticationInfo(string accessToken);
+
+ /// <summary>
+ /// Clears the authentication information.
+ /// </summary>
+ void ClearAuthenticationInfo();
/// <summary>
/// Gets the image URL.
@@ -833,7 +879,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="options">The options.</param>
/// <returns>System.String.</returns>
string GetSubtitleUrl(SubtitleDownloadOptions options);
-
+
/// <summary>
/// Gets an image url that can be used to download an image from the api
/// </summary>
@@ -969,7 +1015,7 @@ namespace MediaBrowser.Model.ApiClient
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{LiveTvInfo}.</returns>
- Task<LiveTvInfo> GetLiveTvInfoAsync(CancellationToken cancellationToken);
+ Task<LiveTvInfo> GetLiveTvInfoAsync(CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv channels asynchronous.
@@ -977,7 +1023,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{LiveTvInfo}.</returns>
- Task<QueryResult<ChannelInfoDto>> GetLiveTvChannelsAsync(ChannelQuery query, CancellationToken cancellationToken);
+ Task<QueryResult<ChannelInfoDto>> GetLiveTvChannelsAsync(LiveTvChannelQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv channel asynchronous.
@@ -986,7 +1032,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="userId">The user identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ChannelInfoDto}.</returns>
- Task<ChannelInfoDto> GetLiveTvChannelAsync(string id, string userId, CancellationToken cancellationToken);
+ Task<ChannelInfoDto> GetLiveTvChannelAsync(string id, string userId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv recordings asynchronous.
@@ -994,7 +1040,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{QueryResult{RecordingInfoDto}}.</returns>
- Task<QueryResult<RecordingInfoDto>> GetLiveTvRecordingsAsync(RecordingQuery query, CancellationToken cancellationToken);
+ Task<QueryResult<RecordingInfoDto>> GetLiveTvRecordingsAsync(RecordingQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv recording asynchronous.
@@ -1003,7 +1049,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="userId">The user identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{RecordingInfoDto}.</returns>
- Task<RecordingInfoDto> GetLiveTvRecordingAsync(string id, string userId, CancellationToken cancellationToken);
+ Task<RecordingInfoDto> GetLiveTvRecordingAsync(string id, string userId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv recording groups asynchronous.
@@ -1011,7 +1057,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{QueryResult{RecordingGroupDto}}.</returns>
- Task<QueryResult<RecordingGroupDto>> GetLiveTvRecordingGroupsAsync(RecordingGroupQuery query, CancellationToken cancellationToken);
+ Task<QueryResult<RecordingGroupDto>> GetLiveTvRecordingGroupsAsync(RecordingGroupQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv recording group asynchronous.
@@ -1020,7 +1066,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="userId">The user identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{RecordingGroupDto}.</returns>
- Task<RecordingGroupDto> GetLiveTvRecordingGroupAsync(string id, string userId, CancellationToken cancellationToken);
+ Task<RecordingGroupDto> GetLiveTvRecordingGroupAsync(string id, string userId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv timers asynchronous.
@@ -1028,7 +1074,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{QueryResult{TimerInfoDto}}.</returns>
- Task<QueryResult<TimerInfoDto>> GetLiveTvTimersAsync(TimerQuery query, CancellationToken cancellationToken);
+ Task<QueryResult<TimerInfoDto>> GetLiveTvTimersAsync(TimerQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv programs asynchronous.
@@ -1036,7 +1082,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{QueryResult{ProgramInfoDto}}.</returns>
- Task<QueryResult<ProgramInfoDto>> GetLiveTvProgramsAsync(ProgramQuery query, CancellationToken cancellationToken);
+ Task<QueryResult<ProgramInfoDto>> GetLiveTvProgramsAsync(ProgramQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv program asynchronous.
@@ -1045,7 +1091,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="userId">The user identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ProgramInfoDto}.</returns>
- Task<ProgramInfoDto> GetLiveTvProgramAsync(string id, string userId, CancellationToken cancellationToken);
+ Task<ProgramInfoDto> GetLiveTvProgramAsync(string id, string userId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the recommended live tv programs asynchronous.
@@ -1053,7 +1099,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{QueryResult{ProgramInfoDto}}.</returns>
- Task<QueryResult<ProgramInfoDto>> GetRecommendedLiveTvProgramsAsync(RecommendedProgramQuery query, CancellationToken cancellationToken);
+ Task<QueryResult<ProgramInfoDto>> GetRecommendedLiveTvProgramsAsync(RecommendedProgramQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Creates the live tv timer asynchronous.
@@ -1061,7 +1107,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="timer">The timer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task CreateLiveTvTimerAsync(BaseTimerInfoDto timer, CancellationToken cancellationToken);
+ Task CreateLiveTvTimerAsync(BaseTimerInfoDto timer, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Updates the live tv timer asynchronous.
@@ -1069,7 +1115,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="timer">The timer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task UpdateLiveTvTimerAsync(TimerInfoDto timer, CancellationToken cancellationToken);
+ Task UpdateLiveTvTimerAsync(TimerInfoDto timer, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Creates the live tv series timer asynchronous.
@@ -1077,7 +1123,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="timer">The timer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task CreateLiveTvSeriesTimerAsync(SeriesTimerInfoDto timer, CancellationToken cancellationToken);
+ Task CreateLiveTvSeriesTimerAsync(SeriesTimerInfoDto timer, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Updates the live tv series timer asynchronous.
@@ -1085,7 +1131,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="timer">The timer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task UpdateLiveTvSeriesTimerAsync(SeriesTimerInfoDto timer, CancellationToken cancellationToken);
+ Task UpdateLiveTvSeriesTimerAsync(SeriesTimerInfoDto timer, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv timer asynchronous.
@@ -1093,7 +1139,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{TimerInfoDto}.</returns>
- Task<TimerInfoDto> GetLiveTvTimerAsync(string id, CancellationToken cancellationToken);
+ Task<TimerInfoDto> GetLiveTvTimerAsync(string id, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv series timers asynchronous.
@@ -1101,7 +1147,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{QueryResult{SeriesTimerInfoDto}}.</returns>
- Task<QueryResult<SeriesTimerInfoDto>> GetLiveTvSeriesTimersAsync(SeriesTimerQuery query, CancellationToken cancellationToken);
+ Task<QueryResult<SeriesTimerInfoDto>> GetLiveTvSeriesTimersAsync(SeriesTimerQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv series timer asynchronous.
@@ -1109,7 +1155,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{SeriesTimerInfoDto}.</returns>
- Task<SeriesTimerInfoDto> GetLiveTvSeriesTimerAsync(string id, CancellationToken cancellationToken);
+ Task<SeriesTimerInfoDto> GetLiveTvSeriesTimerAsync(string id, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Cancels the live tv timer asynchronous.
@@ -1117,7 +1163,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task CancelLiveTvTimerAsync(string id, CancellationToken cancellationToken);
+ Task CancelLiveTvTimerAsync(string id, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Cancels the live tv series timer asynchronous.
@@ -1125,7 +1171,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task CancelLiveTvSeriesTimerAsync(string id, CancellationToken cancellationToken);
+ Task CancelLiveTvSeriesTimerAsync(string id, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Deletes the live tv recording asynchronous.
@@ -1133,21 +1179,21 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task DeleteLiveTvRecordingAsync(string id, CancellationToken cancellationToken);
+ Task DeleteLiveTvRecordingAsync(string id, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the default timer information.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{SeriesTimerInfoDto}.</returns>
- Task<SeriesTimerInfoDto> GetDefaultLiveTvTimerInfo(CancellationToken cancellationToken);
+ Task<SeriesTimerInfoDto> GetDefaultLiveTvTimerInfo(CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the live tv guide information.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{GuideInfo}.</returns>
- Task<GuideInfo> GetLiveTvGuideInfo(CancellationToken cancellationToken);
+ Task<GuideInfo> GetLiveTvGuideInfo(CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the default timer information.
@@ -1155,7 +1201,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="programId">The program identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{SeriesTimerInfoDto}.</returns>
- Task<SeriesTimerInfoDto> GetDefaultLiveTvTimerInfo(string programId, CancellationToken cancellationToken);
+ Task<SeriesTimerInfoDto> GetDefaultLiveTvTimerInfo(string programId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the channel features.
@@ -1163,7 +1209,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="channelId">The channel identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{ChannelFeatures}.</returns>
- Task<ChannelFeatures> GetChannelFeatures(string channelId, CancellationToken cancellationToken);
+ Task<ChannelFeatures> GetChannelFeatures(string channelId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the channel items.
@@ -1171,7 +1217,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{QueryResult{BaseItemDto}}.</returns>
- Task<QueryResult<BaseItemDto>> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken);
+ Task<QueryResult<BaseItemDto>> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Gets the channels.
@@ -1179,6 +1225,45 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{QueryResult{BaseItemDto}}.</returns>
- Task<QueryResult<BaseItemDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken);
+ Task<QueryResult<BaseItemDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken = default(CancellationToken));
+
+ /// <summary>
+ /// Gets the latest channel items.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{QueryResult{BaseItemDto}}.</returns>
+ Task<QueryResult<BaseItemDto>> GetLatestChannelItems(AllChannelMediaQuery query, CancellationToken cancellationToken = default(CancellationToken));
+
+ /// <summary>
+ /// Creates the playlist.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ /// <returns>Task&lt;PlaylistCreationResult&gt;.</returns>
+ Task<PlaylistCreationResult> CreatePlaylist(PlaylistCreationRequest request);
+
+ /// <summary>
+ /// Adds to playlist.
+ /// </summary>
+ /// <param name="playlistId">The playlist identifier.</param>
+ /// <param name="itemIds">The item ids.</param>
+ /// <param name="userId">The user identifier.</param>
+ /// <returns>Task.</returns>
+ Task AddToPlaylist(string playlistId, IEnumerable<string> itemIds, string userId);
+
+ /// <summary>
+ /// Removes from playlist.
+ /// </summary>
+ /// <param name="playlistId">The playlist identifier.</param>
+ /// <param name="entryIds">The entry ids.</param>
+ /// <returns>Task.</returns>
+ Task RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds);
+
+ /// <summary>
+ /// Gets the playlist items.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <returns>Task&lt;QueryResult&lt;BaseItemDto&gt;&gt;.</returns>
+ Task<QueryResult<BaseItemDto>> GetPlaylistItems(PlaylistItemQuery query);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs b/MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs
new file mode 100644
index 000000000..bb2b48e76
--- /dev/null
+++ b/MediaBrowser.Model/ApiClient/ServerDiscoveryInfo.cs
@@ -0,0 +1,22 @@
+
+namespace MediaBrowser.Model.ApiClient
+{
+ public class ServerDiscoveryInfo
+ {
+ /// <summary>
+ /// Gets or sets the address.
+ /// </summary>
+ /// <value>The address.</value>
+ public string Address { get; set; }
+ /// <summary>
+ /// Gets or sets the server identifier.
+ /// </summary>
+ /// <value>The server identifier.</value>
+ public string Id { get; set; }
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Branding/BrandingOptions.cs b/MediaBrowser.Model/Branding/BrandingOptions.cs
new file mode 100644
index 000000000..737cb5c48
--- /dev/null
+++ b/MediaBrowser.Model/Branding/BrandingOptions.cs
@@ -0,0 +1,12 @@
+
+namespace MediaBrowser.Model.Branding
+{
+ public class BrandingOptions
+ {
+ /// <summary>
+ /// Gets or sets the login disclaimer.
+ /// </summary>
+ /// <value>The login disclaimer.</value>
+ public string LoginDisclaimer { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Channels/ChannelItemQuery.cs b/MediaBrowser.Model/Channels/ChannelItemQuery.cs
index a76c6cd2d..4aacc1619 100644
--- a/MediaBrowser.Model/Channels/ChannelItemQuery.cs
+++ b/MediaBrowser.Model/Channels/ChannelItemQuery.cs
@@ -1,6 +1,5 @@
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
-using System.Collections.Generic;
namespace MediaBrowser.Model.Channels
{
@@ -39,13 +38,13 @@ namespace MediaBrowser.Model.Channels
public SortOrder? SortOrder { get; set; }
public string[] SortBy { get; set; }
public ItemFilter[] Filters { get; set; }
- public List<ItemFields> Fields { get; set; }
+ public ItemFields[] Fields { get; set; }
public ChannelItemQuery()
{
Filters = new ItemFilter[] { };
SortBy = new string[] { };
- Fields = new List<ItemFields>();
+ Fields = new ItemFields[] { };
}
}
diff --git a/MediaBrowser.Model/Collections/CollectionCreationResult.cs b/MediaBrowser.Model/Collections/CollectionCreationResult.cs
new file mode 100644
index 000000000..ad7ac9553
--- /dev/null
+++ b/MediaBrowser.Model/Collections/CollectionCreationResult.cs
@@ -0,0 +1,8 @@
+
+namespace MediaBrowser.Model.Collections
+{
+ public class CollectionCreationResult
+ {
+ public string Id { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Configuration/ChannelOptions.cs b/MediaBrowser.Model/Configuration/ChannelOptions.cs
new file mode 100644
index 000000000..26fb1c9bd
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/ChannelOptions.cs
@@ -0,0 +1,21 @@
+namespace MediaBrowser.Model.Configuration
+{
+ public class ChannelOptions
+ {
+ public int? PreferredStreamingWidth { get; set; }
+
+ public string DownloadPath { get; set; }
+ public int? MaxDownloadAge { get; set; }
+
+ public string[] DownloadingChannels { get; set; }
+
+ public double? DownloadSizeLimit { get; set; }
+
+ public ChannelOptions()
+ {
+ DownloadingChannels = new string[] { };
+ DownloadSizeLimit = 1;
+ MaxDownloadAge = 30;
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/ChapterOptions.cs b/MediaBrowser.Model/Configuration/ChapterOptions.cs
new file mode 100644
index 000000000..2e882ee61
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/ChapterOptions.cs
@@ -0,0 +1,23 @@
+namespace MediaBrowser.Model.Configuration
+{
+ public class ChapterOptions
+ {
+ public bool EnableMovieChapterImageExtraction { get; set; }
+ public bool EnableEpisodeChapterImageExtraction { get; set; }
+ public bool EnableOtherVideoChapterImageExtraction { get; set; }
+
+ public bool DownloadMovieChapters { get; set; }
+ public bool DownloadEpisodeChapters { get; set; }
+
+ public string[] FetcherOrder { get; set; }
+ public string[] DisabledFetchers { get; set; }
+
+ public ChapterOptions()
+ {
+ DownloadMovieChapters = true;
+
+ DisabledFetchers = new string[] { };
+ FetcherOrder = new string[] { };
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 0d728ec75..1572c50dc 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -1,6 +1,8 @@
-using MediaBrowser.Model.Weather;
-using System;
-using System.Collections.Generic;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.FileOrganization;
+using MediaBrowser.Model.LiveTv;
+using MediaBrowser.Model.Notifications;
+using MediaBrowser.Model.Providers;
namespace MediaBrowser.Model.Configuration
{
@@ -10,24 +12,6 @@ namespace MediaBrowser.Model.Configuration
public class ServerConfiguration : BaseApplicationConfiguration
{
/// <summary>
- /// Gets or sets the zip code to use when displaying weather
- /// </summary>
- /// <value>The weather location.</value>
- public string WeatherLocation { get; set; }
-
- /// <summary>
- /// Gets or sets the weather unit to use when displaying weather
- /// </summary>
- /// <value>The weather unit.</value>
- public WeatherUnits WeatherUnit { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [enable HTTP level logging].
- /// </summary>
- /// <value><c>true</c> if [enable HTTP level logging]; otherwise, <c>false</c>.</value>
- public bool EnableHttpLevelLogging { get; set; }
-
- /// <summary>
/// Gets or sets a value indicating whether [enable u pn p].
/// </summary>
/// <value><c>true</c> if [enable u pn p]; otherwise, <c>false</c>.</value>
@@ -40,12 +24,6 @@ namespace MediaBrowser.Model.Configuration
public int HttpServerPortNumber { get; set; }
/// <summary>
- /// Gets or sets the legacy web socket port number.
- /// </summary>
- /// <value>The legacy web socket port number.</value>
- public int LegacyWebSocketPortNumber { get; set; }
-
- /// <summary>
/// Gets or sets a value indicating whether [enable internet providers].
/// </summary>
/// <value><c>true</c> if [enable internet providers]; otherwise, <c>false</c>.</value>
@@ -70,24 +48,12 @@ namespace MediaBrowser.Model.Configuration
public string SeasonZeroDisplayName { get; set; }
/// <summary>
- /// Gets or sets the metadata refresh days.
- /// </summary>
- /// <value>The metadata refresh days.</value>
- public int MetadataRefreshDays { get; set; }
-
- /// <summary>
/// Gets or sets a value indicating whether [save local meta].
/// </summary>
/// <value><c>true</c> if [save local meta]; otherwise, <c>false</c>.</value>
public bool SaveLocalMeta { get; set; }
/// <summary>
- /// Gets or sets a value indicating whether [refresh item images].
- /// </summary>
- /// <value><c>true</c> if [refresh item images]; otherwise, <c>false</c>.</value>
- public bool RefreshItemImages { get; set; }
-
- /// <summary>
/// Gets or sets the preferred metadata language.
/// </summary>
/// <value>The preferred metadata language.</value>
@@ -170,9 +136,6 @@ namespace MediaBrowser.Model.Configuration
public bool EnableTmdbUpdates { get; set; }
public bool EnableFanArtUpdates { get; set; }
- public bool RequireMobileManualLogin { get; set; }
- public bool RequireNonMobileManualLogin { get; set; }
-
/// <summary>
/// Gets or sets the image saving convention.
/// </summary>
@@ -191,8 +154,6 @@ namespace MediaBrowser.Model.Configuration
/// <value>The encoding quality.</value>
public EncodingQuality MediaEncodingQuality { get; set; }
- public bool AllowVideoUpscaling { get; set; }
-
public MetadataOptions[] MetadataOptions { get; set; }
public bool EnableDebugEncodingLogging { get; set; }
@@ -215,15 +176,10 @@ namespace MediaBrowser.Model.Configuration
public double DownMixAudioBoost { get; set; }
- public NotificationOptions NotificationOptions { get; set; }
-
- public SubtitleOptions SubtitleOptions { get; set; }
+ public bool DefaultMetadataSettingsApplied { get; set; }
- [Obsolete]
- public string[] ManualLoginClients { get; set; }
-
- public ChannelOptions ChannelOptions { get; set; }
- public ChapterOptions ChapterOptions { get; set; }
+ public bool EnableTokenAuthentication { get; set; }
+ public PeopleMetadataOptions PeopleMetadataOptions { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
@@ -234,8 +190,6 @@ namespace MediaBrowser.Model.Configuration
MediaEncodingQuality = EncodingQuality.Auto;
ImageSavingConvention = ImageSavingConvention.Compatible;
HttpServerPortNumber = 8096;
- LegacyWebSocketPortNumber = 8945;
- EnableHttpLevelLogging = true;
EnableDashboardResponseCaching = true;
EnableAutomaticRestart = true;
@@ -256,7 +210,6 @@ namespace MediaBrowser.Model.Configuration
PathSubstitutions = new PathSubstitution[] { };
- MetadataRefreshDays = 30;
PreferredMetadataLanguage = "en";
MetadataCountryCode = "US";
@@ -264,77 +217,88 @@ namespace MediaBrowser.Model.Configuration
SortRemoveCharacters = new[] { ",", "&", "-", "{", "}", "'" };
SortRemoveWords = new[] { "the", "a", "an" };
- ManualLoginClients = new string[] { };
-
SeasonZeroDisplayName = "Specials";
- LiveTvOptions = new LiveTvOptions();
-
- TvFileOrganizationOptions = new TvFileOrganizationOptions();
-
EnableRealtimeMonitor = true;
- List<MetadataOptions> options = new List<MetadataOptions>
- {
- new MetadataOptions(1, 1280) {ItemType = "Book"},
- new MetadataOptions(1, 1280) {ItemType = "MusicAlbum"},
- new MetadataOptions(1, 1280) {ItemType = "MusicArtist"},
- new MetadataOptions(0, 1280) {ItemType = "Season"}
- };
-
- MetadataOptions = options.ToArray();
-
- DlnaOptions = new DlnaOptions();
-
UICulture = "en-us";
- NotificationOptions = new NotificationOptions();
-
- SubtitleOptions = new SubtitleOptions();
-
- ChannelOptions = new ChannelOptions();
- ChapterOptions = new ChapterOptions();
- }
- }
-
- public class ChannelOptions
- {
- public int? PreferredStreamingWidth { get; set; }
+ PeopleMetadataOptions = new PeopleMetadataOptions();
- public string DownloadPath { get; set; }
- public int? MaxDownloadAge { get; set; }
+ MetadataOptions = new[]
+ {
+ new MetadataOptions(1, 1280) {ItemType = "Book"},
- public string[] DownloadingChannels { get; set; }
+ new MetadataOptions(1, 1280)
+ {
+ ItemType = "MusicAlbum",
+ ImageOptions = new []
+ {
+ new ImageOption
+ {
+ Limit = 1,
+ MinWidth = 1280,
+ Type = ImageType.Backdrop
+ },
+
+ // Don't download this by default as it's rarely used.
+ new ImageOption
+ {
+ Limit = 0,
+ Type = ImageType.Disc
+ }
+ }
+ },
+
+ new MetadataOptions(1, 1280)
+ {
+ ItemType = "MusicArtist",
+ ImageOptions = new []
+ {
+ new ImageOption
+ {
+ Limit = 1,
+ MinWidth = 1280,
+ Type = ImageType.Backdrop
+ },
+
+ // Don't download this by default
+ // They do look great, but most artists won't have them, which means a banner view isn't really possible
+ new ImageOption
+ {
+ Limit = 0,
+ Type = ImageType.Banner
+ },
+
+ // Don't download this by default
+ // Generally not used
+ new ImageOption
+ {
+ Limit = 0,
+ Type = ImageType.Art
+ }
+ }
+ },
- public ChannelOptions()
- {
- DownloadingChannels = new string[] { };
- MaxDownloadAge = 30;
+ new MetadataOptions(0, 1280) {ItemType = "Season"}
+ };
}
}
- public class ChapterOptions
+ public class PeopleMetadataOptions
{
- public bool EnableMovieChapterImageExtraction { get; set; }
- public bool EnableEpisodeChapterImageExtraction { get; set; }
- public bool EnableOtherVideoChapterImageExtraction { get; set; }
-
- public bool DownloadMovieChapters { get; set; }
- public bool DownloadEpisodeChapters { get; set; }
-
- public string[] FetcherOrder { get; set; }
- public string[] DisabledFetchers { get; set; }
-
- public ChapterOptions()
+ public bool DownloadActorMetadata { get; set; }
+ public bool DownloadDirectorMetadata { get; set; }
+ public bool DownloadProducerMetadata { get; set; }
+ public bool DownloadWriterMetadata { get; set; }
+ public bool DownloadComposerMetadata { get; set; }
+ public bool DownloadOtherPeopleMetadata { get; set; }
+ public bool DownloadGuestStarMetadata { get; set; }
+
+ public PeopleMetadataOptions()
{
- EnableMovieChapterImageExtraction = true;
- EnableEpisodeChapterImageExtraction = false;
- EnableOtherVideoChapterImageExtraction = false;
-
- DownloadMovieChapters = true;
-
- DisabledFetchers = new string[] { };
- FetcherOrder = new string[] { };
+ DownloadActorMetadata = true;
+ DownloadDirectorMetadata = true;
}
}
}
diff --git a/MediaBrowser.Model/Configuration/SubtitlePlaybackMode.cs b/MediaBrowser.Model/Configuration/SubtitlePlaybackMode.cs
new file mode 100644
index 000000000..e6a3c3091
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/SubtitlePlaybackMode.cs
@@ -0,0 +1,10 @@
+namespace MediaBrowser.Model.Configuration
+{
+ public enum SubtitlePlaybackMode
+ {
+ Default = 0,
+ Always = 1,
+ OnlyForced = 2,
+ None = 3
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs
index 885172bed..b48018c9a 100644
--- a/MediaBrowser.Model/Configuration/UserConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs
@@ -65,12 +65,20 @@ namespace MediaBrowser.Model.Configuration
public string[] BlockedMediaFolders { get; set; }
public string[] BlockedChannels { get; set; }
+ public string[] DisplayChannelsWithinViews { get; set; }
+
public string[] ExcludeFoldersFromGrouping { get; set; }
public UnratedItem[] BlockUnratedItems { get; set; }
public SubtitlePlaybackMode SubtitleMode { get; set; }
+ public bool DisplayCollectionsView { get; set; }
+ public bool DisplayFoldersView { get; set; }
+ public bool EnableLocalPassword { get; set; }
+
+ public string[] OrderedViews { get; set; }
+
/// <summary>
/// Initializes a new instance of the <see cref="UserConfiguration" /> class.
/// </summary>
@@ -84,19 +92,15 @@ namespace MediaBrowser.Model.Configuration
EnableMediaPlayback = true;
EnableLiveTvAccess = true;
+ OrderedViews = new string[] { };
BlockedMediaFolders = new string[] { };
+ DisplayChannelsWithinViews = new string[] { };
BlockedChannels = new string[] { };
BlockUnratedItems = new UnratedItem[] { };
ExcludeFoldersFromGrouping = new string[] { };
+ DisplayCollectionsView = true;
+ DisplayFoldersView = true;
}
}
-
- public enum SubtitlePlaybackMode
- {
- Default = 0,
- Always = 1,
- OnlyForced = 2,
- None = 3
- }
}
diff --git a/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs
new file mode 100644
index 000000000..86eb40b97
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/XbmcMetadataOptions.cs
@@ -0,0 +1,24 @@
+
+namespace MediaBrowser.Model.Configuration
+{
+ public class XbmcMetadataOptions
+ {
+ public string UserId { get; set; }
+
+ public string ReleaseDateFormat { get; set; }
+
+ public bool SaveImagePathsInNfo { get; set; }
+ public bool EnablePathSubstitution { get; set; }
+
+ public bool EnableExtraThumbsDuplication { get; set; }
+
+ public XbmcMetadataOptions()
+ {
+ ReleaseDateFormat = "yyyy-MM-dd";
+
+ SaveImagePathsInNfo = true;
+ EnablePathSubstitution = true;
+ EnableExtraThumbsDuplication = true;
+ }
+ }
+}
diff --git a/MediaBrowser.Model/Dlna/AudioOptions.cs b/MediaBrowser.Model/Dlna/AudioOptions.cs
index d04133a3d..dd6dad261 100644
--- a/MediaBrowser.Model/Dlna/AudioOptions.cs
+++ b/MediaBrowser.Model/Dlna/AudioOptions.cs
@@ -1,5 +1,5 @@
-using System.Collections.Generic;
-using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Dto;
+using System.Collections.Generic;
namespace MediaBrowser.Model.Dlna
{
@@ -8,6 +8,11 @@ namespace MediaBrowser.Model.Dlna
/// </summary>
public class AudioOptions
{
+ public AudioOptions()
+ {
+ Context = EncodingContext.Streaming;
+ }
+
public string ItemId { get; set; }
public List<MediaSourceInfo> MediaSources { get; set; }
public DeviceProfile Profile { get; set; }
@@ -29,5 +34,41 @@ namespace MediaBrowser.Model.Dlna
/// The application's configured quality setting
/// </summary>
public int? MaxBitrate { get; set; }
+
+ /// <summary>
+ /// Gets or sets the context.
+ /// </summary>
+ /// <value>The context.</value>
+ public EncodingContext Context { get; set; }
+
+ /// <summary>
+ /// Gets or sets the audio transcoding bitrate.
+ /// </summary>
+ /// <value>The audio transcoding bitrate.</value>
+ public int? AudioTranscodingBitrate { get; set; }
+
+ /// <summary>
+ /// Gets the maximum bitrate.
+ /// </summary>
+ /// <returns>System.Nullable&lt;System.Int32&gt;.</returns>
+ public int? GetMaxBitrate()
+ {
+ if (MaxBitrate.HasValue)
+ {
+ return MaxBitrate;
+ }
+
+ if (Profile != null)
+ {
+ if (Context == EncodingContext.Static)
+ {
+ return Profile.MaxStaticBitrate;
+ }
+
+ return Profile.MaxStreamingBitrate;
+ }
+
+ return null;
+ }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs
index 66c3e0b19..89b844ae5 100644
--- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs
+++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs
@@ -175,6 +175,35 @@ namespace MediaBrowser.Model.Dlna
return false;
}
+
+ private bool IsConditionSatisfied(ProfileCondition condition, float? currentValue)
+ {
+ if (!currentValue.HasValue)
+ {
+ // If the value is unknown, it satisfies if not marked as required
+ return !condition.IsRequired;
+ }
+
+ float expected;
+ if (FloatHelper.TryParseCultureInvariant(condition.Value, out expected))
+ {
+ switch (condition.Condition)
+ {
+ case ProfileConditionType.Equals:
+ return currentValue.Value.Equals(expected);
+ case ProfileConditionType.GreaterThanEqual:
+ return currentValue.Value >= expected;
+ case ProfileConditionType.LessThanEqual:
+ return currentValue.Value <= expected;
+ case ProfileConditionType.NotEquals:
+ return !currentValue.Value.Equals(expected);
+ default:
+ throw new InvalidOperationException("Unexpected ProfileConditionType");
+ }
+ }
+
+ return false;
+ }
private bool IsConditionSatisfied(ProfileCondition condition, double? currentValue)
{
diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
index b6d9d9f77..98ebfcdf2 100644
--- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
+++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
@@ -14,17 +14,19 @@ namespace MediaBrowser.Model.Dlna
public string BuildImageHeader(string container,
int? width,
- int? height)
+ int? height,
+ bool isDirectStream,
+ string orgPn = null)
{
string orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetImageOrgOpValue();
// 0 = native, 1 = transcoded
- const string orgCi = ";DLNA.ORG_CI=0";
+ var orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
- DlnaFlags flagValue = DlnaFlags.StreamingTransferMode |
- DlnaFlags.BackgroundTransferMode |
+ DlnaFlags flagValue = DlnaFlags.BackgroundTransferMode |
+ DlnaFlags.InteractiveTransferMode |
DlnaFlags.DlnaV15;
-
+
string dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue));
@@ -32,7 +34,10 @@ namespace MediaBrowser.Model.Dlna
width,
height);
- string orgPn = mediaProfile == null ? null : mediaProfile.OrgPn;
+ if (string.IsNullOrEmpty(orgPn))
+ {
+ orgPn = mediaProfile == null ? null : mediaProfile.OrgPn;
+ }
if (string.IsNullOrEmpty(orgPn))
{
@@ -61,16 +66,17 @@ namespace MediaBrowser.Model.Dlna
DlnaFlags flagValue = DlnaFlags.StreamingTransferMode |
DlnaFlags.BackgroundTransferMode |
+ DlnaFlags.InteractiveTransferMode |
DlnaFlags.DlnaV15;
- if (isDirectStream)
- {
- //flagValue = flagValue | DlnaFlags.DLNA_ORG_FLAG_BYTE_BASED_SEEK;
- }
- else if (runtimeTicks.HasValue)
- {
- //flagValue = flagValue | DlnaFlags.DLNA_ORG_FLAG_TIME_BASED_SEEK;
- }
+ //if (isDirectStream)
+ //{
+ // flagValue = flagValue | DlnaFlags.ByteBasedSeek;
+ //}
+ //else if (runtimeTicks.HasValue)
+ //{
+ // flagValue = flagValue | DlnaFlags.TimeBasedSeek;
+ //}
string dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue));
@@ -92,7 +98,7 @@ namespace MediaBrowser.Model.Dlna
return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
}
- public string BuildVideoHeader(string container,
+ public List<string> BuildVideoHeader(string container,
string videoCodec,
string audioCodec,
int? width,
@@ -119,16 +125,17 @@ namespace MediaBrowser.Model.Dlna
DlnaFlags flagValue = DlnaFlags.StreamingTransferMode |
DlnaFlags.BackgroundTransferMode |
+ DlnaFlags.InteractiveTransferMode |
DlnaFlags.DlnaV15;
- if (isDirectStream)
- {
- //flagValue = flagValue | DlnaFlags.DLNA_ORG_FLAG_BYTE_BASED_SEEK;
- }
- else if (runtimeTicks.HasValue)
- {
- //flagValue = flagValue | DlnaFlags.DLNA_ORG_FLAG_TIME_BASED_SEEK;
- }
+ //if (isDirectStream)
+ //{
+ // flagValue = flagValue | DlnaFlags.ByteBasedSeek;
+ //}
+ //else if (runtimeTicks.HasValue)
+ //{
+ // flagValue = flagValue | DlnaFlags.TimeBasedSeek;
+ //}
string dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue));
@@ -149,30 +156,42 @@ namespace MediaBrowser.Model.Dlna
timestamp,
isAnamorphic);
- string orgPn = mediaProfile == null ? null : mediaProfile.OrgPn;
+ List<string> orgPnValues = new List<string>();
- if (string.IsNullOrEmpty(orgPn))
+ if (mediaProfile != null && !string.IsNullOrEmpty(mediaProfile.OrgPn))
+ {
+ orgPnValues.Add(mediaProfile.OrgPn);
+ }
+ else
{
foreach (string s in GetVideoOrgPnValue(container, videoCodec, audioCodec, width, height, timestamp))
{
- orgPn = s;
+ orgPnValues.Add(s);
break;
}
}
- if (string.IsNullOrEmpty(orgPn))
+ List<string> contentFeatureList = new List<string>();
+
+ foreach (string orgPn in orgPnValues)
{
- // TODO: Support multiple values and return multiple headers?
- foreach (string s in (orgPn ?? string.Empty).Split(','))
- {
- orgPn = s;
- break;
- }
+ string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
+
+ var value = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
+
+ contentFeatureList.Add(value);
}
- string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
+ if (orgPnValues.Count == 0)
+ {
+ string contentFeatures = string.Empty;
- return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
+ var value = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
+
+ contentFeatureList.Add(value);
+ }
+
+ return contentFeatureList;
}
private string GetImageOrgPnValue(string container, int? width, int? height)
diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs
index 807e04427..67cfa0208 100644
--- a/MediaBrowser.Model/Dlna/DeviceProfile.cs
+++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs
@@ -43,14 +43,18 @@ namespace MediaBrowser.Model.Dlna
public string AlbumArtPn { get; set; }
- public int? MaxAlbumArtWidth { get; set; }
- public int? MaxAlbumArtHeight { get; set; }
+ public int MaxAlbumArtWidth { get; set; }
+ public int MaxAlbumArtHeight { get; set; }
public int? MaxIconWidth { get; set; }
public int? MaxIconHeight { get; set; }
- public int? MaxBitrate { get; set; }
-
+ public int? MaxStreamingBitrate { get; set; }
+ public int? MaxStaticBitrate { get; set; }
+
+ public int? MusicStreamingTranscodingBitrate { get; set; }
+ public int? MusicSyncBitrate { get; set; }
+
/// <summary>
/// Controls the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.
/// </summary>
@@ -89,6 +93,8 @@ namespace MediaBrowser.Model.Dlna
public CodecProfile[] CodecProfiles { get; set; }
public ResponseProfile[] ResponseProfiles { get; set; }
+ public SubtitleProfile[] SubtitleProfiles { get; set; }
+
public DeviceProfile()
{
DirectPlayProfiles = new DirectPlayProfile[] { };
@@ -96,7 +102,8 @@ namespace MediaBrowser.Model.Dlna
ResponseProfiles = new ResponseProfile[] { };
CodecProfiles = new CodecProfile[] { };
ContainerProfiles = new ContainerProfile[] { };
-
+ SubtitleProfiles = new SubtitleProfile[] { };
+
XmlRootAttributes = new XmlAttribute[] { };
SupportedMediaTypes = "Audio,Photo,Video";
@@ -115,7 +122,7 @@ namespace MediaBrowser.Model.Dlna
public TranscodingProfile GetAudioTranscodingProfile(string container, string audioCodec)
{
- container = (container ?? string.Empty).TrimStart('.');
+ container = StringHelper.TrimStart((container ?? string.Empty), '.');
foreach (var i in TranscodingProfiles)
{
@@ -141,7 +148,7 @@ namespace MediaBrowser.Model.Dlna
public TranscodingProfile GetVideoTranscodingProfile(string container, string audioCodec, string videoCodec)
{
- container = (container ?? string.Empty).TrimStart('.');
+ container = StringHelper.TrimStart((container ?? string.Empty), '.');
foreach (var i in TranscodingProfiles)
{
@@ -172,7 +179,7 @@ namespace MediaBrowser.Model.Dlna
public ResponseProfile GetAudioMediaProfile(string container, string audioCodec, int? audioChannels, int? audioBitrate)
{
- container = (container ?? string.Empty).TrimStart('.');
+ container = StringHelper.TrimStart((container ?? string.Empty), '.');
foreach (var i in ResponseProfiles)
{
@@ -217,7 +224,7 @@ namespace MediaBrowser.Model.Dlna
public ResponseProfile GetImageMediaProfile(string container, int? width, int? height)
{
- container = (container ?? string.Empty).TrimStart('.');
+ container = StringHelper.TrimStart((container ?? string.Empty), '.');
foreach (var i in ResponseProfiles)
{
@@ -270,7 +277,7 @@ namespace MediaBrowser.Model.Dlna
TransportStreamTimestamp timestamp,
bool? isAnamorphic)
{
- container = (container ?? string.Empty).TrimStart('.');
+ container = StringHelper.TrimStart((container ?? string.Empty), '.');
foreach (var i in ResponseProfiles)
{
diff --git a/MediaBrowser.Model/Dlna/DlnaFlags.cs b/MediaBrowser.Model/Dlna/DlnaFlags.cs
index 23859312d..7c7fe8d8f 100644
--- a/MediaBrowser.Model/Dlna/DlnaFlags.cs
+++ b/MediaBrowser.Model/Dlna/DlnaFlags.cs
@@ -5,17 +5,44 @@ namespace MediaBrowser.Model.Dlna
[Flags]
public enum DlnaFlags : ulong
{
+ /*! <i>Background</i> transfer mode.
+ For use with upload and download transfers to and from the server.
+ The primary difference between \ref DH_TransferMode_Interactive and
+ \ref DH_TransferMode_Bulk is that the latter assumes that the user
+ is not relying on the transfer for immediately rendering the content
+ and there are no issues with causing a buffer overflow if the
+ receiver uses TCP flow control to reduce total throughput.
+ */
BackgroundTransferMode = (1 << 22),
+
ByteBasedSeek = (1 << 29),
ConnectionStall = (1 << 21),
+
DlnaV15 = (1 << 20),
+
+ /*! <i>Interactive</i> transfer mode.
+ For best effort transfer of images and non-real-time transfers.
+ URIs with image content usually support \ref DH_TransferMode_Bulk too.
+ The primary difference between \ref DH_TransferMode_Interactive and
+ \ref DH_TransferMode_Bulk is that the former assumes that the
+ transfer is intended for immediate rendering.
+ */
InteractiveTransferMode = (1 << 23),
+
PlayContainer = (1 << 28),
RtspPause = (1 << 25),
S0Increase = (1 << 27),
SenderPaced = (1L << 31),
SnIncrease = (1 << 26),
+
+ /*! <i>Streaming</i> transfer mode.
+ The server transmits at a throughput sufficient for real-time playback of
+ audio or video. URIs with audio or video often support the
+ \ref DH_TransferMode_Interactive and \ref DH_TransferMode_Bulk transfer modes.
+ The most well-known exception to this general claim is for live streams.
+ */
StreamingTransferMode = (1 << 24),
+
TimeBasedSeek = (1 << 30)
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/DlnaMaps.cs b/MediaBrowser.Model/Dlna/DlnaMaps.cs
index 036c1fc74..9a84eb195 100644
--- a/MediaBrowser.Model/Dlna/DlnaMaps.cs
+++ b/MediaBrowser.Model/Dlna/DlnaMaps.cs
@@ -48,7 +48,7 @@
orgOp += "0";
// Byte-based seeking only possible when not transcoding
- orgOp += "1";
+ orgOp += "0";
return orgOp;
}
diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
index 9bbe52dbf..5101bbe5a 100644
--- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
+++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
@@ -385,7 +385,7 @@ namespace MediaBrowser.Model.Dlna
return ResolveImageJPGFormat(width, height);
if (StringHelper.EqualsIgnoreCase(container, "png"))
- return MediaFormatProfile.PNG_LRG;
+ return ResolveImagePNGFormat(width, height);
if (StringHelper.EqualsIgnoreCase(container, "gif"))
return MediaFormatProfile.GIF_LRG;
@@ -400,6 +400,9 @@ namespace MediaBrowser.Model.Dlna
{
if (width.HasValue && height.HasValue)
{
+ if ((width.Value <= 160) && (height.Value <= 160))
+ return MediaFormatProfile.JPEG_TN;
+
if ((width.Value <= 640) && (height.Value <= 480))
return MediaFormatProfile.JPEG_SM;
@@ -407,9 +410,22 @@ namespace MediaBrowser.Model.Dlna
{
return MediaFormatProfile.JPEG_MED;
}
+
+ return MediaFormatProfile.JPEG_LRG;
+ }
+
+ return MediaFormatProfile.JPEG_SM;
+ }
+
+ private MediaFormatProfile ResolveImagePNGFormat(int? width, int? height)
+ {
+ if (width.HasValue && height.HasValue)
+ {
+ if ((width.Value <= 160) && (height.Value <= 160))
+ return MediaFormatProfile.PNG_TN;
}
- return MediaFormatProfile.JPEG_LRG;
+ return MediaFormatProfile.PNG_LRG;
}
}
}
diff --git a/MediaBrowser.Model/Dlna/SearchCriteria.cs b/MediaBrowser.Model/Dlna/SearchCriteria.cs
index ced852583..67c1b9042 100644
--- a/MediaBrowser.Model/Dlna/SearchCriteria.cs
+++ b/MediaBrowser.Model/Dlna/SearchCriteria.cs
@@ -16,24 +16,34 @@ namespace MediaBrowser.Model.Dlna
SearchType = SearchType.Unknown;
- if (StringHelper.IndexOfIgnoreCase(search, "upnp:class") != -1 &&
- StringHelper.IndexOfIgnoreCase(search, "derivedfrom") != -1)
+ String[] factors = StringHelper.RegexSplit(search, "(and|or)");
+ foreach (String factor in factors)
{
- if (StringHelper.IndexOfIgnoreCase(search, "object.item.audioItem") != -1)
- {
- SearchType = SearchType.Audio;
- }
- else if (StringHelper.IndexOfIgnoreCase(search, "object.item.imageItem") != -1)
- {
- SearchType = SearchType.Image;
- }
- else if (StringHelper.IndexOfIgnoreCase(search, "object.item.videoItem") != -1)
- {
- SearchType = SearchType.Video;
- }
- else if (StringHelper.IndexOfIgnoreCase(search, "object.container.playlistContainer") != -1)
+ String[] subFactors = StringHelper.RegexSplit(factor.Trim().Trim('(').Trim(')').Trim(), "\\s", 3);
+
+ if (subFactors.Length == 3)
{
- SearchType = SearchType.Playlist;
+
+ if (StringHelper.EqualsIgnoreCase("upnp:class", subFactors[0]) &&
+ (StringHelper.EqualsIgnoreCase("=", subFactors[1]) || StringHelper.EqualsIgnoreCase("derivedfrom", subFactors[1])))
+ {
+ if (StringHelper.EqualsIgnoreCase("\"object.item.imageItem\"", subFactors[2]) || StringHelper.EqualsIgnoreCase("\"object.item.imageItem.photo\"", subFactors[2]))
+ {
+ SearchType = SearchType.Image;
+ }
+ else if (StringHelper.EqualsIgnoreCase("\"object.item.videoItem\"", subFactors[2]))
+ {
+ SearchType = SearchType.Video;
+ }
+ else if (StringHelper.EqualsIgnoreCase("\"object.container.playlistContainer\"", subFactors[2]))
+ {
+ SearchType = SearchType.Playlist;
+ }
+ else if (StringHelper.EqualsIgnoreCase("\"object.container.album.musicAlbum\"", subFactors[2]))
+ {
+ SearchType = SearchType.MusicAlbum;
+ }
+ }
}
}
}
diff --git a/MediaBrowser.Model/Dlna/SearchType.cs b/MediaBrowser.Model/Dlna/SearchType.cs
index 68c047603..27b207879 100644
--- a/MediaBrowser.Model/Dlna/SearchType.cs
+++ b/MediaBrowser.Model/Dlna/SearchType.cs
@@ -6,6 +6,7 @@
Audio = 1,
Image = 2,
Video = 3,
- Playlist = 4
+ Playlist = 4,
+ MusicAlbum = 5
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/SortCriteria.cs b/MediaBrowser.Model/Dlna/SortCriteria.cs
index 944d50486..600a2f58e 100644
--- a/MediaBrowser.Model/Dlna/SortCriteria.cs
+++ b/MediaBrowser.Model/Dlna/SortCriteria.cs
@@ -1,8 +1,14 @@
-
+using MediaBrowser.Model.Entities;
+
namespace MediaBrowser.Model.Dlna
{
public class SortCriteria
{
+ public SortOrder SortOrder
+ {
+ get { return SortOrder.Ascending; }
+ }
+
public SortCriteria(string value)
{
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index 877570844..5a3e267e6 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.MediaInfo;
+using MediaBrowser.Model.Session;
using System;
using System.Collections.Generic;
@@ -9,6 +10,8 @@ namespace MediaBrowser.Model.Dlna
{
public class StreamBuilder
{
+ private readonly string[] _serverTextSubtitleOutputs = { "srt", "vtt", "ttml" };
+
public StreamInfo BuildAudioItem(AudioOptions options)
{
ValidateAudioInput(options);
@@ -48,16 +51,13 @@ namespace MediaBrowser.Model.Dlna
List<MediaSourceInfo> mediaSources = options.MediaSources;
- // If the client wants a specific media soure, filter now
+ // If the client wants a specific media source, filter now
if (!string.IsNullOrEmpty(options.MediaSourceId))
{
- // Avoid implicitly captured closure
- string mediaSourceId = options.MediaSourceId;
-
var newMediaSources = new List<MediaSourceInfo>();
foreach (MediaSourceInfo i in mediaSources)
{
- if (StringHelper.EqualsIgnoreCase(i.Id, mediaSourceId))
+ if (StringHelper.EqualsIgnoreCase(i.Id, options.MediaSourceId))
newMediaSources.Add(i);
}
@@ -106,7 +106,7 @@ namespace MediaBrowser.Model.Dlna
RunTimeTicks = item.RunTimeTicks
};
- int? maxBitrateSetting = options.MaxBitrate ?? options.Profile.MaxBitrate;
+ int? maxBitrateSetting = options.GetMaxBitrate();
MediaStream audioStream = item.DefaultAudioStream;
@@ -136,7 +136,12 @@ namespace MediaBrowser.Model.Dlna
foreach (CodecProfile i in options.Profile.CodecProfiles)
{
if (i.Type == CodecType.Audio && i.ContainsCodec(audioCodec))
- conditions.AddRange(i.Conditions);
+ {
+ foreach (var c in i.Conditions)
+ {
+ conditions.Add(c);
+ }
+ }
}
int? audioChannels = audioStream.Channels;
@@ -154,7 +159,7 @@ namespace MediaBrowser.Model.Dlna
if (all)
{
- playlistItem.IsDirectStream = true;
+ playlistItem.PlayMethod = PlayMethod.DirectStream;
playlistItem.Container = item.Container;
return playlistItem;
@@ -166,7 +171,7 @@ namespace MediaBrowser.Model.Dlna
TranscodingProfile transcodingProfile = null;
foreach (TranscodingProfile i in options.Profile.TranscodingProfiles)
{
- if (i.Type == playlistItem.MediaType)
+ if (i.Type == playlistItem.MediaType && i.Context == options.Context)
{
transcodingProfile = i;
break;
@@ -175,7 +180,7 @@ namespace MediaBrowser.Model.Dlna
if (transcodingProfile != null)
{
- playlistItem.IsDirectStream = false;
+ playlistItem.PlayMethod = PlayMethod.Transcode;
playlistItem.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo;
playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength;
playlistItem.Container = transcodingProfile.Container;
@@ -195,7 +200,12 @@ namespace MediaBrowser.Model.Dlna
List<ProfileCondition> audioTranscodingConditions = new List<ProfileCondition>();
foreach (CodecProfile i in audioCodecProfiles)
- audioTranscodingConditions.AddRange(i.Conditions);
+ {
+ foreach (var c in i.Conditions)
+ {
+ audioTranscodingConditions.Add(c);
+ }
+ }
ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
@@ -207,13 +217,11 @@ namespace MediaBrowser.Model.Dlna
playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue);
}
- // Honor requested max bitrate
- if (maxBitrateSetting.HasValue)
- {
- int currentValue = playlistItem.AudioBitrate ?? maxBitrateSetting.Value;
+ var configuredBitrate = options.AudioTranscodingBitrate ??
+ (options.Context == EncodingContext.Static ? options.Profile.MusicSyncBitrate : options.Profile.MusicStreamingTranscodingBitrate) ??
+ 128000;
- playlistItem.AudioBitrate = Math.Min(maxBitrateSetting.Value, currentValue);
- }
+ playlistItem.AudioBitrate = Math.Min(configuredBitrate, playlistItem.AudioBitrate ?? configuredBitrate);
}
return playlistItem;
@@ -229,21 +237,31 @@ namespace MediaBrowser.Model.Dlna
RunTimeTicks = item.RunTimeTicks
};
- MediaStream audioStream = item.DefaultAudioStream;
+ int? audioStreamIndex = options.AudioStreamIndex ?? item.DefaultAudioStreamIndex;
+ playlistItem.SubtitleStreamIndex = options.SubtitleStreamIndex ?? item.DefaultSubtitleStreamIndex;
+
+ MediaStream audioStream = audioStreamIndex.HasValue ? item.GetMediaStream(MediaStreamType.Audio, audioStreamIndex.Value) : null;
+ MediaStream subtitleStream = playlistItem.SubtitleStreamIndex.HasValue ? item.GetMediaStream(MediaStreamType.Subtitle, playlistItem.SubtitleStreamIndex.Value) : null;
+
MediaStream videoStream = item.VideoStream;
- int? maxBitrateSetting = options.MaxBitrate ?? options.Profile.MaxBitrate;
+ int? maxBitrateSetting = options.GetMaxBitrate();
- if (IsEligibleForDirectPlay(item, options, maxBitrateSetting))
+ if (IsEligibleForDirectPlay(item, maxBitrateSetting, subtitleStream, options))
{
// See if it can be direct played
DirectPlayProfile directPlay = GetVideoDirectPlayProfile(options.Profile, item, videoStream, audioStream);
if (directPlay != null)
{
- playlistItem.IsDirectStream = true;
+ playlistItem.PlayMethod = PlayMethod.DirectStream;
playlistItem.Container = item.Container;
+ if (subtitleStream != null)
+ {
+ playlistItem.SubtitleDeliveryMethod = GetSubtitleDeliveryMethod(subtitleStream, options);
+ }
+
return playlistItem;
}
}
@@ -252,7 +270,7 @@ namespace MediaBrowser.Model.Dlna
TranscodingProfile transcodingProfile = null;
foreach (TranscodingProfile i in options.Profile.TranscodingProfiles)
{
- if (i.Type == playlistItem.MediaType)
+ if (i.Type == playlistItem.MediaType && i.Context == options.Context)
{
transcodingProfile = i;
break;
@@ -261,22 +279,29 @@ namespace MediaBrowser.Model.Dlna
if (transcodingProfile != null)
{
- playlistItem.IsDirectStream = false;
+ if (subtitleStream != null)
+ {
+ playlistItem.SubtitleDeliveryMethod = GetSubtitleDeliveryMethod(subtitleStream, options);
+ }
+
+ playlistItem.PlayMethod = PlayMethod.Transcode;
playlistItem.Container = transcodingProfile.Container;
playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength;
playlistItem.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo;
playlistItem.AudioCodec = transcodingProfile.AudioCodec.Split(',')[0];
playlistItem.VideoCodec = transcodingProfile.VideoCodec;
playlistItem.Protocol = transcodingProfile.Protocol;
- playlistItem.AudioStreamIndex = options.AudioStreamIndex ?? item.DefaultAudioStreamIndex;
- playlistItem.SubtitleStreamIndex = options.SubtitleStreamIndex ?? item.DefaultSubtitleStreamIndex;
+ playlistItem.AudioStreamIndex = audioStreamIndex;
List<ProfileCondition> videoTranscodingConditions = new List<ProfileCondition>();
foreach (CodecProfile i in options.Profile.CodecProfiles)
{
if (i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec))
{
- videoTranscodingConditions.AddRange(i.Conditions);
+ foreach (var c in i.Conditions)
+ {
+ videoTranscodingConditions.Add(c);
+ }
break;
}
}
@@ -287,7 +312,10 @@ namespace MediaBrowser.Model.Dlna
{
if (i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec))
{
- audioTranscodingConditions.AddRange(i.Conditions);
+ foreach (var c in i.Conditions)
+ {
+ audioTranscodingConditions.Add(c);
+ }
break;
}
}
@@ -301,12 +329,9 @@ namespace MediaBrowser.Model.Dlna
playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue);
}
- // Honor requested max bitrate
- if (options.MaxAudioTranscodingBitrate.HasValue)
+ if (!playlistItem.AudioBitrate.HasValue)
{
- int currentValue = playlistItem.AudioBitrate ?? options.MaxAudioTranscodingBitrate.Value;
-
- playlistItem.AudioBitrate = Math.Min(options.MaxAudioTranscodingBitrate.Value, currentValue);
+ playlistItem.AudioBitrate = GetAudioBitrate(playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec);
}
// Honor max rate
@@ -323,15 +348,22 @@ namespace MediaBrowser.Model.Dlna
playlistItem.VideoBitrate = Math.Min(videoBitrate, currentValue);
}
+ }
- // Hate to hard-code this, but it's still probably better than being subjected to encoder defaults
- if (!playlistItem.VideoBitrate.HasValue)
+ return playlistItem;
+ }
+
+ private int GetAudioBitrate(int? channels, string codec)
+ {
+ if (channels.HasValue)
+ {
+ if (channels.Value >= 5)
{
- playlistItem.VideoBitrate = 5000000;
+ return 320000;
}
}
- return playlistItem;
+ return 128000;
}
private DirectPlayProfile GetVideoDirectPlayProfile(DeviceProfile profile,
@@ -363,7 +395,10 @@ namespace MediaBrowser.Model.Dlna
if (i.Type == DlnaProfileType.Video &&
ListHelper.ContainsIgnoreCase(i.GetContainers(), container))
{
- conditions.AddRange(i.Conditions);
+ foreach (var c in i.Conditions)
+ {
+ conditions.Add(c);
+ }
}
}
@@ -405,7 +440,12 @@ namespace MediaBrowser.Model.Dlna
foreach (CodecProfile i in profile.CodecProfiles)
{
if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec))
- conditions.AddRange(i.Conditions);
+ {
+ foreach (var c in i.Conditions)
+ {
+ conditions.Add(c);
+ }
+ }
}
foreach (ProfileCondition i in conditions)
@@ -429,7 +469,12 @@ namespace MediaBrowser.Model.Dlna
foreach (CodecProfile i in profile.CodecProfiles)
{
if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec))
- conditions.AddRange(i.Conditions);
+ {
+ foreach (var c in i.Conditions)
+ {
+ conditions.Add(c);
+ }
+ }
}
foreach (ProfileCondition i in conditions)
@@ -444,16 +489,68 @@ namespace MediaBrowser.Model.Dlna
return directPlay;
}
- private bool IsEligibleForDirectPlay(MediaSourceInfo item, VideoOptions options, int? maxBitrate)
+ private bool IsEligibleForDirectPlay(MediaSourceInfo item,
+ int? maxBitrate,
+ MediaStream subtitleStream,
+ VideoOptions options)
{
- if (options.SubtitleStreamIndex.HasValue)
+ if (subtitleStream != null)
{
- return false;
+ if (!subtitleStream.IsTextSubtitleStream)
+ {
+ return false;
+ }
+
+ SubtitleDeliveryMethod subtitleMethod = GetSubtitleDeliveryMethod(subtitleStream, options);
+
+ if (subtitleMethod != SubtitleDeliveryMethod.External && subtitleMethod != SubtitleDeliveryMethod.Embed)
+ {
+ return false;
+ }
}
return IsAudioEligibleForDirectPlay(item, maxBitrate);
}
+ private SubtitleDeliveryMethod GetSubtitleDeliveryMethod(MediaStream subtitleStream,
+ VideoOptions options)
+ {
+ if (subtitleStream.IsTextSubtitleStream)
+ {
+ // See if the device can retrieve the subtitles externally
+ bool supportsSubsExternally = options.Context == EncodingContext.Streaming &&
+ ContainsSubtitleFormat(options.Profile.SubtitleProfiles, SubtitleDeliveryMethod.External, _serverTextSubtitleOutputs);
+
+ if (supportsSubsExternally)
+ {
+ return SubtitleDeliveryMethod.External;
+ }
+
+ // See if the device can retrieve the subtitles externally
+ bool supportsEmbedded = ContainsSubtitleFormat(options.Profile.SubtitleProfiles, SubtitleDeliveryMethod.Embed, _serverTextSubtitleOutputs);
+
+ if (supportsEmbedded)
+ {
+ return SubtitleDeliveryMethod.Embed;
+ }
+ }
+
+ return SubtitleDeliveryMethod.Encode;
+ }
+
+ private bool ContainsSubtitleFormat(SubtitleProfile[] profiles, SubtitleDeliveryMethod method, string[] formats)
+ {
+ foreach (SubtitleProfile profile in profiles)
+ {
+ if (method == profile.Method && ListHelper.ContainsIgnoreCase(formats, profile.Format))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, int? maxBitrate)
{
// Honor the max bitrate setting
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index 8d507ae37..eb686864b 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.MediaInfo;
+using MediaBrowser.Model.Session;
using System;
using System.Collections.Generic;
@@ -15,7 +16,7 @@ namespace MediaBrowser.Model.Dlna
{
public string ItemId { get; set; }
- public bool IsDirectStream { get; set; }
+ public PlayMethod PlayMethod { get; set; }
public DlnaProfileType MediaType { get; set; }
@@ -58,6 +59,9 @@ namespace MediaBrowser.Model.Dlna
public MediaSourceInfo MediaSource { get; set; }
+ public SubtitleDeliveryMethod SubtitleDeliveryMethod { get; set; }
+ public string SubtitleFormat { get; set; }
+
public string MediaSourceId
{
get
@@ -66,6 +70,11 @@ namespace MediaBrowser.Model.Dlna
}
}
+ public bool IsDirectStream
+ {
+ get { return PlayMethod == PlayMethod.DirectStream; }
+ }
+
public string ToUrl(string baseUrl)
{
return ToDlnaUrl(baseUrl);
@@ -91,7 +100,7 @@ namespace MediaBrowser.Model.Dlna
if (StringHelper.EqualsIgnoreCase(Protocol, "hls"))
{
- return string.Format("{0}/videos/{1}/stream.m3u8?{2}", baseUrl, ItemId, dlnaCommand);
+ return string.Format("{0}/videos/{1}/master.m3u8?{2}", baseUrl, ItemId, dlnaCommand);
}
return string.Format("{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, dlnaCommand);
@@ -108,7 +117,7 @@ namespace MediaBrowser.Model.Dlna
item.VideoCodec ?? string.Empty,
item.AudioCodec ?? string.Empty,
item.AudioStreamIndex.HasValue ? StringHelper.ToStringCultureInvariant(item.AudioStreamIndex.Value) : string.Empty,
- item.SubtitleStreamIndex.HasValue ? StringHelper.ToStringCultureInvariant(item.SubtitleStreamIndex.Value) : string.Empty,
+ item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? StringHelper.ToStringCultureInvariant(item.SubtitleStreamIndex.Value) : string.Empty,
item.VideoBitrate.HasValue ? StringHelper.ToStringCultureInvariant(item.VideoBitrate.Value) : string.Empty,
item.AudioBitrate.HasValue ? StringHelper.ToStringCultureInvariant(item.AudioBitrate.Value) : string.Empty,
item.MaxAudioChannels.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxAudioChannels.Value) : string.Empty,
@@ -122,6 +131,56 @@ namespace MediaBrowser.Model.Dlna
return string.Format("Params={0}", string.Join(";", list.ToArray()));
}
+ public List<SubtitleStreamInfo> GetExternalSubtitles(string baseUrl)
+ {
+ if (string.IsNullOrEmpty(baseUrl))
+ {
+ throw new ArgumentNullException(baseUrl);
+ }
+
+ List<SubtitleStreamInfo> list = new List<SubtitleStreamInfo>();
+
+ if (SubtitleDeliveryMethod != SubtitleDeliveryMethod.External)
+ {
+ return list;
+ }
+
+ if (!SubtitleStreamIndex.HasValue)
+ {
+ return list;
+ }
+
+ // HLS will preserve timestamps so we can just grab the full subtitle stream
+ long startPositionTicks = StringHelper.EqualsIgnoreCase(Protocol, "hls")
+ ? 0
+ : StartPositionTicks;
+
+ string url = string.Format("{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}",
+ baseUrl,
+ ItemId,
+ MediaSourceId,
+ StringHelper.ToStringCultureInvariant(SubtitleStreamIndex.Value),
+ StringHelper.ToStringCultureInvariant(startPositionTicks),
+ SubtitleFormat);
+
+ foreach (MediaStream stream in MediaSource.MediaStreams)
+ {
+ if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value)
+ {
+ list.Add(new SubtitleStreamInfo
+ {
+ Url = url,
+ IsForced = stream.IsForced,
+ Language = stream.Language,
+ Name = stream.Language ?? "Unknown",
+ Format = SubtitleFormat
+ });
+ }
+ }
+
+ return list;
+ }
+
/// <summary>
/// Returns the audio stream that will be used
/// </summary>
@@ -135,7 +194,7 @@ namespace MediaBrowser.Model.Dlna
{
foreach (MediaStream i in MediaSource.MediaStreams)
{
- if (i.Index == AudioStreamIndex.Value && i.Type == MediaStreamType.Audio)
+ if (i.Index == AudioStreamIndex.Value && i.Type == MediaStreamType.Audio)
return i;
}
return null;
@@ -270,7 +329,7 @@ namespace MediaBrowser.Model.Dlna
return MaxAudioChannels.HasValue && !IsDirectStream
? (streamChannels.HasValue ? Math.Min(MaxAudioChannels.Value, streamChannels.Value) : MaxAudioChannels.Value)
- : stream == null ? null : streamChannels;
+ : streamChannels;
}
}
@@ -305,8 +364,14 @@ namespace MediaBrowser.Model.Dlna
{
int? totalBitrate = TargetTotalBitrate;
+ double totalSeconds = RunTimeTicks.Value;
+ // Convert to ms
+ totalSeconds /= 10000;
+ // Convert to seconds
+ totalSeconds /= 1000;
+
return totalBitrate.HasValue ?
- Convert.ToInt64(totalBitrate.Value * TimeSpan.FromTicks(RunTimeTicks.Value).TotalSeconds) :
+ Convert.ToInt64(totalBitrate.Value * totalSeconds) :
(long?)null;
}
@@ -375,11 +440,14 @@ namespace MediaBrowser.Model.Dlna
Height = videoStream.Height.Value
};
+ double? maxWidth = MaxWidth.HasValue ? (double)MaxWidth.Value : (double?)null;
+ double? maxHeight = MaxHeight.HasValue ? (double)MaxHeight.Value : (double?)null;
+
ImageSize newSize = DrawingUtils.Resize(size,
null,
null,
- MaxWidth,
- MaxHeight);
+ maxWidth,
+ maxHeight);
return Convert.ToInt32(newSize.Width);
}
@@ -402,11 +470,14 @@ namespace MediaBrowser.Model.Dlna
Height = videoStream.Height.Value
};
+ double? maxWidth = MaxWidth.HasValue ? (double)MaxWidth.Value : (double?)null;
+ double? maxHeight = MaxHeight.HasValue ? (double)MaxHeight.Value : (double?)null;
+
ImageSize newSize = DrawingUtils.Resize(size,
null,
null,
- MaxWidth,
- MaxHeight);
+ maxWidth,
+ maxHeight);
return Convert.ToInt32(newSize.Height);
}
@@ -415,4 +486,33 @@ namespace MediaBrowser.Model.Dlna
}
}
}
+
+ public enum SubtitleDeliveryMethod
+ {
+ /// <summary>
+ /// The encode
+ /// </summary>
+ Encode = 0,
+ /// <summary>
+ /// The embed
+ /// </summary>
+ Embed = 1,
+ /// <summary>
+ /// The external
+ /// </summary>
+ External = 2,
+ /// <summary>
+ /// The HLS
+ /// </summary>
+ Hls = 3
+ }
+
+ public class SubtitleStreamInfo
+ {
+ public string Url { get; set; }
+ public string Language { get; set; }
+ public string Name { get; set; }
+ public bool IsForced { get; set; }
+ public string Format { get; set; }
+ }
}
diff --git a/MediaBrowser.Model/Dlna/SubtitleProfile.cs b/MediaBrowser.Model/Dlna/SubtitleProfile.cs
new file mode 100644
index 000000000..d3989829c
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/SubtitleProfile.cs
@@ -0,0 +1,17 @@
+using System.Xml.Serialization;
+
+namespace MediaBrowser.Model.Dlna
+{
+ public class SubtitleProfile
+ {
+ [XmlAttribute("format")]
+ public string Format { get; set; }
+
+ [XmlAttribute("method")]
+ public SubtitleDeliveryMethod Method { get; set; }
+
+ [XmlAttribute("didlMode")]
+ public string DidlMode { get; set; }
+
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/TranscodingProfile.cs b/MediaBrowser.Model/Dlna/TranscodingProfile.cs
index 51f4bfe61..976f8e8d1 100644
--- a/MediaBrowser.Model/Dlna/TranscodingProfile.cs
+++ b/MediaBrowser.Model/Dlna/TranscodingProfile.cs
@@ -32,6 +32,9 @@ namespace MediaBrowser.Model.Dlna
[XmlAttribute("videoProfile")]
public string VideoProfile { get; set; }
+ [XmlAttribute("context")]
+ public EncodingContext Context { get; set; }
+
public List<string> GetAudioCodecs()
{
List<string> list = new List<string>();
@@ -42,4 +45,10 @@ namespace MediaBrowser.Model.Dlna
return list;
}
}
+
+ public enum EncodingContext
+ {
+ Streaming = 0,
+ Static = 1
+ }
}
diff --git a/MediaBrowser.Model/Dlna/VideoOptions.cs b/MediaBrowser.Model/Dlna/VideoOptions.cs
index 39a5ab1b1..041d2cd5d 100644
--- a/MediaBrowser.Model/Dlna/VideoOptions.cs
+++ b/MediaBrowser.Model/Dlna/VideoOptions.cs
@@ -7,11 +7,5 @@
{
public int? AudioStreamIndex { get; set; }
public int? SubtitleStreamIndex { get; set; }
- public int? MaxAudioTranscodingBitrate { get; set; }
-
- public VideoOptions()
- {
- MaxAudioTranscodingBitrate = 128000;
- }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Drawing/ImageOrientation.cs b/MediaBrowser.Model/Drawing/ImageOrientation.cs
new file mode 100644
index 000000000..c320a8224
--- /dev/null
+++ b/MediaBrowser.Model/Drawing/ImageOrientation.cs
@@ -0,0 +1,15 @@
+
+namespace MediaBrowser.Model.Drawing
+{
+ public enum ImageOrientation
+ {
+ TopLeft = 1,
+ TopRight = 2,
+ BottomRight = 3,
+ BottomLeft = 4,
+ LeftTop = 5,
+ RightTop = 6,
+ RightBottom = 7,
+ LeftBottom = 8,
+ }
+}
diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs
index 1d20080dd..ec5a26eee 100644
--- a/MediaBrowser.Model/Dto/BaseItemDto.cs
+++ b/MediaBrowser.Model/Dto/BaseItemDto.cs
@@ -1,12 +1,13 @@
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Drawing;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Library;
+using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.Serialization;
-using MediaBrowser.Model.Providers;
namespace MediaBrowser.Model.Dto
{
@@ -15,7 +16,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, INotifyPropertyChanged, IItemDto
+ public class BaseItemDto : IHasProviderIds, IHasPropertyChangedEvent, IItemDto
{
/// <summary>
/// Gets or sets the name.
@@ -30,6 +31,12 @@ namespace MediaBrowser.Model.Dto
public string Id { get; set; }
/// <summary>
+ /// Gets or sets the playlist item identifier.
+ /// </summary>
+ /// <value>The playlist item identifier.</value>
+ public string PlaylistItemId { get; set; }
+
+ /// <summary>
/// Gets or sets the date created.
/// </summary>
/// <value>The date created.</value>
@@ -53,6 +60,8 @@ namespace MediaBrowser.Model.Dto
public bool IsUnidentified { get; set; }
public int? AnimeSeriesIndex { get; set; }
+
+ public bool? SupportsSync { get; set; }
/// <summary>
/// Gets or sets the DVD season number.
@@ -220,6 +229,12 @@ namespace MediaBrowser.Model.Dto
public int? ProductionYear { get; set; }
/// <summary>
+ /// Gets or sets the recursive unplayed item count.
+ /// </summary>
+ /// <value>The recursive unplayed item count.</value>
+ public int? RecursiveUnplayedItemCount { get; set; }
+
+ /// <summary>
/// Gets or sets the season count.
/// </summary>
/// <value>The season count.</value>
@@ -340,24 +355,12 @@ namespace MediaBrowser.Model.Dto
public UserItemDataDto UserData { get; set; }
/// <summary>
- /// Gets or sets the played percentage.
- /// </summary>
- /// <value>The played percentage.</value>
- public double? PlayedPercentage { get; set; }
-
- /// <summary>
/// Gets or sets the recursive item count.
/// </summary>
/// <value>The recursive item count.</value>
public int? RecursiveItemCount { get; set; }
/// <summary>
- /// Gets or sets the recursive unplayed item count.
- /// </summary>
- /// <value>The recursive unplayed item count.</value>
- public int? RecursiveUnplayedItemCount { get; set; }
-
- /// <summary>
/// Gets or sets the child count.
/// </summary>
/// <value>The child count.</value>
@@ -524,6 +527,12 @@ namespace MediaBrowser.Model.Dto
}
/// <summary>
+ /// Gets or sets a value indicating whether [supports playlists].
+ /// </summary>
+ /// <value><c>true</c> if [supports playlists]; otherwise, <c>false</c>.</value>
+ public bool SupportsPlaylists { get; set; }
+
+ /// <summary>
/// Determines whether the specified type is type.
/// </summary>
/// <param name="type">The type.</param>
@@ -592,7 +601,19 @@ namespace MediaBrowser.Model.Dto
/// </summary>
/// <value>The parent thumb image tag.</value>
public string ParentThumbImageTag { get; set; }
-
+
+ /// <summary>
+ /// Gets or sets the parent primary image item identifier.
+ /// </summary>
+ /// <value>The parent primary image item identifier.</value>
+ public string ParentPrimaryImageItemId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the parent primary image tag.
+ /// </summary>
+ /// <value>The parent primary image tag.</value>
+ public string ParentPrimaryImageTag { get; set; }
+
/// <summary>
/// Gets or sets the chapters.
/// </summary>
@@ -618,12 +639,6 @@ namespace MediaBrowser.Model.Dto
public string MediaType { get; set; }
/// <summary>
- /// Gets or sets the overview HTML.
- /// </summary>
- /// <value>The overview HTML.</value>
- public string OverviewHtml { get; set; }
-
- /// <summary>
/// Gets or sets the end date.
/// </summary>
/// <value>The end date.</value>
@@ -707,6 +722,21 @@ namespace MediaBrowser.Model.Dto
/// <value><c>true</c> if [enable internet providers]; otherwise, <c>false</c>.</value>
public bool? LockData { get; set; }
+ public int? Width { get; set; }
+ public int? Height { get; set; }
+ public string CameraMake { get; set; }
+ public string CameraModel { get; set; }
+ public string Software { get; set; }
+ public double? ExposureTime { get; set; }
+ public double? FocalLength { get; set; }
+ public ImageOrientation? ImageOrientation { get; set; }
+ public double? Aperture { get; set; }
+ public double? ShutterSpeed { get; set; }
+ public double? Latitude { get; set; }
+ public double? Longitude { get; set; }
+ public double? Altitude { get; set; }
+ public int? IsoSpeedRating { get; set; }
+
/// <summary>
/// Gets a value indicating whether this instance can resume.
/// </summary>
@@ -844,7 +874,7 @@ namespace MediaBrowser.Model.Dto
[IgnoreDataMember]
public bool IsVideo
{
- get { return StringHelper.EqualsIgnoreCase(MediaType, Entities.MediaType.Video); }
+ get { return StringHelper.EqualsIgnoreCase(MediaType, MediaBrowser.Model.Entities.MediaType.Video); }
}
/// <summary>
@@ -854,7 +884,7 @@ namespace MediaBrowser.Model.Dto
[IgnoreDataMember]
public bool IsAudio
{
- get { return StringHelper.EqualsIgnoreCase(MediaType, Entities.MediaType.Audio); }
+ get { return StringHelper.EqualsIgnoreCase(MediaType, MediaBrowser.Model.Entities.MediaType.Audio); }
}
/// <summary>
@@ -864,7 +894,7 @@ namespace MediaBrowser.Model.Dto
[IgnoreDataMember]
public bool IsGame
{
- get { return StringHelper.EqualsIgnoreCase(MediaType, Entities.MediaType.Game); }
+ get { return StringHelper.EqualsIgnoreCase(MediaType, MediaBrowser.Model.Entities.MediaType.Game); }
}
/// <summary>
diff --git a/MediaBrowser.Model/Dto/BaseItemPerson.cs b/MediaBrowser.Model/Dto/BaseItemPerson.cs
index b8393f444..46485316e 100644
--- a/MediaBrowser.Model/Dto/BaseItemPerson.cs
+++ b/MediaBrowser.Model/Dto/BaseItemPerson.cs
@@ -1,6 +1,7 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.Serialization;
+using MediaBrowser.Model.Extensions;
namespace MediaBrowser.Model.Dto
{
@@ -8,7 +9,7 @@ namespace MediaBrowser.Model.Dto
/// This is used by the api to get information about a Person within a BaseItem
/// </summary>
[DebuggerDisplay("Name = {Name}, Role = {Role}, Type = {Type}")]
- public class BaseItemPerson : INotifyPropertyChanged
+ public class BaseItemPerson : IHasPropertyChangedEvent
{
/// <summary>
/// Gets or sets the name.
diff --git a/MediaBrowser.Model/Dto/ChapterInfoDto.cs b/MediaBrowser.Model/Dto/ChapterInfoDto.cs
index 09dd2d582..62b1839d4 100644
--- a/MediaBrowser.Model/Dto/ChapterInfoDto.cs
+++ b/MediaBrowser.Model/Dto/ChapterInfoDto.cs
@@ -1,7 +1,7 @@
-using System;
-using System.ComponentModel;
+using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.Serialization;
+using MediaBrowser.Model.Extensions;
namespace MediaBrowser.Model.Dto
{
@@ -9,7 +9,7 @@ namespace MediaBrowser.Model.Dto
/// Class ChapterInfo
/// </summary>
[DebuggerDisplay("Name = {Name}")]
- public class ChapterInfoDto : INotifyPropertyChanged
+ public class ChapterInfoDto : IHasPropertyChangedEvent
{
/// <summary>
/// Gets or sets the start position ticks.
diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs
index cf5518db0..46c51ed8b 100644
--- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs
+++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs
@@ -103,6 +103,19 @@ namespace MediaBrowser.Model.Dto
return null;
}
}
+
+ public MediaStream GetMediaStream(MediaStreamType type, int index)
+ {
+ foreach (MediaStream i in MediaStreams)
+ {
+ if (i.Type == type && i.Index == index)
+ {
+ return i;
+ }
+ }
+
+ return null;
+ }
}
public enum MediaSourceType
diff --git a/MediaBrowser.Model/Dto/StreamOptions.cs b/MediaBrowser.Model/Dto/StreamOptions.cs
deleted file mode 100644
index 9cf301270..000000000
--- a/MediaBrowser.Model/Dto/StreamOptions.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-namespace MediaBrowser.Model.Dto
-{
- /// <summary>
- /// Class StreamOptions
- /// </summary>
- public class StreamOptions
- {
- /// <summary>
- /// Gets or sets the audio bit rate.
- /// </summary>
- /// <value>The audio bit rate.</value>
- public int? AudioBitRate { get; set; }
-
- /// <summary>
- /// Gets or sets the audio codec.
- /// Omit to copy the original stream
- /// </summary>
- /// <value>The audio encoding format.</value>
- public string AudioCodec { get; set; }
-
- /// <summary>
- /// Gets or sets the item id.
- /// </summary>
- /// <value>The item id.</value>
- public string ItemId { get; set; }
-
- /// <summary>
- /// Gets or sets the max audio channels.
- /// </summary>
- /// <value>The max audio channels.</value>
- public int? MaxAudioChannels { get; set; }
-
- /// <summary>
- /// Gets or sets the max audio sample rate.
- /// </summary>
- /// <value>The max audio sample rate.</value>
- public int? MaxAudioSampleRate { get; set; }
-
- /// <summary>
- /// Gets or sets the start time ticks.
- /// </summary>
- /// <value>The start time ticks.</value>
- public long? StartTimeTicks { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether the original media should be served statically
- /// Only used with progressive streaming
- /// </summary>
- /// <value><c>true</c> if static; otherwise, <c>false</c>.</value>
- public bool? Static { get; set; }
-
- /// <summary>
- /// Gets or sets the output file extension.
- /// </summary>
- /// <value>The output file extension.</value>
- public string OutputFileExtension { get; set; }
-
- /// <summary>
- /// Gets or sets the device id.
- /// </summary>
- /// <value>The device id.</value>
- public string DeviceId { get; set; }
- }
-}
diff --git a/MediaBrowser.Model/Dto/StudioDto.cs b/MediaBrowser.Model/Dto/StudioDto.cs
index 4f21784fd..a0027cc4e 100644
--- a/MediaBrowser.Model/Dto/StudioDto.cs
+++ b/MediaBrowser.Model/Dto/StudioDto.cs
@@ -1,5 +1,4 @@
-using System;
-using System.ComponentModel;
+using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.Serialization;
@@ -18,6 +17,12 @@ namespace MediaBrowser.Model.Dto
public string Name { get; set; }
/// <summary>
+ /// Gets or sets the identifier.
+ /// </summary>
+ /// <value>The identifier.</value>
+ public string Id { get; set; }
+
+ /// <summary>
/// Gets or sets the primary image tag.
/// </summary>
/// <value>The primary image tag.</value>
diff --git a/MediaBrowser.Model/Dto/UserDto.cs b/MediaBrowser.Model/Dto/UserDto.cs
index c4a43c512..787f55ec0 100644
--- a/MediaBrowser.Model/Dto/UserDto.cs
+++ b/MediaBrowser.Model/Dto/UserDto.cs
@@ -3,6 +3,7 @@ using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.Serialization;
+using MediaBrowser.Model.Extensions;
namespace MediaBrowser.Model.Dto
{
@@ -10,7 +11,7 @@ namespace MediaBrowser.Model.Dto
/// Class UserDto
/// </summary>
[DebuggerDisplay("Name = {Name}, ID = {Id}, HasPassword = {HasPassword}")]
- public class UserDto : INotifyPropertyChanged, IItemDto
+ public class UserDto : IHasPropertyChangedEvent, IItemDto
{
/// <summary>
/// Gets or sets the name.
@@ -36,6 +37,8 @@ namespace MediaBrowser.Model.Dto
/// <value><c>true</c> if this instance has password; otherwise, <c>false</c>.</value>
public bool HasPassword { get; set; }
+ public bool HasConfiguredPassword { get; set; }
+
/// <summary>
/// Gets or sets the last login date.
/// </summary>
diff --git a/MediaBrowser.Model/Dto/UserItemDataDto.cs b/MediaBrowser.Model/Dto/UserItemDataDto.cs
index 8e8e7adbe..6ee9f1916 100644
--- a/MediaBrowser.Model/Dto/UserItemDataDto.cs
+++ b/MediaBrowser.Model/Dto/UserItemDataDto.cs
@@ -1,4 +1,5 @@
-using System;
+using MediaBrowser.Model.Extensions;
+using System;
using System.ComponentModel;
namespace MediaBrowser.Model.Dto
@@ -6,7 +7,7 @@ namespace MediaBrowser.Model.Dto
/// <summary>
/// Class UserItemDataDto
/// </summary>
- public class UserItemDataDto : INotifyPropertyChanged
+ public class UserItemDataDto : IHasPropertyChangedEvent
{
/// <summary>
/// Gets or sets the rating.
@@ -15,6 +16,18 @@ namespace MediaBrowser.Model.Dto
public double? Rating { get; set; }
/// <summary>
+ /// Gets or sets the played percentage.
+ /// </summary>
+ /// <value>The played percentage.</value>
+ public double? PlayedPercentage { get; set; }
+
+ /// <summary>
+ /// Gets or sets the unplayed item count.
+ /// </summary>
+ /// <value>The unplayed item count.</value>
+ public int? UnplayedItemCount { get; set; }
+
+ /// <summary>
/// Gets or sets the playback position ticks.
/// </summary>
/// <value>The playback position ticks.</value>
diff --git a/MediaBrowser.Model/Dto/VideoStreamOptions.cs b/MediaBrowser.Model/Dto/VideoStreamOptions.cs
deleted file mode 100644
index 73dc70018..000000000
--- a/MediaBrowser.Model/Dto/VideoStreamOptions.cs
+++ /dev/null
@@ -1,99 +0,0 @@
-namespace MediaBrowser.Model.Dto
-{
- /// <summary>
- /// Class VideoStreamOptions
- /// </summary>
- public class VideoStreamOptions : StreamOptions
- {
- /// <summary>
- /// Gets or sets the video codec.
- /// Omit to copy
- /// </summary>
- /// <value>The video codec.</value>
- public string VideoCodec { get; set; }
-
- /// <summary>
- /// Gets or sets the video bit rate.
- /// </summary>
- /// <value>The video bit rate.</value>
- public int? VideoBitRate { 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 width of the max.
- /// </summary>
- /// <value>The width of the max.</value>
- public int? MaxWidth { get; set; }
-
- /// <summary>
- /// Gets or sets the height of the max.
- /// </summary>
- /// <value>The height of the max.</value>
- public int? MaxHeight { get; set; }
-
- /// <summary>
- /// Gets or sets the frame rate.
- /// </summary>
- /// <value>The frame rate.</value>
- public double? FrameRate { get; set; }
-
- /// <summary>
- /// Gets or sets the index of the audio stream.
- /// </summary>
- /// <value>The index of the audio stream.</value>
- public int? AudioStreamIndex { get; set; }
-
- /// <summary>
- /// Gets or sets the index of the video stream.
- /// </summary>
- /// <value>The index of the video stream.</value>
- public int? VideoStreamIndex { get; set; }
-
- /// <summary>
- /// Gets or sets the index of the subtitle stream.
- /// </summary>
- /// <value>The index of the subtitle stream.</value>
- public int? SubtitleStreamIndex { get; set; }
-
- /// <summary>
- /// Gets or sets the profile.
- /// </summary>
- /// <value>The profile.</value>
- public string Profile { get; set; }
-
- /// <summary>
- /// Gets or sets the level.
- /// </summary>
- /// <value>The level.</value>
- public string Level { get; set; }
-
- /// <summary>
- /// Gets or sets the baseline stream audio bit rate.
- /// </summary>
- /// <value>The baseline stream audio bit rate.</value>
- public int? BaselineStreamAudioBitRate { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [append baseline stream].
- /// </summary>
- /// <value><c>true</c> if [append baseline stream]; otherwise, <c>false</c>.</value>
- public bool AppendBaselineStream { get; set; }
-
- /// <summary>
- /// Gets or sets the time stamp offset ms. Only used with HLS.
- /// </summary>
- /// <value>The time stamp offset ms.</value>
- public int? TimeStampOffsetMs { get; set; }
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Model/Entities/CollectionType.cs b/MediaBrowser.Model/Entities/CollectionType.cs
index 1aae2a89c..a97cc3b12 100644
--- a/MediaBrowser.Model/Entities/CollectionType.cs
+++ b/MediaBrowser.Model/Entities/CollectionType.cs
@@ -1,5 +1,4 @@
-
-namespace MediaBrowser.Model.Entities
+namespace MediaBrowser.Model.Entities
{
public static class CollectionType
{
@@ -24,5 +23,10 @@ namespace MediaBrowser.Model.Entities
public const string Games = "games";
public const string Channels = "channels";
public const string LiveTv = "livetv";
+ public const string Playlists = "playlists";
+ public const string Folders = "folders";
+
+ public const string LiveTvChannels = "LiveTvChannels";
+ public const string LiveTvRecordingGroups = "LiveTvRecordingGroups";
}
}
diff --git a/MediaBrowser.Model/Entities/DisplayPreferences.cs b/MediaBrowser.Model/Entities/DisplayPreferences.cs
index 56a2c6194..cac703c91 100644
--- a/MediaBrowser.Model/Entities/DisplayPreferences.cs
+++ b/MediaBrowser.Model/Entities/DisplayPreferences.cs
@@ -2,13 +2,14 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
+using MediaBrowser.Model.Extensions;
namespace MediaBrowser.Model.Entities
{
/// <summary>
/// Defines the display preferences for any item that supports them (usually Folders)
/// </summary>
- public class DisplayPreferences : INotifyPropertyChanged
+ public class DisplayPreferences : IHasPropertyChangedEvent
{
/// <summary>
/// Occurs when [property changed].
diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs
index 7be8a64b7..f525ae5e0 100644
--- a/MediaBrowser.Model/Entities/MediaStream.cs
+++ b/MediaBrowser.Model/Entities/MediaStream.cs
@@ -1,6 +1,5 @@
using MediaBrowser.Model.Extensions;
using System.Diagnostics;
-using System.Runtime.Serialization;
namespace MediaBrowser.Model.Entities
{
@@ -136,10 +135,13 @@ namespace MediaBrowser.Model.Entities
{
if (Type != MediaStreamType.Subtitle) return false;
- var codec = Codec ?? string.Empty;
+ string codec = Codec ?? string.Empty;
+
+ // sub = external .sub file
return StringHelper.IndexOfIgnoreCase(codec, "pgs") == -1 &&
- StringHelper.IndexOfIgnoreCase(codec, "dvd") == -1;
+ StringHelper.IndexOfIgnoreCase(codec, "dvd") == -1 &&
+ !StringHelper.EqualsIgnoreCase(codec, "sub");
}
}
diff --git a/MediaBrowser.Model/Events/GenericEventArgs.cs b/MediaBrowser.Model/Events/GenericEventArgs.cs
index 5a83419e1..3c558577a 100644
--- a/MediaBrowser.Model/Events/GenericEventArgs.cs
+++ b/MediaBrowser.Model/Events/GenericEventArgs.cs
@@ -13,5 +13,21 @@ namespace MediaBrowser.Model.Events
/// </summary>
/// <value>The argument.</value>
public T Argument { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="GenericEventArgs{T}"/> class.
+ /// </summary>
+ /// <param name="arg">The argument.</param>
+ public GenericEventArgs(T arg)
+ {
+ Argument = arg;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="GenericEventArgs{T}"/> class.
+ /// </summary>
+ public GenericEventArgs()
+ {
+ }
}
}
diff --git a/MediaBrowser.Model/Extensions/IHasPropertyChangedEvent.cs b/MediaBrowser.Model/Extensions/IHasPropertyChangedEvent.cs
new file mode 100644
index 000000000..c87550620
--- /dev/null
+++ b/MediaBrowser.Model/Extensions/IHasPropertyChangedEvent.cs
@@ -0,0 +1,8 @@
+using System.ComponentModel;
+
+namespace MediaBrowser.Model.Extensions
+{
+ public interface IHasPropertyChangedEvent : INotifyPropertyChanged
+ {
+ }
+}
diff --git a/MediaBrowser.Model/Extensions/ListHelper.cs b/MediaBrowser.Model/Extensions/ListHelper.cs
index 6c5d471c0..741f07469 100644
--- a/MediaBrowser.Model/Extensions/ListHelper.cs
+++ b/MediaBrowser.Model/Extensions/ListHelper.cs
@@ -6,7 +6,7 @@ namespace MediaBrowser.Model.Extensions
{
public static class ListHelper
{
- public static bool ContainsIgnoreCase(IEnumerable<string> list, string value)
+ public static bool ContainsIgnoreCase(List<string> list, string value)
{
if (value == null)
{
@@ -15,5 +15,31 @@ namespace MediaBrowser.Model.Extensions
return list.Contains(value, StringComparer.OrdinalIgnoreCase);
}
+ public static bool ContainsIgnoreCase(string[] list, string value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+
+ return list.Contains(value, StringComparer.OrdinalIgnoreCase);
+ }
+
+ public static bool ContainsAnyIgnoreCase(string[] list, string[] values)
+ {
+ if (values == null)
+ {
+ throw new ArgumentNullException("values");
+ }
+
+ foreach (string val in values)
+ {
+ if (ContainsIgnoreCase(list, val))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
}
}
diff --git a/MediaBrowser.Model/Extensions/StringHelper.cs b/MediaBrowser.Model/Extensions/StringHelper.cs
index 1c086655f..206723467 100644
--- a/MediaBrowser.Model/Extensions/StringHelper.cs
+++ b/MediaBrowser.Model/Extensions/StringHelper.cs
@@ -1,5 +1,6 @@
using System;
using System.Globalization;
+using System.Text.RegularExpressions;
namespace MediaBrowser.Model.Extensions
{
@@ -59,5 +60,39 @@ namespace MediaBrowser.Model.Extensions
{
return val.ToString(CultureInfo.InvariantCulture);
}
+
+ /// <summary>
+ /// Trims the start.
+ /// </summary>
+ /// <param name="str">The string.</param>
+ /// <param name="c">The c.</param>
+ /// <returns>System.String.</returns>
+ public static string TrimStart(string str, char c)
+ {
+ return str.TrimStart(c);
+ }
+
+ /// <summary>
+ /// Splits the specified string.
+ /// </summary>
+ /// <param name="str">The string.</param>
+ /// <param name="term">The term.</param>
+ /// <returns>System.String[].</returns>
+ public static string[] RegexSplit(string str, string term)
+ {
+ return Regex.Split(str, term, RegexOptions.IgnoreCase);
+ }
+
+ /// <summary>
+ /// Splits the specified string.
+ /// </summary>
+ /// <param name="str">The string.</param>
+ /// <param name="term">The term.</param>
+ /// <param name="limit">The limit.</param>
+ /// <returns>System.String[].</returns>
+ public static string[] RegexSplit(string str, string term, int limit)
+ {
+ return new Regex(term).Split(str, limit);
+ }
}
}
diff --git a/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs b/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs
new file mode 100644
index 000000000..ae701ea68
--- /dev/null
+++ b/MediaBrowser.Model/FileOrganization/AutoOrganizeOptions.cs
@@ -0,0 +1,17 @@
+
+namespace MediaBrowser.Model.FileOrganization
+{
+ public class AutoOrganizeOptions
+ {
+ /// <summary>
+ /// Gets or sets the tv options.
+ /// </summary>
+ /// <value>The tv options.</value>
+ public TvFileOrganizationOptions TvOptions { get; set; }
+
+ public AutoOrganizeOptions()
+ {
+ TvOptions = new TvFileOrganizationOptions();
+ }
+ }
+}
diff --git a/MediaBrowser.Model/Configuration/TvFileOrganizationOptions.cs b/MediaBrowser.Model/FileOrganization/TvFileOrganizationOptions.cs
index fe32d4a80..973ecf6e7 100644
--- a/MediaBrowser.Model/Configuration/TvFileOrganizationOptions.cs
+++ b/MediaBrowser.Model/FileOrganization/TvFileOrganizationOptions.cs
@@ -1,5 +1,5 @@

-namespace MediaBrowser.Model.Configuration
+namespace MediaBrowser.Model.FileOrganization
{
public class TvFileOrganizationOptions
{
diff --git a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs
index 2d88215bb..27001f721 100644
--- a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs
@@ -1,9 +1,10 @@
using System;
using System.ComponentModel;
+using MediaBrowser.Model.Extensions;
namespace MediaBrowser.Model.LiveTv
{
- public class BaseTimerInfoDto : INotifyPropertyChanged
+ public class BaseTimerInfoDto : IHasPropertyChangedEvent
{
/// <summary>
/// Occurs when a property value changes.
diff --git a/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs b/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs
index a48006755..351378eea 100644
--- a/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Library;
using System.Collections.Generic;
using System.ComponentModel;
@@ -12,7 +13,7 @@ namespace MediaBrowser.Model.LiveTv
/// Class ChannelInfoDto
/// </summary>
[DebuggerDisplay("Name = {Name}, Number = {Number}")]
- public class ChannelInfoDto : INotifyPropertyChanged, IItemDto
+ public class ChannelInfoDto : IHasPropertyChangedEvent, IItemDto
{
/// <summary>
/// Gets or sets the name.
diff --git a/MediaBrowser.Model/Configuration/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs
index 575f0b863..05fdc00b1 100644
--- a/MediaBrowser.Model/Configuration/LiveTvOptions.cs
+++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs
@@ -1,4 +1,4 @@
-namespace MediaBrowser.Model.Configuration
+namespace MediaBrowser.Model.LiveTv
{
public class LiveTvOptions
{
diff --git a/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs b/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs
index 644af027d..50881f72f 100644
--- a/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs
@@ -5,12 +5,13 @@ using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
+using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Library;
namespace MediaBrowser.Model.LiveTv
{
[DebuggerDisplay("Name = {Name}, StartTime = {StartDate}, EndTime = {EndDate}")]
- public class ProgramInfoDto : INotifyPropertyChanged, IItemDto
+ public class ProgramInfoDto : IHasPropertyChangedEvent, IItemDto
{
/// <summary>
/// Id of the program.
diff --git a/MediaBrowser.Model/LiveTv/RecordingGroupDto.cs b/MediaBrowser.Model/LiveTv/RecordingGroupDto.cs
index db96d56b4..07c5ac32f 100644
--- a/MediaBrowser.Model/LiveTv/RecordingGroupDto.cs
+++ b/MediaBrowser.Model/LiveTv/RecordingGroupDto.cs
@@ -1,5 +1,6 @@
using System.ComponentModel;
using System.Diagnostics;
+using MediaBrowser.Model.Extensions;
namespace MediaBrowser.Model.LiveTv
{
@@ -7,7 +8,7 @@ namespace MediaBrowser.Model.LiveTv
/// Class RecordingGroupDto.
/// </summary>
[DebuggerDisplay("Name = {Name}, Count = {RecordingCount}")]
- public class RecordingGroupDto : INotifyPropertyChanged
+ public class RecordingGroupDto : IHasPropertyChangedEvent
{
/// <summary>
/// Gets or sets the name.
diff --git a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs
index 58bca06bd..43ae9681e 100644
--- a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Library;
using System;
using System.Collections.Generic;
@@ -10,7 +11,7 @@ using System.Runtime.Serialization;
namespace MediaBrowser.Model.LiveTv
{
[DebuggerDisplay("Name = {Name}, ChannelName = {ChannelName}")]
- public class RecordingInfoDto : INotifyPropertyChanged, IItemDto
+ public class RecordingInfoDto : IHasPropertyChangedEvent, IItemDto
{
/// <summary>
/// Id of the recording.
diff --git a/MediaBrowser.Model/Logging/ILogger.cs b/MediaBrowser.Model/Logging/ILogger.cs
index fd704a254..be9d6fc50 100644
--- a/MediaBrowser.Model/Logging/ILogger.cs
+++ b/MediaBrowser.Model/Logging/ILogger.cs
@@ -52,14 +52,6 @@ namespace MediaBrowser.Model.Logging
void FatalException(string message, Exception exception, params object[] paramList);
/// <summary>
- /// Logs the specified severity.
- /// </summary>
- /// <param name="severity">The severity.</param>
- /// <param name="message">The message.</param>
- /// <param name="paramList">The param list.</param>
- void Log(LogSeverity severity, string message, params object[] paramList);
-
- /// <summary>
/// Logs the exception.
/// </summary>
/// <param name="message">The message.</param>
@@ -74,5 +66,13 @@ namespace MediaBrowser.Model.Logging
/// <param name="severity">The severity.</param>
/// <param name="additionalContent">Content of the additional.</param>
void LogMultiline(string message, LogSeverity severity, StringBuilder additionalContent);
+
+ /// <summary>
+ /// Logs the specified severity.
+ /// </summary>
+ /// <param name="severity">The severity.</param>
+ /// <param name="message">The message.</param>
+ /// <param name="paramList">The parameter list.</param>
+ void Log(LogSeverity severity, string message, params object[] paramList);
}
}
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index 9efa63283..a760cba05 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -59,12 +59,15 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
+ <Compile Include="Activity\ActivityLogEntry.cs" />
<Compile Include="ApiClient\HttpResponseEventArgs.cs" />
<Compile Include="ApiClient\IApiClient.cs" />
<Compile Include="ApiClient\ApiClientExtensions.cs" />
<Compile Include="ApiClient\IServerEvents.cs" />
<Compile Include="ApiClient\GeneralCommandEventArgs.cs" />
+ <Compile Include="ApiClient\ServerDiscoveryInfo.cs" />
<Compile Include="ApiClient\SessionUpdatesEventArgs.cs" />
+ <Compile Include="Branding\BrandingOptions.cs" />
<Compile Include="Channels\ChannelFeatures.cs" />
<Compile Include="Channels\ChannelInfo.cs" />
<Compile Include="Channels\ChannelItemQuery.cs" />
@@ -73,24 +76,34 @@
<Compile Include="Channels\ChannelQuery.cs" />
<Compile Include="Chapters\RemoteChapterInfo.cs" />
<Compile Include="Chapters\RemoteChapterResult.cs" />
- <Compile Include="Configuration\TvFileOrganizationOptions.cs" />
+ <Compile Include="Collections\CollectionCreationResult.cs" />
+ <Compile Include="Configuration\ChannelOptions.cs" />
+ <Compile Include="Configuration\ChapterOptions.cs" />
+ <Compile Include="Configuration\XbmcMetadataOptions.cs" />
+ <Compile Include="Configuration\SubtitlePlaybackMode.cs" />
+ <Compile Include="Drawing\ImageOrientation.cs" />
+ <Compile Include="FileOrganization\AutoOrganizeOptions.cs" />
+ <Compile Include="FileOrganization\TvFileOrganizationOptions.cs" />
<Compile Include="Configuration\BaseApplicationConfiguration.cs" />
<Compile Include="Configuration\DlnaOptions.cs" />
<Compile Include="Configuration\EncodingQuality.cs" />
<Compile Include="Configuration\ImageOption.cs" />
<Compile Include="Configuration\ImageSavingConvention.cs" />
- <Compile Include="Configuration\LiveTvOptions.cs" />
+ <Compile Include="LiveTv\LiveTvOptions.cs" />
<Compile Include="Configuration\MetadataPlugin.cs" />
<Compile Include="Configuration\MetadataOptions.cs" />
<Compile Include="Configuration\MetadataPluginSummary.cs" />
<Compile Include="Configuration\MetadataPluginType.cs" />
- <Compile Include="Configuration\NotificationOption.cs" />
- <Compile Include="Configuration\NotificationOptions.cs" />
- <Compile Include="Configuration\NotificationType.cs" />
+ <Compile Include="Dlna\SubtitleProfile.cs" />
+ <Compile Include="Notifications\NotificationOption.cs" />
+ <Compile Include="Notifications\NotificationOptions.cs" />
+ <Compile Include="Notifications\NotificationType.cs" />
<Compile Include="Configuration\PathSubstitution.cs" />
- <Compile Include="Configuration\SendToUserType.cs" />
+ <Compile Include="Notifications\SendToUserType.cs" />
<Compile Include="Configuration\ServerConfiguration.cs" />
- <Compile Include="Configuration\SubtitleOptions.cs" />
+ <Compile Include="Playlists\PlaylistCreationRequest.cs" />
+ <Compile Include="Playlists\PlaylistItemQuery.cs" />
+ <Compile Include="Providers\SubtitleOptions.cs" />
<Compile Include="Configuration\UnratedItem.cs" />
<Compile Include="Dlna\AudioOptions.cs" />
<Compile Include="Dlna\CodecProfile.cs" />
@@ -106,8 +119,6 @@
<Compile Include="Dlna\DlnaFlags.cs" />
<Compile Include="Dlna\DlnaMaps.cs" />
<Compile Include="Dlna\DlnaProfileType.cs" />
- <Compile Include="Dlna\EventSubscription.cs" />
- <Compile Include="Dlna\Filter.cs" />
<Compile Include="Dlna\HeaderMatchType.cs" />
<Compile Include="Dlna\HttpHeaderInfo.cs" />
<Compile Include="Dlna\MediaFormatProfile.cs" />
@@ -141,7 +152,6 @@
<Compile Include="Dto\MediaSourceInfo.cs" />
<Compile Include="Dto\RecommendationType.cs" />
<Compile Include="Dto\SubtitleDownloadOptions.cs" />
- <Compile Include="Dto\VideoStreamOptions.cs" />
<Compile Include="Entities\IsoType.cs" />
<Compile Include="Entities\MediaInfo.cs" />
<Compile Include="Entities\MediaStreamType.cs" />
@@ -152,6 +162,7 @@
<Compile Include="Entities\VideoSize.cs" />
<Compile Include="Events\GenericEventArgs.cs" />
<Compile Include="Extensions\DoubleHelper.cs" />
+ <Compile Include="Extensions\IHasPropertyChangedEvent.cs" />
<Compile Include="Extensions\IntHelper.cs" />
<Compile Include="Extensions\ListHelper.cs" />
<Compile Include="Extensions\StringHelper.cs" />
@@ -197,6 +208,7 @@
<Compile Include="Notifications\NotificationRequest.cs" />
<Compile Include="Notifications\NotificationServiceInfo.cs" />
<Compile Include="Notifications\NotificationTypeInfo.cs" />
+ <Compile Include="Playlists\PlaylistCreationResult.cs" />
<Compile Include="Providers\ExternalIdInfo.cs" />
<Compile Include="Providers\ExternalUrl.cs" />
<Compile Include="Providers\ImageProviderInfo.cs" />
@@ -233,6 +245,7 @@
<Compile Include="Querying\ItemCountsQuery.cs" />
<Compile Include="Querying\ItemsByNameQuery.cs" />
<Compile Include="Entities\BaseItemInfo.cs" />
+ <Compile Include="Querying\LatestItemsQuery.cs" />
<Compile Include="Querying\NextUpQuery.cs" />
<Compile Include="Querying\QueryResult.cs" />
<Compile Include="Querying\SeasonQuery.cs" />
@@ -271,7 +284,6 @@
<Compile Include="Querying\ItemQuery.cs" />
<Compile Include="Entities\LibraryUpdateInfo.cs" />
<Compile Include="Entities\ParentalRating.cs" />
- <Compile Include="Dto\StreamOptions.cs" />
<Compile Include="Entities\VirtualFolderInfo.cs" />
<Compile Include="IO\IZipClient.cs" />
<Compile Include="Logging\ILogger.cs" />
@@ -291,6 +303,15 @@
<Compile Include="Session\SessionInfoDto.cs" />
<Compile Include="Session\SessionUserInfo.cs" />
<Compile Include="Session\UserDataChangeInfo.cs" />
+ <Compile Include="Sync\SyncJob.cs" />
+ <Compile Include="Sync\SyncJobCreationResult.cs" />
+ <Compile Include="Sync\SyncJobItem.cs" />
+ <Compile Include="Sync\SyncJobQuery.cs" />
+ <Compile Include="Sync\SyncJobRequest.cs" />
+ <Compile Include="Sync\SyncJobStatus.cs" />
+ <Compile Include="Sync\SyncQuality.cs" />
+ <Compile Include="Sync\SyncTarget.cs" />
+ <Compile Include="System\LogFile.cs" />
<Compile Include="Themes\AppTheme.cs" />
<Compile Include="Themes\AppThemeInfo.cs" />
<Compile Include="Themes\ThemeImage.cs" />
@@ -351,7 +372,7 @@
xcopy "$(TargetPath)" "$(SolutionDir)\Nuget\dlls\net45\" /y /d /r /i
)</PostBuildEvent>
</PropertyGroup>
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" />
<Import Project="Fody.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.Model/MediaInfo/SubtitleFormat.cs b/MediaBrowser.Model/MediaInfo/SubtitleFormat.cs
index 30eb50825..60b0bb54d 100644
--- a/MediaBrowser.Model/MediaInfo/SubtitleFormat.cs
+++ b/MediaBrowser.Model/MediaInfo/SubtitleFormat.cs
@@ -7,5 +7,7 @@
public const string ASS = "ass";
public const string VTT = "vtt";
public const string SUB = "sub";
+ public const string SMI = "smi";
+ public const string TTML = "ttml";
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Notifications/Notification.cs b/MediaBrowser.Model/Notifications/Notification.cs
index 731c3d303..5439b838d 100644
--- a/MediaBrowser.Model/Notifications/Notification.cs
+++ b/MediaBrowser.Model/Notifications/Notification.cs
@@ -19,10 +19,5 @@ namespace MediaBrowser.Model.Notifications
public string Url { get; set; }
public NotificationLevel Level { get; set; }
-
- public Notification()
- {
- Date = DateTime.UtcNow;
- }
}
}
diff --git a/MediaBrowser.Model/Configuration/NotificationOption.cs b/MediaBrowser.Model/Notifications/NotificationOption.cs
index 5fcf3550c..09f7072dd 100644
--- a/MediaBrowser.Model/Configuration/NotificationOption.cs
+++ b/MediaBrowser.Model/Notifications/NotificationOption.cs
@@ -1,4 +1,6 @@
-namespace MediaBrowser.Model.Configuration
+using MediaBrowser.Model.Configuration;
+
+namespace MediaBrowser.Model.Notifications
{
public class NotificationOption
{
diff --git a/MediaBrowser.Model/Configuration/NotificationOptions.cs b/MediaBrowser.Model/Notifications/NotificationOptions.cs
index 5aac1652f..7d80f3177 100644
--- a/MediaBrowser.Model/Configuration/NotificationOptions.cs
+++ b/MediaBrowser.Model/Notifications/NotificationOptions.cs
@@ -1,8 +1,7 @@
-using System;
-using System.Linq;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Extensions;
-namespace MediaBrowser.Model.Configuration
+namespace MediaBrowser.Model.Notifications
{
public class NotificationOptions
{
@@ -90,7 +89,7 @@ namespace MediaBrowser.Model.Configuration
NotificationOption opt = GetOptions(notificationType);
return opt == null ||
- !opt.DisabledServices.Contains(service, StringComparer.OrdinalIgnoreCase);
+ !ListHelper.ContainsIgnoreCase(opt.DisabledServices, service);
}
public bool IsEnabledToMonitorUser(string type, string userId)
@@ -98,7 +97,7 @@ namespace MediaBrowser.Model.Configuration
NotificationOption opt = GetOptions(type);
return opt != null && opt.Enabled &&
- !opt.DisabledMonitorUsers.Contains(userId, StringComparer.OrdinalIgnoreCase);
+ !ListHelper.ContainsIgnoreCase(opt.DisabledMonitorUsers, userId);
}
public bool IsEnabledToSendToUser(string type, string userId, UserConfiguration userConfig)
@@ -117,7 +116,7 @@ namespace MediaBrowser.Model.Configuration
return true;
}
- return opt.SendToUsers.Contains(userId, StringComparer.OrdinalIgnoreCase);
+ return ListHelper.ContainsIgnoreCase(opt.SendToUsers, userId);
}
return false;
diff --git a/MediaBrowser.Model/Notifications/NotificationRequest.cs b/MediaBrowser.Model/Notifications/NotificationRequest.cs
index d47e9c4f2..3cd463422 100644
--- a/MediaBrowser.Model/Notifications/NotificationRequest.cs
+++ b/MediaBrowser.Model/Notifications/NotificationRequest.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Model.Notifications
{
@@ -27,16 +26,12 @@ namespace MediaBrowser.Model.Notifications
public SendToUserType? SendToUserMode { get; set; }
- public List<string> ExcludeUserIds { get; set; }
-
public NotificationRequest()
{
UserIds = new List<string>();
Date = DateTime.UtcNow;
- Variables = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
-
- ExcludeUserIds = new List<string>();
+ Variables = new Dictionary<string, string>();
}
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/NotificationType.cs b/MediaBrowser.Model/Notifications/NotificationType.cs
index d8043b0e1..34e4d32b5 100644
--- a/MediaBrowser.Model/Configuration/NotificationType.cs
+++ b/MediaBrowser.Model/Notifications/NotificationType.cs
@@ -1,4 +1,4 @@
-namespace MediaBrowser.Model.Configuration
+namespace MediaBrowser.Model.Notifications
{
public enum NotificationType
{
diff --git a/MediaBrowser.Model/Configuration/SendToUserType.cs b/MediaBrowser.Model/Notifications/SendToUserType.cs
index a2eac4c2d..1998d3102 100644
--- a/MediaBrowser.Model/Configuration/SendToUserType.cs
+++ b/MediaBrowser.Model/Notifications/SendToUserType.cs
@@ -1,4 +1,4 @@
-namespace MediaBrowser.Model.Configuration
+namespace MediaBrowser.Model.Notifications
{
public enum SendToUserType
{
diff --git a/MediaBrowser.Model/Playlists/PlaylistCreationRequest.cs b/MediaBrowser.Model/Playlists/PlaylistCreationRequest.cs
new file mode 100644
index 000000000..63deb19dc
--- /dev/null
+++ b/MediaBrowser.Model/Playlists/PlaylistCreationRequest.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.Playlists
+{
+ public class PlaylistCreationRequest
+ {
+ public string Name { get; set; }
+
+ public List<string> ItemIdList { get; set; }
+
+ public string MediaType { get; set; }
+
+ public string UserId { get; set; }
+
+ public PlaylistCreationRequest()
+ {
+ ItemIdList = new List<string>();
+ }
+ }
+}
diff --git a/MediaBrowser.Model/Playlists/PlaylistCreationResult.cs b/MediaBrowser.Model/Playlists/PlaylistCreationResult.cs
new file mode 100644
index 000000000..bbab8a18d
--- /dev/null
+++ b/MediaBrowser.Model/Playlists/PlaylistCreationResult.cs
@@ -0,0 +1,8 @@
+
+namespace MediaBrowser.Model.Playlists
+{
+ public class PlaylistCreationResult
+ {
+ public string Id { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Playlists/PlaylistItemQuery.cs b/MediaBrowser.Model/Playlists/PlaylistItemQuery.cs
new file mode 100644
index 000000000..0f6a0c8c5
--- /dev/null
+++ b/MediaBrowser.Model/Playlists/PlaylistItemQuery.cs
@@ -0,0 +1,37 @@
+using MediaBrowser.Model.Querying;
+
+namespace MediaBrowser.Model.Playlists
+{
+ public class PlaylistItemQuery
+ {
+ /// <summary>
+ /// Gets or sets the identifier.
+ /// </summary>
+ /// <value>The identifier.</value>
+ public string Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the user identifier.
+ /// </summary>
+ /// <value>The user identifier.</value>
+ public string UserId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the start index.
+ /// </summary>
+ /// <value>The start index.</value>
+ public int? StartIndex { get; set; }
+
+ /// <summary>
+ /// Gets or sets the limit.
+ /// </summary>
+ /// <value>The limit.</value>
+ public int? Limit { get; set; }
+
+ /// <summary>
+ /// Gets or sets the fields.
+ /// </summary>
+ /// <value>The fields.</value>
+ public ItemFields[] Fields { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Configuration/SubtitleOptions.cs b/MediaBrowser.Model/Providers/SubtitleOptions.cs
index 96e04e511..84f01e0b7 100644
--- a/MediaBrowser.Model/Configuration/SubtitleOptions.cs
+++ b/MediaBrowser.Model/Providers/SubtitleOptions.cs
@@ -1,4 +1,4 @@
-namespace MediaBrowser.Model.Configuration
+namespace MediaBrowser.Model.Providers
{
public class SubtitleOptions
{
@@ -10,6 +10,7 @@ namespace MediaBrowser.Model.Configuration
public string OpenSubtitlesUsername { get; set; }
public string OpenSubtitlesPasswordHash { get; set; }
+ public bool IsOpenSubtitleVipAccount { get; set; }
public SubtitleOptions()
{
diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs
index 790638446..9ceca311c 100644
--- a/MediaBrowser.Model/Querying/ItemFields.cs
+++ b/MediaBrowser.Model/Querying/ItemFields.cs
@@ -157,6 +157,11 @@ namespace MediaBrowser.Model.Querying
Studios,
/// <summary>
+ /// The synchronize information
+ /// </summary>
+ SyncInfo,
+
+ /// <summary>
/// The taglines of the item
/// </summary>
Taglines,
diff --git a/MediaBrowser.Model/Querying/LatestItemsQuery.cs b/MediaBrowser.Model/Querying/LatestItemsQuery.cs
new file mode 100644
index 000000000..ccf5ab087
--- /dev/null
+++ b/MediaBrowser.Model/Querying/LatestItemsQuery.cs
@@ -0,0 +1,54 @@
+
+namespace MediaBrowser.Model.Querying
+{
+ public class LatestItemsQuery
+ {
+ /// <summary>
+ /// The user to localize search results for
+ /// </summary>
+ /// <value>The user id.</value>
+ public string UserId { get; set; }
+
+ /// <summary>
+ /// Specify this to localize the search to a specific item or folder. Omit to use the root.
+ /// </summary>
+ /// <value>The parent id.</value>
+ public string ParentId { get; set; }
+
+ /// <summary>
+ /// Skips over a given number of items within the results. Use for paging.
+ /// </summary>
+ /// <value>The start index.</value>
+ public int? StartIndex { get; set; }
+
+ /// <summary>
+ /// The maximum number of items to return
+ /// </summary>
+ /// <value>The limit.</value>
+ public int? Limit { get; set; }
+
+ /// <summary>
+ /// Fields to return within the items, in addition to basic information
+ /// </summary>
+ /// <value>The fields.</value>
+ public ItemFields[] Fields { get; set; }
+
+ /// <summary>
+ /// Gets or sets the include item types.
+ /// </summary>
+ /// <value>The include item types.</value>
+ public string[] IncludeItemTypes { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is played.
+ /// </summary>
+ /// <value><c>null</c> if [is played] contains no value, <c>true</c> if [is played]; otherwise, <c>false</c>.</value>
+ public bool? IsPlayed { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether [group items].
+ /// </summary>
+ /// <value><c>true</c> if [group items]; otherwise, <c>false</c>.</value>
+ public bool GroupItems { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Serialization/IJsonSerializer.cs b/MediaBrowser.Model/Serialization/IJsonSerializer.cs
index 77a14c1e5..cd1e550e5 100644
--- a/MediaBrowser.Model/Serialization/IJsonSerializer.cs
+++ b/MediaBrowser.Model/Serialization/IJsonSerializer.cs
@@ -83,13 +83,5 @@ namespace MediaBrowser.Model.Serialization
/// <returns>System.String.</returns>
/// <exception cref="System.ArgumentNullException">obj</exception>
string SerializeToString(object obj);
-
- /// <summary>
- /// Serializes to bytes.
- /// </summary>
- /// <param name="obj">The obj.</param>
- /// <returns>System.Byte[][].</returns>
- /// <exception cref="System.ArgumentNullException">obj</exception>
- byte[] SerializeToBytes(object obj);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Serialization/IXmlSerializer.cs b/MediaBrowser.Model/Serialization/IXmlSerializer.cs
index 177377350..eb23d784f 100644
--- a/MediaBrowser.Model/Serialization/IXmlSerializer.cs
+++ b/MediaBrowser.Model/Serialization/IXmlSerializer.cs
@@ -42,12 +42,5 @@ namespace MediaBrowser.Model.Serialization
/// <param name="buffer">The buffer.</param>
/// <returns>System.Object.</returns>
object DeserializeFromBytes(Type type, byte[] buffer);
-
- /// <summary>
- /// Serializes to bytes.
- /// </summary>
- /// <param name="obj">The obj.</param>
- /// <returns>System.Byte[][].</returns>
- byte[] SerializeToBytes(object obj);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Session/GeneralCommand.cs b/MediaBrowser.Model/Session/GeneralCommand.cs
index 7e818245d..ae9ab3adc 100644
--- a/MediaBrowser.Model/Session/GeneralCommand.cs
+++ b/MediaBrowser.Model/Session/GeneralCommand.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
namespace MediaBrowser.Model.Session
{
@@ -13,7 +12,7 @@ namespace MediaBrowser.Model.Session
public GeneralCommand()
{
- Arguments = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ Arguments = new Dictionary<string, string>();
}
}
}
diff --git a/MediaBrowser.Model/Session/SessionInfoDto.cs b/MediaBrowser.Model/Session/SessionInfoDto.cs
index 7217e28f4..98df3efe5 100644
--- a/MediaBrowser.Model/Session/SessionInfoDto.cs
+++ b/MediaBrowser.Model/Session/SessionInfoDto.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Extensions;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -7,25 +8,13 @@ using System.Diagnostics;
namespace MediaBrowser.Model.Session
{
[DebuggerDisplay("Client = {Client}, Username = {UserName}")]
- public class SessionInfoDto : INotifyPropertyChanged
+ public class SessionInfoDto : IHasPropertyChangedEvent
{
/// <summary>
- /// Gets or sets a value indicating whether this instance can seek.
- /// </summary>
- /// <value><c>true</c> if this instance can seek; otherwise, <c>false</c>.</value>
- public bool CanSeek { get; set; }
-
- /// <summary>
/// Gets or sets the supported commands.
/// </summary>
/// <value>The supported commands.</value>
public List<string> SupportedCommands { get; set; }
-
- /// <summary>
- /// Gets or sets the remote end point.
- /// </summary>
- /// <value>The remote end point.</value>
- public string RemoteEndPoint { get; set; }
/// <summary>
/// Gets or sets the queueable media types.
@@ -98,18 +87,6 @@ namespace MediaBrowser.Model.Session
/// </summary>
/// <value>The name of the device.</value>
public string DeviceName { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance is paused.
- /// </summary>
- /// <value><c>true</c> if this instance is paused; otherwise, <c>false</c>.</value>
- public bool IsPaused { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance is muted.
- /// </summary>
- /// <value><c>true</c> if this instance is muted; otherwise, <c>false</c>.</value>
- public bool IsMuted { get; set; }
/// <summary>
/// Gets or sets the now playing item.
@@ -118,12 +95,6 @@ namespace MediaBrowser.Model.Session
public BaseItemInfo NowPlayingItem { get; set; }
/// <summary>
- /// Gets or sets the now playing position ticks.
- /// </summary>
- /// <value>The now playing position ticks.</value>
- public long? NowPlayingPositionTicks { get; set; }
-
- /// <summary>
/// Gets or sets the device id.
/// </summary>
/// <value>The device id.</value>
diff --git a/MediaBrowser.Model/Sync/SyncJob.cs b/MediaBrowser.Model/Sync/SyncJob.cs
new file mode 100644
index 000000000..f69fccae5
--- /dev/null
+++ b/MediaBrowser.Model/Sync/SyncJob.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.Sync
+{
+ public class SyncJob
+ {
+ /// <summary>
+ /// Gets or sets the identifier.
+ /// </summary>
+ /// <value>The identifier.</value>
+ public string Id { get; set; }
+ /// <summary>
+ /// Gets or sets the device identifier.
+ /// </summary>
+ /// <value>The device identifier.</value>
+ public string TargetId { get; set; }
+ /// <summary>
+ /// Gets or sets the quality.
+ /// </summary>
+ /// <value>The quality.</value>
+ public SyncQuality Quality { get; set; }
+ /// <summary>
+ /// Gets or sets the current progress.
+ /// </summary>
+ /// <value>The current progress.</value>
+ public double? Progress { get; set; }
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+ /// <summary>
+ /// Gets or sets the status.
+ /// </summary>
+ /// <value>The status.</value>
+ public SyncJobStatus Status { get; set; }
+ /// <summary>
+ /// Gets or sets the user identifier.
+ /// </summary>
+ /// <value>The user identifier.</value>
+ public string UserId { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether [unwatched only].
+ /// </summary>
+ /// <value><c>true</c> if [unwatched only]; otherwise, <c>false</c>.</value>
+ public bool UnwatchedOnly { get; set; }
+ /// <summary>
+ /// Gets or sets the limit.
+ /// </summary>
+ /// <value>The limit.</value>
+ public long? Limit { get; set; }
+ /// <summary>
+ /// Gets or sets the type of the limit.
+ /// </summary>
+ /// <value>The type of the limit.</value>
+ public SyncLimitType? LimitType { get; set; }
+ /// <summary>
+ /// Gets or sets the requested item ids.
+ /// </summary>
+ /// <value>The requested item ids.</value>
+ public List<string> RequestedItemIds { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is dynamic.
+ /// </summary>
+ /// <value><c>true</c> if this instance is dynamic; otherwise, <c>false</c>.</value>
+ public bool IsDynamic { get; set; }
+ /// <summary>
+ /// Gets or sets the date created.
+ /// </summary>
+ /// <value>The date created.</value>
+ public DateTime DateCreated { get; set; }
+ /// <summary>
+ /// Gets or sets the date last modified.
+ /// </summary>
+ /// <value>The date last modified.</value>
+ public DateTime DateLastModified { get; set; }
+ /// <summary>
+ /// Gets or sets the item count.
+ /// </summary>
+ /// <value>The item count.</value>
+ public int ItemCount { get; set; }
+
+ public string ParentName { get; set; }
+ public string PrimaryImageItemId { get; set; }
+ public string PrimaryImageTag { get; set; }
+ public double? PrimaryImageAspectRatio { get; set; }
+
+ public SyncJob()
+ {
+ RequestedItemIds = new List<string>();
+ }
+ }
+}
diff --git a/MediaBrowser.Model/Sync/SyncJobCreationResult.cs b/MediaBrowser.Model/Sync/SyncJobCreationResult.cs
new file mode 100644
index 000000000..797318b2a
--- /dev/null
+++ b/MediaBrowser.Model/Sync/SyncJobCreationResult.cs
@@ -0,0 +1,8 @@
+
+namespace MediaBrowser.Model.Sync
+{
+ public class SyncJobCreationResult
+ {
+ public SyncJob Job { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Sync/SyncJobItem.cs b/MediaBrowser.Model/Sync/SyncJobItem.cs
new file mode 100644
index 000000000..141546eb5
--- /dev/null
+++ b/MediaBrowser.Model/Sync/SyncJobItem.cs
@@ -0,0 +1,48 @@
+
+namespace MediaBrowser.Model.Sync
+{
+ public class SyncJobItem
+ {
+ /// <summary>
+ /// Gets or sets the identifier.
+ /// </summary>
+ /// <value>The identifier.</value>
+ public string Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the job identifier.
+ /// </summary>
+ /// <value>The job identifier.</value>
+ public string JobId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the item identifier.
+ /// </summary>
+ /// <value>The item identifier.</value>
+ public string ItemId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the target identifier.
+ /// </summary>
+ /// <value>The target identifier.</value>
+ public string TargetId { 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 status.
+ /// </summary>
+ /// <value>The status.</value>
+ public SyncJobStatus Status { get; set; }
+
+ /// <summary>
+ /// Gets or sets the current progress.
+ /// </summary>
+ /// <value>The current progress.</value>
+ public double? CurrentProgress { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Sync/SyncJobQuery.cs b/MediaBrowser.Model/Sync/SyncJobQuery.cs
new file mode 100644
index 000000000..74b35186e
--- /dev/null
+++ b/MediaBrowser.Model/Sync/SyncJobQuery.cs
@@ -0,0 +1,17 @@
+
+namespace MediaBrowser.Model.Sync
+{
+ public class SyncJobQuery
+ {
+ /// <summary>
+ /// Gets or sets the start index.
+ /// </summary>
+ /// <value>The start index.</value>
+ public int? StartIndex { get; set; }
+ /// <summary>
+ /// Gets or sets the limit.
+ /// </summary>
+ /// <value>The limit.</value>
+ public int? Limit { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Sync/SyncJobRequest.cs b/MediaBrowser.Model/Sync/SyncJobRequest.cs
new file mode 100644
index 000000000..7728aad9b
--- /dev/null
+++ b/MediaBrowser.Model/Sync/SyncJobRequest.cs
@@ -0,0 +1,58 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.Sync
+{
+ public class SyncJobRequest
+ {
+ /// <summary>
+ /// Gets or sets the target identifier.
+ /// </summary>
+ /// <value>The target identifier.</value>
+ public string TargetId { get; set; }
+ /// <summary>
+ /// Gets or sets the item ids.
+ /// </summary>
+ /// <value>The item ids.</value>
+ public List<string> ItemIds { get; set; }
+ /// <summary>
+ /// Gets or sets the quality.
+ /// </summary>
+ /// <value>The quality.</value>
+ public SyncQuality Quality { get; set; }
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+ /// <summary>
+ /// Gets or sets the user identifier.
+ /// </summary>
+ /// <value>The user identifier.</value>
+ public string UserId { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether [unwatched only].
+ /// </summary>
+ /// <value><c>true</c> if [unwatched only]; otherwise, <c>false</c>.</value>
+ public bool UnwatchedOnly { get; set; }
+ /// <summary>
+ /// Gets or sets the limit.
+ /// </summary>
+ /// <value>The limit.</value>
+ public long? Limit { get; set; }
+ /// <summary>
+ /// Gets or sets the type of the limit.
+ /// </summary>
+ /// <value>The type of the limit.</value>
+ public SyncLimitType? LimitType { get; set; }
+
+ public SyncJobRequest()
+ {
+ ItemIds = new List<string>();
+ }
+ }
+
+ public enum SyncLimitType
+ {
+ ItemCount = 0
+ }
+}
diff --git a/MediaBrowser.Model/Sync/SyncJobStatus.cs b/MediaBrowser.Model/Sync/SyncJobStatus.cs
new file mode 100644
index 000000000..ebe375ad8
--- /dev/null
+++ b/MediaBrowser.Model/Sync/SyncJobStatus.cs
@@ -0,0 +1,13 @@
+
+namespace MediaBrowser.Model.Sync
+{
+ public enum SyncJobStatus
+ {
+ Queued = 0,
+ Transcoding = 1,
+ TranscodingFailed = 2,
+ Transferring = 3,
+ Completed = 4,
+ Cancelled = 5
+ }
+}
diff --git a/MediaBrowser.Model/Sync/SyncQuality.cs b/MediaBrowser.Model/Sync/SyncQuality.cs
new file mode 100644
index 000000000..f915e2768
--- /dev/null
+++ b/MediaBrowser.Model/Sync/SyncQuality.cs
@@ -0,0 +1,21 @@
+
+namespace MediaBrowser.Model.Sync
+{
+ public enum SyncQuality
+ {
+ /// <summary>
+ /// The good
+ /// </summary>
+ Good = 0,
+
+ /// <summary>
+ /// The better
+ /// </summary>
+ Better = 1,
+
+ /// <summary>
+ /// The best
+ /// </summary>
+ Best = 2
+ }
+}
diff --git a/MediaBrowser.Model/Sync/SyncTarget.cs b/MediaBrowser.Model/Sync/SyncTarget.cs
new file mode 100644
index 000000000..8901f0f27
--- /dev/null
+++ b/MediaBrowser.Model/Sync/SyncTarget.cs
@@ -0,0 +1,17 @@
+
+namespace MediaBrowser.Model.Sync
+{
+ public class SyncTarget
+ {
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+ /// <summary>
+ /// Gets or sets the identifier.
+ /// </summary>
+ /// <value>The identifier.</value>
+ public string Id { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/System/LogFile.cs b/MediaBrowser.Model/System/LogFile.cs
new file mode 100644
index 000000000..ba409c542
--- /dev/null
+++ b/MediaBrowser.Model/System/LogFile.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace MediaBrowser.Model.System
+{
+ public class LogFile
+ {
+ /// <summary>
+ /// Gets or sets the date created.
+ /// </summary>
+ /// <value>The date created.</value>
+ public DateTime DateCreated { get; set; }
+
+ /// <summary>
+ /// Gets or sets the date modified.
+ /// </summary>
+ /// <value>The date modified.</value>
+ public DateTime DateModified { get; set; }
+
+ /// <summary>
+ /// Gets or sets the size.
+ /// </summary>
+ /// <value>The size.</value>
+ public long Size { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs
index 5b1e7d6bb..4e0d82191 100644
--- a/MediaBrowser.Model/System/SystemInfo.cs
+++ b/MediaBrowser.Model/System/SystemInfo.cs
@@ -6,15 +6,9 @@ namespace MediaBrowser.Model.System
/// <summary>
/// Class SystemInfo
/// </summary>
- public class SystemInfo
+ public class SystemInfo : PublicSystemInfo
{
/// <summary>
- /// Gets or sets the version.
- /// </summary>
- /// <value>The version.</value>
- public string Version { get; set; }
-
- /// <summary>
/// Gets or sets the operating sytem.
/// </summary>
/// <value>The operating sytem.</value>
@@ -33,6 +27,12 @@ namespace MediaBrowser.Model.System
public string MacAddress { get; set; }
/// <summary>
+ /// Gets or sets the local address.
+ /// </summary>
+ /// <value>The local address.</value>
+ public string LocalAddress { get; set; }
+
+ /// <summary>
/// Gets or sets a value indicating whether this instance has pending restart.
/// </summary>
/// <value><c>true</c> if this instance has pending restart; otherwise, <c>false</c>.</value>
@@ -87,12 +87,6 @@ namespace MediaBrowser.Model.System
public List<string> FailedPluginAssemblies { get; set; }
/// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- public string Id { get; set; }
-
- /// <summary>
/// Gets or sets the program data path.
/// </summary>
/// <value>The program data path.</value>
@@ -153,12 +147,6 @@ namespace MediaBrowser.Model.System
public bool SupportsAutoRunAtStartup { get; set; }
/// <summary>
- /// Gets or sets the name of the server.
- /// </summary>
- /// <value>The name of the server.</value>
- public string ServerName { get; set; }
-
- /// <summary>
/// Initializes a new instance of the <see cref="SystemInfo" /> class.
/// </summary>
public SystemInfo()
@@ -170,4 +158,25 @@ namespace MediaBrowser.Model.System
FailedPluginAssemblies = new List<string>();
}
}
+
+ public class PublicSystemInfo
+ {
+ /// <summary>
+ /// Gets or sets the name of the server.
+ /// </summary>
+ /// <value>The name of the server.</value>
+ public string ServerName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the version.
+ /// </summary>
+ /// <value>The version.</value>
+ public string Version { get; set; }
+
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ public string Id { get; set; }
+ }
}
diff --git a/MediaBrowser.Model/Tasks/TaskResult.cs b/MediaBrowser.Model/Tasks/TaskResult.cs
index e73b4c9a1..956d68ae4 100644
--- a/MediaBrowser.Model/Tasks/TaskResult.cs
+++ b/MediaBrowser.Model/Tasks/TaskResult.cs
@@ -42,5 +42,11 @@ namespace MediaBrowser.Model.Tasks
/// </summary>
/// <value>The error message.</value>
public string ErrorMessage { get; set; }
+
+ /// <summary>
+ /// Gets or sets the long error message.
+ /// </summary>
+ /// <value>The long error message.</value>
+ public string LongErrorMessage { get; set; }
}
}
diff --git a/MediaBrowser.Model/Themes/AppTheme.cs b/MediaBrowser.Model/Themes/AppTheme.cs
index 40a729963..527f1de72 100644
--- a/MediaBrowser.Model/Themes/AppTheme.cs
+++ b/MediaBrowser.Model/Themes/AppTheme.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
namespace MediaBrowser.Model.Themes
{
@@ -15,7 +14,7 @@ namespace MediaBrowser.Model.Themes
public AppTheme()
{
- Options = new Dictionary<string, string>(StringComparer.Ordinal);
+ Options = new Dictionary<string, string>();
Images = new List<ThemeImage>();
}
diff --git a/MediaBrowser.Model/Updates/CheckForUpdateResult.cs b/MediaBrowser.Model/Updates/CheckForUpdateResult.cs
index c9bc2d6b9..ff0bba197 100644
--- a/MediaBrowser.Model/Updates/CheckForUpdateResult.cs
+++ b/MediaBrowser.Model/Updates/CheckForUpdateResult.cs
@@ -1,5 +1,4 @@
-using System;
-
+
namespace MediaBrowser.Model.Updates
{
/// <summary>
@@ -17,9 +16,9 @@ namespace MediaBrowser.Model.Updates
/// Gets or sets the available version.
/// </summary>
/// <value>The available version.</value>
- public Version AvailableVersion
+ public string AvailableVersion
{
- get { return Package != null ? Package.version : new Version(0, 0); }
+ get { return Package != null ? Package.versionStr : "0.0.0.1"; }
set { } // need this for the serializer
}
diff --git a/MediaBrowser.Model/Updates/PackageVersionInfo.cs b/MediaBrowser.Model/Updates/PackageVersionInfo.cs
index b3d297e8e..b9bf6e7fe 100644
--- a/MediaBrowser.Model/Updates/PackageVersionInfo.cs
+++ b/MediaBrowser.Model/Updates/PackageVersionInfo.cs
@@ -88,4 +88,4 @@ namespace MediaBrowser.Model.Updates
/// <value>The target filename.</value>
public string targetFilename { get; set; }
}
-}
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Users/AuthenticationResult.cs b/MediaBrowser.Model/Users/AuthenticationResult.cs
index 998aaa3a7..b4a7cab2a 100644
--- a/MediaBrowser.Model/Users/AuthenticationResult.cs
+++ b/MediaBrowser.Model/Users/AuthenticationResult.cs
@@ -16,5 +16,17 @@ namespace MediaBrowser.Model.Users
/// </summary>
/// <value>The session information.</value>
public SessionInfoDto SessionInfo { get; set; }
+
+ /// <summary>
+ /// Gets or sets the authentication token.
+ /// </summary>
+ /// <value>The authentication token.</value>
+ public string AccessToken { get; set; }
+
+ /// <summary>
+ /// Gets or sets the server identifier.
+ /// </summary>
+ /// <value>The server identifier.</value>
+ public string ServerId { get; set; }
}
}
diff --git a/MediaBrowser.Mono.sln b/MediaBrowser.Mono.sln
index 9c2397046..daf06c083 100644
--- a/MediaBrowser.Mono.sln
+++ b/MediaBrowser.Mono.sln
@@ -25,6 +25,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSubtitlesHandler", "OpenSubtitlesHandler\OpenSubtitlesHandler.csproj", "{4A4402D4-E910-443B-B8FC-2C18286A2CA0}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.LocalMetadata", "MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj", "{7EF9F3E0-697D-42F3-A08F-19DEB5F84392}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.XbmcMetadata", "MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj", "{23499896-B135-4527-8574-C26E926EA99E}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
@@ -57,6 +61,14 @@ Global
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.Build.0 = Release|Any CPU
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.ActiveCfg = Release|Any CPU
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.Build.0 = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug|x86.Build.0 = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release Mono|Any CPU.Build.0 = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|x86.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|x86.Build.0 = Release|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.ActiveCfg = Debug|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.Build.0 = Debug|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU
@@ -113,6 +125,14 @@ Global
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.Build.0 = Release|Any CPU
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x86.ActiveCfg = Release|Any CPU
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x86.Build.0 = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|x86.Build.0 = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release Mono|Any CPU.Build.0 = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x86.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x86.Build.0 = Release|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x86.ActiveCfg = Debug|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x86.Build.0 = Debug|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU
diff --git a/MediaBrowser.Mono.userprefs b/MediaBrowser.Mono.userprefs
index f115a532e..bac7f9510 100644
--- a/MediaBrowser.Mono.userprefs
+++ b/MediaBrowser.Mono.userprefs
@@ -5,7 +5,7 @@
<File FileName="MediaBrowser.Server.Mono\app.config" Line="1" Column="1" />
<File FileName="MediaBrowser.ServerApplication\ApplicationHost.cs" Line="1" Column="1" />
<File FileName="MediaBrowser.Server.Mono\Native\NativeApp.cs" Line="1" Column="1" />
- <File FileName="MediaBrowser.Server.Mono\Program.cs" Line="24" Column="15" />
+ <File FileName="MediaBrowser.Server.Mono\Program.cs" Line="19" Column="19" />
</Files>
</MonoDevelop.Ide.Workbench>
<MonoDevelop.Ide.DebuggingService.Breakpoints>
diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
index cf7904e5c..e17a96a43 100644
--- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
+++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs
@@ -216,12 +216,6 @@ namespace MediaBrowser.Providers.BoxSets
{
mainResult = _json.DeserializeFromStream<RootObject>(json);
}
-
- if (String.IsNullOrEmpty(mainResult.overview))
- {
- _logger.Error("Unable to find information for (id:" + id + ")");
- return null;
- }
}
}
return mainResult;
diff --git a/MediaBrowser.Providers/GameGenres/AudioChannelItemMetadataService.cs b/MediaBrowser.Providers/Channels/AudioChannelItemMetadataService.cs
index c8e496b71..42b1ea4de 100644
--- a/MediaBrowser.Providers/GameGenres/AudioChannelItemMetadataService.cs
+++ b/MediaBrowser.Providers/Channels/AudioChannelItemMetadataService.cs
@@ -1,13 +1,13 @@
-using MediaBrowser.Common.IO;
+using System.Collections.Generic;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
-using System.Collections.Generic;
-namespace MediaBrowser.Providers.GameGenres
+namespace MediaBrowser.Providers.Channels
{
public class AudioChannelItemMetadataService : MetadataService<ChannelAudioItem, ItemLookupInfo>
{
diff --git a/MediaBrowser.Providers/GameGenres/VideoChannelItemMetadataService.cs b/MediaBrowser.Providers/Channels/VideoChannelItemMetadataService.cs
index 9dd37c959..ddd112207 100644
--- a/MediaBrowser.Providers/GameGenres/VideoChannelItemMetadataService.cs
+++ b/MediaBrowser.Providers/Channels/VideoChannelItemMetadataService.cs
@@ -1,13 +1,13 @@
-using MediaBrowser.Common.IO;
+using System.Collections.Generic;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
-using System.Collections.Generic;
-namespace MediaBrowser.Providers.GameGenres
+namespace MediaBrowser.Providers.Channels
{
public class VideoChannelItemMetadataService : MetadataService<ChannelVideoItem, ItemLookupInfo>
{
diff --git a/MediaBrowser.Providers/Chapters/ChapterManager.cs b/MediaBrowser.Providers/Chapters/ChapterManager.cs
index 5f8664bec..6e2cd77eb 100644
--- a/MediaBrowser.Providers/Chapters/ChapterManager.cs
+++ b/MediaBrowser.Providers/Chapters/ChapterManager.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Chapters;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -8,6 +9,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Chapters;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
@@ -192,8 +194,10 @@ namespace MediaBrowser.Providers.Chapters
if (!includeDisabledProviders)
{
+ var options = GetConfiguration();
+
providers = providers
- .Where(i => !_config.Configuration.ChapterOptions.DisabledFetchers.Contains(i.Name))
+ .Where(i => !options.DisabledFetchers.Contains(i.Name))
.ToArray();
}
@@ -224,8 +228,10 @@ namespace MediaBrowser.Providers.Chapters
private int GetConfiguredOrder(IChapterProvider provider)
{
+ var options = GetConfiguration();
+
// See if there's a user-defined order
- var index = Array.IndexOf(_config.Configuration.ChapterOptions.FetcherOrder, provider.Name);
+ var index = Array.IndexOf(options.FetcherOrder, provider.Name);
if (index != -1)
{
@@ -257,5 +263,25 @@ namespace MediaBrowser.Providers.Chapters
{
return _itemRepo.SaveChapters(new Guid(itemId), chapters, cancellationToken);
}
+
+ public ChapterOptions GetConfiguration()
+ {
+ return _config.GetConfiguration<ChapterOptions>("chapters");
+ }
+ }
+
+ public class ChapterConfigurationStore : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new List<ConfigurationStore>
+ {
+ new ConfigurationStore
+ {
+ Key = "chapters",
+ ConfigurationType = typeof (ChapterOptions)
+ }
+ };
+ }
}
}
diff --git a/MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs b/MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs
index f72b27be6..0f7e6d10a 100644
--- a/MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs
+++ b/MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Playlists;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
@@ -31,6 +32,12 @@ namespace MediaBrowser.Providers.FolderImages
public Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken)
{
+ var playlist = item as Playlist;
+ if (playlist != null)
+ {
+ return GetImages(string.Empty, cancellationToken);
+ }
+
var view = item as UserView;
if (view != null)
@@ -111,7 +118,7 @@ namespace MediaBrowser.Providers.FolderImages
public bool Supports(IHasImages item)
{
- return item is UserView || item is ICollectionFolder;
+ return item is UserView || item is ICollectionFolder || item is Playlist;
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs
index 12af93dbd..d7110c1ec 100644
--- a/MediaBrowser.Providers/Manager/ImageSaver.cs
+++ b/MediaBrowser.Providers/Manager/ImageSaver.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -291,7 +292,7 @@ namespace MediaBrowser.Providers.Manager
private string GetStandardSavePath(IHasImages item, ImageType type, int? imageIndex, string mimeType, bool saveLocally)
{
string filename;
-
+
switch (type)
{
case ImageType.Art:
@@ -304,7 +305,7 @@ namespace MediaBrowser.Providers.Manager
filename = item is MusicAlbum ? "cdart" : "disc";
break;
case ImageType.Primary:
- filename = item is Episode ? Path.GetFileNameWithoutExtension(item.Path) : "folder";
+ filename = item is Episode ? _fileSystem.GetFileNameWithoutExtension(item.Path) : "folder";
break;
case ImageType.Backdrop:
filename = GetBackdropSaveFilename(item.GetImages(type), "backdrop", "backdrop", imageIndex);
@@ -366,7 +367,7 @@ namespace MediaBrowser.Providers.Manager
return zeroIndexFilename;
}
- var filenames = images.Select(i => Path.GetFileNameWithoutExtension(i.Path)).ToList();
+ var filenames = images.Select(i => _fileSystem.GetFileNameWithoutExtension(i.Path)).ToList();
var current = 1;
while (filenames.Contains(numberedIndexPrefix + current.ToString(UsCulture), StringComparer.OrdinalIgnoreCase))
@@ -441,11 +442,16 @@ namespace MediaBrowser.Providers.Manager
var extraFanartFilename = GetBackdropSaveFilename(item.GetImages(ImageType.Backdrop), "fanart", "fanart", outputIndex);
- return new[]
- {
- Path.Combine(item.ContainingFolderPath, "extrafanart", extraFanartFilename + extension),
- Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + outputIndex.ToString(UsCulture) + extension)
- };
+ var list = new List<string>
+ {
+ Path.Combine(item.ContainingFolderPath, "extrafanart", extraFanartFilename + extension)
+ };
+
+ if (EnableExtraThumbsDuplication)
+ {
+ list.Add(Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + outputIndex.ToString(UsCulture) + extension));
+ }
+ return list.ToArray();
}
if (type == ImageType.Primary)
@@ -467,7 +473,7 @@ namespace MediaBrowser.Providers.Manager
{
var seasonFolder = Path.GetDirectoryName(item.Path);
- var imageFilename = Path.GetFileNameWithoutExtension(item.Path) + "-thumb" + extension;
+ var imageFilename = _fileSystem.GetFileNameWithoutExtension(item.Path) + "-thumb" + extension;
return new[] { Path.Combine(seasonFolder, imageFilename) };
}
@@ -528,6 +534,16 @@ namespace MediaBrowser.Providers.Manager
return new[] { GetStandardSavePath(item, type, imageIndex, mimeType, true) };
}
+ private bool EnableExtraThumbsDuplication
+ {
+ get
+ {
+ var config = _config.GetConfiguration<XbmcMetadataOptions>("xbmcmetadata");
+
+ return config.EnableExtraThumbsDuplication;
+ }
+ }
+
/// <summary>
/// Gets the save path for item in mixed folder.
/// </summary>
@@ -544,7 +560,7 @@ namespace MediaBrowser.Providers.Manager
}
var folder = Path.GetDirectoryName(item.Path);
- return Path.Combine(folder, Path.GetFileNameWithoutExtension(item.Path) + "-" + imageFilename + extension);
+ return Path.Combine(folder, _fileSystem.GetFileNameWithoutExtension(item.Path) + "-" + imageFilename + extension);
}
}
}
diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
index 9e69d0857..ef5c30975 100644
--- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs
+++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
@@ -236,6 +236,11 @@ namespace MediaBrowser.Providers.Manager
{
try
{
+ if (!item.SupportsRemoteImageDownloading)
+ {
+ return;
+ }
+
if (!refreshOptions.ReplaceAllImages &&
refreshOptions.ReplaceImages.Count == 0 &&
ContainsImages(item, provider.GetSupportedImages(item).ToList(), savedOptions, backdropLimit, screenshotLimit))
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index 717b93524..eee8b59e2 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -8,7 +8,6 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -104,9 +103,6 @@ namespace MediaBrowser.Providers.Manager
refreshResult.AddStatus(ProviderRefreshStatus.Failure, ex.Message);
}
- // Identify item
- TIdType id = null;
-
// Next run metadata providers
if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
{
@@ -123,23 +119,19 @@ namespace MediaBrowser.Providers.Manager
if (providers.Count > 0)
{
- id = await CreateInitialLookupInfo(itemOfType, cancellationToken).ConfigureAwait(false);
+ var id = await CreateInitialLookupInfo(itemOfType, cancellationToken).ConfigureAwait(false);
+
var result = await RefreshWithProviders(itemOfType, id, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false);
updateType = updateType | result.UpdateType;
refreshResult.AddStatus(result.Status, result.ErrorMessage);
refreshResult.SetDateLastMetadataRefresh(DateTime.UtcNow);
refreshResult.AddImageProvidersRefreshed(result.Providers);
- }
- }
- if (id == null)
- {
- id = await CreateInitialLookupInfo(itemOfType, cancellationToken).ConfigureAwait(false);
+ MergeIdentities(itemOfType, id);
+ }
}
- MergeIdentities(itemOfType, id);
-
// Next run remote image providers, but only if local image providers didn't throw an exception
if (!localImagesFailed && refreshOptions.ImageRefreshMode != ImageRefreshMode.ValidationOnly)
{
@@ -296,11 +288,19 @@ namespace MediaBrowser.Providers.Manager
var temp = CreateNew();
temp.Path = item.Path;
+ var successfulProviderCount = 0;
+ var failedProviderCount = 0;
// If replacing all metadata, run internet providers first
if (options.ReplaceAllMetadata)
{
- await ExecuteRemoteProviders(item, temp, id, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false);
+ var remoteResult = await ExecuteRemoteProviders(item, temp, id, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), cancellationToken)
+ .ConfigureAwait(false);
+ refreshResult.UpdateType = refreshResult.UpdateType | remoteResult.UpdateType;
+ refreshResult.Status = remoteResult.Status;
+ refreshResult.ErrorMessage = remoteResult.ErrorMessage;
+ successfulProviderCount += remoteResult.Successes;
+ failedProviderCount += remoteResult.Failures;
}
var hasLocalMetadata = false;
@@ -328,7 +328,7 @@ namespace MediaBrowser.Providers.Manager
// Only one local provider allowed per item
hasLocalMetadata = true;
- item.IsUnidentified = false;
+ successfulProviderCount++;
break;
}
@@ -340,20 +340,35 @@ namespace MediaBrowser.Providers.Manager
}
catch (Exception ex)
{
+ failedProviderCount++;
+
+ Logger.ErrorException("Error in {0}", ex, provider.Name);
+
// If a local provider fails, consider that a failure
refreshResult.Status = ProviderRefreshStatus.Failure;
refreshResult.ErrorMessage = ex.Message;
- Logger.ErrorException("Error in {0}", ex, provider.Name);
- // If the local provider fails don't continue with remote providers because the user's saved metadata could be lost
- return refreshResult;
+ if (options.MetadataRefreshMode != MetadataRefreshMode.FullRefresh)
+ {
+ // If the local provider fails don't continue with remote providers because the user's saved metadata could be lost
+ return refreshResult;
+ }
}
}
// Local metadata is king - if any is found don't run remote providers
if (!options.ReplaceAllMetadata && (!hasLocalMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh))
{
- await ExecuteRemoteProviders(item, temp, id, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false);
+ var remoteResult = await ExecuteRemoteProviders(item, temp, id, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), cancellationToken)
+ .ConfigureAwait(false);
+
+ refreshResult.UpdateType = refreshResult.UpdateType | remoteResult.UpdateType;
+ if (remoteResult.Status != ProviderRefreshStatus.Success)
+ {
+ refreshResult.Status = remoteResult.Status;
+ refreshResult.ErrorMessage = remoteResult.ErrorMessage;
+ }
+ successfulProviderCount += remoteResult.Successes;
}
if (refreshResult.UpdateType > ItemUpdateType.None)
@@ -361,6 +376,14 @@ namespace MediaBrowser.Providers.Manager
MergeData(temp, item, item.LockedFields, true, true);
}
+ var isUnidentified = failedProviderCount > 0 && successfulProviderCount == 0;
+
+ if (item.IsUnidentified != isUnidentified)
+ {
+ item.IsUnidentified = isUnidentified;
+ refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport;
+ }
+
foreach (var provider in customProviders.Where(i => !(i is IPreRefreshProvider)))
{
await RunCustomProvider(provider, item, options, refreshResult, cancellationToken).ConfigureAwait(false);
@@ -394,10 +417,9 @@ namespace MediaBrowser.Providers.Manager
return new TItemType();
}
- private async Task ExecuteRemoteProviders(TItemType item, TItemType temp, TIdType id, IEnumerable<IRemoteMetadataProvider<TItemType, TIdType>> providers, RefreshResult refreshResult, CancellationToken cancellationToken)
+ private async Task<RefreshResult> ExecuteRemoteProviders(TItemType item, TItemType temp, TIdType id, IEnumerable<IRemoteMetadataProvider<TItemType, TIdType>> providers, CancellationToken cancellationToken)
{
- var unidentifiedCount = 0;
- var identifiedCount = 0;
+ var refreshResult = new RefreshResult();
foreach (var provider in providers)
{
@@ -419,11 +441,11 @@ namespace MediaBrowser.Providers.Manager
refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataDownload;
- identifiedCount++;
+ refreshResult.Successes++;
}
else
{
- unidentifiedCount++;
+ refreshResult.Failures++;
Logger.Debug("{0} returned no metadata for {1}", providerName, item.Path ?? item.Name);
}
}
@@ -433,20 +455,24 @@ namespace MediaBrowser.Providers.Manager
}
catch (Exception ex)
{
- unidentifiedCount++;
+ refreshResult.Failures++;
refreshResult.Status = ProviderRefreshStatus.CompletedWithErrors;
refreshResult.ErrorMessage = ex.Message;
Logger.ErrorException("Error in {0}", ex, provider.Name);
}
}
- var isUnidentified = unidentifiedCount > 0 && identifiedCount == 0;
-
- if (item.IsUnidentified != isUnidentified)
+ if (refreshResult.Successes > 0)
{
- item.IsUnidentified = isUnidentified;
- refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataImport;
+ AfterRemoteRefresh(temp);
}
+
+ return refreshResult;
+ }
+
+ protected virtual void AfterRemoteRefresh(TItemType item)
+ {
+
}
private async Task<TIdType> CreateInitialLookupInfo(TItemType item, CancellationToken cancellationToken)
@@ -456,7 +482,14 @@ namespace MediaBrowser.Providers.Manager
var hasIdentity = info as IHasIdentities<IItemIdentity>;
if (hasIdentity != null)
{
- await hasIdentity.FindIdentities(ProviderManager, cancellationToken).ConfigureAwait(false);
+ try
+ {
+ await hasIdentity.FindIdentities(ProviderManager, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error in identity providers", ex);
+ }
}
return info;
@@ -507,5 +540,7 @@ namespace MediaBrowser.Providers.Manager
public ProviderRefreshStatus Status { get; set; }
public string ErrorMessage { get; set; }
public List<Guid> Providers { get; set; }
+ public int Successes { get; set; }
+ public int Failures { get; set; }
}
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 593d88cf5..f2ec85cfa 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -188,15 +188,10 @@ namespace MediaBrowser.Providers.Manager
if (preferredLanguages.Count > 0)
{
result = result.Where(i => string.IsNullOrEmpty(i.Language) ||
- preferredLanguages.Contains(i.Language, StringComparer.OrdinalIgnoreCase));
+ preferredLanguages.Contains(i.Language, StringComparer.OrdinalIgnoreCase) ||
+ string.Equals(i.Language, "en", StringComparison.OrdinalIgnoreCase));
}
- //if (string.Equals(preferredLanguage, "en", StringComparison.OrdinalIgnoreCase))
- //{
- // result = result.Where(i => string.IsNullOrEmpty(i.Language) ||
- // string.Equals(i.Language, "en", StringComparison.OrdinalIgnoreCase));
- //}
-
return result;
}
catch (OperationCanceledException)
@@ -347,14 +342,17 @@ namespace MediaBrowser.Providers.Manager
if (provider is IRemoteImageProvider || provider is IDynamicImageProvider)
{
- if (!ConfigurationManager.Configuration.EnableInternetProviders)
+ if (Array.IndexOf(options.DisabledImageFetchers, provider.Name) != -1)
{
return false;
}
- if (Array.IndexOf(options.DisabledImageFetchers, provider.Name) != -1)
+ if (provider is IRemoteImageProvider)
{
- return false;
+ if (!ConfigurationManager.Configuration.EnableInternetProviders)
+ {
+ return false;
+ }
}
}
}
@@ -545,18 +543,10 @@ namespace MediaBrowser.Providers.Manager
Type = MetadataPluginType.LocalImageProvider
}));
- if (ConfigurationManager.Configuration.EnableInternetProviders)
- {
- // Fetchers
- list.AddRange(imageProviders.Where(i => i is IRemoteImageProvider).Select(i => new MetadataPlugin
- {
- Name = i.Name,
- Type = MetadataPluginType.ImageFetcher
- }));
- }
+ var enableInternet = ConfigurationManager.Configuration.EnableInternetProviders;
// Fetchers
- list.AddRange(imageProviders.Where(i => i is IDynamicImageProvider).Select(i => new MetadataPlugin
+ list.AddRange(imageProviders.Where(i => i is IDynamicImageProvider || (enableInternet && i is IRemoteImageProvider)).Select(i => new MetadataPlugin
{
Name = i.Name,
Type = MetadataPluginType.ImageFetcher
diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs
index 2783fda6b..f09890c40 100644
--- a/MediaBrowser.Providers/Manager/ProviderUtils.cs
+++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs
@@ -170,7 +170,7 @@ namespace MediaBrowser.Providers.Manager
var key = id.Key;
// Don't replace existing Id's.
- if (!target.ProviderIds.ContainsKey(key))
+ if (replaceData || !target.ProviderIds.ContainsKey(key))
{
target.ProviderIds[key] = id.Value;
}
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 3234a8ae0..b69a4bc2f 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -53,6 +53,12 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.10\lib\net35\DvdLib.dll</HintPath>
</Reference>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
+ </Reference>
+ <Reference Include="policy.2.0.taglib-sharp">
+ <HintPath>..\packages\taglib.2.1.0.0\lib\policy.2.0.taglib-sharp.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net" />
@@ -61,8 +67,9 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
- <Reference Include="MoreLinq">
- <HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
+ <Reference Include="taglib-sharp">
+ <HintPath>..\packages\taglib.2.1.0.0\lib\taglib-sharp.dll</HintPath>
+ <Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -70,41 +77,28 @@
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="AdultVideos\AdultVideoMetadataService.cs" />
- <Compile Include="AdultVideos\AdultVideoXmlProvider.cs" />
- <Compile Include="All\InternalMetadataFolderImageProvider.cs" />
- <Compile Include="All\LocalImageProvider.cs" />
<Compile Include="Books\BookMetadataService.cs" />
<Compile Include="BoxSets\BoxSetMetadataService.cs" />
- <Compile Include="BoxSets\BoxSetXmlParser.cs" />
<Compile Include="BoxSets\MovieDbBoxSetImageProvider.cs" />
<Compile Include="BoxSets\MovieDbBoxSetProvider.cs" />
<Compile Include="Channels\ChannelMetadataService.cs" />
<Compile Include="Chapters\ChapterManager.cs" />
<Compile Include="FolderImages\DefaultImageProvider.cs" />
- <Compile Include="Folders\CollectionFolderImageProvider.cs" />
<Compile Include="Folders\FolderMetadataService.cs" />
- <Compile Include="Folders\ImagesByNameImageProvider.cs" />
- <Compile Include="GameGenres\AudioChannelItemMetadataService.cs" />
+ <Compile Include="Channels\AudioChannelItemMetadataService.cs" />
<Compile Include="GameGenres\GameGenreMetadataService.cs" />
- <Compile Include="GameGenres\VideoChannelItemMetadataService.cs" />
+ <Compile Include="Channels\VideoChannelItemMetadataService.cs" />
<Compile Include="Games\GameMetadataService.cs" />
<Compile Include="Games\GameSystemMetadataService.cs" />
- <Compile Include="Games\GameSystemXmlParser.cs" />
<Compile Include="Genres\GenreMetadataService.cs" />
<Compile Include="LiveTv\AudioRecordingService.cs" />
<Compile Include="LiveTv\ChannelMetadataService.cs" />
- <Compile Include="LiveTv\ChannelXmlProvider.cs" />
<Compile Include="LiveTv\ProgramMetadataService.cs" />
<Compile Include="LiveTv\VideoRecordingService.cs" />
<Compile Include="Manager\ImageSaver.cs" />
<Compile Include="Manager\ItemImageProvider.cs" />
<Compile Include="Manager\ProviderManager.cs" />
<Compile Include="Manager\MetadataService.cs" />
- <Compile Include="BaseXmlProvider.cs" />
- <Compile Include="Folders\FolderXmlProvider.cs" />
- <Compile Include="Games\GameXmlParser.cs" />
- <Compile Include="Games\GameXmlProvider.cs" />
- <Compile Include="Games\GameSystemXmlProvider.cs" />
<Compile Include="Manager\SeriesOrderManager.cs" />
<Compile Include="MediaInfo\FFProbeAudioInfo.cs" />
<Compile Include="MediaInfo\FFProbeHelpers.cs" />
@@ -112,22 +106,20 @@
<Compile Include="MediaInfo\FFProbeVideoInfo.cs" />
<Compile Include="MediaInfo\SubtitleDownloader.cs" />
<Compile Include="MediaInfo\SubtitleResolver.cs" />
+ <Compile Include="MediaInfo\SubtitleScheduledTask.cs" />
<Compile Include="Movies\MovieDbTrailerProvider.cs" />
<Compile Include="Movies\MovieExternalIds.cs" />
<Compile Include="Movies\TrailerMetadataService.cs" />
<Compile Include="Movies\GenericMovieDbInfo.cs" />
<Compile Include="Movies\MovieDbSearch.cs" />
<Compile Include="Movies\MovieMetadataService.cs" />
- <Compile Include="Movies\MovieXmlProvider.cs" />
<Compile Include="Movies\TmdbSettings.cs" />
- <Compile Include="Movies\TrailerXmlProvider.cs" />
<Compile Include="MusicGenres\MusicGenreImageProvider.cs" />
<Compile Include="GameGenres\GameGenreImageProvider.cs" />
<Compile Include="Genres\GenreImageProvider.cs" />
<Compile Include="ImagesByName\ImageUtils.cs" />
<Compile Include="MediaInfo\AudioImageProvider.cs" />
<Compile Include="MediaInfo\VideoImageProvider.cs" />
- <Compile Include="BoxSets\BoxSetXmlProvider.cs" />
<Compile Include="Movies\MovieDbImageProvider.cs" />
<Compile Include="Movies\FanartMovieImageProvider.cs" />
<Compile Include="MusicGenres\MusicGenreMetadataService.cs" />
@@ -141,68 +133,42 @@
<Compile Include="Music\AudioDbExternalIds.cs" />
<Compile Include="Music\AudioMetadataService.cs" />
<Compile Include="Music\Extensions.cs" />
- <Compile Include="Music\LastfmArtistProvider.cs" />
<Compile Include="Music\MovieDbMusicVideoProvider.cs" />
<Compile Include="Music\MusicBrainzArtistProvider.cs" />
<Compile Include="Music\MusicExternalIds.cs" />
<Compile Include="Music\MusicVideoMetadataService.cs" />
- <Compile Include="Music\MusicVideoXmlProvider.cs" />
<Compile Include="Omdb\OmdbProvider.cs" />
<Compile Include="Omdb\OmdbItemProvider.cs" />
<Compile Include="People\MovieDbPersonImageProvider.cs" />
<Compile Include="Movies\MovieUpdatesPrescanTask.cs" />
- <Compile Include="Movies\MovieXmlParser.cs" />
<Compile Include="Movies\FanArtMovieUpdatesPostScanTask.cs" />
<Compile Include="Movies\MovieDbProvider.cs" />
- <Compile Include="Music\AlbumXmlProvider.cs" />
- <Compile Include="Music\ArtistXmlProvider.cs" />
<Compile Include="Music\FanArtUpdatesPostScanTask.cs" />
- <Compile Include="Music\LastfmAlbumProvider.cs" />
- <Compile Include="Music\LastfmHelper.cs" />
<Compile Include="Music\FanArtAlbumProvider.cs" />
<Compile Include="Music\FanArtArtistProvider.cs" />
- <Compile Include="Music\LastFmImageProvider.cs" />
<Compile Include="Music\MusicBrainzAlbumProvider.cs" />
- <Compile Include="Music\MusicVideoXmlParser.cs" />
- <Compile Include="Music\SoundtrackPostScanTask.cs" />
<Compile Include="People\PersonMetadataService.cs" />
- <Compile Include="People\PersonXmlProvider.cs" />
<Compile Include="People\MovieDbPersonProvider.cs" />
- <Compile Include="Photos\ExifReader.cs" />
- <Compile Include="Photos\ExifTags.cs" />
<Compile Include="Photos\PhotoHelper.cs" />
<Compile Include="Photos\PhotoMetadataService.cs" />
<Compile Include="Photos\PhotoProvider.cs" />
+ <Compile Include="Playlists\PlaylistMetadataService.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Manager\ProviderUtils.cs" />
- <Compile Include="Savers\AlbumXmlSaver.cs" />
- <Compile Include="Savers\ArtistXmlSaver.cs" />
- <Compile Include="Savers\BoxSetXmlSaver.cs" />
- <Compile Include="Savers\ChannelXmlSaver.cs" />
- <Compile Include="Savers\EpisodeXmlSaver.cs" />
- <Compile Include="Savers\FolderXmlSaver.cs" />
- <Compile Include="Savers\GameSystemXmlSaver.cs" />
- <Compile Include="Savers\GameXmlSaver.cs" />
- <Compile Include="Savers\MovieXmlSaver.cs" />
- <Compile Include="Savers\PersonXmlSaver.cs" />
- <Compile Include="Savers\SeasonXmlSaver.cs" />
- <Compile Include="Savers\SeriesXmlSaver.cs" />
- <Compile Include="Savers\XmlSaverHelpers.cs" />
<Compile Include="Studios\StudiosImageProvider.cs" />
<Compile Include="Studios\StudioMetadataService.cs" />
+ <Compile Include="Subtitles\ConfigurationExtension.cs" />
<Compile Include="Subtitles\OpenSubtitleDownloader.cs" />
<Compile Include="Subtitles\SubtitleManager.cs" />
- <Compile Include="TV\EpisodeLocalImageProvider.cs" />
<Compile Include="TV\EpisodeMetadataService.cs" />
- <Compile Include="TV\EpisodeXmlProvider.cs" />
- <Compile Include="TV\EpisodeXmlParser.cs" />
<Compile Include="TV\FanArtTvUpdatesPostScanTask.cs" />
<Compile Include="TV\FanArtSeasonProvider.cs" />
<Compile Include="TV\FanartSeriesProvider.cs" />
<Compile Include="TV\MissingEpisodeProvider.cs" />
+ <Compile Include="TV\MovieDbEpisodeImageProvider.cs" />
+ <Compile Include="TV\MovieDbSeasonProvider.cs" />
<Compile Include="TV\MovieDbSeriesImageProvider.cs" />
<Compile Include="TV\MovieDbSeriesProvider.cs" />
- <Compile Include="TV\SeasonXmlParser.cs" />
<Compile Include="TV\SeriesMetadataService.cs" />
<Compile Include="TV\TvdbEpisodeImageProvider.cs" />
<Compile Include="People\TvdbPersonImageProvider.cs" />
@@ -212,16 +178,11 @@
<Compile Include="TV\SeasonMetadataService.cs" />
<Compile Include="TV\TvdbEpisodeProvider.cs" />
<Compile Include="TV\TvdbSeriesProvider.cs" />
- <Compile Include="TV\SeasonXmlProvider.cs" />
<Compile Include="TV\SeriesPostScanTask.cs" />
- <Compile Include="TV\SeriesXmlProvider.cs" />
- <Compile Include="TV\SeriesXmlParser.cs" />
<Compile Include="TV\TvdbPrescanTask.cs" />
<Compile Include="TV\TvExternalIds.cs" />
<Compile Include="Users\UserMetadataService.cs" />
<Compile Include="Videos\VideoMetadataService.cs" />
- <Compile Include="Videos\VideoXmlProvider.cs" />
- <Compile Include="Xbmc\XbmcImageSaver.cs" />
<Compile Include="Years\YearMetadataService.cs" />
</ItemGroup>
<ItemGroup>
@@ -248,8 +209,9 @@
<ItemGroup>
<EmbeddedResource Include="MediaInfo\whitelist.txt" />
</ItemGroup>
+ <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.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">
diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
index b2ca97f55..9188a2281 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
@@ -6,7 +6,6 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -24,40 +23,17 @@ namespace MediaBrowser.Providers.MediaInfo
{
private readonly ConcurrentDictionary<string, SemaphoreSlim> _locks = new ConcurrentDictionary<string, SemaphoreSlim>();
- private readonly IIsoManager _isoManager;
private readonly IMediaEncoder _mediaEncoder;
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
- public AudioImageProvider(IIsoManager isoManager, IMediaEncoder mediaEncoder, IServerConfigurationManager config, IFileSystem fileSystem)
+ public AudioImageProvider(IMediaEncoder mediaEncoder, IServerConfigurationManager config, IFileSystem fileSystem)
{
- _isoManager = isoManager;
_mediaEncoder = mediaEncoder;
_config = config;
_fileSystem = fileSystem;
}
- /// <summary>
- /// The null mount task result
- /// </summary>
- protected readonly Task<IIsoMount> NullMountTaskResult = Task.FromResult<IIsoMount>(null);
-
- /// <summary>
- /// Mounts the iso if needed.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task{IIsoMount}.</returns>
- protected Task<IIsoMount> MountIsoIfNeeded(Video item, CancellationToken cancellationToken)
- {
- if (item.VideoType == VideoType.Iso)
- {
- return _isoManager.Mount(item.Path, cancellationToken);
- }
-
- return NullMountTaskResult;
- }
-
public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
{
return new List<ImageType> { ImageType.Primary };
@@ -156,7 +132,7 @@ namespace MediaBrowser.Providers.MediaInfo
public bool Supports(IHasImages item)
{
- return item.LocationType == LocationType.FileSystem && item is Audio;
+ return item is Audio;
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
index 0f2ed1642..a856d5dba 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
@@ -98,7 +98,7 @@ namespace MediaBrowser.Providers.MediaInfo
audio.FormatName = mediaInfo.Format;
audio.TotalBitrate = mediaInfo.TotalBitrate;
- audio.HasEmbeddedImage = mediaStreams.Any(i => i.Type == MediaStreamType.Video);
+ audio.HasEmbeddedImage = mediaStreams.Any(i => i.Type == MediaStreamType.EmbeddedImage);
if (data.streams != null)
{
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs b/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs
index 49c7ebec8..2044979e4 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeHelpers.cs
@@ -12,6 +12,11 @@ namespace MediaBrowser.Providers.MediaInfo
/// <param name="result">The result.</param>
public static void NormalizeFFProbeResult(InternalMediaInfoResult result)
{
+ if (result == null)
+ {
+ throw new ArgumentNullException("result");
+ }
+
if (result.format != null && result.format.tags != null)
{
result.format.tags = ConvertDictionaryToCaseInSensitive(result.format.tags);
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
index 9e9936cab..e3324fe82 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
@@ -168,6 +168,15 @@ namespace MediaBrowser.Providers.MediaInfo
return true;
}
+ if (item is Audio)
+ {
+ // Moved to plural AlbumArtists
+ if (date < new DateTime(2014, 8, 28))
+ {
+ return true;
+ }
+ }
+
if (item.SupportsLocalMetadata)
{
var video = item as Video;
@@ -175,7 +184,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (video != null && !video.IsPlaceHolder)
{
return !video.SubtitleFiles
- .SequenceEqual(SubtitleResolver.GetSubtitleFiles(video, directoryService, false)
+ .SequenceEqual(SubtitleResolver.GetSubtitleFiles(video, directoryService, _fileSystem, false)
.Select(i => i.FullName)
.OrderBy(i => i), StringComparer.OrdinalIgnoreCase);
}
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index 65faae327..f48707582 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -13,10 +13,12 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
+using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
@@ -234,7 +236,7 @@ namespace MediaBrowser.Providers.MediaInfo
await _itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken).ConfigureAwait(false);
if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh ||
- options.MetadataRefreshMode == MetadataRefreshMode.EnsureMetadata)
+ options.MetadataRefreshMode == MetadataRefreshMode.Default)
{
try
{
@@ -255,11 +257,13 @@ namespace MediaBrowser.Providers.MediaInfo
AddDummyChapters(video, chapters);
}
+ NormalizeChapterNames(chapters);
+
await _encodingManager.RefreshChapterImages(new ChapterImageRefreshOptions
{
Chapters = chapters,
Video = video,
- ExtractImages = false,
+ ExtractImages = true,
SaveChapters = false
}, cancellationToken).ConfigureAwait(false);
@@ -268,6 +272,25 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
+ private void NormalizeChapterNames(List<ChapterInfo> chapters)
+ {
+ var index = 1;
+
+ foreach (var chapter in chapters)
+ {
+ TimeSpan time;
+
+ // Check if the name is empty and/or if the name is a time
+ // Some ripping programs do that.
+ if (string.IsNullOrWhiteSpace(chapter.Name) ||
+ TimeSpan.TryParse(chapter.Name, out time))
+ {
+ chapter.Name = string.Format(_localization.GetLocalizedString("LabelChapterName"), index.ToString(CultureInfo.InvariantCulture));
+ }
+ index++;
+ }
+ }
+
private ChapterInfo GetChapterInfo(MediaChapter chapter)
{
var info = new ChapterInfo();
@@ -443,6 +466,11 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
+ private SubtitleOptions GetOptions()
+ {
+ return _config.GetConfiguration<SubtitleOptions>("subtitles");
+ }
+
/// <summary>
/// Adds the external subtitles.
/// </summary>
@@ -456,16 +484,18 @@ namespace MediaBrowser.Providers.MediaInfo
MetadataRefreshOptions options,
CancellationToken cancellationToken)
{
- var subtitleResolver = new SubtitleResolver(_localization);
+ var subtitleResolver = new SubtitleResolver(_localization, _fileSystem);
var externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, currentStreams.Count, options.DirectoryService, false).ToList();
- var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.EnsureMetadata ||
+ var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.Default ||
options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh;
- if (enableSubtitleDownloading && (_config.Configuration.SubtitleOptions.DownloadEpisodeSubtitles &&
+ var subtitleOptions = GetOptions();
+
+ if (enableSubtitleDownloading && (subtitleOptions.DownloadEpisodeSubtitles &&
video is Episode) ||
- (_config.Configuration.SubtitleOptions.DownloadMovieSubtitles &&
+ (subtitleOptions.DownloadMovieSubtitles &&
video is Movie))
{
var downloadedLanguages = await new SubtitleDownloader(_logger,
@@ -473,9 +503,9 @@ namespace MediaBrowser.Providers.MediaInfo
.DownloadSubtitles(video,
currentStreams,
externalSubtitleStreams,
- _config.Configuration.SubtitleOptions.SkipIfGraphicalSubtitlesPresent,
- _config.Configuration.SubtitleOptions.SkipIfAudioTrackMatches,
- _config.Configuration.SubtitleOptions.DownloadLanguages,
+ subtitleOptions.SkipIfGraphicalSubtitlesPresent,
+ subtitleOptions.SkipIfAudioTrackMatches,
+ subtitleOptions.DownloadLanguages,
cancellationToken).ConfigureAwait(false);
// Rescan
@@ -492,9 +522,11 @@ namespace MediaBrowser.Providers.MediaInfo
private async Task<List<ChapterInfo>> DownloadChapters(Video video, List<ChapterInfo> currentChapters, CancellationToken cancellationToken)
{
- if ((_config.Configuration.ChapterOptions.DownloadEpisodeChapters &&
+ var options = _chapterManager.GetConfiguration();
+
+ if ((options.DownloadEpisodeChapters &&
video is Episode) ||
- (_config.Configuration.ChapterOptions.DownloadMovieChapters &&
+ (options.DownloadMovieChapters &&
video is Movie))
{
var results = await _chapterManager.Search(video, cancellationToken).ConfigureAwait(false);
@@ -568,7 +600,6 @@ namespace MediaBrowser.Providers.MediaInfo
{
chapters.Add(new ChapterInfo
{
- Name = "Chapter " + index,
StartPositionTicks = currentChapterTicks
});
@@ -768,7 +799,7 @@ namespace MediaBrowser.Providers.MediaInfo
// Assuming they're named "vts_05_01", take all files whose second part matches that of the first file
if (files.Count > 0)
{
- var parts = Path.GetFileNameWithoutExtension(files[0].FullName).Split('_');
+ var parts = _fileSystem.GetFileNameWithoutExtension(files[0]).Split('_');
if (parts.Length == 3)
{
@@ -776,7 +807,7 @@ namespace MediaBrowser.Providers.MediaInfo
files = files.TakeWhile(f =>
{
- var fileParts = Path.GetFileNameWithoutExtension(f.FullName).Split('_');
+ var fileParts = _fileSystem.GetFileNameWithoutExtension(f).Split('_');
return fileParts.Length == 3 && string.Equals(title, fileParts[1], StringComparison.OrdinalIgnoreCase);
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
index c12f74fa6..78d1fac47 100644
--- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
@@ -13,10 +14,12 @@ namespace MediaBrowser.Providers.MediaInfo
public class SubtitleResolver
{
private readonly ILocalizationManager _localization;
+ private readonly IFileSystem _fileSystem;
- public SubtitleResolver(ILocalizationManager localization)
+ public SubtitleResolver(ILocalizationManager localization, IFileSystem fileSystem)
{
_localization = localization;
+ _fileSystem = fileSystem;
}
public IEnumerable<MediaStream> GetExternalSubtitleStreams(Video video,
@@ -24,17 +27,17 @@ namespace MediaBrowser.Providers.MediaInfo
IDirectoryService directoryService,
bool clearCache)
{
- var files = GetSubtitleFiles(video, directoryService, clearCache);
+ var files = GetSubtitleFiles(video, directoryService, _fileSystem, clearCache);
var streams = new List<MediaStream>();
- var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
+ var videoFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(video.Path);
foreach (var file in files)
{
var fullName = file.FullName;
- var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName);
+ var fileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(file);
var codec = Path.GetExtension(fullName).ToLower().TrimStart('.');
@@ -96,7 +99,7 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
- public static IEnumerable<FileSystemInfo> GetSubtitleFiles(Video video, IDirectoryService directoryService, bool clearCache)
+ public static IEnumerable<FileSystemInfo> GetSubtitleFiles(Video video, IDirectoryService directoryService, IFileSystem fileSystem, bool clearCache)
{
var containingPath = video.ContainingFolderPath;
@@ -107,16 +110,14 @@ namespace MediaBrowser.Providers.MediaInfo
var files = directoryService.GetFiles(containingPath, clearCache);
- var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
+ var videoFileNameWithoutExtension = fileSystem.GetFileNameWithoutExtension(video.Path);
return files.Where(i =>
{
if (!i.Attributes.HasFlag(FileAttributes.Directory) &&
SubtitleExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
{
- var fullName = i.FullName;
-
- var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fullName);
+ var fileNameWithoutExtension = fileSystem.GetFileNameWithoutExtension(i);
if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase))
{
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs
new file mode 100644
index 000000000..63df3f50d
--- /dev/null
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs
@@ -0,0 +1,137 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Subtitles;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Model.Providers;
+
+namespace MediaBrowser.Providers.MediaInfo
+{
+ public class SubtitleScheduledTask : IScheduledTask
+ {
+ private readonly ILibraryManager _libraryManager;
+ private readonly IServerConfigurationManager _config;
+ private readonly ISubtitleManager _subtitleManager;
+ private readonly ILogger _logger;
+
+ public SubtitleScheduledTask(ILibraryManager libraryManager, IServerConfigurationManager config, ISubtitleManager subtitleManager, ILogger logger)
+ {
+ _libraryManager = libraryManager;
+ _config = config;
+ _subtitleManager = subtitleManager;
+ _logger = logger;
+ }
+
+ public string Name
+ {
+ get { return "Download missing subtitles"; }
+ }
+
+ public string Description
+ {
+ get { return "Searches the internet for missing subtitles based on metadata configuration."; }
+ }
+
+ public string Category
+ {
+ get { return "Library"; }
+ }
+
+ private SubtitleOptions GetOptions()
+ {
+ return _config.GetConfiguration<SubtitleOptions>("subtitles");
+ }
+
+ public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
+ {
+ var options = GetOptions();
+
+ var videos = _libraryManager.RootFolder
+ .RecursiveChildren
+ .OfType<Video>()
+ .Where(i =>
+ {
+ if (i.LocationType == LocationType.Remote || i.LocationType == LocationType.Virtual)
+ {
+ return false;
+ }
+
+ return (options.DownloadEpisodeSubtitles &&
+ i is Episode) ||
+ (options.DownloadMovieSubtitles &&
+ i is Movie);
+ })
+ .ToList();
+
+ var numComplete = 0;
+
+ foreach (var video in videos)
+ {
+ try
+ {
+ await DownloadSubtitles(video, options, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error downloading subtitles for {0}", ex, video.Path);
+ }
+
+ // Update progress
+ numComplete++;
+ double percent = numComplete;
+ percent /= videos.Count;
+
+ progress.Report(100 * percent);
+ }
+ }
+
+ private async Task DownloadSubtitles(Video video, SubtitleOptions options, CancellationToken cancellationToken)
+ {
+ if ((options.DownloadEpisodeSubtitles &&
+ video is Episode) ||
+ (options.DownloadMovieSubtitles &&
+ video is Movie))
+ {
+ var mediaStreams = video.GetMediaSources(false).First().MediaStreams;
+
+ var externalSubtitleStreams = mediaStreams.Where(i => i.Type == MediaStreamType.Subtitle && i.IsExternal).ToList();
+ var currentStreams = mediaStreams.Except(externalSubtitleStreams).ToList();
+
+ var downloadedLanguages = await new SubtitleDownloader(_logger,
+ _subtitleManager)
+ .DownloadSubtitles(video,
+ currentStreams,
+ externalSubtitleStreams,
+ options.SkipIfGraphicalSubtitlesPresent,
+ options.SkipIfAudioTrackMatches,
+ options.DownloadLanguages,
+ cancellationToken).ConfigureAwait(false);
+
+ // Rescan
+ if (downloadedLanguages.Count > 0)
+ {
+ await video.RefreshMetadata(cancellationToken).ConfigureAwait(false);
+ }
+ }
+ }
+
+ public IEnumerable<ITaskTrigger> GetDefaultTriggers()
+ {
+ return new ITaskTrigger[]
+ {
+ new DailyTrigger { TimeOfDay = TimeSpan.FromHours(3) },
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
index a2ec897a1..82ccdc4ac 100644
--- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
@@ -5,11 +5,11 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
+using MediaBrowser.Model.MediaInfo;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Providers.MediaInfo
{
diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
index d812abe9f..32d53db43 100644
--- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
@@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.Movies
private readonly ILocalizationManager _localization;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
-
+
public MovieDbProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization)
{
_jsonSerializer = jsonSerializer;
@@ -90,7 +90,7 @@ namespace MediaBrowser.Providers.Movies
remoteResult.ProductionYear = remoteResult.PremiereDate.Value.Year;
}
}
-
+
remoteResult.SetProviderId(MetadataProviders.Tmdb, obj.id.ToString(_usCulture));
if (!string.IsNullOrWhiteSpace(obj.imdb_id))
@@ -252,7 +252,7 @@ namespace MediaBrowser.Providers.Movies
var path = GetMovieDataPath(_configurationManager.ApplicationPaths, tmdbId);
var filename = string.Format("all-{0}.json",
- preferredLanguage ?? string.Empty);
+ preferredLanguage);
return Path.Combine(path, filename);
}
@@ -286,8 +286,9 @@ namespace MediaBrowser.Providers.Movies
url += string.Format("&language={0}", language);
}
+ var includeImageLanguageParam = string.Join(",", imageLanguages.ToArray());
// Get images in english and with no language
- url += "&include_image_language=" + string.Join(",", imageLanguages.ToArray());
+ url += "&include_image_language=" + includeImageLanguageParam;
CompleteMovieData mainResult;
@@ -312,7 +313,7 @@ namespace MediaBrowser.Providers.Movies
{
_logger.Info("MovieDbProvider couldn't find meta for language " + language + ". Trying English...");
- url = string.Format(GetMovieInfo3, id, ApiKey) + "&include_image_language=en,null&language=en";
+ url = string.Format(GetMovieInfo3, id, ApiKey) + "&include_image_language=" + includeImageLanguageParam + "&language=en";
using (var json = await GetMovieDbResponse(new HttpRequestOptions
{
@@ -324,14 +325,9 @@ namespace MediaBrowser.Providers.Movies
{
mainResult = _jsonSerializer.DeserializeFromStream<CompleteMovieData>(json);
}
-
- if (String.IsNullOrEmpty(mainResult.overview))
- {
- _logger.Error("MovieDbProvider - Unable to find information for (id:" + id + ")");
- return null;
- }
}
}
+
return mainResult;
}
diff --git a/MediaBrowser.Providers/Movies/MovieDbSearch.cs b/MediaBrowser.Providers/Movies/MovieDbSearch.cs
index 500b71a79..85a0d5fa1 100644
--- a/MediaBrowser.Providers/Movies/MovieDbSearch.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbSearch.cs
@@ -109,7 +109,8 @@ namespace MediaBrowser.Providers.Movies
{
if (year.HasValue && i.ProductionYear.HasValue)
{
- return year.Value == i.ProductionYear.Value;
+ // Allow one year tolerance
+ return Math.Abs(year.Value - i.ProductionYear.Value) <= 1;
}
return true;
@@ -146,7 +147,7 @@ namespace MediaBrowser.Providers.Movies
Name = i.title ?? i.original_title ?? i.name,
ImageUrl = string.IsNullOrWhiteSpace(i.poster_path) ? null : baseImageUrl + i.poster_path
};
-
+
if (!string.IsNullOrWhiteSpace(i.release_date))
{
DateTime r;
@@ -177,11 +178,19 @@ namespace MediaBrowser.Providers.Movies
// These dates are always in this exact format
if (DateTime.TryParseExact(result.release_date, "yyyy-MM-dd", EnUs, DateTimeStyles.None, out r))
{
- return Math.Abs(r.Year - year.Value);
+ // Allow one year tolernace, preserve order from Tmdb
+ var variance = Math.Abs(r.Year - year.Value);
+
+ if (variance <= 1)
+ {
+ return 0;
+ }
+
+ return variance;
}
}
- return 0;
+ return int.MaxValue;
}
/// <summary>
diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs
index f049c79e1..a3d9b5642 100644
--- a/MediaBrowser.Providers/Music/AlbumMetadataService.cs
+++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs
@@ -9,8 +9,6 @@ using MediaBrowser.Providers.Manager;
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
namespace MediaBrowser.Providers.Music
{
@@ -104,17 +102,15 @@ namespace MediaBrowser.Providers.Music
{
var updateType = ItemUpdateType.None;
- var albumArtist = songs
+ var albumArtists = songs
.SelectMany(i => i.AlbumArtists)
- .FirstOrDefault(i => !string.IsNullOrEmpty(i));
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
- if (!string.IsNullOrEmpty(albumArtist))
+ if (!item.AlbumArtists.SequenceEqual(albumArtists, StringComparer.OrdinalIgnoreCase))
{
- if (!string.Equals(item.AlbumArtist, albumArtist, StringComparison.Ordinal))
- {
- item.AlbumArtist = albumArtist;
- updateType = updateType | ItemUpdateType.MetadataDownload;
- }
+ item.AlbumArtists = albumArtists;
+ updateType = updateType | ItemUpdateType.MetadataDownload;
}
return updateType;
diff --git a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs
index a9b3d8e11..3667d70cf 100644
--- a/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/AudioDbAlbumProvider.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
@@ -69,7 +70,10 @@ namespace MediaBrowser.Providers.Music
private void ProcessResult(MusicAlbum item, Album result)
{
- item.AlbumArtist = result.strArtist;
+ if (!string.IsNullOrWhiteSpace(result.strArtist))
+ {
+ item.AlbumArtists = new List<string> { result.strArtist };
+ }
if (!string.IsNullOrEmpty(result.intYearReleased))
{
@@ -86,6 +90,8 @@ namespace MediaBrowser.Providers.Music
item.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, result.strMusicBrainzArtistID);
item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, result.strMusicBrainzID);
+
+ item.Overview = (result.strDescriptionEN ?? string.Empty).StripHtml();
}
public string Name
diff --git a/MediaBrowser.Providers/Music/Extensions.cs b/MediaBrowser.Providers/Music/Extensions.cs
index b14a1ba09..c83e69165 100644
--- a/MediaBrowser.Providers/Music/Extensions.cs
+++ b/MediaBrowser.Providers/Music/Extensions.cs
@@ -8,15 +8,15 @@ namespace MediaBrowser.Providers.Music
{
public static string GetAlbumArtist(this AlbumInfo info)
{
- var id = info.AlbumArtists.FirstOrDefault();
+ var id = info.SongInfos.SelectMany(i => i.AlbumArtists)
+ .FirstOrDefault(i => !string.IsNullOrEmpty(i));
- if (string.IsNullOrEmpty(id))
+ if (!string.IsNullOrEmpty(id))
{
- return info.SongInfos.SelectMany(i => i.AlbumArtists)
- .FirstOrDefault(i => !string.IsNullOrEmpty(i));
+ return id;
}
- return id;
+ return info.AlbumArtists.FirstOrDefault();
}
public static string GetReleaseGroupId(this AlbumInfo info)
diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
index ccab30bc6..94d682f44 100644
--- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
@@ -67,7 +67,7 @@ namespace MediaBrowser.Providers.Music
if (!string.IsNullOrEmpty(artistMusicBrainzId))
{
- await FanartArtistProvider.Current.EnsureMovieXml(artistMusicBrainzId, cancellationToken).ConfigureAwait(false);
+ await FanartArtistProvider.Current.EnsureArtistXml(artistMusicBrainzId, cancellationToken).ConfigureAwait(false);
var artistXmlPath = FanartArtistProvider.GetArtistXmlPath(_config.CommonApplicationPaths, artistMusicBrainzId);
diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
index b9916dfba..a8df95fd1 100644
--- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
@@ -79,7 +79,7 @@ namespace MediaBrowser.Providers.Music
if (!String.IsNullOrEmpty(artistMusicBrainzId))
{
- await EnsureMovieXml(artistMusicBrainzId, cancellationToken).ConfigureAwait(false);
+ await EnsureArtistXml(artistMusicBrainzId, cancellationToken).ConfigureAwait(false);
var artistXmlPath = GetArtistXmlPath(_config.CommonApplicationPaths, artistMusicBrainzId);
@@ -390,7 +390,7 @@ namespace MediaBrowser.Providers.Music
}
private readonly Task _cachedTask = Task.FromResult(true);
- internal Task EnsureMovieXml(string musicBrainzId, CancellationToken cancellationToken)
+ internal Task EnsureArtistXml(string musicBrainzId, CancellationToken cancellationToken)
{
var xmlPath = GetArtistXmlPath(_config.ApplicationPaths, musicBrainzId);
diff --git a/MediaBrowser.Providers/Music/LastFmImageProvider.cs b/MediaBrowser.Providers/Music/LastFmImageProvider.cs
deleted file mode 100644
index b55a97351..000000000
--- a/MediaBrowser.Providers/Music/LastFmImageProvider.cs
+++ /dev/null
@@ -1,164 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Providers.Music
-{
- public class LastfmImageProvider : IRemoteImageProvider, IHasOrder
- {
- private readonly IHttpClient _httpClient;
- private readonly IServerConfigurationManager _config;
-
- public LastfmImageProvider(IHttpClient httpClient, IServerConfigurationManager config)
- {
- _httpClient = httpClient;
- _config = config;
- }
-
- public string Name
- {
- get { return ProviderName; }
- }
-
- public static string ProviderName
- {
- get { return "last.fm"; }
- }
-
- public bool Supports(IHasImages item)
- {
- return item is MusicAlbum || item is MusicArtist;
- }
-
- public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
- {
- return new List<ImageType>
- {
- ImageType.Primary
- };
- }
-
- public Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken)
- {
- var list = new List<RemoteImageInfo>();
-
- RemoteImageInfo info = null;
-
- var musicBrainzId = item is MusicAlbum ?
- item.GetProviderId(MetadataProviders.MusicBrainzAlbum) :
- item.GetProviderId(MetadataProviders.MusicBrainzArtist);
-
- if (!string.IsNullOrEmpty(musicBrainzId))
- {
- var cachePath = Path.Combine(_config.ApplicationPaths.CachePath, "lastfm", musicBrainzId, "image.txt");
-
- try
- {
- var parts = File.ReadAllText(cachePath).Split('|');
-
- info = GetInfo(parts.FirstOrDefault(), parts.LastOrDefault());
- }
- catch (DirectoryNotFoundException)
- {
- }
- catch (FileNotFoundException)
- {
- }
- }
-
- if (info == null)
- {
- var musicBrainzReleaseGroupId = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
-
- if (!string.IsNullOrEmpty(musicBrainzReleaseGroupId))
- {
- var cachePath = Path.Combine(_config.ApplicationPaths.CachePath, "lastfm", musicBrainzReleaseGroupId, "image.txt");
-
- try
- {
- var parts = File.ReadAllText(cachePath).Split('|');
-
- info = GetInfo(parts.FirstOrDefault(), parts.LastOrDefault());
- }
- catch (DirectoryNotFoundException)
- {
- }
- catch (FileNotFoundException)
- {
- }
- }
- }
-
- if (info != null)
- {
- list.Add(info);
- }
-
- // The only info we have is size
- return Task.FromResult<IEnumerable<RemoteImageInfo>>(list.OrderByDescending(i => i.Width ?? 0));
- }
-
- private RemoteImageInfo GetInfo(string url, string size)
- {
- if (string.IsNullOrEmpty(url))
- {
- return null;
- }
-
- var info = new RemoteImageInfo
- {
- ProviderName = Name,
- Url = url,
- Type = ImageType.Primary
- };
-
- if (string.Equals(size, "mega", StringComparison.OrdinalIgnoreCase))
- {
-
- }
- else if (string.Equals(size, "extralarge", StringComparison.OrdinalIgnoreCase))
- {
-
- }
- else if (string.Equals(size, "large", StringComparison.OrdinalIgnoreCase))
- {
-
- }
- else if (string.Equals(size, "medium", StringComparison.OrdinalIgnoreCase))
- {
-
- }
-
- return info;
- }
-
- public int Order
- {
- get
- {
- // After all others
- return 3;
- }
- }
-
- public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
- {
- return _httpClient.GetResponse(new HttpRequestOptions
- {
- CancellationToken = cancellationToken,
- Url = url,
- ResourcePool = LastfmArtistProvider.LastfmResourcePool
- });
- }
- }
-}
diff --git a/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs b/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs
deleted file mode 100644
index 846539748..000000000
--- a/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs
+++ /dev/null
@@ -1,322 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Serialization;
-using MoreLinq;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Providers.Music
-{
- public class LastfmAlbumProvider : IRemoteMetadataProvider<MusicAlbum, AlbumInfo>, IHasOrder
- {
- private readonly IJsonSerializer _json;
- private readonly IHttpClient _httpClient;
-
- private readonly IServerConfigurationManager _config;
- private readonly ILogger _logger;
-
- public LastfmAlbumProvider(IHttpClient httpClient, IJsonSerializer json, IServerConfigurationManager config, ILogger logger)
- {
- _httpClient = httpClient;
- _json = json;
- _config = config;
- _logger = logger;
- }
-
- public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
- {
- return new List<RemoteSearchResult>();
- }
-
- public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo id, CancellationToken cancellationToken)
- {
- var result = new MetadataResult<MusicAlbum>();
-
- var lastFmData = await GetAlbumResult(id, cancellationToken).ConfigureAwait(false);
-
- if (lastFmData != null && lastFmData.album != null)
- {
- result.HasMetadata = true;
- result.Item = new MusicAlbum();
- ProcessAlbumData(result.Item, lastFmData.album);
- }
-
- return result;
- }
-
- private async Task<LastfmGetAlbumResult> GetAlbumResult(AlbumInfo item, CancellationToken cancellationToken)
- {
- // Try album release Id
- var id = item.GetReleaseId();
- if (!string.IsNullOrEmpty(id))
- {
- var result = await GetAlbumResult(id, cancellationToken).ConfigureAwait(false);
-
- if (result != null && result.album != null)
- {
- return result;
- }
- }
-
- // Try album release group Id
- id = item.GetReleaseGroupId();
- if (!string.IsNullOrEmpty(id))
- {
- var result = await GetAlbumResult(id, cancellationToken).ConfigureAwait(false);
-
- if (result != null && result.album != null)
- {
- return result;
- }
- }
-
- var albumArtist = item.GetAlbumArtist();
- // Get each song, distinct by the combination of AlbumArtist and Album
- var songs = item.SongInfos.DistinctBy(i => (i.AlbumArtists.FirstOrDefault() ?? string.Empty) + (i.Album ?? string.Empty), StringComparer.OrdinalIgnoreCase).ToList();
-
- foreach (var song in songs.Where(song => !string.IsNullOrEmpty(song.Album) && !string.IsNullOrEmpty(song.AlbumArtists.FirstOrDefault())))
- {
- var result = await GetAlbumResult(song.AlbumArtists.FirstOrDefault(), song.Album, cancellationToken).ConfigureAwait(false);
-
- if (result != null && result.album != null)
- {
- return result;
- }
- }
-
- if (string.IsNullOrEmpty(albumArtist))
- {
- return null;
- }
-
- return await GetAlbumResult(albumArtist, item.Name, cancellationToken);
- }
-
- private async Task<LastfmGetAlbumResult> GetAlbumResult(string artist, string album, CancellationToken cancellationToken)
- {
- // Get albu info using artist and album name
- var url = LastfmArtistProvider.RootUrl + string.Format("method=album.getInfo&artist={0}&album={1}&api_key={2}&format=json", UrlEncode(artist), UrlEncode(album), LastfmArtistProvider.ApiKey);
-
- using (var json = await _httpClient.Get(new HttpRequestOptions
- {
- Url = url,
- ResourcePool = LastfmArtistProvider.LastfmResourcePool,
- CancellationToken = cancellationToken,
- EnableHttpCompression = false
-
- }).ConfigureAwait(false))
- {
- using (var reader = new StreamReader(json))
- {
- var jsonText = await reader.ReadToEndAsync().ConfigureAwait(false);
-
- // Fix their bad json
- jsonText = jsonText.Replace("\"#text\"", "\"url\"");
-
- return _json.DeserializeFromString<LastfmGetAlbumResult>(jsonText);
- }
- }
- }
-
- private async Task<LastfmGetAlbumResult> GetAlbumResult(string musicbraizId, CancellationToken cancellationToken)
- {
- // Get albu info using artist and album name
- var url = LastfmArtistProvider.RootUrl + string.Format("method=album.getInfo&mbid={0}&api_key={1}&format=json", musicbraizId, LastfmArtistProvider.ApiKey);
-
- using (var json = await _httpClient.Get(new HttpRequestOptions
- {
- Url = url,
- ResourcePool = LastfmArtistProvider.LastfmResourcePool,
- CancellationToken = cancellationToken,
- EnableHttpCompression = false
-
- }).ConfigureAwait(false))
- {
- return _json.DeserializeFromStream<LastfmGetAlbumResult>(json);
- }
- }
-
- private void ProcessAlbumData(MusicAlbum item, LastfmAlbum data)
- {
- var overview = data.wiki != null ? data.wiki.content : null;
-
- if (!item.LockedFields.Contains(MetadataFields.Overview))
- {
- item.Overview = overview;
- }
-
- // Only grab the date here if the album doesn't already have one, since id3 tags are preferred
- DateTime release;
-
- if (DateTime.TryParse(data.releasedate, out release))
- {
- // Lastfm sends back null as sometimes 1901, other times 0
- if (release.Year > 1901)
- {
- if (!item.PremiereDate.HasValue)
- {
- item.PremiereDate = release;
- }
-
- if (!item.ProductionYear.HasValue)
- {
- item.ProductionYear = release.Year;
- }
- }
- }
-
- string imageSize;
- var url = LastfmHelper.GetImageUrl(data, out imageSize);
-
- var musicBrainzId = item.GetProviderId(MetadataProviders.MusicBrainzAlbum) ??
- item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
-
- if (!string.IsNullOrEmpty(musicBrainzId) && !string.IsNullOrEmpty(url))
- {
- LastfmHelper.SaveImageInfo(_config.ApplicationPaths, _logger, musicBrainzId, url, imageSize);
- }
- }
-
- /// <summary>
- /// Encodes an URL.
- /// </summary>
- /// <param name="name">The name.</param>
- /// <returns>System.String.</returns>
- private string UrlEncode(string name)
- {
- return WebUtility.UrlEncode(name);
- }
-
- public string Name
- {
- get { return "last.fm"; }
- }
-
- public int Order
- {
- get
- {
- // After fanart & audiodb
- return 2;
- }
- }
-
- public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
- {
- throw new NotImplementedException();
- }
- }
-
- #region Result Objects
-
- public class LastfmStats
- {
- public string listeners { get; set; }
- public string playcount { get; set; }
- }
-
- public class LastfmTag
- {
- public string name { get; set; }
- public string url { get; set; }
- }
-
-
- public class LastfmTags
- {
- public List<LastfmTag> tag { get; set; }
- }
-
- public class LastfmFormationInfo
- {
- public string yearfrom { get; set; }
- public string yearto { get; set; }
- }
-
- public class LastFmBio
- {
- public string published { get; set; }
- public string summary { get; set; }
- public string content { get; set; }
- public string placeformed { get; set; }
- public string yearformed { get; set; }
- public List<LastfmFormationInfo> formationlist { get; set; }
- }
-
- public class LastFmImage
- {
- public string url { get; set; }
- public string size { get; set; }
- }
-
- public class LastfmArtist : IHasLastFmImages
- {
- public string name { get; set; }
- public string mbid { get; set; }
- public string url { get; set; }
- public string streamable { get; set; }
- public string ontour { get; set; }
- public LastfmStats stats { get; set; }
- public List<LastfmArtist> similar { get; set; }
- public LastfmTags tags { get; set; }
- public LastFmBio bio { get; set; }
- public List<LastFmImage> image { get; set; }
- }
-
-
- public class LastfmAlbum : IHasLastFmImages
- {
- public string name { get; set; }
- public string artist { get; set; }
- public string id { get; set; }
- public string mbid { get; set; }
- public string releasedate { get; set; }
- public int listeners { get; set; }
- public int playcount { get; set; }
- public LastfmTags toptags { get; set; }
- public LastFmBio wiki { get; set; }
- public List<LastFmImage> image { get; set; }
- }
-
- public interface IHasLastFmImages
- {
- List<LastFmImage> image { get; set; }
- }
-
- public class LastfmGetAlbumResult
- {
- public LastfmAlbum album { get; set; }
- }
-
- public class LastfmGetArtistResult
- {
- public LastfmArtist artist { get; set; }
- }
-
- public class Artistmatches
- {
- public List<LastfmArtist> artist { get; set; }
- }
-
- public class LastfmArtistSearchResult
- {
- public Artistmatches artistmatches { get; set; }
- }
-
- public class LastfmArtistSearchResults
- {
- public LastfmArtistSearchResult results { get; set; }
- }
-
- #endregion
-}
diff --git a/MediaBrowser.Providers/Music/LastfmArtistProvider.cs b/MediaBrowser.Providers/Music/LastfmArtistProvider.cs
deleted file mode 100644
index a2aa9d719..000000000
--- a/MediaBrowser.Providers/Music/LastfmArtistProvider.cs
+++ /dev/null
@@ -1,160 +0,0 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Serialization;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Net;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Providers.Music
-{
- public class LastfmArtistProvider : IRemoteMetadataProvider<MusicArtist, ArtistInfo>, IHasOrder
- {
- private readonly IJsonSerializer _json;
- private readonly IHttpClient _httpClient;
-
- internal static readonly SemaphoreSlim LastfmResourcePool = new SemaphoreSlim(4, 4);
-
- internal const string RootUrl = @"http://ws.audioscrobbler.com/2.0/?";
- internal static string ApiKey = "7b76553c3eb1d341d642755aecc40a33";
-
- private readonly IServerConfigurationManager _config;
- private readonly ILogger _logger;
-
- public LastfmArtistProvider(IHttpClient httpClient, IJsonSerializer json, IServerConfigurationManager config, ILogger logger)
- {
- _httpClient = httpClient;
- _json = json;
- _config = config;
- _logger = logger;
- }
-
- public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
- {
- return new List<RemoteSearchResult>();
- }
-
- public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo id, CancellationToken cancellationToken)
- {
- var result = new MetadataResult<MusicArtist>();
-
- var musicBrainzId = id.GetMusicBrainzArtistId();
-
- if (!String.IsNullOrWhiteSpace(musicBrainzId))
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- result.Item = new MusicArtist();
- result.HasMetadata = true;
-
- await FetchLastfmData(result.Item, musicBrainzId, cancellationToken).ConfigureAwait(false);
- }
-
- return result;
- }
-
- protected async Task FetchLastfmData(MusicArtist item, string musicBrainzId, CancellationToken cancellationToken)
- {
- // Get artist info with provided id
- var url = RootUrl + String.Format("method=artist.getInfo&mbid={0}&api_key={1}&format=json", UrlEncode(musicBrainzId), ApiKey);
-
- LastfmGetArtistResult result;
-
- using (var json = await _httpClient.Get(new HttpRequestOptions
- {
- Url = url,
- ResourcePool = LastfmResourcePool,
- CancellationToken = cancellationToken,
- EnableHttpCompression = false
-
- }).ConfigureAwait(false))
- {
- using (var reader = new StreamReader(json))
- {
- var jsonText = await reader.ReadToEndAsync().ConfigureAwait(false);
-
- // Fix their bad json
- jsonText = jsonText.Replace("\"#text\"", "\"url\"");
-
- result = _json.DeserializeFromString<LastfmGetArtistResult>(jsonText);
- }
- }
-
- if (result != null && result.artist != null)
- {
- ProcessArtistData(item, result.artist, musicBrainzId);
- }
- }
-
- private void ProcessArtistData(MusicArtist artist, LastfmArtist data, string musicBrainzId)
- {
- var yearFormed = 0;
-
- if (data.bio != null)
- {
- Int32.TryParse(data.bio.yearformed, out yearFormed);
- if (!artist.LockedFields.Contains(MetadataFields.Overview))
- {
- artist.Overview = (data.bio.content ?? string.Empty).StripHtml();
- }
- if (!string.IsNullOrEmpty(data.bio.placeformed) && !artist.LockedFields.Contains(MetadataFields.ProductionLocations))
- {
- artist.AddProductionLocation(data.bio.placeformed);
- }
- }
-
- if (yearFormed > 0)
- {
- artist.PremiereDate = new DateTime(yearFormed, 1, 1, 0, 0, 0, DateTimeKind.Utc);
-
- artist.ProductionYear = yearFormed;
- }
-
- string imageSize;
- var url = LastfmHelper.GetImageUrl(data, out imageSize);
-
- if (!string.IsNullOrEmpty(musicBrainzId) && !string.IsNullOrEmpty(url))
- {
- LastfmHelper.SaveImageInfo(_config.ApplicationPaths, _logger, musicBrainzId, url, imageSize);
- }
- }
-
- /// <summary>
- /// Encodes an URL.
- /// </summary>
- /// <param name="name">The name.</param>
- /// <returns>System.String.</returns>
- private string UrlEncode(string name)
- {
- return WebUtility.UrlEncode(name);
- }
-
- public string Name
- {
- get { return "last.fm"; }
- }
-
- public int Order
- {
- get
- {
- // After fanart & audiodb
- return 2;
- }
- }
-
- public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/MediaBrowser.Providers/Music/LastfmHelper.cs b/MediaBrowser.Providers/Music/LastfmHelper.cs
deleted file mode 100644
index 7c83cec6b..000000000
--- a/MediaBrowser.Providers/Music/LastfmHelper.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Model.Logging;
-using System;
-using System.IO;
-using System.Linq;
-
-namespace MediaBrowser.Providers.Music
-{
- public static class LastfmHelper
- {
- public static string GetImageUrl(IHasLastFmImages data, out string size)
- {
- size = null;
-
- if (data.image == null)
- {
- return null;
- }
-
- var validImages = data.image
- .Where(i => !string.IsNullOrWhiteSpace(i.url))
- .ToList();
-
- var img = validImages
- .FirstOrDefault(i => string.Equals(i.size, "mega", StringComparison.OrdinalIgnoreCase)) ??
- data.image.FirstOrDefault(i => string.Equals(i.size, "extralarge", StringComparison.OrdinalIgnoreCase)) ??
- data.image.FirstOrDefault(i => string.Equals(i.size, "large", StringComparison.OrdinalIgnoreCase)) ??
- data.image.FirstOrDefault(i => string.Equals(i.size, "medium", StringComparison.OrdinalIgnoreCase)) ??
- data.image.FirstOrDefault();
-
- if (img != null)
- {
- size = img.size;
- return img.url;
- }
-
- return null;
- }
-
- public static void SaveImageInfo(IApplicationPaths appPaths, ILogger logger, string musicBrainzId, string url, string size)
- {
- if (appPaths == null)
- {
- throw new ArgumentNullException("appPaths");
- }
- if (string.IsNullOrEmpty(musicBrainzId))
- {
- throw new ArgumentNullException("musicBrainzId");
- }
- if (string.IsNullOrEmpty(url))
- {
- throw new ArgumentNullException("url");
- }
-
- var cachePath = Path.Combine(appPaths.CachePath, "lastfm", musicBrainzId, "image.txt");
-
- try
- {
- if (string.IsNullOrEmpty(url))
- {
- File.Delete(cachePath);
- }
- else
- {
- Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
- File.WriteAllText(cachePath, url + "|" + size);
- }
- }
- catch (IOException ex)
- {
- // Don't fail if this is unable to write
- logger.ErrorException("Error saving to {0}", ex, cachePath);
- }
- }
- }
-}
diff --git a/MediaBrowser.Providers/Music/SoundtrackPostScanTask.cs b/MediaBrowser.Providers/Music/SoundtrackPostScanTask.cs
deleted file mode 100644
index dc94460f4..000000000
--- a/MediaBrowser.Providers/Music/SoundtrackPostScanTask.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using MediaBrowser.Controller.Library;
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Providers.Music
-{
- public class SoundtrackPostScanTask : ILibraryPostScanTask
- {
- private readonly ILibraryManager _libraryManager;
-
- public SoundtrackPostScanTask(ILibraryManager libraryManager)
- {
- _libraryManager = libraryManager;
- }
-
- private readonly Task _cachedTask = Task.FromResult(true);
- public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
- {
- RunInternal(progress, cancellationToken);
-
- return _cachedTask;
- }
-
- private void RunInternal(IProgress<double> progress, CancellationToken cancellationToken)
- {
- // Reimplement this when more kinds of associations are supported.
-
- progress.Report(100);
- }
- }
-}
diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
index 76d93d946..08e9a3abf 100644
--- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
+++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
@@ -57,22 +57,27 @@ namespace MediaBrowser.Providers.Omdb
Item = new Series()
};
- var imdbId = info.GetProviderId(MetadataProviders.Imdb);
-
var searchResult = await GetSeriesImdbId(info, cancellationToken).ConfigureAwait(false);
- result.Item.Name = searchResult.Item3;
+ result.Item.Name = searchResult.Item4;
- if (string.IsNullOrEmpty(imdbId))
+ if (!string.IsNullOrEmpty(searchResult.Item1))
{
- imdbId = searchResult.Item1;
+ result.Item.SetProviderId(MetadataProviders.Imdb, searchResult.Item1);
+ }
- if (!string.IsNullOrEmpty(searchResult.Item2))
- {
- result.Item.SetProviderId(MetadataProviders.Tvdb, searchResult.Item2);
- }
+ if (!string.IsNullOrEmpty(searchResult.Item2))
+ {
+ result.Item.SetProviderId(MetadataProviders.Tmdb, searchResult.Item2);
}
-
- if (!string.IsNullOrEmpty(imdbId))
+
+ if (!string.IsNullOrEmpty(searchResult.Item3))
+ {
+ result.Item.SetProviderId(MetadataProviders.Tvdb, searchResult.Item3);
+ }
+
+ var imdbId = result.Item.GetProviderId(MetadataProviders.Imdb);
+
+ if (!string.IsNullOrEmpty(info.GetProviderId(MetadataProviders.Imdb)))
{
result.Item.SetProviderId(MetadataProviders.Imdb, imdbId);
result.HasMetadata = true;
@@ -148,16 +153,26 @@ namespace MediaBrowser.Providers.Omdb
return new Tuple<string, string, string>(imdb, tmdb, name);
}
- private async Task<Tuple<string, string, string>> GetSeriesImdbId(SeriesInfo info, CancellationToken cancellationToken)
+ private async Task<Tuple<string, string, string, string>> GetSeriesImdbId(SeriesInfo info, CancellationToken cancellationToken)
{
- var result = await TvdbSeriesProvider.Current.GetMetadata(info, cancellationToken)
- .ConfigureAwait(false);
+ //var result = await TvdbSeriesProvider.Current.GetMetadata(info, cancellationToken)
+ // .ConfigureAwait(false);
+
+ //var imdb = result.HasMetadata ? result.Item.GetProviderId(MetadataProviders.Imdb) : null;
+ //var tvdb = result.HasMetadata ? result.Item.GetProviderId(MetadataProviders.Tvdb) : null;
+ //var name = result.HasMetadata ? result.Item.Name : null;
+
+ //return new Tuple<string, string, string>(imdb, tvdb, name);
+
+ var result = await MovieDbSeriesProvider.Current.GetMetadata(info, cancellationToken)
+ .ConfigureAwait(false);
var imdb = result.HasMetadata ? result.Item.GetProviderId(MetadataProviders.Imdb) : null;
+ var tmdb = result.HasMetadata ? result.Item.GetProviderId(MetadataProviders.Tmdb) : null;
var tvdb = result.HasMetadata ? result.Item.GetProviderId(MetadataProviders.Tvdb) : null;
var name = result.HasMetadata ? result.Item.Name : null;
- return new Tuple<string, string, string>(imdb, tvdb, name);
+ return new Tuple<string, string, string, string>(imdb, tmdb, tvdb, name);
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Providers/Photos/ExifReader.cs b/MediaBrowser.Providers/Photos/ExifReader.cs
deleted file mode 100644
index 8526a7f2a..000000000
--- a/MediaBrowser.Providers/Photos/ExifReader.cs
+++ /dev/null
@@ -1,613 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Text;
-
-namespace MediaBrowser.Providers.Photos
-{
- /// <summary>
- /// A class for reading Exif data from a JPEG file. The file will be open for reading for as long as the class exists.
- /// <seealso cref="http://gvsoft.homedns.org/exif/Exif-explanation.html"/>
- /// </summary>
- public class ExifReader : IDisposable
- {
- private readonly FileStream fileStream = null;
- private readonly BinaryReader reader = null;
-
- /// <summary>
- /// The catalogue of tag ids and their absolute offsets within the
- /// file
- /// </summary>
- private Dictionary<ushort, long> catalogue;
-
- /// <summary>
- /// Indicates whether to read data using big or little endian byte aligns
- /// </summary>
- private bool isLittleEndian;
-
- /// <summary>
- /// The position in the filestream at which the TIFF header starts
- /// </summary>
- private long tiffHeaderStart;
-
- public ExifReader(string fileName)
- {
- // JPEG encoding uses big endian (i.e. Motorola) byte aligns. The TIFF encoding
- // found later in the document will specify the byte aligns used for the
- // rest of the document.
- isLittleEndian = false;
-
- try
- {
- // Open the file in a stream
- fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
- reader = new BinaryReader(fileStream);
-
- // Make sure the file's a JPEG.
- if (ReadUShort() != 0xFFD8)
- throw new Exception("File is not a valid JPEG");
-
- // Scan to the start of the Exif content
- ReadToExifStart();
-
- // Create an index of all Exif tags found within the document
- CreateTagIndex();
- }
- catch (Exception)
- {
- // If instantiation fails, make sure there's no mess left behind
- Dispose();
-
- throw;
- }
- }
-
- #region TIFF methods
-
- /// <summary>
- /// Returns the length (in bytes) per component of the specified TIFF data type
- /// </summary>
- /// <returns></returns>
- private byte GetTIFFFieldLength(ushort tiffDataType)
- {
- switch (tiffDataType)
- {
- case 1:
- case 2:
- case 6:
- return 1;
- case 3:
- case 8:
- return 2;
- case 4:
- case 7:
- case 9:
- case 11:
- return 4;
- case 5:
- case 10:
- case 12:
- return 8;
- default:
- throw new Exception(string.Format("Unknown TIFF datatype: {0}", tiffDataType));
- }
- }
-
- #endregion
-
- #region Methods for reading data directly from the filestream
-
- /// <summary>
- /// Gets a 2 byte unsigned integer from the file
- /// </summary>
- /// <returns></returns>
- private ushort ReadUShort()
- {
- return ToUShort(ReadBytes(2));
- }
-
- /// <summary>
- /// Gets a 4 byte unsigned integer from the file
- /// </summary>
- /// <returns></returns>
- private uint ReadUint()
- {
- return ToUint(ReadBytes(4));
- }
-
- private string ReadString(int chars)
- {
- return Encoding.ASCII.GetString(ReadBytes(chars));
- }
-
- private byte[] ReadBytes(int byteCount)
- {
- return reader.ReadBytes(byteCount);
- }
-
- /// <summary>
- /// Reads some bytes from the specified TIFF offset
- /// </summary>
- /// <param name="tiffOffset"></param>
- /// <param name="byteCount"></param>
- /// <returns></returns>
- private byte[] ReadBytes(ushort tiffOffset, int byteCount)
- {
- // Keep the current file offset
- long originalOffset = fileStream.Position;
-
- // Move to the TIFF offset and retrieve the data
- fileStream.Seek(tiffOffset + tiffHeaderStart, SeekOrigin.Begin);
-
- byte[] data = reader.ReadBytes(byteCount);
-
- // Restore the file offset
- fileStream.Position = originalOffset;
-
- return data;
- }
-
- #endregion
-
- #region Data conversion methods for interpreting datatypes from a byte array
-
- /// <summary>
- /// Converts 2 bytes to a ushort using the current byte aligns
- /// </summary>
- /// <returns></returns>
- private ushort ToUShort(byte[] data)
- {
- if (isLittleEndian != BitConverter.IsLittleEndian)
- Array.Reverse(data);
-
- return BitConverter.ToUInt16(data, 0);
- }
-
- /// <summary>
- /// Converts 8 bytes to an unsigned rational using the current byte aligns.
- /// </summary>
- /// <param name="data"></param>
- /// <returns></returns>
- /// <seealso cref="ToRational"/>
- private double ToURational(byte[] data)
- {
- var numeratorData = new byte[4];
- var denominatorData = new byte[4];
-
- Array.Copy(data, numeratorData, 4);
- Array.Copy(data, 4, denominatorData, 0, 4);
-
- uint numerator = ToUint(numeratorData);
- uint denominator = ToUint(denominatorData);
-
- return numerator / (double)denominator;
- }
-
- /// <summary>
- /// Converts 8 bytes to a signed rational using the current byte aligns.
- /// </summary>
- /// <remarks>
- /// A TIFF rational contains 2 4-byte integers, the first of which is
- /// the numerator, and the second of which is the denominator.
- /// </remarks>
- /// <param name="data"></param>
- /// <returns></returns>
- private double ToRational(byte[] data)
- {
- var numeratorData = new byte[4];
- var denominatorData = new byte[4];
-
- Array.Copy(data, numeratorData, 4);
- Array.Copy(data, 4, denominatorData, 0, 4);
-
- int numerator = ToInt(numeratorData);
- int denominator = ToInt(denominatorData);
-
- return numerator / (double)denominator;
- }
-
- /// <summary>
- /// Converts 4 bytes to a uint using the current byte aligns
- /// </summary>
- /// <returns></returns>
- private uint ToUint(byte[] data)
- {
- if (isLittleEndian != BitConverter.IsLittleEndian)
- Array.Reverse(data);
-
- return BitConverter.ToUInt32(data, 0);
- }
-
- /// <summary>
- /// Converts 4 bytes to an int using the current byte aligns
- /// </summary>
- /// <returns></returns>
- private int ToInt(byte[] data)
- {
- if (isLittleEndian != BitConverter.IsLittleEndian)
- Array.Reverse(data);
-
- return BitConverter.ToInt32(data, 0);
- }
-
- private double ToDouble(byte[] data)
- {
- if (isLittleEndian != BitConverter.IsLittleEndian)
- Array.Reverse(data);
-
- return BitConverter.ToDouble(data, 0);
- }
-
- private float ToSingle(byte[] data)
- {
- if (isLittleEndian != BitConverter.IsLittleEndian)
- Array.Reverse(data);
-
- return BitConverter.ToSingle(data, 0);
- }
-
- private short ToShort(byte[] data)
- {
- if (isLittleEndian != BitConverter.IsLittleEndian)
- Array.Reverse(data);
-
- return BitConverter.ToInt16(data, 0);
- }
-
- private sbyte ToSByte(byte[] data)
- {
- // An sbyte should just be a byte with an offset range.
- return (sbyte)(data[0] - byte.MaxValue);
- }
-
- /// <summary>
- /// Retrieves an array from a byte array using the supplied converter
- /// to read each individual element from the supplied byte array
- /// </summary>
- /// <param name="data"></param>
- /// <param name="elementLengthBytes"></param>
- /// <param name="converter"></param>
- /// <returns></returns>
- private Array GetArray<T>(byte[] data, int elementLengthBytes, ConverterMethod<T> converter)
- {
- Array convertedData = Array.CreateInstance(typeof(T), data.Length / elementLengthBytes);
-
- var buffer = new byte[elementLengthBytes];
-
- // Read each element from the array
- for (int elementCount = 0; elementCount < data.Length / elementLengthBytes; elementCount++)
- {
- // Place the data for the current element into the buffer
- Array.Copy(data, elementCount * elementLengthBytes, buffer, 0, elementLengthBytes);
-
- // Process the data and place it into the output array
- convertedData.SetValue(converter(buffer), elementCount);
- }
-
- return convertedData;
- }
-
- /// <summary>
- /// A delegate used to invoke any of the data conversion methods
- /// </summary>
- /// <param name="data"></param>
- /// <returns></returns>
- private delegate T ConverterMethod<out T>(byte[] data);
-
- #endregion
-
- #region Stream seek methods - used to get to locations within the JPEG
-
- /// <summary>
- /// Scans to the Exif block
- /// </summary>
- private void ReadToExifStart()
- {
- // The file has a number of blocks (Exif/JFIF), each of which
- // has a tag number followed by a length. We scan the document until the required tag (0xFFE1)
- // is found. All tags start with FF, so a non FF tag indicates an error.
-
- // Get the next tag.
- byte markerStart;
- byte markerNumber = 0;
- while (((markerStart = reader.ReadByte()) == 0xFF) && (markerNumber = reader.ReadByte()) != 0xE1)
- {
- // Get the length of the data.
- ushort dataLength = ReadUShort();
-
- // Jump to the end of the data (note that the size field includes its own size)!
- reader.BaseStream.Seek(dataLength - 2, SeekOrigin.Current);
- }
-
- // It's only success if we found the 0xFFE1 marker
- if (markerStart != 0xFF || markerNumber != 0xE1)
- throw new Exception("Could not find Exif data block");
- }
-
- /// <summary>
- /// Reads through the Exif data and builds an index of all Exif tags in the document
- /// </summary>
- /// <returns></returns>
- private void CreateTagIndex()
- {
- // The next 4 bytes are the size of the Exif data.
- ReadUShort();
-
- // Next is the Exif data itself. It starts with the ASCII "Exif" followed by 2 zero bytes.
- if (ReadString(4) != "Exif")
- throw new Exception("Exif data not found");
-
- // 2 zero bytes
- if (ReadUShort() != 0)
- throw new Exception("Malformed Exif data");
-
- // We're now into the TIFF format
- tiffHeaderStart = reader.BaseStream.Position;
-
- // What byte align will be used for the TIFF part of the document? II for Intel, MM for Motorola
- isLittleEndian = ReadString(2) == "II";
-
- // Next 2 bytes are always the same.
- if (ReadUShort() != 0x002A)
- throw new Exception("Error in TIFF data");
-
- // Get the offset to the IFD (image file directory)
- uint ifdOffset = ReadUint();
-
- // Note that this offset is from the first byte of the TIFF header. Jump to the IFD.
- fileStream.Position = ifdOffset + tiffHeaderStart;
-
- // Catalogue this first IFD (there will be another IFD)
- CatalogueIFD();
-
- // There's more data stored in the subifd, the offset to which is found in tag 0x8769.
- // As with all TIFF offsets, it will be relative to the first byte of the TIFF header.
- uint offset;
- if (!GetTagValue(0x8769, out offset))
- throw new Exception("Unable to locate Exif data");
-
- // Jump to the exif SubIFD
- fileStream.Position = offset + tiffHeaderStart;
-
- // Add the subIFD to the catalogue too
- CatalogueIFD();
-
- // Go to the GPS IFD and catalogue that too. It's an optional
- // section.
- if (GetTagValue(0x8825, out offset))
- {
- // Jump to the GPS SubIFD
- fileStream.Position = offset + tiffHeaderStart;
-
- // Add the subIFD to the catalogue too
- CatalogueIFD();
- }
- }
-
- #endregion
-
- #region Exif data catalog and retrieval methods
-
- public bool GetTagValue<T>(ExifTags tag, out T result)
- {
- return GetTagValue((ushort)tag, out result);
- }
-
- /// <summary>
- /// Retrieves an Exif value with the requested tag ID
- /// </summary>
- /// <param name="tagID"></param>
- /// <param name="result"></param>
- /// <returns></returns>
- public bool GetTagValue<T>(ushort tagID, out T result)
- {
- ushort tiffDataType;
- uint numberOfComponents;
- byte[] tagData = GetTagBytes(tagID, out tiffDataType, out numberOfComponents);
-
- if (tagData == null)
- {
- result = default(T);
- return false;
- }
-
- byte fieldLength = GetTIFFFieldLength(tiffDataType);
-
- // Convert the data to the appropriate datatype. Note the weird boxing via object.
- // The compiler doesn't like it otherwise.
- switch (tiffDataType)
- {
- case 1:
- // unsigned byte
- if (numberOfComponents == 1)
- result = (T)(object)tagData[0];
- else
- result = (T)(object)tagData;
- return true;
- case 2:
- // ascii string
- string str = Encoding.ASCII.GetString(tagData);
-
- // There may be a null character within the string
- int nullCharIndex = str.IndexOf('\0');
- if (nullCharIndex != -1)
- str = str.Substring(0, nullCharIndex);
-
- // Special processing for dates.
- if (typeof(T) == typeof(DateTime))
- {
- result =
- (T)(object)DateTime.ParseExact(str, "yyyy:MM:dd HH:mm:ss", CultureInfo.InvariantCulture);
- return true;
- }
-
- result = (T)(object)str;
- return true;
- case 3:
- // unsigned short
- if (numberOfComponents == 1)
- result = (T)(object)ToUShort(tagData);
- else
- result = (T)(object)GetArray(tagData, fieldLength, ToUShort);
- return true;
- case 4:
- // unsigned long
- if (numberOfComponents == 1)
- result = (T)(object)ToUint(tagData);
- else
- result = (T)(object)GetArray(tagData, fieldLength, ToUint);
- return true;
- case 5:
- // unsigned rational
- if (numberOfComponents == 1)
- result = (T)(object)ToURational(tagData);
- else
- result = (T)(object)GetArray(tagData, fieldLength, ToURational);
- return true;
- case 6:
- // signed byte
- if (numberOfComponents == 1)
- result = (T)(object)ToSByte(tagData);
- else
- result = (T)(object)GetArray(tagData, fieldLength, ToSByte);
- return true;
- case 7:
- // undefined. Treat it as an unsigned integer.
- if (numberOfComponents == 1)
- result = (T)(object)ToUint(tagData);
- else
- result = (T)(object)GetArray(tagData, fieldLength, ToUint);
- return true;
- case 8:
- // Signed short
- if (numberOfComponents == 1)
- result = (T)(object)ToShort(tagData);
- else
- result = (T)(object)GetArray(tagData, fieldLength, ToShort);
- return true;
- case 9:
- // Signed long
- if (numberOfComponents == 1)
- result = (T)(object)ToInt(tagData);
- else
- result = (T)(object)GetArray(tagData, fieldLength, ToInt);
- return true;
- case 10:
- // signed rational
- if (numberOfComponents == 1)
- result = (T)(object)ToRational(tagData);
- else
- result = (T)(object)GetArray(tagData, fieldLength, ToRational);
- return true;
- case 11:
- // single float
- if (numberOfComponents == 1)
- result = (T)(object)ToSingle(tagData);
- else
- result = (T)(object)GetArray(tagData, fieldLength, ToSingle);
- return true;
- case 12:
- // double float
- if (numberOfComponents == 1)
- result = (T)(object)ToDouble(tagData);
- else
- result = (T)(object)GetArray(tagData, fieldLength, ToDouble);
- return true;
- default:
- throw new Exception(string.Format("Unknown TIFF datatype: {0}", tiffDataType));
- }
- }
-
- /// <summary>
- /// Gets the data in the specified tag ID, starting from before the IFD block.
- /// </summary>
- /// <param name="tiffDataType"></param>
- /// <param name="numberOfComponents">The number of items which make up the data item - i.e. for a string, this will be the
- /// number of characters in the string</param>
- /// <param name="tagID"></param>
- private byte[] GetTagBytes(ushort tagID, out ushort tiffDataType, out uint numberOfComponents)
- {
- // Get the tag's offset from the catalogue and do some basic error checks
- if (fileStream == null || reader == null || catalogue == null || !catalogue.ContainsKey(tagID))
- {
- tiffDataType = 0;
- numberOfComponents = 0;
- return null;
- }
-
- long tagOffset = catalogue[tagID];
-
- // Jump to the TIFF offset
- fileStream.Position = tagOffset;
-
- // Read the tag number from the file
- ushort currentTagID = ReadUShort();
-
- if (currentTagID != tagID)
- throw new Exception("Tag number not at expected offset");
-
- // Read the offset to the Exif IFD
- tiffDataType = ReadUShort();
- numberOfComponents = ReadUint();
- byte[] tagData = ReadBytes(4);
-
- // If the total space taken up by the field is longer than the
- // 2 bytes afforded by the tagData, tagData will contain an offset
- // to the actual data.
- var dataSize = (int)(numberOfComponents * GetTIFFFieldLength(tiffDataType));
-
- if (dataSize > 4)
- {
- ushort offsetAddress = ToUShort(tagData);
- return ReadBytes(offsetAddress, dataSize);
- }
-
- // The value is stored in the tagData starting from the left
- Array.Resize(ref tagData, dataSize);
-
- return tagData;
- }
-
- /// <summary>
- /// Records all Exif tags and their offsets within
- /// the file from the current IFD
- /// </summary>
- private void CatalogueIFD()
- {
- if (catalogue == null)
- catalogue = new Dictionary<ushort, long>();
-
- // Assume we're just before the IFD.
-
- // First 2 bytes is the number of entries in this IFD
- ushort entryCount = ReadUShort();
-
- for (ushort currentEntry = 0; currentEntry < entryCount; currentEntry++)
- {
- ushort currentTagNumber = ReadUShort();
-
- // Record this in the catalogue
- catalogue[currentTagNumber] = fileStream.Position - 2;
-
- // Go to the end of this item (10 bytes, as each entry is 12 bytes long)
- reader.BaseStream.Seek(10, SeekOrigin.Current);
- }
- }
-
- #endregion
-
- #region IDisposable Members
-
- public void Dispose()
- {
- // Make sure the file handle is released
- if (reader != null)
- reader.Close();
- if (fileStream != null)
- fileStream.Close();
- }
-
- #endregion
- }
-}
diff --git a/MediaBrowser.Providers/Photos/ExifTags.cs b/MediaBrowser.Providers/Photos/ExifTags.cs
deleted file mode 100644
index 39e153f2e..000000000
--- a/MediaBrowser.Providers/Photos/ExifTags.cs
+++ /dev/null
@@ -1,132 +0,0 @@
-
-namespace MediaBrowser.Providers.Photos
-{
- /// <summary>
- /// All exif tags as per the Exif standard 2.2, JEITA CP-2451
- /// </summary>
- public enum ExifTags : ushort
- {
- // IFD0 items
- ImageWidth = 0x100,
- ImageLength = 0x101,
- BitsPerSample = 0x102,
- Compression = 0x103,
- PhotometricInterpretation = 0x106,
- ImageDescription = 0x10E,
- Make = 0x10F,
- Model = 0x110,
- StripOffsets = 0x111,
- Orientation = 0x112,
- SamplesPerPixel = 0x115,
- RowsPerStrip = 0x116,
- StripByteCounts = 0x117,
- XResolution = 0x11A,
- YResolution = 0x11B,
- PlanarConfiguration = 0x11C,
- ResolutionUnit = 0x128,
- TransferFunction = 0x12D,
- Software = 0x131,
- DateTime = 0x132,
- Artist = 0x13B,
- WhitePoint = 0x13E,
- PrimaryChromaticities = 0x13F,
- JPEGInterchangeFormat = 0x201,
- JPEGInterchangeFormatLength = 0x202,
- YCbCrCoefficients = 0x211,
- YCbCrSubSampling = 0x212,
- YCbCrPositioning = 0x213,
- ReferenceBlackWhite = 0x214,
- Copyright = 0x8298,
-
- // SubIFD items
- ExposureTime = 0x829A,
- FNumber = 0x829D,
- ExposureProgram = 0x8822,
- SpectralSensitivity = 0x8824,
- ISOSpeedRatings = 0x8827,
- OECF = 0x8828,
- ExifVersion = 0x9000,
- DateTimeOriginal = 0x9003,
- DateTimeDigitized = 0x9004,
- ComponentsConfiguration = 0x9101,
- CompressedBitsPerPixel = 0x9102,
- ShutterSpeedValue = 0x9201,
- ApertureValue = 0x9202,
- BrightnessValue = 0x9203,
- ExposureBiasValue = 0x9204,
- MaxApertureValue = 0x9205,
- SubjectDistance = 0x9206,
- MeteringMode = 0x9207,
- LightSource = 0x9208,
- Flash = 0x9209,
- FocalLength = 0x920A,
- SubjectArea = 0x9214,
- MakerNote = 0x927C,
- UserComment = 0x9286,
- SubsecTime = 0x9290,
- SubsecTimeOriginal = 0x9291,
- SubsecTimeDigitized = 0x9292,
- FlashpixVersion = 0xA000,
- ColorSpace = 0xA001,
- PixelXDimension = 0xA002,
- PixelYDimension = 0xA003,
- RelatedSoundFile = 0xA004,
- FlashEnergy = 0xA20B,
- SpatialFrequencyResponse = 0xA20C,
- FocalPlaneXResolution = 0xA20E,
- FocalPlaneYResolution = 0xA20F,
- FocalPlaneResolutionUnit = 0xA210,
- SubjectLocation = 0xA214,
- ExposureIndex = 0xA215,
- SensingMethod = 0xA217,
- FileSource = 0xA300,
- SceneType = 0xA301,
- CFAPattern = 0xA302,
- CustomRendered = 0xA401,
- ExposureMode = 0xA402,
- WhiteBalance = 0xA403,
- DigitalZoomRatio = 0xA404,
- FocalLengthIn35mmFilm = 0xA405,
- SceneCaptureType = 0xA406,
- GainControl = 0xA407,
- Contrast = 0xA408,
- Saturation = 0xA409,
- Sharpness = 0xA40A,
- DeviceSettingDescription = 0xA40B,
- SubjectDistanceRange = 0xA40C,
- ImageUniqueID = 0xA420,
-
- // GPS subifd items
- GPSVersionID = 0x0,
- GPSLatitudeRef = 0x1,
- GPSLatitude = 0x2,
- GPSLongitudeRef = 0x3,
- GPSLongitude = 0x4,
- GPSAltitudeRef = 0x5,
- GPSAltitude = 0x6,
- GPSTimeStamp = 0x7,
- GPSSatellites = 0x8,
- GPSStatus = 0x9,
- GPSMeasureMode = 0xA,
- GPSDOP = 0xB,
- GPSSpeedRef = 0xC,
- GPSSpeed = 0xD,
- GPSTrackRef = 0xE,
- GPSTrack = 0xF,
- GPSImgDirectionRef = 0x10,
- GPSImgDirection = 0x11,
- GPSMapDatum = 0x12,
- GPSDestLatitudeRef = 0x13,
- GPSDestLatitude = 0x14,
- GPSDestLongitudeRef = 0x15,
- GPSDestLongitude = 0x16,
- GPSDestBearingRef = 0x17,
- GPSDestBearing = 0x18,
- GPSDestDistanceRef = 0x19,
- GPSDestDistance = 0x1A,
- GPSProcessingMethod = 0x1B,
- GPSAreaInformation = 0x1C,
- GPSDateStamp = 0x1D,
- GPSDifferential = 0x1E
- }
-}
diff --git a/MediaBrowser.Providers/Photos/PhotoHelper.cs b/MediaBrowser.Providers/Photos/PhotoHelper.cs
index a5ce6f81f..2334c792e 100644
--- a/MediaBrowser.Providers/Photos/PhotoHelper.cs
+++ b/MediaBrowser.Providers/Photos/PhotoHelper.cs
@@ -1,25 +1,10 @@
-using MediaBrowser.Controller.Entities;
-using System;
-using System.Collections.Generic;
+using System;
using System.Text;
namespace MediaBrowser.Providers.Photos
{
public static class PhotoHelper
{
- public static List<BaseItem> ShuffleList(List<BaseItem> list)
- {
- var rnd = new Random(DateTime.Now.Second);
- for (var i = 1; i < list.Count; i++)
- {
- var pos = rnd.Next(i + 1);
- var x = list[i];
- list[i] = list[pos];
- list[pos] = x;
- }
- return list;
- }
-
public static string Dec2Frac(double dbl)
{
char neg = ' ';
diff --git a/MediaBrowser.Providers/Photos/PhotoProvider.cs b/MediaBrowser.Providers/Photos/PhotoProvider.cs
index c0f53e0c3..b298c62e7 100644
--- a/MediaBrowser.Providers/Photos/PhotoProvider.cs
+++ b/MediaBrowser.Providers/Photos/PhotoProvider.cs
@@ -5,9 +5,13 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
-using System.Globalization;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using TagLib;
+using TagLib.IFD;
+using TagLib.IFD.Entries;
+using TagLib.IFD.Tags;
namespace MediaBrowser.Providers.Photos
{
@@ -25,102 +29,122 @@ namespace MediaBrowser.Providers.Photos
public Task<ItemUpdateType> FetchAsync(Photo item, MetadataRefreshOptions options, CancellationToken cancellationToken)
{
item.SetImagePath(ImageType.Primary, item.Path);
- item.SetImagePath(ImageType.Backdrop, item.Path);
- if (item.Path.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) || item.Path.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase))
+ // Examples: https://github.com/mono/taglib-sharp/blob/a5f6949a53d09ce63ee7495580d6802921a21f14/tests/fixtures/TagLib.Tests.Images/NullOrientationTest.cs
+
+ try
{
- try
- {
- using (var reader = new ExifReader(item.Path))
- {
- double aperture = 0;
- double shutterSpeed = 0;
+ var file = File.Create(item.Path);
- DateTime dateTaken;
+ var image = file as TagLib.Image.File;
- string manufacturer;
- string model;
+ var tag = file.GetTag(TagTypes.TiffIFD) as IFDTag;
- reader.GetTagValue(ExifTags.FNumber, out aperture);
- reader.GetTagValue(ExifTags.ExposureTime, out shutterSpeed);
- reader.GetTagValue(ExifTags.DateTimeOriginal, out dateTaken);
+ if (tag != null)
+ {
+ var structure = tag.Structure;
- reader.GetTagValue(ExifTags.Make, out manufacturer);
- reader.GetTagValue(ExifTags.Model, out model);
+ if (structure != null)
+ {
+ var exif = structure.GetEntry(0, (ushort)IFDEntryTag.ExifIFD) as SubIFDEntry;
- if (dateTaken > DateTime.MinValue)
+ if (exif != null)
{
- item.DateCreated = dateTaken;
- item.PremiereDate = dateTaken;
- item.ProductionYear = dateTaken.Year;
+ var exifStructure = exif.Structure;
+
+ if (exifStructure != null)
+ {
+ var entry = exifStructure.GetEntry(0, (ushort)ExifEntryTag.ApertureValue) as RationalIFDEntry;
+
+ if (entry != null)
+ {
+ double val = entry.Value.Numerator;
+ val /= entry.Value.Denominator;
+ item.Aperture = val;
+ }
+
+ entry = exifStructure.GetEntry(0, (ushort)ExifEntryTag.ShutterSpeedValue) as RationalIFDEntry;
+
+ if (entry != null)
+ {
+ double val = entry.Value.Numerator;
+ val /= entry.Value.Denominator;
+ item.ShutterSpeed = val;
+ }
+ }
}
+ }
+ }
+
+ item.CameraMake = image.ImageTag.Make;
+ item.CameraModel = image.ImageTag.Model;
- var cameraModel = manufacturer ?? string.Empty;
- cameraModel += " ";
- cameraModel += model ?? string.Empty;
+ var rating = image.ImageTag.Rating;
+ if (rating.HasValue)
+ {
+ item.CommunityRating = rating;
+ }
+ else
+ {
+ item.CommunityRating = null;
+ }
- var size = _imageProcessor.GetImageSize(item.Path);
- var xResolution = size.Width;
- var yResolution = size.Height;
+ item.Overview = image.ImageTag.Comment;
- item.Overview = "Taken " + dateTaken.ToString("F") + "\n" +
- (!string.IsNullOrWhiteSpace(cameraModel) ? "With a " + cameraModel : "") +
- (aperture > 0 && shutterSpeed > 0 ? " at f" + aperture.ToString(CultureInfo.InvariantCulture) + " and " + PhotoHelper.Dec2Frac(shutterSpeed) + "s" : "") + "\n"
- + (xResolution > 0 ? "\n<br/>Resolution: " + xResolution + "x" + yResolution : "");
+ if (!string.IsNullOrWhiteSpace(image.ImageTag.Title))
+ {
+ item.Name = image.ImageTag.Title;
+ }
+
+ var dateTaken = image.ImageTag.DateTime;
+ if (dateTaken.HasValue)
+ {
+ item.DateCreated = dateTaken.Value;
+ item.PremiereDate = dateTaken.Value;
+ item.ProductionYear = dateTaken.Value.Year;
+ }
+
+ item.Genres = image.ImageTag.Genres.ToList();
+ item.Tags = image.ImageTag.Keywords.ToList();
+ item.Software = image.ImageTag.Software;
+
+ if (image.ImageTag.Orientation == TagLib.Image.ImageOrientation.None)
+ {
+ item.Orientation = null;
+ }
+ else
+ {
+ Model.Drawing.ImageOrientation orientation;
+ if (Enum.TryParse(image.ImageTag.Orientation.ToString(), true, out orientation))
+ {
+ item.Orientation = orientation;
}
+ }
+ item.ExposureTime = image.ImageTag.ExposureTime;
+ item.FocalLength = image.ImageTag.FocalLength;
+
+ item.Latitude = image.ImageTag.Latitude;
+ item.Longitude = image.ImageTag.Longitude;
+ item.Altitude = image.ImageTag.Altitude;
+
+ if (image.ImageTag.ISOSpeedRatings.HasValue)
+ {
+ item.IsoSpeedRating = Convert.ToInt32(image.ImageTag.ISOSpeedRatings.Value);
}
- catch (Exception e)
+ else
{
- _logger.ErrorException("Image Provider - Error reading image tag for {0}", e, item.Path);
+ item.IsoSpeedRating = null;
}
}
+ catch (Exception e)
+ {
+ _logger.ErrorException("Image Provider - Error reading image tag for {0}", e, item.Path);
+ }
- //// Get additional tags from xmp
- //try
- //{
- // using (var fs = new FileStream(item.Path, FileMode.Open, FileAccess.Read))
- // {
- // var bf = BitmapFrame.Create(fs);
-
- // if (bf != null)
- // {
- // var data = (BitmapMetadata)bf.Metadata;
- // if (data != null)
- // {
-
- // DateTime dateTaken;
- // var cameraModel = "";
-
- // DateTime.TryParse(data.DateTaken, out dateTaken);
- // if (dateTaken > DateTime.MinValue) item.DateCreated = dateTaken;
- // cameraModel = data.CameraModel;
-
- // item.PremiereDate = dateTaken;
- // item.ProductionYear = dateTaken.Year;
- // item.Overview = "Taken " + dateTaken.ToString("F") + "\n" +
- // (cameraModel != "" ? "With a " + cameraModel : "") +
- // (aperture > 0 && shutterSpeed > 0 ? " at f" + aperture.ToString(CultureInfo.InvariantCulture) + " and " + PhotoHelper.Dec2Frac(shutterSpeed) + "s" : "") + "\n"
- // + (bf.Width > 0 ? "\n<br/>Resolution: " + (int)bf.Width + "x" + (int)bf.Height : "");
-
- // var photo = item as Photo;
- // if (data.Keywords != null) item.Genres = photo.Tags = new List<string>(data.Keywords);
- // item.Name = !string.IsNullOrWhiteSpace(data.Title) ? data.Title : item.Name;
- // item.CommunityRating = data.Rating;
- // if (!string.IsNullOrWhiteSpace(data.Subject)) photo.AddTagline(data.Subject);
- // }
- // }
-
- // }
- //}
- //catch (NotSupportedException)
- //{
- // // No problem - move on
- //}
- //catch (Exception e)
- //{
- // _logger.ErrorException("Error trying to read extended data from {0}", e, item.Path);
- //}
+ var size = _imageProcessor.GetImageSize(item.Path);
+ item.Height = Convert.ToInt32(size.Height);
+ item.Width = Convert.ToInt32(size.Width);
const ItemUpdateType result = ItemUpdateType.ImageUpdate | ItemUpdateType.MetadataImport;
return Task.FromResult(result);
@@ -133,6 +157,13 @@ namespace MediaBrowser.Providers.Photos
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
{
+ // Moved to plural AlbumArtists
+ if (date < new DateTime(2014, 8, 29))
+ {
+ // Revamped vaptured metadata
+ return true;
+ }
+
return item.DateModified > date;
}
}
diff --git a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs
new file mode 100644
index 000000000..41c4dcb0d
--- /dev/null
+++ b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs
@@ -0,0 +1,53 @@
+using System.Linq;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Playlists;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Providers.Manager;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Providers.Playlists
+{
+ class PlaylistMetadataService : MetadataService<Playlist, ItemLookupInfo>
+ {
+ public PlaylistMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem)
+ : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem)
+ {
+ }
+
+ /// <summary>
+ /// Merges the specified source.
+ /// </summary>
+ /// <param name="source">The source.</param>
+ /// <param name="target">The target.</param>
+ /// <param name="lockedFields">The locked fields.</param>
+ /// <param name="replaceData">if set to <c>true</c> [replace data].</param>
+ /// <param name="mergeMetadataSettings">if set to <c>true</c> [merge metadata settings].</param>
+ protected override void MergeData(Playlist source, Playlist target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
+ {
+ ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+
+ if (replaceData || string.IsNullOrEmpty(target.PlaylistMediaType))
+ {
+ target.PlaylistMediaType = source.PlaylistMediaType;
+ }
+
+ if (replaceData || string.IsNullOrEmpty(target.OwnerUserId))
+ {
+ target.OwnerUserId = source.OwnerUserId;
+ }
+
+ if (mergeMetadataSettings)
+ {
+ var list = source.LinkedChildren.ToList();
+
+ list.AddRange(target.LinkedChildren);
+
+ target.LinkedChildren = list;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Subtitles/ConfigurationExtension.cs b/MediaBrowser.Providers/Subtitles/ConfigurationExtension.cs
new file mode 100644
index 000000000..f520915d8
--- /dev/null
+++ b/MediaBrowser.Providers/Subtitles/ConfigurationExtension.cs
@@ -0,0 +1,29 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Providers;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Providers.Subtitles
+{
+ public static class ConfigurationExtension
+ {
+ public static SubtitleOptions GetSubtitleConfiguration(this IConfigurationManager manager)
+ {
+ return manager.GetConfiguration<SubtitleOptions>("subtitles");
+ }
+ }
+
+ public class SubtitleConfigurationFactory : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new List<ConfigurationStore>
+ {
+ new ConfigurationStore
+ {
+ Key = "subtitles",
+ ConfigurationType = typeof (SubtitleOptions)
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs b/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs
index 297f05867..722d0d3f3 100644
--- a/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs
+++ b/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Providers;
@@ -6,7 +7,6 @@ using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using OpenSubtitlesHandler;
@@ -29,6 +29,15 @@ namespace MediaBrowser.Providers.Subtitles
private readonly IServerConfigurationManager _config;
private readonly IEncryptionManager _encryption;
+ private Timer _dailyTimer;
+
+ // This is limited to 200 per day
+ private int _dailyDownloadCount;
+
+ // It's 200 but this will be in-exact so buffer a little
+ // And the user may restart the server
+ private const int MaxDownloadsPerDay = 150;
+
public OpenSubtitleDownloader(ILogManager logManager, IHttpClient httpClient, IServerConfigurationManager config, IEncryptionManager encryption)
{
_logger = logManager.GetLogger(GetType().Name);
@@ -36,13 +45,21 @@ namespace MediaBrowser.Providers.Subtitles
_config = config;
_encryption = encryption;
- _config.ConfigurationUpdating += _config_ConfigurationUpdating;
+ _config.NamedConfigurationUpdating += _config_NamedConfigurationUpdating;
+
+ // Reset the count every 24 hours
+ _dailyTimer = new Timer(state => _dailyDownloadCount = 0, null, TimeSpan.FromHours(24), TimeSpan.FromHours(24));
}
private const string PasswordHashPrefix = "h:";
- void _config_ConfigurationUpdating(object sender, GenericEventArgs<ServerConfiguration> e)
+ void _config_NamedConfigurationUpdating(object sender, ConfigurationUpdateEventArgs e)
{
- var options = e.Argument.SubtitleOptions;
+ if (!string.Equals(e.Key, "subtitles", StringComparison.OrdinalIgnoreCase))
+ {
+ return;
+ }
+
+ var options = (SubtitleOptions)e.NewConfiguration;
if (options != null &&
!string.IsNullOrWhiteSpace(options.OpenSubtitlesPasswordHash) &&
@@ -73,12 +90,19 @@ namespace MediaBrowser.Providers.Subtitles
get { return "Open Subtitles"; }
}
+ private SubtitleOptions GetOptions()
+ {
+ return _config.GetSubtitleConfiguration();
+ }
+
public IEnumerable<VideoContentType> SupportedMediaTypes
{
get
{
- if (string.IsNullOrWhiteSpace(_config.Configuration.SubtitleOptions.OpenSubtitlesUsername) ||
- string.IsNullOrWhiteSpace(_config.Configuration.SubtitleOptions.OpenSubtitlesPasswordHash))
+ var options = GetOptions();
+
+ if (string.IsNullOrWhiteSpace(options.OpenSubtitlesUsername) ||
+ string.IsNullOrWhiteSpace(options.OpenSubtitlesPasswordHash))
{
return new VideoContentType[] { };
}
@@ -89,10 +113,11 @@ namespace MediaBrowser.Providers.Subtitles
public Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken)
{
- return GetSubtitlesInternal(id, cancellationToken);
+ return GetSubtitlesInternal(id, GetOptions(), cancellationToken);
}
private async Task<SubtitleResponse> GetSubtitlesInternal(string id,
+ SubtitleOptions options,
CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(id))
@@ -100,6 +125,12 @@ namespace MediaBrowser.Providers.Subtitles
throw new ArgumentNullException("id");
}
+ if (_dailyDownloadCount >= MaxDownloadsPerDay &&
+ !options.IsOpenSubtitleVipAccount)
+ {
+ throw new InvalidOperationException("Open Subtitle's daily download limit has been exceeded. Please try again tomorrow.");
+ }
+
var idParts = id.Split(new[] { '-' }, 3);
var format = idParts[0];
@@ -149,7 +180,7 @@ namespace MediaBrowser.Providers.Subtitles
return;
}
- var options = _config.Configuration.SubtitleOptions ?? new SubtitleOptions();
+ var options = GetOptions();
var user = options.OpenSubtitlesUsername ?? string.Empty;
var password = DecryptPassword(options.OpenSubtitlesPasswordHash);
@@ -247,7 +278,7 @@ namespace MediaBrowser.Providers.Subtitles
var hasCopy = hash;
return results.Where(x => x.SubBad == "0" && mediaFilter(x))
- .OrderBy(x => x.MovieHash == hash)
+ .OrderBy(x => (x.MovieHash == hash ? 0 : 1))
.ThenBy(x => Math.Abs(long.Parse(x.MovieByteSize, _usCulture) - movieByteSize))
.ThenByDescending(x => int.Parse(x.SubDownloadsCnt, _usCulture))
.ThenByDescending(x => double.Parse(x.SubRating, _usCulture))
@@ -271,7 +302,13 @@ namespace MediaBrowser.Providers.Subtitles
public void Dispose()
{
- _config.ConfigurationUpdating -= _config_ConfigurationUpdating;
+ _config.NamedConfigurationUpdating -= _config_NamedConfigurationUpdating;
+
+ if (_dailyTimer != null)
+ {
+ _dailyTimer.Dispose();
+ _dailyTimer = null;
+ }
}
}
}
diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
index 08499a20b..179ab425b 100644
--- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
+++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
@@ -28,6 +29,9 @@ namespace MediaBrowser.Providers.Subtitles
private readonly ILibraryManager _libraryManager;
private readonly IItemRepository _itemRepo;
+ public event EventHandler<SubtitleDownloadEventArgs> SubtitlesDownloaded;
+ public event EventHandler<SubtitleDownloadFailureEventArgs> SubtitleDownloadFailure;
+
public SubtitleManager(ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor, ILibraryManager libraryManager, IItemRepository itemRepo)
{
_logger = logger;
@@ -100,35 +104,63 @@ namespace MediaBrowser.Providers.Subtitles
string subtitleId,
CancellationToken cancellationToken)
{
- var response = await GetRemoteSubtitles(subtitleId, cancellationToken).ConfigureAwait(false);
+ var parts = subtitleId.Split(new[] { '_' }, 2);
+ var provider = GetProvider(parts.First());
- using (var stream = response.Stream)
+ try
{
- var savePath = Path.Combine(Path.GetDirectoryName(video.Path),
- Path.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower());
+ var response = await GetRemoteSubtitles(subtitleId, cancellationToken).ConfigureAwait(false);
- if (response.IsForced)
+ using (var stream = response.Stream)
{
- savePath += ".forced";
- }
+ var savePath = Path.Combine(Path.GetDirectoryName(video.Path),
+ _fileSystem.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower());
- savePath += "." + response.Format.ToLower();
+ if (response.IsForced)
+ {
+ savePath += ".forced";
+ }
- _logger.Info("Saving subtitles to {0}", savePath);
+ savePath += "." + response.Format.ToLower();
- _monitor.ReportFileSystemChangeBeginning(savePath);
+ _logger.Info("Saving subtitles to {0}", savePath);
- try
- {
- using (var fs = _fileSystem.GetFileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ _monitor.ReportFileSystemChangeBeginning(savePath);
+
+ try
+ {
+ using (var fs = _fileSystem.GetFileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ {
+ await stream.CopyToAsync(fs).ConfigureAwait(false);
+ }
+
+ EventHelper.FireEventIfNotNull(SubtitlesDownloaded, this, new SubtitleDownloadEventArgs
+ {
+ Item = video,
+ Format = response.Format,
+ Language = response.Language,
+ IsForced = response.IsForced,
+ Provider = provider.Name
+
+ }, _logger);
+ }
+ finally
{
- await stream.CopyToAsync(fs).ConfigureAwait(false);
+ _monitor.ReportFileSystemChangeComplete(savePath, false);
}
}
- finally
+ }
+ catch (Exception ex)
+ {
+ EventHelper.FireEventIfNotNull(SubtitleDownloadFailure, this, new SubtitleDownloadFailureEventArgs
{
- _monitor.ReportFileSystemChangeComplete(savePath, false);
- }
+ Item = video,
+ Exception = ex,
+ Provider = provider.Name
+
+ }, _logger);
+
+ throw;
}
}
@@ -267,5 +299,6 @@ namespace MediaBrowser.Providers.Subtitles
Id = GetProviderId(i.Name)
});
}
+
}
}
diff --git a/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs
new file mode 100644
index 000000000..7979711ec
--- /dev/null
+++ b/MediaBrowser.Providers/TV/MovieDbEpisodeImageProvider.cs
@@ -0,0 +1,347 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Localization;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Model.Serialization;
+using MediaBrowser.Providers.Movies;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Providers.TV
+{
+ public class MovieDbEpisodeImageProvider : IRemoteImageProvider, IHasOrder
+ {
+ private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}/season/{1}/episode/{2}?api_key={3}&append_to_response=images,external_ids,credits,videos";
+ private readonly IHttpClient _httpClient;
+ private readonly IServerConfigurationManager _configurationManager;
+ private readonly IJsonSerializer _jsonSerializer;
+ private readonly IFileSystem _fileSystem;
+ private readonly ILocalizationManager _localization;
+
+ public MovieDbEpisodeImageProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization)
+ {
+ _httpClient = httpClient;
+ _configurationManager = configurationManager;
+ _jsonSerializer = jsonSerializer;
+ _fileSystem = fileSystem;
+ _localization = localization;
+ }
+
+ public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
+ {
+ return new List<ImageType>
+ {
+ ImageType.Primary
+ };
+ }
+
+ public async Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken)
+ {
+ var episode = (Controller.Entities.TV.Episode)item;
+ var series = episode.Series;
+
+ var seriesId = series != null ? series.GetProviderId(MetadataProviders.Tmdb) : null;
+
+ var list = new List<RemoteImageInfo>();
+
+ if (string.IsNullOrEmpty(seriesId))
+ {
+ return list;
+ }
+
+ var seasonNumber = episode.ParentIndexNumber;
+ var episodeNumber = episode.IndexNumber;
+
+ if (!seasonNumber.HasValue || !episodeNumber.HasValue)
+ {
+ return list;
+ }
+
+ var response = await GetEpisodeInfo(seriesId, seasonNumber.Value, episodeNumber.Value,
+ item.GetPreferredMetadataLanguage(), cancellationToken).ConfigureAwait(false);
+
+ var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+
+ var tmdbImageUrl = tmdbSettings.images.base_url + "original";
+
+ list.AddRange(GetPosters(response.images).Select(i => new RemoteImageInfo
+ {
+ Url = tmdbImageUrl + i.file_path,
+ CommunityRating = i.vote_average,
+ VoteCount = i.vote_count,
+ Width = i.width,
+ Height = i.height,
+ ProviderName = Name,
+ Type = ImageType.Primary,
+ RatingType = RatingType.Score
+ }));
+
+ var language = item.GetPreferredMetadataLanguage();
+
+ var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase);
+
+ return list.OrderByDescending(i =>
+ {
+ if (string.Equals(language, i.Language, StringComparison.OrdinalIgnoreCase))
+ {
+ return 3;
+ }
+ if (!isLanguageEn)
+ {
+ if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase))
+ {
+ return 2;
+ }
+ }
+ if (string.IsNullOrEmpty(i.Language))
+ {
+ return isLanguageEn ? 3 : 2;
+ }
+ return 0;
+ })
+ .ThenByDescending(i => i.CommunityRating ?? 0)
+ .ThenByDescending(i => i.VoteCount ?? 0)
+ .ToList();
+
+ }
+
+ private IEnumerable<Still> GetPosters(Images images)
+ {
+ return images.stills ?? new List<Still>();
+ }
+
+
+ public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ return _httpClient.GetResponse(new HttpRequestOptions
+ {
+ CancellationToken = cancellationToken,
+ Url = url,
+ ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ });
+ }
+
+ public string Name
+ {
+ get { return "TheMovieDb"; }
+ }
+
+ public bool Supports(IHasImages item)
+ {
+ return item is Controller.Entities.TV.Episode;
+ }
+
+ private async Task<RootObject> GetEpisodeInfo(string seriesTmdbId, int season, int episodeNumber, string preferredMetadataLanguage,
+ CancellationToken cancellationToken)
+ {
+ await EnsureEpisodeInfo(seriesTmdbId, season, episodeNumber, preferredMetadataLanguage, cancellationToken)
+ .ConfigureAwait(false);
+
+ var dataFilePath = GetDataFilePath(seriesTmdbId, season, episodeNumber, preferredMetadataLanguage);
+
+ return _jsonSerializer.DeserializeFromFile<RootObject>(dataFilePath);
+ }
+
+ internal Task EnsureEpisodeInfo(string tmdbId, int seasonNumber, int episodeNumber, string language, CancellationToken cancellationToken)
+ {
+ if (string.IsNullOrEmpty(tmdbId))
+ {
+ throw new ArgumentNullException("tmdbId");
+ }
+ if (string.IsNullOrEmpty(language))
+ {
+ throw new ArgumentNullException("language");
+ }
+
+ var path = GetDataFilePath(tmdbId, seasonNumber, episodeNumber, language);
+
+ var fileInfo = _fileSystem.GetFileSystemInfo(path);
+
+ if (fileInfo.Exists)
+ {
+ // If it's recent or automatic updates are enabled, don't re-download
+ if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 3)
+ {
+ return Task.FromResult(true);
+ }
+ }
+
+ return DownloadEpisodeInfo(tmdbId, seasonNumber, episodeNumber, language, cancellationToken);
+ }
+
+ internal string GetDataFilePath(string tmdbId, int seasonNumber, int episodeNumber, string preferredLanguage)
+ {
+ if (string.IsNullOrEmpty(tmdbId))
+ {
+ throw new ArgumentNullException("tmdbId");
+ }
+ if (string.IsNullOrEmpty(preferredLanguage))
+ {
+ throw new ArgumentNullException("preferredLanguage");
+ }
+
+ var path = MovieDbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId);
+
+ var filename = string.Format("season-{0}-episode-{1}-{2}.json",
+ seasonNumber.ToString(CultureInfo.InvariantCulture),
+ episodeNumber.ToString(CultureInfo.InvariantCulture),
+ preferredLanguage);
+
+ return Path.Combine(path, filename);
+ }
+
+ internal async Task DownloadEpisodeInfo(string id, int seasonNumber, int episodeNumber, string preferredMetadataLanguage, CancellationToken cancellationToken)
+ {
+ var mainResult = await FetchMainResult(id, seasonNumber, episodeNumber, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
+
+ var dataFilePath = GetDataFilePath(id, seasonNumber, episodeNumber, preferredMetadataLanguage);
+
+ Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _jsonSerializer.SerializeToFile(mainResult, dataFilePath);
+ }
+
+ internal async Task<RootObject> FetchMainResult(string id, int seasonNumber, int episodeNumber, string language, CancellationToken cancellationToken)
+ {
+ var url = string.Format(GetTvInfo3, id, seasonNumber.ToString(CultureInfo.InvariantCulture), episodeNumber, MovieDbProvider.ApiKey);
+
+ var imageLanguages = _localization.GetCultures()
+ .Select(i => i.TwoLetterISOLanguageName)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+
+ imageLanguages.Add("null");
+
+ if (!string.IsNullOrEmpty(language))
+ {
+ // If preferred language isn't english, get those images too
+ if (imageLanguages.Contains(language, StringComparer.OrdinalIgnoreCase))
+ {
+ imageLanguages.Add(language);
+ }
+
+ url += string.Format("&language={0}", language);
+ }
+
+ // Get images in english and with no language
+ url += "&include_image_language=" + string.Join(",", imageLanguages.ToArray());
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ {
+ Url = url,
+ CancellationToken = cancellationToken,
+ AcceptHeader = MovieDbProvider.AcceptHeader
+
+ }).ConfigureAwait(false))
+ {
+ return _jsonSerializer.DeserializeFromStream<RootObject>(json);
+ }
+ }
+
+ public class Still
+ {
+ public double aspect_ratio { get; set; }
+ public string file_path { get; set; }
+ public int height { get; set; }
+ public string id { get; set; }
+ public object iso_639_1 { get; set; }
+ public double vote_average { get; set; }
+ public int vote_count { get; set; }
+ public int width { get; set; }
+ }
+
+ public class Images
+ {
+ public List<Still> stills { get; set; }
+ }
+
+ public class ExternalIds
+ {
+ public string imdb_id { get; set; }
+ public object freebase_id { get; set; }
+ public string freebase_mid { get; set; }
+ public int tvdb_id { get; set; }
+ public int tvrage_id { get; set; }
+ }
+
+ public class Cast
+ {
+ public string character { get; set; }
+ public string credit_id { get; set; }
+ public int id { get; set; }
+ public string name { get; set; }
+ public string profile_path { get; set; }
+ public int order { get; set; }
+ }
+
+ public class Crew
+ {
+ public int id { get; set; }
+ public string credit_id { get; set; }
+ public string name { get; set; }
+ public string department { get; set; }
+ public string job { get; set; }
+ public string profile_path { get; set; }
+ }
+
+ public class GuestStar
+ {
+ public int id { get; set; }
+ public string name { get; set; }
+ public string credit_id { get; set; }
+ public string character { get; set; }
+ public int order { get; set; }
+ public string profile_path { get; set; }
+ }
+
+ public class Credits
+ {
+ public List<Cast> cast { get; set; }
+ public List<Crew> crew { get; set; }
+ public List<GuestStar> guest_stars { get; set; }
+ }
+
+ public class Videos
+ {
+ public List<object> results { get; set; }
+ }
+
+ public class RootObject
+ {
+ public string air_date { get; set; }
+ public int episode_number { get; set; }
+ public string name { get; set; }
+ public string overview { get; set; }
+ public int id { get; set; }
+ public object production_code { get; set; }
+ public int season_number { get; set; }
+ public string still_path { get; set; }
+ public double vote_average { get; set; }
+ public int vote_count { get; set; }
+ public Images images { get; set; }
+ public ExternalIds external_ids { get; set; }
+ public Credits credits { get; set; }
+ public Videos videos { get; set; }
+ }
+
+ public int Order
+ {
+ get
+ {
+ // After tvdb
+ return 1;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs
new file mode 100644
index 000000000..49b0d67f9
--- /dev/null
+++ b/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs
@@ -0,0 +1,319 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Localization;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Net;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Model.Serialization;
+using MediaBrowser.Providers.Movies;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Providers.TV
+{
+ public class MovieDbSeasonProvider : IRemoteMetadataProvider<Season, SeasonInfo>
+ {
+ private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}/season/{1}?api_key={2}&append_to_response=images,keywords,external_ids,credits,videos";
+ private readonly IHttpClient _httpClient;
+ private readonly IServerConfigurationManager _configurationManager;
+ private readonly IJsonSerializer _jsonSerializer;
+ private readonly IFileSystem _fileSystem;
+ private readonly ILocalizationManager _localization;
+ private readonly ILogger _logger;
+
+ public MovieDbSeasonProvider(IHttpClient httpClient, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, ILogManager logManager)
+ {
+ _httpClient = httpClient;
+ _configurationManager = configurationManager;
+ _fileSystem = fileSystem;
+ _localization = localization;
+ _jsonSerializer = jsonSerializer;
+ _logger = logManager.GetLogger(GetType().Name);
+ }
+
+ public async Task<MetadataResult<Season>> GetMetadata(SeasonInfo info, CancellationToken cancellationToken)
+ {
+ var result = new MetadataResult<Season>();
+
+ string seriesTmdbId;
+ info.SeriesProviderIds.TryGetValue(MetadataProviders.Tmdb.ToString(), out seriesTmdbId);
+
+ var seasonNumber = info.IndexNumber;
+
+ if (!string.IsNullOrWhiteSpace(seriesTmdbId) && seasonNumber.HasValue)
+ {
+ result.HasMetadata = true;
+ result.Item = new Season();
+
+ try
+ {
+ var seasonInfo = await GetSeasonInfo(seriesTmdbId, seasonNumber.Value, info.MetadataLanguage, cancellationToken)
+ .ConfigureAwait(false);
+
+ result.Item.Name = info.Name;
+ result.Item.Overview = seasonInfo.overview;
+ result.Item.IndexNumber = seasonNumber;
+
+ if (seasonInfo.external_ids.tvdb_id > 0)
+ {
+ result.Item.SetProviderId(MetadataProviders.Tvdb, seasonInfo.external_ids.tvdb_id.ToString(CultureInfo.InvariantCulture));
+ }
+
+ var credits = seasonInfo.credits;
+ if (credits != null)
+ {
+ //Actors, Directors, Writers - all in People
+ //actors come from cast
+ if (credits.cast != null)
+ {
+ //foreach (var actor in credits.cast.OrderBy(a => a.order)) result.Item.AddPerson(new PersonInfo { Name = actor.name.Trim(), Role = actor.character, Type = PersonType.Actor, SortOrder = actor.order });
+ }
+
+ //and the rest from crew
+ if (credits.crew != null)
+ {
+ //foreach (var person in credits.crew) result.Item.AddPerson(new PersonInfo { Name = person.name.Trim(), Role = person.job, Type = person.department });
+ }
+ }
+
+ result.Item.PremiereDate = seasonInfo.air_date;
+ result.Item.ProductionYear = result.Item.PremiereDate.Value.Year;
+ }
+ catch (HttpException ex)
+ {
+ _logger.Error("No metadata found for {0}", seasonNumber.Value);
+
+ if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound)
+ {
+ return result;
+ }
+
+ throw;
+ }
+ }
+
+ return result;
+ }
+
+ public string Name
+ {
+ get { return "TheMovieDb"; }
+ }
+
+ public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeasonInfo searchInfo, CancellationToken cancellationToken)
+ {
+ return Task.FromResult<IEnumerable<RemoteSearchResult>>(new List<RemoteSearchResult>());
+ }
+
+ public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
+ {
+ return _httpClient.GetResponse(new HttpRequestOptions
+ {
+ CancellationToken = cancellationToken,
+ Url = url,
+ ResourcePool = MovieDbProvider.Current.MovieDbResourcePool
+ });
+ }
+
+ private async Task<RootObject> GetSeasonInfo(string seriesTmdbId, int season, string preferredMetadataLanguage,
+ CancellationToken cancellationToken)
+ {
+ await EnsureSeasonInfo(seriesTmdbId, season, preferredMetadataLanguage, cancellationToken)
+ .ConfigureAwait(false);
+
+ var dataFilePath = GetDataFilePath(seriesTmdbId, season, preferredMetadataLanguage);
+
+ return _jsonSerializer.DeserializeFromFile<RootObject>(dataFilePath);
+ }
+
+ private readonly Task _cachedTask = Task.FromResult(true);
+ internal Task EnsureSeasonInfo(string tmdbId, int seasonNumber, string language, CancellationToken cancellationToken)
+ {
+ if (string.IsNullOrEmpty(tmdbId))
+ {
+ throw new ArgumentNullException("tmdbId");
+ }
+ if (string.IsNullOrEmpty(language))
+ {
+ throw new ArgumentNullException("language");
+ }
+
+ var path = GetDataFilePath(tmdbId, seasonNumber, language);
+
+ var fileInfo = _fileSystem.GetFileSystemInfo(path);
+
+ if (fileInfo.Exists)
+ {
+ // If it's recent or automatic updates are enabled, don't re-download
+ if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 3)
+ {
+ return _cachedTask;
+ }
+ }
+
+ return DownloadSeasonInfo(tmdbId, seasonNumber, language, cancellationToken);
+ }
+
+ internal string GetDataFilePath(string tmdbId, int seasonNumber, string preferredLanguage)
+ {
+ if (string.IsNullOrEmpty(tmdbId))
+ {
+ throw new ArgumentNullException("tmdbId");
+ }
+ if (string.IsNullOrEmpty(preferredLanguage))
+ {
+ throw new ArgumentNullException("preferredLanguage");
+ }
+
+ var path = MovieDbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId);
+
+ var filename = string.Format("season-{0}-{1}.json",
+ seasonNumber.ToString(CultureInfo.InvariantCulture),
+ preferredLanguage);
+
+ return Path.Combine(path, filename);
+ }
+
+ internal async Task DownloadSeasonInfo(string id, int seasonNumber, string preferredMetadataLanguage, CancellationToken cancellationToken)
+ {
+ var mainResult = await FetchMainResult(id, seasonNumber, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false);
+
+ var dataFilePath = GetDataFilePath(id, seasonNumber, preferredMetadataLanguage);
+
+ Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _jsonSerializer.SerializeToFile(mainResult, dataFilePath);
+ }
+
+ internal async Task<RootObject> FetchMainResult(string id, int seasonNumber, string language, CancellationToken cancellationToken)
+ {
+ var url = string.Format(GetTvInfo3, id, seasonNumber.ToString(CultureInfo.InvariantCulture), MovieDbProvider.ApiKey);
+
+ var imageLanguages = _localization.GetCultures()
+ .Select(i => i.TwoLetterISOLanguageName)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+
+ imageLanguages.Add("null");
+
+ if (!string.IsNullOrEmpty(language))
+ {
+ // If preferred language isn't english, get those images too
+ if (imageLanguages.Contains(language, StringComparer.OrdinalIgnoreCase))
+ {
+ imageLanguages.Add(language);
+ }
+
+ url += string.Format("&language={0}", language);
+ }
+
+ // Get images in english and with no language
+ url += "&include_image_language=" + string.Join(",", imageLanguages.ToArray());
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ {
+ Url = url,
+ CancellationToken = cancellationToken,
+ AcceptHeader = MovieDbProvider.AcceptHeader
+
+ }).ConfigureAwait(false))
+ {
+ return _jsonSerializer.DeserializeFromStream<RootObject>(json);
+ }
+ }
+
+ public class Episode
+ {
+ public string air_date { get; set; }
+ public int episode_number { get; set; }
+ public int id { get; set; }
+ public string name { get; set; }
+ public string overview { get; set; }
+ public string still_path { get; set; }
+ public double vote_average { get; set; }
+ public int vote_count { get; set; }
+ }
+
+ public class Cast
+ {
+ public string character { get; set; }
+ public string credit_id { get; set; }
+ public int id { get; set; }
+ public string name { get; set; }
+ public string profile_path { get; set; }
+ public int order { get; set; }
+ }
+
+ public class Crew
+ {
+ public string credit_id { get; set; }
+ public string department { get; set; }
+ public int id { get; set; }
+ public string name { get; set; }
+ public string job { get; set; }
+ public string profile_path { get; set; }
+ }
+
+ public class Credits
+ {
+ public List<Cast> cast { get; set; }
+ public List<Crew> crew { get; set; }
+ }
+
+ public class Poster
+ {
+ public double aspect_ratio { get; set; }
+ public string file_path { get; set; }
+ public int height { get; set; }
+ public string id { get; set; }
+ public string iso_639_1 { get; set; }
+ public double vote_average { get; set; }
+ public int vote_count { get; set; }
+ public int width { get; set; }
+ }
+
+ public class Images
+ {
+ public List<Poster> posters { get; set; }
+ }
+
+ public class ExternalIds
+ {
+ public string freebase_id { get; set; }
+ public string freebase_mid { get; set; }
+ public int tvdb_id { get; set; }
+ public object tvrage_id { get; set; }
+ }
+
+ public class Videos
+ {
+ public List<object> results { get; set; }
+ }
+
+ public class RootObject
+ {
+ public DateTime air_date { get; set; }
+ public List<Episode> episodes { get; set; }
+ public string name { get; set; }
+ public string overview { get; set; }
+ public int id { get; set; }
+ public string poster_path { get; set; }
+ public int season_number { get; set; }
+ public Credits credits { get; set; }
+ public Images images { get; set; }
+ public ExternalIds external_ids { get; set; }
+ public Videos videos { get; set; }
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs
index fc53d4c15..0546701f3 100644
--- a/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/MovieDbSeriesProvider.cs
@@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.TV
{
public class MovieDbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder
{
- private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}?api_key={1}&append_to_response=casts,images,keywords,external_ids";
+ private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}?api_key={1}&append_to_response=credits,images,keywords,external_ids,videos";
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
internal static MovieDbSeriesProvider Current { get; private set; }
@@ -165,7 +165,7 @@ namespace MediaBrowser.Providers.TV
{
cancellationToken.ThrowIfCancellationRequested();
- result.Item = await FetchMovieData(tmdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
+ result.Item = await FetchMovieData(tmdbId, info.MetadataLanguage, cancellationToken).ConfigureAwait(false);
result.HasMetadata = result.Item != null;
}
@@ -173,7 +173,7 @@ namespace MediaBrowser.Providers.TV
return result;
}
- private async Task<Series> FetchMovieData(string tmdbId, string language, string preferredCountryCode, CancellationToken cancellationToken)
+ private async Task<Series> FetchMovieData(string tmdbId, string language, CancellationToken cancellationToken)
{
string dataFilePath = null;
RootObject seriesInfo = null;
@@ -198,12 +198,12 @@ namespace MediaBrowser.Providers.TV
var item = new Series();
- ProcessMainInfo(item, preferredCountryCode, seriesInfo);
+ ProcessMainInfo(item, seriesInfo);
return item;
}
- private void ProcessMainInfo(Series series, string countryCode, RootObject seriesInfo)
+ private void ProcessMainInfo(Series series, RootObject seriesInfo)
{
series.Name = seriesInfo.name;
series.SetProviderId(MetadataProviders.Tmdb, seriesInfo.id.ToString(_usCulture));
@@ -231,7 +231,7 @@ namespace MediaBrowser.Providers.TV
}
series.HomePageUrl = seriesInfo.homepage;
-
+
series.RunTimeTicks = seriesInfo.episode_run_time.Select(i => TimeSpan.FromMinutes(i).Ticks).FirstOrDefault();
if (string.Equals(seriesInfo.status, "Ended", StringComparison.OrdinalIgnoreCase))
@@ -349,7 +349,7 @@ namespace MediaBrowser.Providers.TV
if (fileInfo.Exists)
{
// If it's recent or automatic updates are enabled, don't re-download
- if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 7)
+ if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 3)
{
return _cachedTask;
}
@@ -464,10 +464,37 @@ namespace MediaBrowser.Providers.TV
public class Season
{
public string air_date { get; set; }
+ public int id { get; set; }
public string poster_path { get; set; }
public int season_number { get; set; }
}
+ public class Cast
+ {
+ public string character { get; set; }
+ public string credit_id { get; set; }
+ public int id { get; set; }
+ public string name { get; set; }
+ public string profile_path { get; set; }
+ public int order { get; set; }
+ }
+
+ public class Crew
+ {
+ public string credit_id { get; set; }
+ public string department { get; set; }
+ public int id { get; set; }
+ public string name { get; set; }
+ public string job { get; set; }
+ public string profile_path { get; set; }
+ }
+
+ public class Credits
+ {
+ public List<Cast> cast { get; set; }
+ public List<Crew> crew { get; set; }
+ }
+
public class Backdrop
{
public double aspect_ratio { get; set; }
@@ -484,6 +511,7 @@ namespace MediaBrowser.Providers.TV
public double aspect_ratio { get; set; }
public string file_path { get; set; }
public int height { get; set; }
+ public string id { get; set; }
public string iso_639_1 { get; set; }
public double vote_average { get; set; }
public int vote_count { get; set; }
@@ -496,6 +524,11 @@ namespace MediaBrowser.Providers.TV
public List<Poster> posters { get; set; }
}
+ public class Keywords
+ {
+ public List<object> results { get; set; }
+ }
+
public class ExternalIds
{
public string imdb_id { get; set; }
@@ -505,6 +538,11 @@ namespace MediaBrowser.Providers.TV
public int tvrage_id { get; set; }
}
+ public class Videos
+ {
+ public List<object> results { get; set; }
+ }
+
public class RootObject
{
public string backdrop_path { get; set; }
@@ -530,8 +568,11 @@ namespace MediaBrowser.Providers.TV
public string status { get; set; }
public double vote_average { get; set; }
public int vote_count { get; set; }
+ public Credits credits { get; set; }
public Images images { get; set; }
+ public Keywords keywords { get; set; }
public ExternalIds external_ids { get; set; }
+ public Videos videos { get; set; }
}
public int Order
diff --git a/MediaBrowser.Providers/TV/SeasonMetadataService.cs b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
index 4c0149d2e..5e7570ad1 100644
--- a/MediaBrowser.Providers/TV/SeasonMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
@@ -28,5 +28,15 @@ namespace MediaBrowser.Providers.TV
{
ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
}
+
+ protected override void AfterRemoteRefresh(Season item)
+ {
+ base.AfterRemoteRefresh(item);
+
+ if (item.IndexNumber.HasValue && item.IndexNumber.Value == 0)
+ {
+ item.Name = ServerConfigurationManager.Configuration.SeasonZeroDisplayName;
+ }
+ }
}
}
diff --git a/MediaBrowser.Providers/TV/TvExternalIds.cs b/MediaBrowser.Providers/TV/TvExternalIds.cs
index 60f132157..82baae250 100644
--- a/MediaBrowser.Providers/TV/TvExternalIds.cs
+++ b/MediaBrowser.Providers/TV/TvExternalIds.cs
@@ -51,6 +51,29 @@ namespace MediaBrowser.Providers.TV
}
}
+ public class TvdbSeasonExternalId : IExternalId
+ {
+ public string Name
+ {
+ get { return "TheTVDB"; }
+ }
+
+ public string Key
+ {
+ get { return MetadataProviders.Tvdb.ToString(); }
+ }
+
+ public string UrlFormatString
+ {
+ get { return null; }
+ }
+
+ public bool Supports(IHasProviderIds item)
+ {
+ return item is Season;
+ }
+ }
+
public class TvdbEpisodeExternalId : IExternalId
{
public string Name
diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs
index ef3778450..d10517470 100644
--- a/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs
@@ -188,9 +188,11 @@ namespace MediaBrowser.Providers.TV
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
{
- if (item.LocationType != LocationType.Virtual)
+ var episode = (Episode)item;
+
+ if (!episode.IsVirtualUnaired)
{
- // For non-virtual items, only enable if configured
+ // For non-unaired items, only enable if configured
if (!_config.Configuration.EnableTvDbUpdates)
{
return false;
@@ -199,7 +201,6 @@ namespace MediaBrowser.Providers.TV
if (!item.HasImage(ImageType.Primary))
{
- var episode = (Episode)item;
var series = episode.Series;
var seriesId = series != null ? series.GetProviderId(MetadataProviders.Tvdb) : null;
diff --git a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs
index af1edeed0..efafeae96 100644
--- a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs
@@ -65,8 +65,7 @@ namespace MediaBrowser.Providers.TV
var season = (Season)item;
var series = season.Series;
- var identity = season.Identities.OfType<SeasonIdentity>().FirstOrDefault(id => id.Type == MetadataProviders.Tvdb.ToString());
- var seriesId = identity != null ? identity.SeriesId : null;
+ var seriesId = series != null ? series.GetProviderId(MetadataProviders.Tvdb) : null;
if (!string.IsNullOrEmpty(seriesId) && season.IndexNumber.HasValue)
{
@@ -77,9 +76,18 @@ namespace MediaBrowser.Providers.TV
var path = Path.Combine(seriesDataPath, "banners.xml");
+ var identity = season.Identities.OfType<SeasonIdentity>()
+ .FirstOrDefault(id => id.Type == MetadataProviders.Tvdb.ToString());
+
+ var seasonNumber = season.IndexNumber.Value;
+
+ if (identity != null)
+ {
+ seasonNumber = AdjustForSeriesOffset(series, identity.SeasonIndex);
+ }
+
try
{
- int seasonNumber = AdjustForSeriesOffset(series, identity.SeasonIndex);
return GetImages(path, item.GetPreferredMetadataLanguage(), seasonNumber, cancellationToken);
}
catch (FileNotFoundException)
@@ -95,7 +103,7 @@ namespace MediaBrowser.Providers.TV
{
var offset = TvdbSeriesProvider.GetSeriesOffset(series.ProviderIds);
if (offset != null)
- return (int) (seasonNumber + offset);
+ return (seasonNumber + offset.Value);
return seasonNumber;
}
diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
index 6ca548829..97eabcfa9 100644
--- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
@@ -57,11 +57,30 @@ namespace MediaBrowser.Providers.TV
{
var seriesId = searchInfo.GetProviderId(MetadataProviders.Tvdb);
- if (!string.IsNullOrEmpty(seriesId))
+ if (string.IsNullOrEmpty(seriesId))
{
+ return await FindSeries(searchInfo.Name, cancellationToken).ConfigureAwait(false);
}
-
- return new List<RemoteSearchResult>();
+
+ var metadata = await GetMetadata(searchInfo, cancellationToken).ConfigureAwait(false);
+
+ var list = new List<RemoteSearchResult>();
+
+ if (metadata.HasMetadata)
+ {
+ var res = new RemoteSearchResult
+ {
+ Name = metadata.Item.Name,
+ PremiereDate = metadata.Item.PremiereDate,
+ ProductionYear = metadata.Item.ProductionYear,
+ ProviderIds = metadata.Item.ProviderIds,
+ SearchProviderName = Name
+ };
+
+ list.Add(res);
+ }
+
+ return list;
}
public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo itemId, CancellationToken cancellationToken)
@@ -79,18 +98,13 @@ namespace MediaBrowser.Providers.TV
if (string.IsNullOrEmpty(seriesId))
{
- seriesId = await FindSeries(itemId.Name, cancellationToken).ConfigureAwait(false);
- }
+ var srch = await GetSearchResults(itemId, cancellationToken).ConfigureAwait(false);
- if (string.IsNullOrEmpty(seriesId))
- {
- int? yearInName = null;
- string nameWithoutYear;
- NameParser.ParseName(itemId.Name, out nameWithoutYear, out yearInName);
+ var entry = srch.FirstOrDefault();
- if (!string.IsNullOrEmpty(nameWithoutYear) && !string.Equals(nameWithoutYear, itemId.Name, StringComparison.OrdinalIgnoreCase))
+ if (entry != null)
{
- seriesId = await FindSeries(nameWithoutYear, cancellationToken).ConfigureAwait(false);
+ seriesId = entry.GetProviderId(MetadataProviders.Tvdb);
}
}
}
@@ -223,7 +237,7 @@ namespace MediaBrowser.Providers.TV
var download = false;
var automaticUpdatesEnabled = _config.Configuration.EnableTvDbUpdates;
- const int cacheDays = 3;
+ const int cacheDays = 2;
var seriesFile = files.FirstOrDefault(i => string.Equals(seriesXmlFilename, i.Name, StringComparison.OrdinalIgnoreCase));
// No need to check age if automatic updates are enabled
@@ -262,8 +276,29 @@ namespace MediaBrowser.Providers.TV
/// <param name="name">The name.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.String}.</returns>
- private async Task<string> FindSeries(string name, CancellationToken cancellationToken)
+ private async Task<IEnumerable<RemoteSearchResult>> FindSeries(string name, CancellationToken cancellationToken)
+ {
+ var results = (await FindSeriesInternal(name, cancellationToken).ConfigureAwait(false)).ToList();
+
+ if (results.Count == 0)
+ {
+ int? yearInName = null;
+ string nameWithoutYear;
+ NameParser.ParseName(name, out nameWithoutYear, out yearInName);
+
+ if (!string.IsNullOrEmpty(nameWithoutYear) && !string.Equals(nameWithoutYear, name, StringComparison.OrdinalIgnoreCase))
+ {
+ results = (await FindSeriesInternal(nameWithoutYear, cancellationToken).ConfigureAwait(false)).ToList();
+ }
+ }
+
+ return results;
+ }
+
+ private async Task<IEnumerable<RemoteSearchResult>> FindSeriesInternal(string name, CancellationToken cancellationToken)
{
+ // TODO: Support returning more data, including image url's for the identify function
+
var url = string.Format(RootUrl + SeriesQuery, WebUtility.UrlEncode(name));
var doc = new XmlDocument();
@@ -278,6 +313,8 @@ namespace MediaBrowser.Providers.TV
doc.Load(results);
}
+ var searchResults = new List<RemoteSearchResult>();
+
if (doc.HasChildNodes)
{
var nodes = doc.SelectNodes("//Series");
@@ -305,7 +342,17 @@ namespace MediaBrowser.Providers.TV
{
var id = node.SelectSingleNode("./seriesid");
if (id != null)
- return id.InnerText;
+ {
+ var searchResult = new RemoteSearchResult
+ {
+ Name = titles.FirstOrDefault(),
+ SearchProviderName = Name
+ };
+
+ searchResult.SetProviderId(MetadataProviders.Tvdb, id.InnerText);
+
+ searchResults.Add(searchResult);
+ }
}
foreach (var title in titles)
@@ -317,7 +364,7 @@ namespace MediaBrowser.Providers.TV
}
_logger.Info("TVDb Provider - Could not find " + name + ". Check name on Thetvdb.org.");
- return null;
+ return searchResults;
}
/// <summary>
@@ -1133,11 +1180,20 @@ namespace MediaBrowser.Providers.TV
{
string tvdbId;
if (!info.ProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out tvdbId))
- tvdbId = await FindSeries(info.Name, CancellationToken.None);
+ {
+ var srch = await GetSearchResults(info, CancellationToken.None).ConfigureAwait(false);
+
+ var entry = srch.FirstOrDefault();
+
+ if (entry != null)
+ {
+ tvdbId = entry.GetProviderId(MetadataProviders.Tvdb);
+ }
+ }
if (!string.IsNullOrEmpty(tvdbId))
{
- return new SeriesIdentity {Type = MetadataProviders.Tvdb.ToString(), Id = tvdbId};
+ return new SeriesIdentity { Type = MetadataProviders.Tvdb.ToString(), Id = tvdbId };
}
return null;
diff --git a/MediaBrowser.Providers/packages.config b/MediaBrowser.Providers/packages.config
index 9d3b60ff5..29a802156 100644
--- a/MediaBrowser.Providers/packages.config
+++ b/MediaBrowser.Providers/packages.config
@@ -2,4 +2,5 @@
<packages>
<package id="MediaBrowser.BdInfo" version="1.0.0.10" targetFramework="net45" />
<package id="morelinq" version="1.0.16006" targetFramework="net45" />
+ <package id="taglib" version="2.1.0.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Activity/ActivityManager.cs b/MediaBrowser.Server.Implementations/Activity/ActivityManager.cs
new file mode 100644
index 000000000..7b123bad2
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Activity/ActivityManager.cs
@@ -0,0 +1,40 @@
+using MediaBrowser.Common.Events;
+using MediaBrowser.Controller.Activity;
+using MediaBrowser.Model.Activity;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Querying;
+using System;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Activity
+{
+ public class ActivityManager : IActivityManager
+ {
+ public event EventHandler<GenericEventArgs<ActivityLogEntry>> EntryCreated;
+
+ private readonly IActivityRepository _repo;
+ private readonly ILogger _logger;
+
+ public ActivityManager(ILogger logger, IActivityRepository repo)
+ {
+ _logger = logger;
+ _repo = repo;
+ }
+
+ public async Task Create(ActivityLogEntry entry)
+ {
+ entry.Id = Guid.NewGuid().ToString("N");
+ entry.Date = DateTime.UtcNow;
+
+ await _repo.Create(entry).ConfigureAwait(false);
+
+ EventHelper.FireEventIfNotNull(EntryCreated, this, new GenericEventArgs<ActivityLogEntry>(entry), _logger);
+ }
+
+ public QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit)
+ {
+ return _repo.GetActivityLogEntries(minDate, startIndex, limit);
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs
new file mode 100644
index 000000000..f491a5c44
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs
@@ -0,0 +1,309 @@
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Activity;
+using MediaBrowser.Model.Activity;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Querying;
+using MediaBrowser.Server.Implementations.Persistence;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Globalization;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Activity
+{
+ public class ActivityRepository : IActivityRepository, IDisposable
+ {
+ private IDbConnection _connection;
+ private readonly ILogger _logger;
+ private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1);
+ private readonly IServerApplicationPaths _appPaths;
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
+ private IDbCommand _saveActivityCommand;
+
+ public ActivityRepository(ILogger logger, IServerApplicationPaths appPaths)
+ {
+ _logger = logger;
+ _appPaths = appPaths;
+ }
+
+ public async Task Initialize()
+ {
+ var dbFile = Path.Combine(_appPaths.DataPath, "activitylog.db");
+
+ _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
+
+ string[] queries = {
+
+ "create table if not exists ActivityLogEntries (Id GUID PRIMARY KEY, Name TEXT, Overview TEXT, ShortOverview TEXT, Type TEXT, ItemId TEXT, UserId TEXT, DateCreated DATETIME, LogSeverity TEXT)",
+ "create index if not exists idx_ActivityLogEntries on ActivityLogEntries(Id)",
+
+ //pragmas
+ "pragma temp_store = memory",
+
+ "pragma shrink_memory"
+ };
+
+ _connection.RunQueries(queries, _logger);
+
+ PrepareStatements();
+ }
+
+ private void PrepareStatements()
+ {
+ _saveActivityCommand = _connection.CreateCommand();
+ _saveActivityCommand.CommandText = "replace into ActivityLogEntries (Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) values (@Id, @Name, @Overview, @ShortOverview, @Type, @ItemId, @UserId, @DateCreated, @LogSeverity)";
+
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@Id");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@Name");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@Overview");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@ShortOverview");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@Type");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@ItemId");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@UserId");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@DateCreated");
+ _saveActivityCommand.Parameters.Add(_saveActivityCommand, "@LogSeverity");
+ }
+
+ private const string BaseActivitySelectText = "select Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity from ActivityLogEntries";
+
+ public Task Create(ActivityLogEntry entry)
+ {
+ return Update(entry);
+ }
+
+ public async Task Update(ActivityLogEntry entry)
+ {
+ if (entry == null)
+ {
+ throw new ArgumentNullException("entry");
+ }
+
+ await _writeLock.WaitAsync().ConfigureAwait(false);
+
+ IDbTransaction transaction = null;
+
+ try
+ {
+ transaction = _connection.BeginTransaction();
+
+ var index = 0;
+
+ _saveActivityCommand.GetParameter(index++).Value = new Guid(entry.Id);
+ _saveActivityCommand.GetParameter(index++).Value = entry.Name;
+ _saveActivityCommand.GetParameter(index++).Value = entry.Overview;
+ _saveActivityCommand.GetParameter(index++).Value = entry.ShortOverview;
+ _saveActivityCommand.GetParameter(index++).Value = entry.Type;
+ _saveActivityCommand.GetParameter(index++).Value = entry.ItemId;
+ _saveActivityCommand.GetParameter(index++).Value = entry.UserId;
+ _saveActivityCommand.GetParameter(index++).Value = entry.Date;
+ _saveActivityCommand.GetParameter(index++).Value = entry.Severity.ToString();
+
+ _saveActivityCommand.Transaction = transaction;
+
+ _saveActivityCommand.ExecuteNonQuery();
+
+ transaction.Commit();
+ }
+ catch (OperationCanceledException)
+ {
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ catch (Exception e)
+ {
+ _logger.ErrorException("Failed to save record:", e);
+
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ finally
+ {
+ if (transaction != null)
+ {
+ transaction.Dispose();
+ }
+
+ _writeLock.Release();
+ }
+ }
+
+ public QueryResult<ActivityLogEntry> GetActivityLogEntries(DateTime? minDate, int? startIndex, int? limit)
+ {
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = BaseActivitySelectText;
+
+ var whereClauses = new List<string>();
+
+ if (minDate.HasValue)
+ {
+ whereClauses.Add("DateCreated>=@DateCreated");
+ cmd.Parameters.Add(cmd, "@DateCreated", DbType.Date).Value = minDate.Value;
+ }
+
+ var whereTextWithoutPaging = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ if (startIndex.HasValue && startIndex.Value > 0)
+ {
+ var pagingWhereText = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM ActivityLogEntries {0} ORDER BY DateCreated DESC LIMIT {1})",
+ pagingWhereText,
+ startIndex.Value.ToString(_usCulture)));
+ }
+
+ var whereText = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ cmd.CommandText += whereText;
+
+ cmd.CommandText += " ORDER BY DateCreated DESC";
+
+ if (limit.HasValue)
+ {
+ cmd.CommandText += " LIMIT " + limit.Value.ToString(_usCulture);
+ }
+
+ cmd.CommandText += "; select count (Id) from ActivityLogEntries" + whereTextWithoutPaging;
+
+ var list = new List<ActivityLogEntry>();
+ var count = 0;
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
+ {
+ while (reader.Read())
+ {
+ list.Add(GetEntry(reader));
+ }
+
+ if (reader.NextResult() && reader.Read())
+ {
+ count = reader.GetInt32(0);
+ }
+ }
+
+ return new QueryResult<ActivityLogEntry>()
+ {
+ Items = list.ToArray(),
+ TotalRecordCount = count
+ };
+ }
+ }
+
+ private ActivityLogEntry GetEntry(IDataReader reader)
+ {
+ var index = 0;
+
+ var info = new ActivityLogEntry
+ {
+ Id = reader.GetGuid(index).ToString("N")
+ };
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.Name = reader.GetString(index);
+ }
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.Overview = reader.GetString(index);
+ }
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.ShortOverview = reader.GetString(index);
+ }
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.Type = reader.GetString(index);
+ }
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.ItemId = reader.GetString(index);
+ }
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.UserId = reader.GetString(index);
+ }
+
+ index++;
+ info.Date = reader.GetDateTime(index).ToUniversalTime();
+
+ index++;
+ if (!reader.IsDBNull(index))
+ {
+ info.Severity = (LogSeverity)Enum.Parse(typeof(LogSeverity), reader.GetString(index), true);
+ }
+
+ return info;
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ private readonly object _disposeLock = new object();
+
+ /// <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)
+ {
+ try
+ {
+ lock (_disposeLock)
+ {
+ if (_connection != null)
+ {
+ if (_connection.IsOpen())
+ {
+ _connection.Close();
+ }
+
+ _connection.Dispose();
+ _connection = null;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error disposing database", ex);
+ }
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Branding/BrandingConfigurationFactory.cs b/MediaBrowser.Server.Implementations/Branding/BrandingConfigurationFactory.cs
new file mode 100644
index 000000000..d6cd3424b
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Branding/BrandingConfigurationFactory.cs
@@ -0,0 +1,21 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Branding;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Server.Implementations.Branding
+{
+ public class BrandingConfigurationFactory : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new[]
+ {
+ new ConfigurationStore
+ {
+ ConfigurationType = typeof(BrandingOptions),
+ Key = "branding"
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs b/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs
new file mode 100644
index 000000000..9dfb0404e
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelConfigurations.cs
@@ -0,0 +1,29 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Configuration;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Server.Implementations.Channels
+{
+ public static class ChannelConfigurationExtension
+ {
+ public static ChannelOptions GetChannelsConfiguration(this IConfigurationManager manager)
+ {
+ return manager.GetConfiguration<ChannelOptions>("channels");
+ }
+ }
+
+ public class ChannelConfigurationFactory : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new List<ConfigurationStore>
+ {
+ new ConfigurationStore
+ {
+ Key = "channels",
+ ConfigurationType = typeof (ChannelOptions)
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
index ce5c41f89..39f747e0a 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
@@ -7,6 +7,7 @@ using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Channels;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
@@ -71,7 +72,7 @@ namespace MediaBrowser.Server.Implementations.Channels
var startingPercent = numComplete * percentPerUser * 100;
var innerProgress = new ActionableProgress<double>();
- innerProgress.RegisterAction(p => progress.Report(startingPercent + (.8 * p)));
+ innerProgress.RegisterAction(p => progress.Report(startingPercent + (percentPerUser * p)));
await DownloadContent(user, cancellationToken, innerProgress).ConfigureAwait(false);
@@ -146,13 +147,15 @@ namespace MediaBrowser.Server.Implementations.Channels
{
var numComplete = 0;
+ var options = _config.GetChannelsConfiguration();
+
foreach (var item in result.Items)
{
- if (_config.Configuration.ChannelOptions.DownloadingChannels.Contains(item.ChannelId))
+ if (options.DownloadingChannels.Contains(item.ChannelId))
{
try
{
- await DownloadChannelItem(item, cancellationToken, path);
+ await DownloadChannelItem(item, options, cancellationToken, path);
}
catch (OperationCanceledException)
{
@@ -174,9 +177,18 @@ namespace MediaBrowser.Server.Implementations.Channels
}
private async Task DownloadChannelItem(BaseItemDto item,
+ ChannelOptions channelOptions,
CancellationToken cancellationToken,
string path)
{
+ if (channelOptions.DownloadSizeLimit.HasValue)
+ {
+ if (IsSizeLimitReached(path, channelOptions.DownloadSizeLimit.Value))
+ {
+ return;
+ }
+ }
+
var sources = await _manager.GetChannelItemMediaSources(item.Id, cancellationToken)
.ConfigureAwait(false);
@@ -218,7 +230,8 @@ namespace MediaBrowser.Server.Implementations.Channels
if (item.IsVideo && response.ContentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
{
var extension = response.ContentType.Split('/')
- .Last();
+ .Last()
+ .Replace("quicktime", "mov", StringComparison.OrdinalIgnoreCase);
destination += "." + extension;
}
@@ -237,7 +250,7 @@ namespace MediaBrowser.Server.Implementations.Channels
throw new ApplicationException("Unexpected response type encountered: " + response.ContentType);
}
- File.Move(response.TempFilePath, destination);
+ File.Copy(response.TempFilePath, destination, true);
await RefreshMediaSourceItem(destination, cancellationToken).ConfigureAwait(false);
@@ -251,6 +264,25 @@ namespace MediaBrowser.Server.Implementations.Channels
}
}
+ private bool IsSizeLimitReached(string path, double gbLimit)
+ {
+ var byteLimit = gbLimit*1000000000;
+
+ long total = 0;
+
+ foreach (var file in new DirectoryInfo(path).EnumerateFiles("*", SearchOption.AllDirectories))
+ {
+ total += file.Length;
+
+ if (total >= byteLimit)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
private async Task RefreshMediaSourceItems(IEnumerable<MediaSourceInfo> items, CancellationToken cancellationToken)
{
foreach (var item in items)
@@ -282,12 +314,14 @@ namespace MediaBrowser.Server.Implementations.Channels
private void CleanChannelContent(CancellationToken cancellationToken)
{
- if (!_config.Configuration.ChannelOptions.MaxDownloadAge.HasValue)
+ var options = _config.GetChannelsConfiguration();
+
+ if (!options.MaxDownloadAge.HasValue)
{
return;
}
- var minDateModified = DateTime.UtcNow.AddDays(0 - _config.Configuration.ChannelOptions.MaxDownloadAge.Value);
+ var minDateModified = DateTime.UtcNow.AddDays(0 - options.MaxDownloadAge.Value);
var path = _manager.ChannelDownloadPath;
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index 188a26c60..c7ca6bb30 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -1,5 +1,4 @@
-using System.Collections.Concurrent;
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
@@ -16,6 +15,7 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Serialization;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -28,7 +28,6 @@ namespace MediaBrowser.Server.Implementations.Channels
{
private IChannel[] _channels;
private IChannelFactory[] _factories;
- private List<Channel> _channelEntities = new List<Channel>();
private readonly IUserManager _userManager;
private readonly IUserDataManager _userDataManager;
@@ -63,13 +62,13 @@ namespace MediaBrowser.Server.Implementations.Channels
{
get
{
- return TimeSpan.FromDays(1);
+ return TimeSpan.FromHours(12);
}
}
public void AddParts(IEnumerable<IChannel> channels, IEnumerable<IChannelFactory> factories)
{
- _channels = channels.ToArray();
+ _channels = channels.Where(i => !(i is IFactoryChannel)).ToArray();
_factories = factories.ToArray();
}
@@ -77,9 +76,11 @@ namespace MediaBrowser.Server.Implementations.Channels
{
get
{
- if (!string.IsNullOrWhiteSpace(_config.Configuration.ChannelOptions.DownloadPath))
+ var options = _config.GetChannelsConfiguration();
+
+ if (!string.IsNullOrWhiteSpace(options.DownloadPath))
{
- return _config.Configuration.ChannelOptions.DownloadPath;
+ return options.DownloadPath;
}
return Path.Combine(_config.ApplicationPaths.ProgramDataPath, "channels");
@@ -105,13 +106,16 @@ namespace MediaBrowser.Server.Implementations.Channels
.OrderBy(i => i.Name);
}
- public Task<QueryResult<BaseItemDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken)
+ public Task<QueryResult<Channel>> GetChannelsInternal(ChannelQuery query, CancellationToken cancellationToken)
{
var user = string.IsNullOrWhiteSpace(query.UserId)
? null
: _userManager.GetUserById(new Guid(query.UserId));
- var channels = _channelEntities.OrderBy(i => i.SortName).ToList();
+ var channels = GetAllChannels()
+ .Select(GetChannelEntity)
+ .OrderBy(i => i.SortName)
+ .ToList();
if (query.SupportsLatestItems.HasValue)
{
@@ -144,29 +148,46 @@ namespace MediaBrowser.Server.Implementations.Channels
all = all.Take(query.Limit.Value).ToList();
}
+ var returnItems = all.ToArray();
+
+ var result = new QueryResult<Channel>
+ {
+ Items = returnItems,
+ TotalRecordCount = totalCount
+ };
+
+ return Task.FromResult(result);
+ }
+
+ public async Task<QueryResult<BaseItemDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken)
+ {
+ var user = string.IsNullOrWhiteSpace(query.UserId)
+ ? null
+ : _userManager.GetUserById(new Guid(query.UserId));
+
+ var internalResult = await GetChannelsInternal(query, cancellationToken).ConfigureAwait(false);
+
// Get everything
var fields = Enum.GetNames(typeof(ItemFields))
.Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
.ToList();
- var returnItems = all.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
+ var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
.ToArray();
var result = new QueryResult<BaseItemDto>
{
Items = returnItems,
- TotalRecordCount = totalCount
+ TotalRecordCount = internalResult.TotalRecordCount
};
- return Task.FromResult(result);
+ return result;
}
public async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
{
var allChannelsList = GetAllChannels().ToList();
- var list = new List<Channel>();
-
var numComplete = 0;
foreach (var channelInfo in allChannelsList)
@@ -177,8 +198,6 @@ namespace MediaBrowser.Server.Implementations.Channels
{
var item = await GetChannel(channelInfo, cancellationToken).ConfigureAwait(false);
- list.Add(item);
-
_libraryManager.RegisterItem(item);
}
catch (OperationCanceledException)
@@ -197,16 +216,28 @@ namespace MediaBrowser.Server.Implementations.Channels
progress.Report(100 * percent);
}
- _channelEntities = list.ToList();
progress.Report(100);
}
+ private Channel GetChannelEntity(IChannel channel)
+ {
+ var item = GetChannel(GetInternalChannelId(channel.Name).ToString("N"));
+
+ if (item == null)
+ {
+ item = GetChannel(channel, CancellationToken.None).Result;
+
+ _libraryManager.RegisterItem(item);
+ }
+
+ return item;
+ }
+
public async Task<IEnumerable<MediaSourceInfo>> GetChannelItemMediaSources(string id, CancellationToken cancellationToken)
{
var item = (IChannelMediaItem)_libraryManager.GetItemById(id);
- var channelGuid = new Guid(item.ChannelId);
- var channel = _channelEntities.First(i => i.Id == channelGuid);
+ var channel = GetChannel(item.ChannelId);
var channelPlugin = GetChannelProvider(channel);
var requiresCallback = channelPlugin as IRequiresMediaInfoCallback;
@@ -374,17 +405,23 @@ namespace MediaBrowser.Server.Implementations.Channels
{
var list = channelMediaSources.ToList();
- var width = _config.Configuration.ChannelOptions.PreferredStreamingWidth;
+ var options = _config.GetChannelsConfiguration();
+
+ var width = options.PreferredStreamingWidth;
if (width.HasValue)
{
var val = width.Value;
- return list
- .OrderBy(i => i.Width.HasValue && i.Width.Value <= val)
- .ThenBy(i => Math.Abs(i.Width ?? 0 - val))
+ var res = list
+ .OrderBy(i => (i.Width.HasValue && i.Width.Value <= val ? 0 : 1))
+ .ThenBy(i => Math.Abs((i.Width ?? 0) - val))
.ThenByDescending(i => i.Width ?? 0)
- .ThenBy(list.IndexOf);
+ .ThenBy(list.IndexOf)
+ .ToList();
+
+
+ return res;
}
return list
@@ -476,7 +513,8 @@ namespace MediaBrowser.Server.Implementations.Channels
public IEnumerable<ChannelFeatures> GetAllChannelFeatures()
{
- return _channelEntities
+ return GetAllChannels()
+ .Select(GetChannelEntity)
.OrderBy(i => i.SortName)
.Select(i => GetChannelFeatures(i.Id.ToString("N")));
}
@@ -529,7 +567,12 @@ namespace MediaBrowser.Server.Implementations.Channels
? null
: _userManager.GetUserById(new Guid(query.UserId));
- var channels = _channels;
+ if (!string.IsNullOrWhiteSpace(query.UserId) && user == null)
+ {
+ throw new ArgumentException("User not found.");
+ }
+
+ var channels = GetAllChannels();
if (query.ChannelIds.Length > 0)
{
@@ -590,8 +633,8 @@ namespace MediaBrowser.Server.Implementations.Channels
var itemTasks = items.Select(i =>
{
var channelProvider = i.Item1;
- var channel = GetChannel(GetInternalChannelId(channelProvider.Name).ToString("N"));
- return GetChannelItemEntity(i.Item2, channelProvider, channel, token);
+ var internalChannelId = GetInternalChannelId(channelProvider.Name);
+ return GetChannelItemEntity(i.Item2, channelProvider, internalChannelId, token);
});
var internalItems = await Task.WhenAll(itemTasks).ConfigureAwait(false);
@@ -683,7 +726,7 @@ namespace MediaBrowser.Server.Implementations.Channels
? null
: _userManager.GetUserById(new Guid(query.UserId));
- var channels = _channels;
+ var channels = GetAllChannels();
if (query.ChannelIds.Length > 0)
{
@@ -748,8 +791,8 @@ namespace MediaBrowser.Server.Implementations.Channels
var itemTasks = items.Select(i =>
{
var channelProvider = i.Item1;
- var channel = GetChannel(GetInternalChannelId(channelProvider.Name).ToString("N"));
- return GetChannelItemEntity(i.Item2, channelProvider, channel, token);
+ var internalChannelId = GetInternalChannelId(channelProvider.Name);
+ return GetChannelItemEntity(i.Item2, channelProvider, internalChannelId, token);
});
var internalItems = await Task.WhenAll(itemTasks).ConfigureAwait(false);
@@ -822,11 +865,10 @@ namespace MediaBrowser.Server.Implementations.Channels
}
}
- public async Task<QueryResult<BaseItemDto>> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken)
+ public async Task<QueryResult<BaseItem>> GetChannelItemsInternal(ChannelItemQuery query, CancellationToken cancellationToken)
{
- var queryChannelId = query.ChannelId;
// Get the internal channel entity
- var channel = _channelEntities.First(i => i.Id == new Guid(queryChannelId));
+ var channel = GetChannel(query.ChannelId);
// Find the corresponding channel provider plugin
var channelProvider = GetChannelProvider(channel);
@@ -845,6 +887,12 @@ namespace MediaBrowser.Server.Implementations.Channels
throw new ArgumentException(string.Format("{0} channel only supports a maximum of {1} records at a time.", channel.Name, channelInfo.MaxPageSize.Value));
}
providerLimit = query.Limit;
+
+ // This will cause some providers to fail
+ if (providerLimit == 0)
+ {
+ providerLimit = 1;
+ }
}
var user = string.IsNullOrWhiteSpace(query.UserId)
@@ -873,7 +921,7 @@ namespace MediaBrowser.Server.Implementations.Channels
var providerTotalRecordCount = providerLimit.HasValue ? itemsResult.TotalRecordCount : null;
- var tasks = itemsResult.Items.Select(i => GetChannelItemEntity(i, channelProvider, channel, cancellationToken));
+ var tasks = itemsResult.Items.Select(i => GetChannelItemEntity(i, channelProvider, channel.Id, cancellationToken));
var internalItems = await Task.WhenAll(tasks).ConfigureAwait(false);
@@ -890,6 +938,31 @@ namespace MediaBrowser.Server.Implementations.Channels
return await GetReturnItems(internalItems, providerTotalRecordCount, user, query, cancellationToken).ConfigureAwait(false);
}
+ public async Task<QueryResult<BaseItemDto>> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken)
+ {
+ var user = string.IsNullOrWhiteSpace(query.UserId)
+ ? null
+ : _userManager.GetUserById(new Guid(query.UserId));
+
+ var internalResult = await GetChannelItemsInternal(query, cancellationToken).ConfigureAwait(false);
+
+ // Get everything
+ var fields = Enum.GetNames(typeof(ItemFields))
+ .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
+ .ToList();
+
+ var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
+ .ToArray();
+
+ var result = new QueryResult<BaseItemDto>
+ {
+ Items = returnItems,
+ TotalRecordCount = internalResult.TotalRecordCount
+ };
+
+ return result;
+ }
+
private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1);
private async Task<ChannelItemResult> GetChannelItems(IChannel channel,
User user,
@@ -1031,7 +1104,7 @@ namespace MediaBrowser.Server.Implementations.Channels
filename + ".json");
}
- private async Task<QueryResult<BaseItemDto>> GetReturnItems(IEnumerable<BaseItem> items, int? totalCountFromProvider, User user, ChannelItemQuery query, CancellationToken cancellationToken)
+ private async Task<QueryResult<BaseItem>> GetReturnItems(IEnumerable<BaseItem> items, int? totalCountFromProvider, User user, ChannelItemQuery query, CancellationToken cancellationToken)
{
items = ApplyFilters(items, query.Filters, user);
@@ -1055,10 +1128,9 @@ namespace MediaBrowser.Server.Implementations.Channels
await RefreshIfNeeded(all, cancellationToken).ConfigureAwait(false);
- var returnItemArray = all.Select(i => _dtoService.GetBaseItemDto(i, query.Fields, user))
- .ToArray();
+ var returnItemArray = all.ToArray();
- return new QueryResult<BaseItemDto>
+ return new QueryResult<BaseItem>
{
Items = returnItemArray,
TotalRecordCount = totalCount
@@ -1073,7 +1145,7 @@ namespace MediaBrowser.Server.Implementations.Channels
(channelProvider.Name ?? string.Empty) + "16";
}
- private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info, IChannel channelProvider, Channel internalChannel, CancellationToken cancellationToken)
+ private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info, IChannel channelProvider, Guid internalChannelId, CancellationToken cancellationToken)
{
BaseItem item;
Guid id;
@@ -1129,6 +1201,8 @@ namespace MediaBrowser.Server.Implementations.Channels
item.CommunityRating = info.CommunityRating;
item.OfficialRating = info.OfficialRating;
item.Overview = info.Overview;
+ item.IndexNumber = info.IndexNumber;
+ item.ParentIndexNumber = info.ParentIndexNumber;
item.People = info.People;
item.PremiereDate = info.PremiereDate;
item.ProductionYear = info.ProductionYear;
@@ -1143,7 +1217,7 @@ namespace MediaBrowser.Server.Implementations.Channels
channelItem.OriginalImageUrl = info.ImageUrl;
channelItem.ExternalId = info.Id;
- channelItem.ChannelId = internalChannel.Id.ToString("N");
+ channelItem.ChannelId = internalChannelId.ToString("N");
channelItem.ChannelItemType = info.Type;
if (isNew)
@@ -1155,13 +1229,14 @@ namespace MediaBrowser.Server.Implementations.Channels
if (channelMediaItem != null)
{
- channelMediaItem.IsInfiniteStream = info.IsInfiniteStream;
channelMediaItem.ContentType = info.ContentType;
channelMediaItem.ChannelMediaSources = info.MediaSources;
var mediaSource = info.MediaSources.FirstOrDefault();
item.Path = mediaSource == null ? null : mediaSource.Path;
+
+ item.DisplayMediaType = channelMediaItem.ContentType.ToString();
}
if (isNew)
diff --git a/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs
index ee75e4d05..c6ecfc250 100644
--- a/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs
@@ -42,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.Channels
{
return new ITaskTrigger[]
{
- new StartupTrigger(),
+ new StartupTrigger{DelayMs = 10000},
new SystemEventTrigger{ SystemEvent = SystemEvent.WakeFromSleep},
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
index a69f9e94b..fe4b16645 100644
--- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
+++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
@@ -1,16 +1,18 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Logging;
+using MoreLinq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MoreLinq;
namespace MediaBrowser.Server.Implementations.Collections
{
@@ -19,12 +21,24 @@ namespace MediaBrowser.Server.Implementations.Collections
private readonly ILibraryManager _libraryManager;
private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _iLibraryMonitor;
+ private readonly ILogger _logger;
- public CollectionManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor)
+ public event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
+ public event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
+ public event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
+
+ public CollectionManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor, ILogger logger)
{
_libraryManager = libraryManager;
_fileSystem = fileSystem;
_iLibraryMonitor = iLibraryMonitor;
+ _logger = logger;
+ }
+
+ public Folder GetCollectionsFolder(string userId)
+ {
+ return _libraryManager.RootFolder.Children.OfType<ManualCollectionsFolder>()
+ .FirstOrDefault();
}
public async Task<BoxSet> CreateCollection(CollectionCreationOptions options)
@@ -68,9 +82,16 @@ namespace MediaBrowser.Server.Implementations.Collections
if (options.ItemIdList.Count > 0)
{
- await AddToCollection(collection.Id, options.ItemIdList);
+ await AddToCollection(collection.Id, options.ItemIdList, false);
}
+ EventHelper.FireEventIfNotNull(CollectionCreated, this, new CollectionCreatedEventArgs
+ {
+ Collection = collection,
+ Options = options
+
+ }, _logger);
+
return collection;
}
finally
@@ -104,11 +125,15 @@ namespace MediaBrowser.Server.Implementations.Collections
}
}
- return _libraryManager.RootFolder.Children.OfType<ManualCollectionsFolder>().FirstOrDefault() ??
- _libraryManager.RootFolder.GetHiddenChildren().OfType<ManualCollectionsFolder>().FirstOrDefault();
+ return GetCollectionsFolder(string.Empty);
}
- public async Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
+ public Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
+ {
+ return AddToCollection(collectionId, ids, true);
+ }
+
+ private async Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent)
{
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
@@ -118,6 +143,7 @@ namespace MediaBrowser.Server.Implementations.Collections
}
var list = new List<LinkedChild>();
+ var itemList = new List<BaseItem>();
var currentLinkedChildren = collection.GetLinkedChildren().ToList();
foreach (var itemId in ids)
@@ -129,18 +155,14 @@ namespace MediaBrowser.Server.Implementations.Collections
throw new ArgumentException("No item exists with the supplied Id");
}
+ itemList.Add(item);
+
if (currentLinkedChildren.Any(i => i.Id == itemId))
{
throw new ArgumentException("Item already exists in collection");
}
- list.Add(new LinkedChild
- {
- ItemName = item.Name,
- ItemYear = item.ProductionYear,
- ItemType = item.GetType().Name,
- Type = LinkedChildType.Manual
- });
+ list.Add(LinkedChild.Create(item));
var supportsGrouping = item as ISupportsBoxSetGrouping;
@@ -160,6 +182,16 @@ namespace MediaBrowser.Server.Implementations.Collections
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false);
+
+ if (fireEvent)
+ {
+ EventHelper.FireEventIfNotNull(ItemsAddedToCollection, this, new CollectionModifiedEventArgs
+ {
+ Collection = collection,
+ ItemsChanged = itemList
+
+ }, _logger);
+ }
}
public async Task RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds)
@@ -172,6 +204,7 @@ namespace MediaBrowser.Server.Implementations.Collections
}
var list = new List<LinkedChild>();
+ var itemList = new List<BaseItem>();
foreach (var itemId in itemIds)
{
@@ -185,6 +218,12 @@ namespace MediaBrowser.Server.Implementations.Collections
list.Add(child);
var childItem = _libraryManager.GetItemById(itemId);
+
+ if (childItem != null)
+ {
+ itemList.Add(childItem);
+ }
+
var supportsGrouping = childItem as ISupportsBoxSetGrouping;
if (supportsGrouping != null)
@@ -216,7 +255,7 @@ namespace MediaBrowser.Server.Implementations.Collections
{
File.Delete(file);
}
-
+
foreach (var child in list)
{
collection.LinkedChildren.Remove(child);
@@ -233,6 +272,13 @@ namespace MediaBrowser.Server.Implementations.Collections
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false);
+
+ EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs
+ {
+ Collection = collection,
+ ItemsChanged = itemList
+
+ }, _logger);
}
public IEnumerable<BaseItem> CollapseItemsWithinBoxSets(IEnumerable<BaseItem> items, User user)
diff --git a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
index c58b9181b..b02c52874 100644
--- a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
+++ b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
@@ -8,26 +8,28 @@ namespace MediaBrowser.Server.Implementations.Collections
public ManualCollectionsFolder()
{
Name = "Collections";
+ DisplayMediaType = "CollectionFolder";
}
public override bool IsVisible(User user)
{
- if (!GetChildren(user, true).Any())
- {
- return false;
- }
-
- return base.IsVisible(user);
+ return GetChildren(user, true).Any() &&
+ base.IsVisible(user);
}
public override bool IsHidden
{
get
{
- return !ActualChildren.Any() || base.IsHidden;
+ return true;
}
}
+ public override bool IsHiddenFromUser(User user)
+ {
+ return !user.Configuration.DisplayCollectionsView;
+ }
+
public override string CollectionType
{
get { return Model.Entities.CollectionType.BoxSets; }
diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
index 59267e856..031ca85f9 100644
--- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
+++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
@@ -3,12 +3,17 @@ using MediaBrowser.Common.Events;
using MediaBrowser.Common.Implementations.Configuration;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System;
using System.IO;
+using System.Linq;
namespace MediaBrowser.Server.Implementations.Configuration
{
@@ -205,5 +210,55 @@ namespace MediaBrowser.Server.Implementations.Configuration
}
}
}
+
+ public void DisableMetadataService(string service)
+ {
+ DisableMetadataService(typeof(Movie), Configuration, service);
+ DisableMetadataService(typeof(MusicAlbum), Configuration, service);
+ DisableMetadataService(typeof(MusicArtist), Configuration, service);
+ DisableMetadataService(typeof(Episode), Configuration, service);
+ DisableMetadataService(typeof(Season), Configuration, service);
+ DisableMetadataService(typeof(Series), Configuration, service);
+ DisableMetadataService(typeof(MusicVideo), Configuration, service);
+ DisableMetadataService(typeof(Trailer), Configuration, service);
+ DisableMetadataService(typeof(AdultVideo), Configuration, service);
+ DisableMetadataService(typeof(Video), Configuration, service);
+ }
+
+ private void DisableMetadataService(Type type, ServerConfiguration config, string service)
+ {
+ var options = GetMetadataOptions(type, config);
+
+ if (!options.DisabledMetadataSavers.Contains(service, StringComparer.OrdinalIgnoreCase))
+ {
+ var list = options.DisabledMetadataSavers.ToList();
+
+ list.Add(service);
+
+ options.DisabledMetadataSavers = list.ToArray();
+ }
+ }
+
+ private MetadataOptions GetMetadataOptions(Type type, ServerConfiguration config)
+ {
+ var options = config.MetadataOptions
+ .FirstOrDefault(i => string.Equals(i.ItemType, type.Name, StringComparison.OrdinalIgnoreCase));
+
+ if (options == null)
+ {
+ var list = config.MetadataOptions.ToList();
+
+ options = new MetadataOptions
+ {
+ ItemType = type.Name
+ };
+
+ list.Add(options);
+
+ config.MetadataOptions = list.ToArray();
+ }
+
+ return options;
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectData.cs b/MediaBrowser.Server.Implementations/Connect/ConnectData.cs
new file mode 100644
index 000000000..1816b103e
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectData.cs
@@ -0,0 +1,17 @@
+
+namespace MediaBrowser.Server.Implementations.Connect
+{
+ public class ConnectData
+ {
+ /// <summary>
+ /// Gets or sets the server identifier.
+ /// </summary>
+ /// <value>The server identifier.</value>
+ public string ServerId { get; set; }
+ /// <summary>
+ /// Gets or sets the access key.
+ /// </summary>
+ /// <value>The access key.</value>
+ public string AccessKey { get; set; }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
new file mode 100644
index 000000000..2ee78ba01
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
@@ -0,0 +1,125 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Connect;
+using MediaBrowser.Controller.Plugins;
+using MediaBrowser.Model.Logging;
+using System;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Threading;
+
+namespace MediaBrowser.Server.Implementations.Connect
+{
+ public class ConnectEntryPoint : IServerEntryPoint
+ {
+ private Timer _timer;
+ private readonly IHttpClient _httpClient;
+ private readonly IApplicationPaths _appPaths;
+ private readonly ILogger _logger;
+ private readonly IConnectManager _connectManager;
+
+ private readonly INetworkManager _networkManager;
+
+ public ConnectEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, INetworkManager networkManager, IConnectManager connectManager)
+ {
+ _httpClient = httpClient;
+ _appPaths = appPaths;
+ _logger = logger;
+ _networkManager = networkManager;
+ _connectManager = connectManager;
+ }
+
+ public void Run()
+ {
+ LoadCachedAddress();
+
+ _timer = new Timer(TimerCallback, null, TimeSpan.FromSeconds(30), TimeSpan.FromHours(24));
+ }
+
+ private async void TimerCallback(object state)
+ {
+ try
+ {
+ using (var stream = await _httpClient.Get(new HttpRequestOptions
+ {
+ Url = "http://bot.whatismyipaddress.com/"
+
+ }).ConfigureAwait(false))
+ {
+ using (var reader = new StreamReader(stream))
+ {
+ var address = await reader.ReadToEndAsync().ConfigureAwait(false);
+
+ if (IsValid(address))
+ {
+ ((ConnectManager) _connectManager).OnWanAddressResolved(address);
+ CacheAddress(address);
+ }
+ }
+ }
+ }
+ catch
+ {
+ }
+ }
+
+ private string CacheFilePath
+ {
+ get { return Path.Combine(_appPaths.DataPath, "wan.txt"); }
+ }
+
+ private void CacheAddress(string address)
+ {
+ var path = CacheFilePath;
+
+ try
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+ File.WriteAllText(path, address, Encoding.UTF8);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error saving data", ex);
+ }
+ }
+
+ private void LoadCachedAddress()
+ {
+ var path = CacheFilePath;
+
+ try
+ {
+ var endpoint = File.ReadAllText(path, Encoding.UTF8);
+
+ if (IsValid(endpoint))
+ {
+ ((ConnectManager)_connectManager).OnWanAddressResolved(endpoint);
+ }
+ }
+ catch (IOException)
+ {
+ // File isn't there. no biggie
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error loading data", ex);
+ }
+ }
+
+ private bool IsValid(string address)
+ {
+ IPAddress ipAddress;
+ return IPAddress.TryParse(address, out ipAddress);
+ }
+
+ public void Dispose()
+ {
+ if (_timer != null)
+ {
+ _timer.Dispose();
+ _timer = null;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
new file mode 100644
index 000000000..504814fe0
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
@@ -0,0 +1,204 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Connect;
+using MediaBrowser.Controller.Security;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Connect
+{
+ public class ConnectManager : IConnectManager
+ {
+ private readonly ILogger _logger;
+ private readonly IApplicationPaths _appPaths;
+ private readonly IJsonSerializer _json;
+ private readonly IEncryptionManager _encryption;
+ private readonly IHttpClient _httpClient;
+ private readonly IServerApplicationHost _appHost;
+ private readonly IServerConfigurationManager _config;
+
+ public string ConnectServerId { get; set; }
+ public string ConnectAccessKey { get; set; }
+
+ public string WanIpAddress { get; private set; }
+
+ public string WanApiAddress
+ {
+ get
+ {
+ var ip = WanIpAddress;
+
+ if (!string.IsNullOrEmpty(ip))
+ {
+ if (!ip.StartsWith("http://", StringComparison.OrdinalIgnoreCase) &&
+ !ip.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
+ {
+ ip = "http://" + ip;
+ }
+
+ return ip + ":" + _config.Configuration.HttpServerPortNumber.ToString(CultureInfo.InvariantCulture);
+ }
+
+ return null;
+ }
+ }
+
+ public ConnectManager(ILogger logger,
+ IApplicationPaths appPaths,
+ IJsonSerializer json,
+ IEncryptionManager encryption,
+ IHttpClient httpClient,
+ IServerApplicationHost appHost,
+ IServerConfigurationManager config)
+ {
+ _logger = logger;
+ _appPaths = appPaths;
+ _json = json;
+ _encryption = encryption;
+ _httpClient = httpClient;
+ _appHost = appHost;
+ _config = config;
+
+ LoadCachedData();
+ }
+
+ internal void OnWanAddressResolved(string address)
+ {
+ WanIpAddress = address;
+
+ UpdateConnectInfo();
+ }
+
+ private async void UpdateConnectInfo()
+ {
+ var wanApiAddress = WanApiAddress;
+
+ if (string.IsNullOrWhiteSpace(wanApiAddress))
+ {
+ _logger.Warn("Cannot update Media Browser Connect information without a WanApiAddress");
+ return;
+ }
+
+ try
+ {
+ var hasExistingRecord = !string.IsNullOrWhiteSpace(ConnectServerId) &&
+ !string.IsNullOrWhiteSpace(ConnectAccessKey);
+
+ if (hasExistingRecord)
+ {
+ //await UpdateServerRegistration(wanApiAddress).ConfigureAwait(false);
+ }
+ else
+ {
+ //await CreateServerRegistration(wanApiAddress).ConfigureAwait(false);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error registering with Connect", ex);
+ }
+ }
+
+ private async Task CreateServerRegistration(string wanApiAddress)
+ {
+ var url = "Servers";
+ url = GetConnectUrl(url);
+ url += "?Name=" + WebUtility.UrlEncode(_appHost.FriendlyName);
+ url += "&Url=" + WebUtility.UrlEncode(wanApiAddress);
+
+ using (var stream = await _httpClient.Post(url, new Dictionary<string, string>(), CancellationToken.None).ConfigureAwait(false))
+ {
+ var data = _json.DeserializeFromStream<ServerRegistrationResponse>(stream);
+
+ ConnectServerId = data.Id;
+ ConnectAccessKey = data.AccessKey;
+
+ CacheData();
+ }
+ }
+
+ private async Task UpdateServerRegistration(string wanApiAddress)
+ {
+ var url = "Servers/" + ConnectServerId;
+ url = GetConnectUrl(url);
+ url += "?Name=" + WebUtility.UrlEncode(_appHost.FriendlyName);
+ url += "&Url=" + WebUtility.UrlEncode(wanApiAddress);
+
+ // TODO: Add AccessKey http request header
+
+ // No need to examine the response
+ using (var stream = await _httpClient.Post(url, new Dictionary<string, string>(), CancellationToken.None).ConfigureAwait(false))
+ {
+ }
+ }
+
+ private string CacheFilePath
+ {
+ get { return Path.Combine(_appPaths.DataPath, "connect.txt"); }
+ }
+
+ private void CacheData()
+ {
+ var path = CacheFilePath;
+
+ try
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+
+ var json = _json.SerializeToString(new ConnectData
+ {
+ AccessKey = ConnectAccessKey,
+ ServerId = ConnectServerId
+ });
+
+ var encrypted = _encryption.EncryptString(json);
+
+ File.WriteAllText(path, encrypted, Encoding.UTF8);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error saving data", ex);
+ }
+ }
+
+ private void LoadCachedData()
+ {
+ var path = CacheFilePath;
+
+ try
+ {
+ var encrypted = File.ReadAllText(path, Encoding.UTF8);
+
+ var json = _encryption.DecryptString(encrypted);
+
+ var data = _json.DeserializeFromString<ConnectData>(json);
+
+ ConnectAccessKey = data.AccessKey;
+ ConnectServerId = data.ServerId;
+ }
+ catch (IOException)
+ {
+ // File isn't there. no biggie
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error loading data", ex);
+ }
+ }
+
+ private string GetConnectUrl(string handler)
+ {
+ return "http://mb3admin.com/admin/connect/" + handler;
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Connect/ServerRegistrationResponse.cs b/MediaBrowser.Server.Implementations/Connect/ServerRegistrationResponse.cs
new file mode 100644
index 000000000..75c55e26e
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Connect/ServerRegistrationResponse.cs
@@ -0,0 +1,18 @@
+
+namespace MediaBrowser.Server.Implementations.Connect
+{
+ public class ServerRegistrationResponse
+ {
+ public string Id { get; set; }
+ public string Url { get; set; }
+ public string Name { get; set; }
+ public string AccessKey { get; set; }
+ }
+
+ public class UpdateServerRegistrationResponse
+ {
+ public string Id { get; set; }
+ public string Url { get; set; }
+ public string Name { get; set; }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
index 86bd6b731..e66899efa 100644
--- a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
+++ b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using Imazen.WebP;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Drawing;
@@ -118,26 +119,27 @@ namespace MediaBrowser.Server.Implementations.Drawing
public async Task ProcessImage(ImageProcessingOptions options, Stream toStream)
{
- if (options == null)
+ var file = await ProcessImage(options).ConfigureAwait(false);
+
+ using (var fileStream = _fileSystem.GetFileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, true))
{
- throw new ArgumentNullException("options");
+ await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
}
+ }
- if (toStream == null)
+ public async Task<string> ProcessImage(ImageProcessingOptions options)
+ {
+ if (options == null)
{
- throw new ArgumentNullException("toStream");
+ throw new ArgumentNullException("options");
}
var originalImagePath = options.Image.Path;
- if (options.HasDefaultOptions() && options.Enhancers.Count == 0 && !options.CropWhiteSpace)
+ if (options.HasDefaultOptions(originalImagePath) && options.Enhancers.Count == 0 && !options.CropWhiteSpace)
{
// Just spit out the original file if all the options are default
- using (var fileStream = _fileSystem.GetFileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
- {
- await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
- return;
- }
+ return originalImagePath;
}
var dateModified = options.Image.DateModified;
@@ -163,33 +165,16 @@ namespace MediaBrowser.Server.Implementations.Drawing
// Determine the output size based on incoming parameters
var newSize = DrawingUtils.Resize(originalImageSize, options.Width, options.Height, options.MaxWidth, options.MaxHeight);
- if (options.HasDefaultOptionsWithoutSize() && newSize.Equals(originalImageSize) && options.Enhancers.Count == 0)
+ if (options.HasDefaultOptionsWithoutSize(originalImagePath) && newSize.Equals(originalImageSize) && options.Enhancers.Count == 0)
{
// Just spit out the original file if the new size equals the old
- using (var fileStream = _fileSystem.GetFileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
- {
- await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
- return;
- }
+ return originalImagePath;
}
var quality = options.Quality ?? 90;
var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, options.OutputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.BackgroundColor);
- try
- {
- using (var fileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
- {
- await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
- return;
- }
- }
- catch (IOException)
- {
- // Cache file doesn't exist or is currently being written to
- }
-
var semaphore = GetLock(cacheFilePath);
await semaphore.WaitAsync().ConfigureAwait(false);
@@ -197,17 +182,12 @@ namespace MediaBrowser.Server.Implementations.Drawing
// Check again in case of lock contention
try
{
- using (var fileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
+ if (File.Exists(cacheFilePath))
{
- await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
semaphore.Release();
- return;
+ return cacheFilePath;
}
}
- catch (IOException)
- {
- // Cache file doesn't exist or is currently being written to
- }
catch
{
semaphore.Release();
@@ -218,37 +198,6 @@ namespace MediaBrowser.Server.Implementations.Drawing
{
var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed.HasValue;
- //if (!hasPostProcessing)
- //{
- // using (var outputStream = await _mediaEncoder.EncodeImage(new ImageEncodingOptions
- // {
- // InputPath = originalImagePath,
- // MaxHeight = options.MaxHeight,
- // MaxWidth = options.MaxWidth,
- // Height = options.Height,
- // Width = options.Width,
- // Quality = options.Quality,
- // Format = options.OutputFormat == ImageOutputFormat.Original ? Path.GetExtension(originalImagePath).TrimStart('.') : options.OutputFormat.ToString().ToLower()
-
- // }, CancellationToken.None).ConfigureAwait(false))
- // {
- // using (var outputMemoryStream = new MemoryStream())
- // {
- // // Save to the memory stream
- // await outputStream.CopyToAsync(outputMemoryStream).ConfigureAwait(false);
-
- // var bytes = outputMemoryStream.ToArray();
-
- // await toStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
-
- // // kick off a task to cache the result
- // await CacheResizedImage(cacheFilePath, bytes).ConfigureAwait(false);
- // }
-
- // return;
- // }
- //}
-
using (var fileStream = _fileSystem.GetFileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
{
// Copy to memory stream to avoid Image locking file
@@ -262,7 +211,12 @@ namespace MediaBrowser.Server.Implementations.Drawing
var newHeight = Convert.ToInt32(newSize.Height);
// Graphics.FromImage will throw an exception if the PixelFormat is Indexed, so we need to handle that here
- using (var thumbnail = new Bitmap(newWidth, newHeight, PixelFormat.Format32bppPArgb))
+ // Also, Webp only supports Format32bppArgb and Format32bppRgb
+ var pixelFormat = options.OutputFormat == ImageOutputFormat.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)
@@ -289,18 +243,23 @@ namespace MediaBrowser.Server.Implementations.Drawing
var outputFormat = GetOutputFormat(originalImage, options.OutputFormat);
- using (var outputMemoryStream = new MemoryStream())
- {
- // Save to the memory stream
- thumbnail.Save(outputFormat, outputMemoryStream, quality);
-
- var bytes = outputMemoryStream.ToArray();
-
- await toStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
+ Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
- // kick off a task to cache the result
- await CacheResizedImage(cacheFilePath, bytes).ConfigureAwait(false);
+ // Save to the cache location
+ using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, false))
+ {
+ if (options.OutputFormat == ImageOutputFormat.Webp)
+ {
+ new SimpleEncoder().Encode(thumbnail, cacheFileStream, quality, false);
+ }
+ else
+ {
+ // Save to the memory stream
+ thumbnail.Save(outputFormat, cacheFileStream, quality);
+ }
}
+
+ return cacheFilePath;
}
}
@@ -315,33 +274,6 @@ namespace MediaBrowser.Server.Implementations.Drawing
}
/// <summary>
- /// Caches the resized image.
- /// </summary>
- /// <param name="cacheFilePath">The cache file path.</param>
- /// <param name="bytes">The bytes.</param>
- /// <returns>Task.</returns>
- private async Task CacheResizedImage(string cacheFilePath, byte[] bytes)
- {
- try
- {
- var parentPath = Path.GetDirectoryName(cacheFilePath);
-
- Directory.CreateDirectory(parentPath);
-
- // Save to the cache location
- using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
- {
- // Save to the filestream
- await cacheFileStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
- }
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error writing to image cache file {0}", ex, cacheFilePath);
- }
- }
-
- /// <summary>
/// Sets the color of the background.
/// </summary>
/// <param name="graphics">The graphics.</param>
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index 061898176..922287f6e 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -1,5 +1,4 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
@@ -11,7 +10,9 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Playlists;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Controller.Sync;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@@ -38,8 +39,9 @@ namespace MediaBrowser.Server.Implementations.Dto
private readonly IProviderManager _providerManager;
private readonly Func<IChannelManager> _channelManagerFactory;
+ private readonly ISyncManager _syncManager;
- public DtoService(ILogger logger, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager, Func<IChannelManager> channelManagerFactory)
+ public DtoService(ILogger logger, ILibraryManager libraryManager, IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager, Func<IChannelManager> channelManagerFactory, ISyncManager syncManager)
{
_logger = logger;
_libraryManager = libraryManager;
@@ -50,6 +52,7 @@ namespace MediaBrowser.Server.Implementations.Dto
_fileSystem = fileSystem;
_providerManager = providerManager;
_channelManagerFactory = channelManagerFactory;
+ _syncManager = syncManager;
}
/// <summary>
@@ -63,6 +66,39 @@ namespace MediaBrowser.Server.Implementations.Dto
/// <exception cref="System.ArgumentNullException">item</exception>
public BaseItemDto GetBaseItemDto(BaseItem item, List<ItemFields> fields, User user = null, BaseItem owner = null)
{
+ var dto = GetBaseItemDtoInternal(item, fields, user, owner);
+
+ var byName = item as IItemByName;
+
+ if (byName != null && !(item is LiveTvChannel))
+ {
+ IEnumerable<BaseItem> libraryItems;
+
+ var artist = item as MusicArtist;
+
+ if (artist == null || artist.IsAccessedByName)
+ {
+ libraryItems = user != null ?
+ user.RootFolder.GetRecursiveChildren(user) :
+ _libraryManager.RootFolder.RecursiveChildren;
+ }
+ else
+ {
+ libraryItems = user != null ?
+ artist.GetRecursiveChildren(user) :
+ artist.RecursiveChildren;
+ }
+
+ SetItemByNameInfo(item, dto, byName.GetTaggedItems(libraryItems).ToList(), user);
+
+ return dto;
+ }
+
+ return dto;
+ }
+
+ private BaseItemDto GetBaseItemDtoInternal(BaseItem item, List<ItemFields> fields, User user = null, BaseItem owner = null)
+ {
if (item == null)
{
throw new ArgumentNullException("item");
@@ -75,6 +111,8 @@ namespace MediaBrowser.Server.Implementations.Dto
var dto = new BaseItemDto();
+ dto.SupportsPlaylists = item.SupportsAddingToPlaylist;
+
if (fields.Contains(ItemFields.People))
{
AttachPeople(dto, item);
@@ -126,6 +164,11 @@ namespace MediaBrowser.Server.Implementations.Dto
AttachBasicFields(dto, item, owner, fields);
+ if (fields.Contains(ItemFields.SyncInfo))
+ {
+ dto.SupportsSync = _syncManager.SupportsSync(item);
+ }
+
if (fields.Contains(ItemFields.SoundtrackIds))
{
var hasSoundtracks = item as IHasSoundtracks;
@@ -138,23 +181,26 @@ namespace MediaBrowser.Server.Implementations.Dto
}
}
+ if (item is Playlist)
+ {
+ AttachLinkedChildImages(dto, (Folder)item, user);
+ }
+
return dto;
}
- public BaseItemDto GetItemByNameDto<T>(T item, List<ItemFields> fields, User user = null)
+ public BaseItemDto GetItemByNameDto<T>(T item, List<ItemFields> fields, List<BaseItem> taggedItems, User user = null)
where T : BaseItem, IItemByName
{
- var libraryItems = user != null ? user.RootFolder.GetRecursiveChildren(user) :
- _libraryManager.RootFolder.RecursiveChildren;
+ var dto = GetBaseItemDtoInternal(item, fields, user);
+
+ SetItemByNameInfo(item, dto, taggedItems, user);
- return GetItemByNameDto(item, fields, item.GetTaggedItems(libraryItems).ToList(), user);
+ return dto;
}
- public BaseItemDto GetItemByNameDto<T>(T item, List<ItemFields> fields, List<BaseItem> taggedItems, User user = null)
- where T : BaseItem, IItemByName
+ private void SetItemByNameInfo(BaseItem item, BaseItemDto dto, List<BaseItem> taggedItems, User user = null)
{
- var dto = GetBaseItemDto(item, fields, user);
-
if (item is MusicArtist || item is MusicGenre)
{
dto.AlbumCount = taggedItems.Count(i => i is MusicAlbum);
@@ -181,8 +227,6 @@ namespace MediaBrowser.Server.Implementations.Dto
}
dto.ChildCount = taggedItems.Count;
-
- return dto;
}
/// <summary>
@@ -196,23 +240,29 @@ namespace MediaBrowser.Server.Implementations.Dto
{
if (item.IsFolder)
{
+ var userData = _userDataRepository.GetUserData(user.Id, item.GetUserDataKey());
+
+ // Skip the user data manager because we've already looped through the recursive tree and don't want to do it twice
+ // TODO: Improve in future
+ dto.UserData = GetUserItemDataDto(userData);
+
var folder = (Folder)item;
dto.ChildCount = GetChildCount(folder, user);
- if (!(folder is UserRootFolder))
+ // These are just far too slow.
+ // TODO: Disable for CollectionFolder
+ if (!(folder is UserRootFolder) && !(folder is UserView))
{
SetSpecialCounts(folder, user, dto, fields);
}
- }
-
- var userData = _userDataRepository.GetUserData(user.Id, item.GetUserDataKey());
- dto.UserData = GetUserItemDataDto(userData);
+ dto.UserData.Played = dto.UserData.PlayedPercentage.HasValue && dto.UserData.PlayedPercentage.Value >= 100;
+ }
- if (item.IsFolder)
+ else
{
- dto.UserData.Played = dto.PlayedPercentage.HasValue && dto.PlayedPercentage.Value >= 100;
+ dto.UserData = _userDataRepository.GetUserDataDto(item, user);
}
dto.PlayAccess = item.GetPlayAccess(user);
@@ -306,13 +356,40 @@ namespace MediaBrowser.Server.Implementations.Dto
{
dto.SeriesName = item.SeriesName;
}
+ private void SetPhotoProperties(BaseItemDto dto, Photo item)
+ {
+ dto.Width = item.Width;
+ dto.Height = item.Height;
+ dto.CameraMake = item.CameraMake;
+ dto.CameraModel = item.CameraModel;
+ dto.Software = item.Software;
+ dto.ExposureTime = item.ExposureTime;
+ dto.FocalLength = item.FocalLength;
+ dto.ImageOrientation = item.Orientation;
+ dto.Aperture = item.Aperture;
+ dto.ShutterSpeed = item.ShutterSpeed;
+
+ dto.Latitude = item.Latitude;
+ dto.Longitude = item.Longitude;
+ dto.Altitude = item.Altitude;
+ dto.IsoSpeedRating = item.IsoSpeedRating;
+
+ var album = item.Album;
+
+ if (album != null)
+ {
+ dto.Album = item.Name;
+ dto.AlbumId = item.Id.ToString("N");
+ }
+ }
private void SetMusicVideoProperties(BaseItemDto dto, MusicVideo item)
{
if (!string.IsNullOrEmpty(item.Album))
{
var parentAlbum = _libraryManager.RootFolder
- .GetRecursiveChildren(i => i is MusicAlbum)
+ .GetRecursiveChildren()
+ .Where(i => i is MusicAlbum)
.FirstOrDefault(i => string.Equals(i.Name, item.Album, StringComparison.OrdinalIgnoreCase));
if (parentAlbum != null)
@@ -407,7 +484,37 @@ namespace MediaBrowser.Server.Implementations.Dto
// Ordering by person type to ensure actors and artists are at the front.
// This is taking advantage of the fact that they both begin with A
// This should be improved in the future
- var people = item.People.OrderBy(i => i.SortOrder ?? int.MaxValue).ThenBy(i => i.Type).ToList();
+ var people = item.People.OrderBy(i => i.SortOrder ?? int.MaxValue)
+ .ThenBy(i =>
+ {
+ if (i.IsType(PersonType.Actor))
+ {
+ return 0;
+ }
+ if (i.IsType(PersonType.GuestStar))
+ {
+ return 1;
+ }
+ if (i.IsType(PersonType.Director))
+ {
+ return 2;
+ }
+ if (i.IsType(PersonType.Writer))
+ {
+ return 3;
+ }
+ if (i.IsType(PersonType.Producer))
+ {
+ return 4;
+ }
+ if (i.IsType(PersonType.Composer))
+ {
+ return 4;
+ }
+
+ return 10;
+ })
+ .ToList();
// Attach People by transforming them into BaseItemPerson (DTO)
dto.People = new BaseItemPerson[people.Count];
@@ -419,7 +526,7 @@ namespace MediaBrowser.Server.Implementations.Dto
{
return _libraryManager.GetPerson(c);
}
- catch (IOException ex)
+ catch (Exception ex)
{
_logger.ErrorException("Error getting person {0}", ex, c);
return null;
@@ -492,6 +599,7 @@ namespace MediaBrowser.Server.Implementations.Dto
if (dictionary.TryGetValue(studio, out entity))
{
+ studioDto.Id = entity.Id.ToString("N");
studioDto.PrimaryImageTag = GetImageCacheTag(entity, ImageType.Primary);
}
@@ -744,7 +852,7 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.DisplayOrder = hasDisplayOrder.DisplayOrder;
}
- var collectionFolder = item as CollectionFolder;
+ var collectionFolder = item as ICollectionFolder;
if (collectionFolder != null)
{
dto.CollectionType = collectionFolder.CollectionType;
@@ -768,17 +876,7 @@ namespace MediaBrowser.Server.Implementations.Dto
if (fields.Contains(ItemFields.Overview))
{
- // TODO: Remove this after a while, since it's been moved to the providers
- if (item is MusicArtist)
- {
- var strippedOverview = string.IsNullOrEmpty(item.Overview) ? item.Overview : item.Overview.StripHtml();
-
- dto.Overview = strippedOverview;
- }
- else
- {
- dto.Overview = item.Overview;
- }
+ dto.Overview = item.Overview;
}
if (fields.Contains(ItemFields.ShortOverview))
@@ -1061,16 +1159,17 @@ namespace MediaBrowser.Server.Implementations.Dto
if (episode != null)
{
- series = item.FindParent<Series>();
-
- dto.SeriesId = GetDtoId(series);
- dto.SeriesName = series.Name;
- dto.AirTime = series.AirTime;
- dto.SeriesStudio = series.Studios.FirstOrDefault();
-
- dto.SeriesThumbImageTag = GetImageCacheTag(series, ImageType.Thumb);
+ series = episode.Series;
- dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary);
+ if (series != null)
+ {
+ dto.SeriesId = GetDtoId(series);
+ dto.SeriesName = series.Name;
+ dto.AirTime = series.AirTime;
+ dto.SeriesStudio = series.Studios.FirstOrDefault();
+ dto.SeriesThumbImageTag = GetImageCacheTag(series, ImageType.Thumb);
+ dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary);
+ }
}
// Add SeasonInfo
@@ -1078,14 +1177,17 @@ namespace MediaBrowser.Server.Implementations.Dto
if (season != null)
{
- series = item.FindParent<Series>();
+ series = season.Series;
- dto.SeriesId = GetDtoId(series);
- dto.SeriesName = series.Name;
- dto.AirTime = series.AirTime;
- dto.SeriesStudio = series.Studios.FirstOrDefault();
+ if (series != null)
+ {
+ dto.SeriesId = GetDtoId(series);
+ dto.SeriesName = series.Name;
+ dto.AirTime = series.AirTime;
+ dto.SeriesStudio = series.Studios.FirstOrDefault();
- dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary);
+ dto.SeriesPrimaryImageTag = GetImageCacheTag(series, ImageType.Primary);
+ }
}
var game = item as Game;
@@ -1110,21 +1212,24 @@ namespace MediaBrowser.Server.Implementations.Dto
}
var book = item as Book;
-
if (book != null)
{
SetBookProperties(dto, book);
}
- var tvChannel = item as LiveTvChannel;
+ var photo = item as Photo;
+ if (photo != null)
+ {
+ SetPhotoProperties(dto, photo);
+ }
+ var tvChannel = item as LiveTvChannel;
if (tvChannel != null)
{
dto.MediaSources = tvChannel.GetMediaSources(true).ToList();
}
var channelItem = item as IChannelItem;
-
if (channelItem != null)
{
dto.ChannelId = channelItem.ChannelId;
@@ -1132,6 +1237,45 @@ namespace MediaBrowser.Server.Implementations.Dto
}
}
+ private void AttachLinkedChildImages(BaseItemDto dto, Folder folder, User user)
+ {
+ List<BaseItem> linkedChildren = null;
+
+ if (dto.BackdropImageTags.Count == 0)
+ {
+ if (linkedChildren == null)
+ {
+ linkedChildren = user == null
+ ? folder.GetRecursiveChildren().ToList()
+ : folder.GetRecursiveChildren(user, true).ToList();
+ }
+ var parentWithBackdrop = linkedChildren.FirstOrDefault(i => i.GetImages(ImageType.Backdrop).Any());
+
+ if (parentWithBackdrop != null)
+ {
+ dto.ParentBackdropItemId = GetDtoId(parentWithBackdrop);
+ dto.ParentBackdropImageTags = GetBackdropImageTags(parentWithBackdrop);
+ }
+ }
+
+ if (!dto.ImageTags.ContainsKey(ImageType.Primary))
+ {
+ if (linkedChildren == null)
+ {
+ linkedChildren = user == null
+ ? folder.GetRecursiveChildren().ToList()
+ : folder.GetRecursiveChildren(user, true).ToList();
+ }
+ var parentWithImage = linkedChildren.FirstOrDefault(i => i.GetImages(ImageType.Primary).Any());
+
+ if (parentWithImage != null)
+ {
+ dto.ParentPrimaryImageItemId = GetDtoId(parentWithImage);
+ dto.ParentPrimaryImageTag = GetImageCacheTag(parentWithImage, ImageType.Primary);
+ }
+ }
+ }
+
private string GetMappedPath(IHasMetadata item)
{
var path = item.Path;
@@ -1201,7 +1345,8 @@ namespace MediaBrowser.Server.Implementations.Dto
}
else
{
- children = folder.GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual);
+ children = folder.GetRecursiveChildren(user)
+ .Where(i => !i.IsFolder && i.LocationType != LocationType.Virtual);
}
// Loop through each recursive child
@@ -1248,11 +1393,12 @@ namespace MediaBrowser.Server.Implementations.Dto
}
dto.RecursiveItemCount = recursiveItemCount;
+ dto.UserData.UnplayedItemCount = unplayed;
dto.RecursiveUnplayedItemCount = unplayed;
if (recursiveItemCount > 0)
{
- dto.PlayedPercentage = totalPercentPlayed / recursiveItemCount;
+ dto.UserData.PlayedPercentage = totalPercentPlayed / recursiveItemCount;
}
if (runtime > 0 && fields.Contains(ItemFields.CumulativeRunTimeTicks))
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs
new file mode 100644
index 000000000..fb1010f1b
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs
@@ -0,0 +1,569 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Implementations.Logging;
+using MediaBrowser.Common.Plugins;
+using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Common.Updates;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Activity;
+using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.Localization;
+using MediaBrowser.Controller.Plugins;
+using MediaBrowser.Controller.Session;
+using MediaBrowser.Controller.Subtitles;
+using MediaBrowser.Model.Activity;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Tasks;
+using MediaBrowser.Model.Updates;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.EntryPoints
+{
+ public class ActivityLogEntryPoint : IServerEntryPoint
+ {
+ private readonly IInstallationManager _installationManager;
+
+ //private readonly ILogManager _logManager;
+ private readonly ILogger _logger;
+ private readonly ISessionManager _sessionManager;
+ private readonly ITaskManager _taskManager;
+ private readonly IActivityManager _activityManager;
+ private readonly ILocalizationManager _localization;
+
+ private readonly ILibraryManager _libraryManager;
+ private readonly ISubtitleManager _subManager;
+ private readonly IUserManager _userManager;
+ private readonly IServerConfigurationManager _config;
+ private readonly IServerApplicationHost _appHost;
+
+ public ActivityLogEntryPoint(ISessionManager sessionManager, ITaskManager taskManager, IActivityManager activityManager, ILocalizationManager localization, IInstallationManager installationManager, ILibraryManager libraryManager, ISubtitleManager subManager, IUserManager userManager, IServerConfigurationManager config, IServerApplicationHost appHost)
+ {
+ //_logger = _logManager.GetLogger("ActivityLogEntryPoint");
+ _sessionManager = sessionManager;
+ _taskManager = taskManager;
+ _activityManager = activityManager;
+ _localization = localization;
+ _installationManager = installationManager;
+ _libraryManager = libraryManager;
+ _subManager = subManager;
+ _userManager = userManager;
+ _config = config;
+ //_logManager = logManager;
+ _appHost = appHost;
+ }
+
+ public void Run()
+ {
+ //_taskManager.TaskExecuting += _taskManager_TaskExecuting;
+ //_taskManager.TaskCompleted += _taskManager_TaskCompleted;
+
+ //_installationManager.PluginInstalled += _installationManager_PluginInstalled;
+ //_installationManager.PluginUninstalled += _installationManager_PluginUninstalled;
+ //_installationManager.PluginUpdated += _installationManager_PluginUpdated;
+
+ //_libraryManager.ItemAdded += _libraryManager_ItemAdded;
+ //_libraryManager.ItemRemoved += _libraryManager_ItemRemoved;
+
+ _sessionManager.SessionStarted += _sessionManager_SessionStarted;
+ _sessionManager.AuthenticationFailed += _sessionManager_AuthenticationFailed;
+ _sessionManager.AuthenticationSucceeded += _sessionManager_AuthenticationSucceeded;
+ _sessionManager.SessionEnded += _sessionManager_SessionEnded;
+
+ _sessionManager.PlaybackStart += _sessionManager_PlaybackStart;
+ _sessionManager.PlaybackStopped += _sessionManager_PlaybackStopped;
+
+ //_subManager.SubtitlesDownloaded += _subManager_SubtitlesDownloaded;
+ _subManager.SubtitleDownloadFailure += _subManager_SubtitleDownloadFailure;
+
+ _userManager.UserCreated += _userManager_UserCreated;
+ _userManager.UserPasswordChanged += _userManager_UserPasswordChanged;
+ _userManager.UserDeleted += _userManager_UserDeleted;
+ _userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated;
+
+ //_config.ConfigurationUpdated += _config_ConfigurationUpdated;
+ //_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
+
+ //_logManager.LoggerLoaded += _logManager_LoggerLoaded;
+
+ _appHost.ApplicationUpdated += _appHost_ApplicationUpdated;
+ }
+
+ void _subManager_SubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("SubtitleDownloadFailureForItem"), Notifications.Notifications.GetItemName(e.Item)),
+ Type = "SubtitleDownloadFailure",
+ ItemId = e.Item.Id.ToString("N"),
+ ShortOverview = string.Format(_localization.GetLocalizedString("ProviderValue"), e.Provider),
+ Overview = LogHelper.GetLogMessage(e.Exception).ToString()
+ });
+ }
+
+ void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e)
+ {
+ var item = e.MediaInfo;
+
+ if (item == null)
+ {
+ //_logger.Warn("PlaybackStopped reported with null media info.");
+ return;
+ }
+
+ var themeMedia = item as IThemeMedia;
+ if (themeMedia != null && themeMedia.IsThemeMedia)
+ {
+ // Don't report theme song or local trailer playback
+ return;
+ }
+
+ if (e.Users.Count == 0)
+ {
+ return;
+ }
+
+ var username = e.Users.First().Name;
+
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"), username, item.Name),
+ Type = "PlaybackStopped",
+ ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), e.ClientName, e.DeviceName)
+ });
+ }
+
+ void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e)
+ {
+ var item = e.MediaInfo;
+
+ if (item == null)
+ {
+ //_logger.Warn("PlaybackStart reported with null media info.");
+ return;
+ }
+
+ var themeMedia = item as IThemeMedia;
+ if (themeMedia != null && themeMedia.IsThemeMedia)
+ {
+ // Don't report theme song or local trailer playback
+ return;
+ }
+
+ if (e.Users.Count == 0)
+ {
+ return;
+ }
+
+ var username = e.Users.First().Name;
+
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("UserStartedPlayingItemWithValues"), username, item.Name),
+ Type = "PlaybackStart",
+ ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), e.ClientName, e.DeviceName)
+ });
+ }
+
+ void _sessionManager_SessionEnded(object sender, SessionEventArgs e)
+ {
+ string name;
+ var session = e.SessionInfo;
+
+ if (string.IsNullOrWhiteSpace(session.UserName))
+ {
+ name = string.Format(_localization.GetLocalizedString("DeviceOfflineWithName"), session.DeviceName);
+
+ // Causing too much spam for now
+ return;
+ }
+ else
+ {
+ name = string.Format(_localization.GetLocalizedString("UserOfflineFromDevice"), session.UserName, session.DeviceName);
+ }
+
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = name,
+ Type = "SessionEnded",
+ ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), session.RemoteEndPoint)
+ });
+ }
+
+ void _sessionManager_AuthenticationSucceeded(object sender, GenericEventArgs<AuthenticationRequest> e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("AuthenticationSucceededWithUserName"), e.Argument.Username),
+ Type = "AuthenticationSucceeded",
+ ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), e.Argument.RemoteEndPoint)
+ });
+ }
+
+ void _sessionManager_AuthenticationFailed(object sender, GenericEventArgs<AuthenticationRequest> e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("FailedLoginAttemptWithUserName"), e.Argument.Username),
+ Type = "AuthenticationFailed",
+ ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), e.Argument.RemoteEndPoint),
+ Severity = LogSeverity.Error
+ });
+ }
+
+ void _appHost_ApplicationUpdated(object sender, GenericEventArgs<PackageVersionInfo> e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = _localization.GetLocalizedString("MessageApplicationUpdated"),
+ Type = "ApplicationUpdated",
+ ShortOverview = string.Format(_localization.GetLocalizedString("VersionNumber"), e.Argument.versionStr),
+ Overview = e.Argument.description
+ });
+ }
+
+ void _logManager_LoggerLoaded(object sender, EventArgs e)
+ {
+ }
+
+ void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("MessageNamedServerConfigurationUpdatedWithValue"), e.Key),
+ Type = "NamedConfigurationUpdated"
+ });
+ }
+
+ void _config_ConfigurationUpdated(object sender, EventArgs e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = _localization.GetLocalizedString("MessageServerConfigurationUpdated"),
+ Type = "ServerConfigurationUpdated"
+ });
+ }
+
+ void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs<User> e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("UserConfigurationUpdatedWithName"), e.Argument.Name),
+ Type = "UserConfigurationUpdated"
+ });
+ }
+
+ void _userManager_UserDeleted(object sender, GenericEventArgs<User> e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("UserDeletedWithName"), e.Argument.Name),
+ Type = "UserDeleted"
+ });
+ }
+
+ void _userManager_UserPasswordChanged(object sender, GenericEventArgs<User> e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("UserPasswordChangedWithName"), e.Argument.Name),
+ Type = "UserPasswordChanged"
+ });
+ }
+
+ void _userManager_UserCreated(object sender, GenericEventArgs<User> e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("UserCreatedWithName"), e.Argument.Name),
+ Type = "UserCreated"
+ });
+ }
+
+ void _subManager_SubtitlesDownloaded(object sender, SubtitleDownloadEventArgs e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("SubtitlesDownloadedForItem"), Notifications.Notifications.GetItemName(e.Item)),
+ Type = "SubtitlesDownloaded",
+ ItemId = e.Item.Id.ToString("N"),
+ ShortOverview = string.Format(_localization.GetLocalizedString("ProviderValue"), e.Provider)
+ });
+ }
+
+ void _sessionManager_SessionStarted(object sender, SessionEventArgs e)
+ {
+ string name;
+ var session = e.SessionInfo;
+
+ if (string.IsNullOrWhiteSpace(session.UserName))
+ {
+ name = string.Format(_localization.GetLocalizedString("DeviceOnlineWithName"), session.DeviceName);
+
+ // Causing too much spam for now
+ return;
+ }
+ else
+ {
+ name = string.Format(_localization.GetLocalizedString("UserOnlineFromDevice"), session.UserName, session.DeviceName);
+ }
+
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = name,
+ Type = "SessionStarted",
+ ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), session.RemoteEndPoint)
+ });
+ }
+
+ void _libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
+ {
+ if (e.Item is LiveTvProgram || e.Item is IChannelItem)
+ {
+ return;
+ }
+
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("ItemRemovedWithName"), Notifications.Notifications.GetItemName(e.Item)),
+ Type = "ItemRemoved"
+ });
+ }
+
+ void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
+ {
+ if (e.Item is LiveTvProgram || e.Item is IChannelItem)
+ {
+ return;
+ }
+
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("ItemAddedWithName"), Notifications.Notifications.GetItemName(e.Item)),
+ Type = "ItemAdded",
+ ItemId = e.Item.Id.ToString("N")
+ });
+ }
+
+ void _installationManager_PluginUpdated(object sender, GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("PluginUpdatedWithName"), e.Argument.Item1.Name),
+ Type = "PluginUpdated",
+ ShortOverview = string.Format(_localization.GetLocalizedString("VersionNumber"), e.Argument.Item2.versionStr),
+ Overview = e.Argument.Item2.description
+ });
+ }
+
+ void _installationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("PluginUninstalledWithName"), e.Argument.Name),
+ Type = "PluginUninstalled"
+ });
+ }
+
+ void _installationManager_PluginInstalled(object sender, GenericEventArgs<PackageVersionInfo> e)
+ {
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("PluginInstalledWithName"), e.Argument.name),
+ Type = "PluginInstalled",
+ ShortOverview = string.Format(_localization.GetLocalizedString("VersionNumber"), e.Argument.versionStr)
+ });
+ }
+
+ void _taskManager_TaskExecuting(object sender, GenericEventArgs<IScheduledTaskWorker> e)
+ {
+ var task = e.Argument;
+
+ var activityTask = task.ScheduledTask as IScheduledTaskActivityLog;
+ if (activityTask != null && !activityTask.IsActivityLogged)
+ {
+ return;
+ }
+
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("ScheduledTaskStartedWithName"), task.Name),
+ Type = "ScheduledTaskStarted"
+ });
+ }
+
+ void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e)
+ {
+ var result = e.Result;
+ var task = e.Task;
+
+ var activityTask = task.ScheduledTask as IScheduledTaskActivityLog;
+ if (activityTask != null && !activityTask.IsActivityLogged)
+ {
+ return;
+ }
+
+ var time = result.EndTimeUtc - result.StartTimeUtc;
+ var runningTime = string.Format(_localization.GetLocalizedString("LabelRunningTimeValue"), ToUserFriendlyString(time));
+
+ if (result.Status == TaskCompletionStatus.Cancelled)
+ {
+ return;
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("ScheduledTaskCancelledWithName"), task.Name),
+ Type = "ScheduledTaskCancelled",
+ ShortOverview = runningTime
+ });
+ }
+ else if (result.Status == TaskCompletionStatus.Completed)
+ {
+ return;
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("ScheduledTaskCompletedWithName"), task.Name),
+ Type = "ScheduledTaskCompleted",
+ ShortOverview = runningTime
+ });
+ }
+ else if (result.Status == TaskCompletionStatus.Failed)
+ {
+ var vals = new List<string>();
+
+ if (!string.IsNullOrWhiteSpace(e.Result.ErrorMessage))
+ {
+ vals.Add(e.Result.ErrorMessage);
+ }
+ if (!string.IsNullOrWhiteSpace(e.Result.LongErrorMessage))
+ {
+ vals.Add(e.Result.LongErrorMessage);
+ }
+
+ CreateLogEntry(new ActivityLogEntry
+ {
+ Name = string.Format(_localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name),
+ Type = "ScheduledTaskFailed",
+ Overview = string.Join(Environment.NewLine, vals.ToArray()),
+ ShortOverview = runningTime,
+ Severity = LogSeverity.Error
+ });
+ }
+ }
+
+ private async void CreateLogEntry(ActivityLogEntry entry)
+ {
+ try
+ {
+ await _activityManager.Create(entry).ConfigureAwait(false);
+ }
+ catch
+ {
+ // Logged at lower levels
+ }
+ }
+
+ public void Dispose()
+ {
+ _taskManager.TaskExecuting -= _taskManager_TaskExecuting;
+ _taskManager.TaskCompleted -= _taskManager_TaskCompleted;
+
+ _installationManager.PluginInstalled -= _installationManager_PluginInstalled;
+ _installationManager.PluginUninstalled -= _installationManager_PluginUninstalled;
+ _installationManager.PluginUpdated -= _installationManager_PluginUpdated;
+
+ _libraryManager.ItemAdded -= _libraryManager_ItemAdded;
+ _libraryManager.ItemRemoved -= _libraryManager_ItemRemoved;
+
+ _sessionManager.SessionStarted -= _sessionManager_SessionStarted;
+ _sessionManager.AuthenticationFailed -= _sessionManager_AuthenticationFailed;
+ _sessionManager.AuthenticationSucceeded -= _sessionManager_AuthenticationSucceeded;
+ _sessionManager.SessionEnded -= _sessionManager_SessionEnded;
+
+ _sessionManager.PlaybackStart -= _sessionManager_PlaybackStart;
+ _sessionManager.PlaybackStopped -= _sessionManager_PlaybackStopped;
+
+ _subManager.SubtitlesDownloaded -= _subManager_SubtitlesDownloaded;
+ _subManager.SubtitleDownloadFailure -= _subManager_SubtitleDownloadFailure;
+
+ _userManager.UserCreated -= _userManager_UserCreated;
+ _userManager.UserPasswordChanged -= _userManager_UserPasswordChanged;
+ _userManager.UserDeleted -= _userManager_UserDeleted;
+ _userManager.UserConfigurationUpdated -= _userManager_UserConfigurationUpdated;
+
+ _config.ConfigurationUpdated -= _config_ConfigurationUpdated;
+ _config.NamedConfigurationUpdated -= _config_NamedConfigurationUpdated;
+
+ //_logManager.LoggerLoaded -= _logManager_LoggerLoaded;
+
+ _appHost.ApplicationUpdated -= _appHost_ApplicationUpdated;
+ }
+
+ /// <summary>
+ /// Constructs a user-friendly string for this TimeSpan instance.
+ /// </summary>
+ public static string ToUserFriendlyString(TimeSpan span)
+ {
+ const int DaysInYear = 365;
+ const int DaysInMonth = 30;
+
+ // Get each non-zero value from TimeSpan component
+ List<string> values = new List<string>();
+
+ // Number of years
+ int days = span.Days;
+ if (days >= DaysInYear)
+ {
+ int years = (days / DaysInYear);
+ values.Add(CreateValueString(years, "year"));
+ days = (days % DaysInYear);
+ }
+ // Number of months
+ if (days >= DaysInMonth)
+ {
+ int months = (days / DaysInMonth);
+ values.Add(CreateValueString(months, "month"));
+ days = (days % DaysInMonth);
+ }
+ // Number of days
+ if (days >= 1)
+ values.Add(CreateValueString(days, "day"));
+ // Number of hours
+ if (span.Hours >= 1)
+ values.Add(CreateValueString(span.Hours, "hour"));
+ // Number of minutes
+ if (span.Minutes >= 1)
+ values.Add(CreateValueString(span.Minutes, "minute"));
+ // Number of seconds (include when 0 if no other components included)
+ if (span.Seconds >= 1 || values.Count == 0)
+ values.Add(CreateValueString(span.Seconds, "second"));
+
+ // Combine values into string
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < values.Count; i++)
+ {
+ if (builder.Length > 0)
+ builder.Append((i == (values.Count - 1)) ? " and " : ", ");
+ builder.Append(values[i]);
+ }
+ // Return result
+ return builder.ToString();
+ }
+
+ /// <summary>
+ /// Constructs a string description of a time-span value.
+ /// </summary>
+ /// <param name="value">The value of this item</param>
+ /// <param name="description">The name of this item (singular form)</param>
+ private static string CreateValueString(int value, string description)
+ {
+ return String.Format("{0:#,##0} {1}",
+ value, (value == 1) ? description : String.Format("{0}s", description));
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
index 04ddb4c4b..2d050d4a7 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
@@ -4,8 +4,10 @@ using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging;
using Mono.Nat;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Text;
+using System.Threading;
namespace MediaBrowser.Server.Implementations.EntryPoints
{
@@ -17,6 +19,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private bool _isStarted;
+ private Timer _timer;
+
public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config)
{
_logger = logmanager.GetLogger("PortMapper");
@@ -43,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
public void Run()
{
//NatUtility.Logger = new LogWriter(_logger);
-
+
Reload();
}
@@ -52,13 +56,22 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
if (_config.Configuration.EnableUPnP)
{
_logger.Debug("Starting NAT discovery");
-
+
NatUtility.DeviceFound += NatUtility_DeviceFound;
+
+ // Mono.Nat does never rise this event. The event is there however it is useless.
+ // You could remove it with no risk.
NatUtility.DeviceLost += NatUtility_DeviceLost;
+
+
+ // it is hard to say what one should do when an unhandled exception is raised
+ // because there isn't anything one can do about it. Probably save a log or ignored it.
NatUtility.UnhandledException += NatUtility_UnhandledException;
NatUtility.StartDiscovery();
_isStarted = true;
+
+ _timer = new Timer(s => _createdRules = new List<string>(), null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
}
}
@@ -88,19 +101,32 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
}
catch (Exception)
{
+ // 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
+ // CreatePortMap is invoked it can fails with a 718-ConflictInMappingEntry or not. That depends
+ // on the router's upnp implementation (specs says it should fail however some routers don't do it)
+ // 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);
}
}
+ private List<string> _createdRules = new List<string>();
private void CreateRules(INatDevice device)
{
- var info = _appHost.GetSystemInfo();
+ // 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
- CreatePortMap(device, info.HttpServerPortNumber);
+ var address = device.LocalAddress.ToString();
- if (info.WebSocketPortNumber != info.HttpServerPortNumber)
+ if (!_createdRules.Contains(address))
{
- CreatePortMap(device, info.WebSocketPortNumber);
+ _createdRules.Add(address);
+
+ var info = _appHost.GetSystemInfo();
+
+ CreatePortMap(device, info.HttpServerPortNumber);
}
}
@@ -114,6 +140,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
});
}
+ // As I said before, this method will be never invoked. You can remove it.
void NatUtility_DeviceLost(object sender, DeviceEventArgs e)
{
var device = e.Device;
@@ -129,13 +156,27 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{
_logger.Debug("Stopping NAT discovery");
+ if (_timer != null)
+ {
+ _timer.Dispose();
+ _timer = null;
+ }
+
try
{
+ // This is not a significant improvement
+ NatUtility.StopDiscovery();
NatUtility.DeviceFound -= NatUtility_DeviceFound;
NatUtility.DeviceLost -= NatUtility_DeviceLost;
NatUtility.UnhandledException -= NatUtility_UnhandledException;
- NatUtility.StopDiscovery();
}
+ // Statements in try-block will no fail because StopDiscovery is a one-line
+ // method that was no chances to fail.
+ // public static void StopDiscovery ()
+ // {
+ // searching.Reset();
+ // }
+ // IMO you could remove the catch-block
catch (Exception ex)
{
_logger.ErrorException("Error stopping NAT Discovery", ex);
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs
index b10b64c3e..2d824f36c 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs
@@ -1,15 +1,14 @@
-using MediaBrowser.Common.Plugins;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller;
-using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
@@ -37,7 +36,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
private readonly ITaskManager _taskManager;
private readonly INotificationManager _notificationManager;
- private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
private readonly ISessionManager _sessionManager;
private readonly IServerApplicationHost _appHost;
@@ -45,17 +43,19 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
private Timer LibraryUpdateTimer { get; set; }
private readonly object _libraryChangedSyncLock = new object();
- public Notifications(IInstallationManager installationManager, IUserManager userManager, ILogger logger, ITaskManager taskManager, INotificationManager notificationManager, IServerConfigurationManager config, ILibraryManager libraryManager, ISessionManager sessionManager, IServerApplicationHost appHost)
+ private readonly IConfigurationManager _config;
+
+ public Notifications(IInstallationManager installationManager, IUserManager userManager, ILogger logger, ITaskManager taskManager, INotificationManager notificationManager, ILibraryManager libraryManager, ISessionManager sessionManager, IServerApplicationHost appHost, IConfigurationManager config)
{
_installationManager = installationManager;
_userManager = userManager;
_logger = logger;
_taskManager = taskManager;
_notificationManager = notificationManager;
- _config = config;
_libraryManager = libraryManager;
_sessionManager = sessionManager;
_appHost = appHost;
+ _config = config;
}
public void Run()
@@ -164,20 +164,25 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
await SendNotification(notification).ConfigureAwait(false);
}
- void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e)
- {
- var item = e.MediaInfo;
+ private NotificationOptions GetOptions()
+ {
+ return _config.GetConfiguration<NotificationOptions>("notifications");
+ }
- if (item == null)
- {
- _logger.Warn("PlaybackStart reported with null media info.");
- return;
- }
+ void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e)
+ {
+ var item = e.MediaInfo;
- var type = GetPlaybackNotificationType(item.MediaType);
+ if (item == null)
+ {
+ _logger.Warn("PlaybackStart reported with null media info.");
+ return;
+ }
- SendPlaybackNotification(type, e);
- }
+ var type = GetPlaybackNotificationType(item.MediaType);
+
+ SendPlaybackNotification(type, e);
+ }
void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e)
{
@@ -198,20 +203,24 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
{
var user = e.Users.FirstOrDefault();
+ if (user != null && !GetOptions().IsEnabledToMonitorUser(type, user.Id.ToString("N")))
+ {
+ return;
+ }
+
var item = e.MediaInfo;
+ var themeMedia = item as IThemeMedia;
- if (e.Item != null && e.Item.Parent == null)
+ if (themeMedia != null && themeMedia.IsThemeMedia)
{
// Don't report theme song or local trailer playback
- // TODO: This will also cause movie specials to not be reported
return;
}
+
var notification = new NotificationRequest
{
- NotificationType = type,
-
- ExcludeUserIds = e.Users.Select(i => i.Id.ToString("N")).ToList()
+ NotificationType = type
};
notification.Variables["ItemName"] = item.Name;
@@ -317,7 +326,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
}
}
- private string GetItemName(BaseItem item)
+ public static string GetItemName(BaseItem item)
{
var name = item.Name;
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/WebSocketNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/WebSocketNotifier.cs
index 42aadf62e..5f1db03c6 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/WebSocketNotifier.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/WebSocketNotifier.cs
@@ -23,7 +23,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
public void Run()
{
_notificationsRepo.NotificationAdded += _notificationsRepo_NotificationAdded;
- _notificationsRepo.NotificationUpdated += _notificationsRepo_NotificationUpdated;
_notificationsRepo.NotificationsMarkedRead += _notificationsRepo_NotificationsMarkedRead;
}
@@ -40,13 +39,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
_serverManager.SendWebSocketMessage("NotificationsMarkedRead", msg);
}
- void _notificationsRepo_NotificationUpdated(object sender, NotificationUpdateEventArgs e)
- {
- var msg = e.Notification.UserId + "|" + e.Notification.Id;
-
- _serverManager.SendWebSocketMessage("NotificationUpdated", msg);
- }
-
void _notificationsRepo_NotificationAdded(object sender, NotificationUpdateEventArgs e)
{
var msg = e.Notification.UserId + "|" + e.Notification.Id;
@@ -57,7 +49,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
public void Dispose()
{
_notificationsRepo.NotificationAdded -= _notificationsRepo_NotificationAdded;
- _notificationsRepo.NotificationUpdated -= _notificationsRepo_NotificationUpdated;
}
}
}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs
index 305f2800f..1b29971da 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs
@@ -88,7 +88,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs<User> e)
{
- var dto = _dtoService.GetUserDto(e.Argument);
+ var dto = _userManager.GetUserDto(e.Argument);
_serverManager.SendWebSocketMessage("UserConfigurationUpdated", dto);
}
@@ -145,8 +145,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// <param name="e">The e.</param>
void userManager_UserUpdated(object sender, GenericEventArgs<User> e)
{
- var dto = _dtoService.GetUserDto(e.Argument);
-
+ var dto = _userManager.GetUserDto(e.Argument);
+
_serverManager.SendWebSocketMessage("UserUpdated", dto);
}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs
index 7e5d5d3d8..386c16513 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs
@@ -1,8 +1,8 @@
using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
using MediaBrowser.Server.Implementations.Udp;
using System.Net.Sockets;
@@ -27,30 +27,24 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// The _network manager
/// </summary>
private readonly INetworkManager _networkManager;
- /// <summary>
- /// The _server configuration manager
- /// </summary>
- private readonly IServerConfigurationManager _serverConfigurationManager;
- /// <summary>
- /// The _HTTP server
- /// </summary>
- private readonly IHttpServer _httpServer;
+ private readonly IServerApplicationHost _appHost;
+ private readonly IJsonSerializer _json;
public const int PortNumber = 7359;
/// <summary>
- /// Initializes a new instance of the <see cref="UdpServerEntryPoint"/> class.
+ /// Initializes a new instance of the <see cref="UdpServerEntryPoint" /> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="networkManager">The network manager.</param>
- /// <param name="serverConfigurationManager">The server configuration manager.</param>
- /// <param name="httpServer">The HTTP server.</param>
- public UdpServerEntryPoint(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager, IHttpServer httpServer)
+ /// <param name="appHost">The application host.</param>
+ /// <param name="json">The json.</param>
+ public UdpServerEntryPoint(ILogger logger, INetworkManager networkManager, IServerApplicationHost appHost, IJsonSerializer json)
{
_logger = logger;
_networkManager = networkManager;
- _serverConfigurationManager = serverConfigurationManager;
- _httpServer = httpServer;
+ _appHost = appHost;
+ _json = json;
}
/// <summary>
@@ -58,7 +52,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// </summary>
public void Run()
{
- var udpServer = new UdpServer(_logger, _networkManager, _serverConfigurationManager, _httpServer);
+ var udpServer = new UdpServer(_logger, _networkManager, _appHost, _json);
try
{
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs
index af3fde34b..de53201c9 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs
@@ -26,7 +26,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private Timer _timer;
private readonly TimeSpan _frequency = TimeSpan.FromHours(24);
- private const string DefaultDeviceVersion = "Unknown version";
private readonly ConcurrentDictionary<Guid, ClientInfo> _apps = new ConcurrentDictionary<Guid, ClientInfo>();
public UsageEntryPoint(ILogger logger, IApplicationHost applicationHost, INetworkManager networkManager, IHttpClient httpClient, ISessionManager sessionManager)
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
index d7186aa21..c31f46215 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
@@ -1,10 +1,11 @@
-using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Session;
+using MoreLinq;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -17,21 +18,21 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{
private readonly ISessionManager _sessionManager;
private readonly ILogger _logger;
- private readonly IDtoService _dtoService;
private readonly IUserDataManager _userDataManager;
+ private readonly IUserManager _userManager;
private readonly object _syncLock = new object();
private Timer UpdateTimer { get; set; }
private const int UpdateDuration = 500;
- private readonly Dictionary<Guid, List<string>> _changedKeys = new Dictionary<Guid, List<string>>();
+ private readonly Dictionary<Guid, List<IHasUserData>> _changedItems = new Dictionary<Guid, List<IHasUserData>>();
- public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, IDtoService dtoService, ILogger logger)
+ public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, ILogger logger, IUserManager userManager)
{
_userDataManager = userDataManager;
_sessionManager = sessionManager;
- _dtoService = dtoService;
_logger = logger;
+ _userManager = userManager;
}
public void Run()
@@ -58,15 +59,28 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
UpdateTimer.Change(UpdateDuration, Timeout.Infinite);
}
- List<string> keys;
+ List<IHasUserData> keys;
- if (!_changedKeys.TryGetValue(e.UserId, out keys))
+ if (!_changedItems.TryGetValue(e.UserId, out keys))
{
- keys = new List<string>();
- _changedKeys[e.UserId] = keys;
+ keys = new List<IHasUserData>();
+ _changedItems[e.UserId] = keys;
}
- keys.Add(e.Key);
+ keys.Add(e.Item);
+
+ var baseItem = e.Item as BaseItem;
+
+ // Go up one level for indicators
+ if (baseItem != null)
+ {
+ var parent = baseItem.Parent;
+
+ if (parent != null)
+ {
+ keys.Add(parent);
+ }
+ }
}
}
@@ -75,8 +89,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
lock (_syncLock)
{
// Remove dupes in case some were saved multiple times
- var changes = _changedKeys.ToList();
- _changedKeys.Clear();
+ var changes = _changedItems.ToList();
+ _changedItems.Clear();
SendNotifications(changes, CancellationToken.None);
@@ -88,7 +102,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
}
}
- private async Task SendNotifications(IEnumerable<KeyValuePair<Guid, List<string>>> changes, CancellationToken cancellationToken)
+ private async Task SendNotifications(IEnumerable<KeyValuePair<Guid, List<IHasUserData>>> changes, CancellationToken cancellationToken)
{
foreach (var pair in changes)
{
@@ -99,8 +113,11 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
if (userSessions.Count > 0)
{
+ var user = _userManager.GetUserById(userId);
+
var dtoList = pair.Value
- .Select(i => _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(userId, i)))
+ .DistinctBy(i => i.Id)
+ .Select(i => _userDataManager.GetUserDataDto(i, user))
.ToList();
var info = new UserDataChangeInfo
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
index d44811886..cf9571824 100644
--- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
+++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
@@ -126,7 +126,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId));
- await OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, _config.Configuration.TvFileOrganizationOptions, true, result, cancellationToken).ConfigureAwait(false);
+ await OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, options, true, result, cancellationToken).ConfigureAwait(false);
await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
@@ -248,12 +248,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
.ToList();
var folder = Path.GetDirectoryName(targetPath);
- var targetFileNameWithoutExtension = Path.GetFileNameWithoutExtension(targetPath);
-
+ var targetFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(targetPath);
+
try
{
var filesOfOtherExtensions = Directory.EnumerateFiles(folder, "*", SearchOption.TopDirectoryOnly)
- .Where(i => EntityResolutionHelper.IsVideoFile(i) && string.Equals(Path.GetFileNameWithoutExtension(i), targetFileNameWithoutExtension, StringComparison.OrdinalIgnoreCase));
+ .Where(i => EntityResolutionHelper.IsVideoFile(i) && string.Equals(_fileSystem.GetFileNameWithoutExtension(i), targetFileNameWithoutExtension, StringComparison.OrdinalIgnoreCase));
episodePaths.AddRange(filesOfOtherExtensions);
}
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs b/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs
new file mode 100644
index 000000000..e43ab3665
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/FileOrganization/Extensions.cs
@@ -0,0 +1,29 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.FileOrganization;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Server.Implementations.FileOrganization
+{
+ public static class ConfigurationExtension
+ {
+ public static AutoOrganizeOptions GetAutoOrganizeOptions(this IConfigurationManager manager)
+ {
+ return manager.GetConfiguration<AutoOrganizeOptions>("autoorganize");
+ }
+ }
+
+ public class AutoOrganizeOptionsFactory : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new List<ConfigurationStore>
+ {
+ new ConfigurationStore
+ {
+ Key = "autoorganize",
+ ConfigurationType = typeof (AutoOrganizeOptions)
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs
index 7cf38b0a0..7c5269678 100644
--- a/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs
+++ b/MediaBrowser.Server.Implementations/FileOrganization/FileOrganizationService.cs
@@ -95,6 +95,11 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
return _repo.Delete(resultId);
}
+ private TvFileOrganizationOptions GetTvOptions()
+ {
+ return _config.GetAutoOrganizeOptions().TvOptions;
+ }
+
public async Task PerformOrganization(string resultId)
{
var result = _repo.GetResult(resultId);
@@ -107,7 +112,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager,
_libraryMonitor, _providerManager);
- await organizer.OrganizeEpisodeFile(result.OriginalPath, _config.Configuration.TvFileOrganizationOptions, true, CancellationToken.None)
+ await organizer.OrganizeEpisodeFile(result.OriginalPath, GetTvOptions(), true, CancellationToken.None)
.ConfigureAwait(false);
}
@@ -121,7 +126,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager,
_libraryMonitor, _providerManager);
- await organizer.OrganizeWithCorrection(request, _config.Configuration.TvFileOrganizationOptions, CancellationToken.None).ConfigureAwait(false);
+ await organizer.OrganizeWithCorrection(request, GetTvOptions(), CancellationToken.None).ConfigureAwait(false);
}
}
}
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs
index fbb743f94..8dfdfdaec 100644
--- a/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/FileOrganization/OrganizerScheduledTask.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.FileOrganization;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
@@ -12,7 +13,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.FileOrganization
{
- public class OrganizerScheduledTask : IScheduledTask, IConfigurableScheduledTask
+ public class OrganizerScheduledTask : IScheduledTask, IConfigurableScheduledTask, IScheduledTaskActivityLog
{
private readonly ILibraryMonitor _libraryMonitor;
private readonly ILibraryManager _libraryManager;
@@ -48,10 +49,15 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
get { return "Library"; }
}
+ private TvFileOrganizationOptions GetTvOptions()
+ {
+ return _config.GetAutoOrganizeOptions().TvOptions;
+ }
+
public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{
return new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config, _providerManager)
- .Organize(_config.Configuration.TvFileOrganizationOptions, cancellationToken, progress);
+ .Organize(GetTvOptions(), cancellationToken, progress);
}
public IEnumerable<ITaskTrigger> GetDefaultTriggers()
@@ -64,12 +70,17 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
public bool IsHidden
{
- get { return !_config.Configuration.TvFileOrganizationOptions.IsEnabled; }
+ get { return !GetTvOptions().IsEnabled; }
}
public bool IsEnabled
{
- get { return _config.Configuration.TvFileOrganizationOptions.IsEnabled; }
+ get { return GetTvOptions().IsEnabled; }
+ }
+
+ public bool IsActivityLogged
+ {
+ get { return false; }
}
}
}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
index 0fc9265f6..1cec4461b 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -1,11 +1,11 @@
-using System.Net.Sockets;
-using System.Runtime.Serialization;
-using Funq;
+using Funq;
using MediaBrowser.Common;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Server.Implementations.HttpServer.NetListener;
+using MediaBrowser.Server.Implementations.HttpServer.SocketSharp;
using ServiceStack;
using ServiceStack.Api.Swagger;
using ServiceStack.Host;
@@ -14,11 +14,9 @@ using ServiceStack.Host.HttpListener;
using ServiceStack.Logging;
using ServiceStack.Web;
using System;
-using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Net;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
@@ -27,7 +25,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
{
public class HttpListenerHost : ServiceStackHost, IHttpServer
{
- private string ServerName { get; set; }
private string HandlerPath { get; set; }
private string DefaultRedirectPath { get; set; }
@@ -36,14 +33,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private readonly List<IRestfulService> _restServices = new List<IRestfulService>();
- private HttpListener Listener { get; set; }
- protected bool IsStarted = false;
-
- private readonly List<AutoResetEvent> _autoResetEvents = new List<AutoResetEvent>();
+ private IHttpListener _listener;
private readonly ContainerAdapter _containerAdapter;
- private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
/// <summary>
@@ -52,24 +45,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <value>The local end points.</value>
public IEnumerable<string> LocalEndPoints
{
- get { return _localEndPoints.Keys.ToList(); }
+ get { return _listener == null ? new List<string>() : _listener.LocalEndPoints; }
}
public HttpListenerHost(IApplicationHost applicationHost, ILogManager logManager, string serviceName, string handlerPath, string defaultRedirectPath, params Assembly[] assembliesWithServices)
: base(serviceName, assembliesWithServices)
{
DefaultRedirectPath = defaultRedirectPath;
- ServerName = serviceName;
HandlerPath = handlerPath;
_logger = logManager.GetLogger("HttpServer");
_containerAdapter = new ContainerAdapter(applicationHost);
-
- for (var i = 0; i < 1; i++)
- {
- _autoResetEvents.Add(new AutoResetEvent(false));
- }
}
public override void Configure(Container container)
@@ -81,7 +68,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer
{typeof (InvalidOperationException), 422},
{typeof (ResourceNotFoundException), 404},
{typeof (FileNotFoundException), 404},
- {typeof (DirectoryNotFoundException), 404}
+ {typeof (DirectoryNotFoundException), 404},
+ {typeof (Implementations.Security.AuthenticationException), 401}
};
HostConfig.Instance.DebugMode = true;
@@ -95,7 +83,21 @@ namespace MediaBrowser.Server.Implementations.HttpServer
container.Adapter = _containerAdapter;
Plugins.Add(new SwaggerFeature());
- Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization"));
+ Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization, Range, X-MediaBrowser-Token"));
+
+ //Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] {
+ // new SessionAuthProvider(_containerAdapter.Resolve<ISessionContext>()),
+ //}));
+
+ PreRequestFilters.Add((httpReq, httpRes) =>
+ {
+ //Handles Request and closes Responses after emitting global HTTP Headers
+ if (string.Equals(httpReq.Verb, "OPTIONS", StringComparison.OrdinalIgnoreCase))
+ {
+ httpRes.EndRequest(); //add a 'using ServiceStack;'
+ }
+ });
+
HostContext.GlobalResponseFilters.Add(new ResponseFilter(_logger).FilterResponse);
}
@@ -154,213 +156,39 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// </summary>
private void StartListener()
{
- // *** Already running - just leave it in place
- if (IsStarted)
- return;
-
- if (Listener == null)
- Listener = new HttpListener();
-
HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(UrlPrefixes.First());
- foreach (var prefix in UrlPrefixes)
- {
- _logger.Info("Adding HttpListener prefix " + prefix);
- Listener.Prefixes.Add(prefix);
- }
+ _listener = NativeWebSocket.IsSupported
+ ? _listener = new HttpListenerServer(_logger)
+ //? _listener = new WebSocketSharpListener(_logger)
+ : _listener = new WebSocketSharpListener(_logger);
- IsStarted = true;
- _logger.Info("Starting HttpListner");
- Listener.Start();
-
- for (var i = 0; i < _autoResetEvents.Count; i++)
- {
- var index = i;
- ThreadPool.QueueUserWorkItem(o => Listen(o, index));
- }
- }
+ _listener.WebSocketHandler = WebSocketHandler;
+ _listener.ErrorHandler = ErrorHandler;
+ _listener.RequestHandler = RequestHandler;
- private bool IsListening
- {
- get { return this.IsStarted && this.Listener != null && this.Listener.IsListening; }
+ _listener.Start(UrlPrefixes);
}
- // Loop here to begin processing of new requests.
- private void Listen(object state, int index)
+ private void WebSocketHandler(WebSocketConnectEventArgs args)
{
- while (IsListening)
+ if (WebSocketConnected != null)
{
- if (Listener == null) return;
-
- try
- {
- Listener.BeginGetContext(c => ListenerCallback(c, index), Listener);
-
- _autoResetEvents[index].WaitOne();
- }
- catch (Exception ex)
- {
- _logger.Error("Listen()", ex);
- return;
- }
- if (Listener == null) return;
+ WebSocketConnected(this, args);
}
}
- // Handle the processing of a request in here.
- private void ListenerCallback(IAsyncResult asyncResult, int index)
+ private void ErrorHandler(Exception ex, IRequest httpReq)
{
- var listener = asyncResult.AsyncState as HttpListener;
- HttpListenerContext context = null;
-
- if (listener == null) return;
-
try
{
- if (!IsListening)
- {
- _logger.Debug("Ignoring ListenerCallback() as HttpListener is no longer listening");
- return;
- }
- // The EndGetContext() method, as with all Begin/End asynchronous methods in the .NET Framework,
- // blocks until there is a request to be processed or some type of data is available.
- context = listener.EndGetContext(asyncResult);
- }
- catch (Exception ex)
- {
- // You will get an exception when httpListener.Stop() is called
- // because there will be a thread stopped waiting on the .EndGetContext()
- // method, and again, that is just the way most Begin/End asynchronous
- // methods of the .NET Framework work.
- var errMsg = ex + ": " + IsListening;
- _logger.Warn(errMsg);
- return;
- }
- finally
- {
- // Once we know we have a request (or exception), we signal the other thread
- // so that it calls the BeginGetContext() (or possibly exits if we're not
- // listening any more) method to start handling the next incoming request
- // while we continue to process this request on a different thread.
- _autoResetEvents[index].Set();
- }
-
- var date = DateTime.Now;
-
- Task.Factory.StartNew(async () =>
- {
- try
- {
- var request = context.Request;
-
- LogHttpRequest(request, index);
-
- if (request.IsWebSocketRequest)
- {
- await ProcessWebSocketRequest(context).ConfigureAwait(false);
- return;
- }
-
- var localPath = request.Url.LocalPath;
-
- if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase))
- {
- context.Response.Redirect(DefaultRedirectPath);
- context.Response.Close();
- return;
- }
- if (string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase))
- {
- context.Response.Redirect("mediabrowser/" + DefaultRedirectPath);
- context.Response.Close();
- return;
- }
- if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase))
- {
- context.Response.Redirect("mediabrowser/" + DefaultRedirectPath);
- context.Response.Close();
- return;
- }
- if (string.IsNullOrEmpty(localPath))
- {
- context.Response.Redirect("/mediabrowser/" + DefaultRedirectPath);
- context.Response.Close();
- return;
- }
-
- var url = request.Url.ToString();
- var endPoint = request.RemoteEndPoint;
-
- await ProcessRequestAsync(context).ConfigureAwait(false);
-
- var duration = DateTime.Now - date;
-
- if (EnableHttpRequestLogging)
- {
- LoggerUtils.LogResponse(_logger, context.Response, url, endPoint, duration);
- }
- }
- catch (Exception ex)
- {
- _logger.ErrorException("ProcessRequest failure", ex);
-
- HandleError(ex, context, _logger);
- }
-
- });
- }
-
- /// <summary>
- /// Logs the HTTP request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <param name="index">The index.</param>
- private void LogHttpRequest(HttpListenerRequest request, int index)
- {
- var endpoint = request.LocalEndPoint;
-
- if (endpoint != null)
- {
- var address = endpoint.ToString();
-
- _localEndPoints.GetOrAdd(address, address);
- }
-
- if (EnableHttpRequestLogging)
- {
- LoggerUtils.LogRequest(_logger, request, index);
- }
- }
+ var httpRes = httpReq.Response;
- /// <summary>
- /// Processes the web socket request.
- /// </summary>
- /// <param name="ctx">The CTX.</param>
- /// <returns>Task.</returns>
- private async Task ProcessWebSocketRequest(HttpListenerContext ctx)
- {
-#if !__MonoCS__
- try
- {
- var webSocketContext = await ctx.AcceptWebSocketAsync(null).ConfigureAwait(false);
- if (WebSocketConnected != null)
+ if (httpRes.IsClosed)
{
- WebSocketConnected(this, new WebSocketConnectEventArgs { WebSocket = new NativeWebSocket(webSocketContext.WebSocket, _logger), Endpoint = ctx.Request.RemoteEndPoint.ToString() });
+ return;
}
- }
- catch (Exception ex)
- {
- _logger.ErrorException("AcceptWebSocketAsync error", ex);
- ctx.Response.StatusCode = 500;
- ctx.Response.Close();
- }
-#endif
- }
- public static void HandleError(Exception ex, HttpListenerContext context, ILogger logger)
- {
- try
- {
var errorResponse = new ErrorResponse
{
ResponseStatus = new ResponseStatus
@@ -371,9 +199,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
}
};
- var operationName = context.Request.GetOperationName();
- var httpReq = GetRequest(context, operationName);
- var httpRes = httpReq.Response;
var contentType = httpReq.ResponseContentType;
var serializer = HostContext.ContentTypes.GetResponseSerializer(contentType);
@@ -402,48 +227,61 @@ namespace MediaBrowser.Server.Implementations.HttpServer
}
catch (Exception errorEx)
{
- logger.ErrorException("Error this.ProcessRequest(context)(Exception while writing error to the response)", errorEx);
+ _logger.ErrorException("Error this.ProcessRequest(context)(Exception while writing error to the response)", errorEx);
}
}
- private static ListenerRequest GetRequest(HttpListenerContext httpContext, string operationName)
- {
- var req = new ListenerRequest(httpContext, operationName, RequestAttributes.None);
- req.RequestAttributes = req.GetAttributes();
- return req;
- }
-
/// <summary>
/// Shut down the Web Service
/// </summary>
public void Stop()
{
- if (Listener != null)
+ if (_listener != null)
{
- foreach (var prefix in UrlPrefixes)
- {
- Listener.Prefixes.Remove(prefix);
- }
-
- Listener.Close();
+ _listener.Stop();
}
}
/// <summary>
/// Overridable method that can be used to implement a custom hnandler
/// </summary>
- /// <param name="context"></param>
- protected Task ProcessRequestAsync(HttpListenerContext context)
+ /// <param name="httpReq">The HTTP req.</param>
+ /// <param name="url">The URL.</param>
+ /// <returns>Task.</returns>
+ protected Task RequestHandler(IHttpRequest httpReq, Uri url)
{
- if (string.IsNullOrEmpty(context.Request.RawUrl))
- return ((object)null).AsTaskResult();
-
- var operationName = context.Request.GetOperationName();
+ var date = DateTime.Now;
- var httpReq = GetRequest(context, operationName);
var httpRes = httpReq.Response;
+
+ var operationName = httpReq.OperationName;
+ var localPath = url.LocalPath;
+
+ if (string.Equals(localPath, "/" + HandlerPath + "/", StringComparison.OrdinalIgnoreCase))
+ {
+ httpRes.RedirectToUrl(DefaultRedirectPath);
+ return Task.FromResult(true);
+ }
+ if (string.Equals(localPath, "/" + HandlerPath, StringComparison.OrdinalIgnoreCase))
+ {
+ httpRes.RedirectToUrl(HandlerPath + "/" + DefaultRedirectPath);
+ return Task.FromResult(true);
+ }
+ if (string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase))
+ {
+ httpRes.RedirectToUrl(HandlerPath + "/" + DefaultRedirectPath);
+ return Task.FromResult(true);
+ }
+ if (string.IsNullOrEmpty(localPath))
+ {
+ httpRes.RedirectToUrl("/" + HandlerPath + "/" + DefaultRedirectPath);
+ return Task.FromResult(true);
+ }
+
var handler = HttpHandlerFactory.GetHandler(httpReq);
+ var remoteIp = httpReq.RemoteIp;
+
var serviceStackHandler = handler as IServiceStackHandler;
if (serviceStackHandler != null)
{
@@ -454,8 +292,21 @@ namespace MediaBrowser.Server.Implementations.HttpServer
}
var task = serviceStackHandler.ProcessRequestAsync(httpReq, httpRes, operationName);
- task.ContinueWith(x => httpRes.Close());
+ task.ContinueWith(x => httpRes.Close(), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent);
+ //Matches Exceptions handled in HttpListenerBase.InitTask()
+
+ var urlString = url.ToString();
+
+ task.ContinueWith(x =>
+ {
+ var statusCode = httpRes.StatusCode;
+
+ var duration = DateTime.Now - date;
+
+ LoggerUtils.LogResponse(_logger, statusCode, urlString, remoteIp, duration);
+
+ }, TaskContinuationOptions.None);
return task;
}
@@ -464,12 +315,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
}
/// <summary>
- /// Gets or sets a value indicating whether [enable HTTP request logging].
- /// </summary>
- /// <value><c>true</c> if [enable HTTP request logging]; otherwise, <c>false</c>.</value>
- public bool EnableHttpRequestLogging { get; set; }
-
- /// <summary>
/// Adds the rest handlers.
/// </summary>
/// <param name="services">The services.</param>
@@ -484,6 +329,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer
base.Init();
}
+ //public override RouteAttribute[] GetRouteAttributes(System.Type requestType)
+ //{
+ // var routes = base.GetRouteAttributes(requestType);
+ // routes.Each(x => x.Path = "/api" + x.Path);
+ // return routes;
+ //}
+
/// <summary>
/// Releases the specified instance.
/// </summary>
@@ -525,10 +377,5 @@ namespace MediaBrowser.Server.Implementations.HttpServer
UrlPrefixes = urlPrefixes.ToList();
Start(UrlPrefixes.First());
}
-
- public bool SupportsWebSockets
- {
- get { return NativeWebSocket.IsSupported; }
- }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs
index 925ef8050..9997cfbdb 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs
@@ -289,30 +289,28 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return null;
}
- /// <summary>
- /// Gets the static file result.
- /// </summary>
- /// <param name="requestContext">The request context.</param>
- /// <param name="path">The path.</param>
- /// <param name="fileShare">The file share.</param>
- /// <param name="responseHeaders">The response headers.</param>
- /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
- /// <returns>System.Object.</returns>
- /// <exception cref="System.ArgumentNullException">path</exception>
- public object GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false)
+ public object GetStaticFileResult(IRequest requestContext,
+ string path,
+ FileShare fileShare = FileShare.Read)
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentNullException("path");
}
- return GetStaticFileResult(requestContext, path, MimeTypes.GetMimeType(path), fileShare, responseHeaders, isHeadRequest);
+ return GetStaticFileResult(requestContext, new StaticFileResultOptions
+ {
+ Path = path,
+ FileShare = fileShare
+ });
}
- public object GetStaticFileResult(IRequest requestContext, string path, string contentType,
- FileShare fileShare = FileShare.Read, IDictionary<string, string> responseHeaders = null,
- bool isHeadRequest = false)
+ public object GetStaticFileResult(IRequest requestContext,
+ StaticFileResultOptions options)
{
+ var path = options.Path;
+ var fileShare = options.FileShare;
+
if (string.IsNullOrEmpty(path))
{
throw new ArgumentNullException("path");
@@ -323,11 +321,18 @@ namespace MediaBrowser.Server.Implementations.HttpServer
throw new ArgumentException("FileShare must be either Read or ReadWrite");
}
- var dateModified = _fileSystem.GetLastWriteTimeUtc(path);
+ if (string.IsNullOrWhiteSpace(options.ContentType))
+ {
+ options.ContentType = MimeTypes.GetMimeType(path);
+ }
+
+ options.DateLastModified = _fileSystem.GetLastWriteTimeUtc(path);
+ var cacheKey = path + options.DateLastModified.Value.Ticks;
- var cacheKey = path + dateModified.Ticks;
+ options.CacheKey = cacheKey.GetMD5();
+ options.ContentFactory = () => Task.FromResult(GetFileStream(path, fileShare));
- return GetStaticResult(requestContext, cacheKey.GetMD5(), dateModified, null, contentType, () => Task.FromResult(GetFileStream(path, fileShare)), responseHeaders, isHeadRequest);
+ return GetStaticResult(requestContext, options);
}
/// <summary>
@@ -341,41 +346,46 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, fileShare, true);
}
- /// <summary>
- /// Gets the static result.
- /// </summary>
- /// <param name="requestContext">The request context.</param>
- /// <param name="cacheKey">The cache key.</param>
- /// <param name="lastDateModified">The last date modified.</param>
- /// <param name="cacheDuration">Duration of the cache.</param>
- /// <param name="contentType">Type of the content.</param>
- /// <param name="factoryFn">The factory fn.</param>
- /// <param name="responseHeaders">The response headers.</param>
- /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
- /// <returns>System.Object.</returns>
- /// <exception cref="System.ArgumentNullException">cacheKey
- /// or
- /// factoryFn</exception>
- public object GetStaticResult(IRequest requestContext, Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType, Func<Task<Stream>> factoryFn, IDictionary<string, string> responseHeaders = null, bool isHeadRequest = false)
+ public object GetStaticResult(IRequest requestContext,
+ Guid cacheKey,
+ DateTime? lastDateModified,
+ TimeSpan? cacheDuration,
+ string contentType,
+ Func<Task<Stream>> factoryFn,
+ IDictionary<string, string> responseHeaders = null,
+ bool isHeadRequest = false)
{
+ return GetStaticResult(requestContext, new StaticResultOptions
+ {
+ CacheDuration = cacheDuration,
+ CacheKey = cacheKey,
+ ContentFactory = factoryFn,
+ ContentType = contentType,
+ DateLastModified = lastDateModified,
+ IsHeadRequest = isHeadRequest,
+ ResponseHeaders = responseHeaders
+ });
+ }
+
+ public object GetStaticResult(IRequest requestContext, StaticResultOptions options)
+ {
+ var cacheKey = options.CacheKey;
+ options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary<string, string>();
+ var contentType = options.ContentType;
+
if (cacheKey == Guid.Empty)
{
throw new ArgumentNullException("cacheKey");
}
- if (factoryFn == null)
+ if (options.ContentFactory == null)
{
throw new ArgumentNullException("factoryFn");
}
var key = cacheKey.ToString("N");
- if (responseHeaders == null)
- {
- responseHeaders = new Dictionary<string, string>();
- }
-
// See if the result is already cached in the browser
- var result = GetCachedResult(requestContext, responseHeaders, cacheKey, key, lastDateModified, cacheDuration, contentType);
+ var result = GetCachedResult(requestContext, options.ResponseHeaders, cacheKey, key, options.DateLastModified, options.CacheDuration, contentType);
if (result != null)
{
@@ -383,10 +393,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer
}
var compress = ShouldCompressResponse(requestContext, contentType);
-
- var hasOptions = GetStaticResult(requestContext, responseHeaders, contentType, factoryFn, compress, isHeadRequest).Result;
-
- AddResponseHeaders(hasOptions, responseHeaders);
+ var hasOptions = GetStaticResult(requestContext, options, compress).Result;
+ AddResponseHeaders(hasOptions, options.ResponseHeaders);
return hasOptions;
}
@@ -442,18 +450,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// </summary>
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
- /// <summary>
- /// Gets the static result.
- /// </summary>
- /// <param name="requestContext">The request context.</param>
- /// <param name="responseHeaders">The response headers.</param>
- /// <param name="contentType">Type of the content.</param>
- /// <param name="factoryFn">The factory fn.</param>
- /// <param name="compress">if set to <c>true</c> [compress].</param>
- /// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
- /// <returns>Task{IHasOptions}.</returns>
- private async Task<IHasOptions> GetStaticResult(IRequest requestContext, IDictionary<string, string> responseHeaders, string contentType, Func<Task<Stream>> factoryFn, bool compress, bool isHeadRequest)
+ private async Task<IHasOptions> GetStaticResult(IRequest requestContext, StaticResultOptions options, bool compress)
{
+ var isHeadRequest = options.IsHeadRequest;
+ var factoryFn = options.ContentFactory;
+ var contentType = options.ContentType;
+ var responseHeaders = options.ResponseHeaders;
+
var requestedCompressionType = requestContext.GetCompressionType();
if (!compress || string.IsNullOrEmpty(requestedCompressionType))
@@ -464,7 +467,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer
if (!string.IsNullOrEmpty(rangeHeader))
{
- return new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest);
+ return new RangeRequestWriter(rangeHeader, stream, contentType, isHeadRequest)
+ {
+ Throttle = options.Throttle,
+ ThrottleLimit = options.ThrottleLimit,
+ MinThrottlePosition = options.MinThrottlePosition
+ };
}
responseHeaders["Content-Length"] = stream.Length.ToString(UsCulture);
@@ -476,7 +484,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return GetHttpResult(new byte[] { }, contentType);
}
- return new StreamWriter(stream, contentType, _logger);
+ return new StreamWriter(stream, contentType, _logger)
+ {
+ Throttle = options.Throttle,
+ ThrottleLimit = options.ThrottleLimit,
+ MinThrottlePosition = options.MinThrottlePosition
+ };
}
string content;
@@ -705,14 +718,5 @@ namespace MediaBrowser.Server.Implementations.HttpServer
throw error;
}
-
- public object GetOptimizedSerializedResultUsingCache<T>(IRequest request, T result)
- where T : class
- {
- var json = _jsonSerializer.SerializeToString(result);
- var cacheKey = json.GetMD5();
-
- return GetOptimizedResultUsingCache(request, cacheKey, null, null, () => result);
- }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs
new file mode 100644
index 000000000..1d80a263c
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs
@@ -0,0 +1,42 @@
+using System.Threading.Tasks;
+using MediaBrowser.Common.Net;
+using ServiceStack.Web;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Server.Implementations.HttpServer
+{
+ public interface IHttpListener : IDisposable
+ {
+ IEnumerable<string> LocalEndPoints { get; }
+
+ /// <summary>
+ /// Gets or sets the error handler.
+ /// </summary>
+ /// <value>The error handler.</value>
+ Action<Exception, IRequest> ErrorHandler { get; set; }
+
+ /// <summary>
+ /// Gets or sets the request handler.
+ /// </summary>
+ /// <value>The request handler.</value>
+ Func<IHttpRequest, Uri, Task> RequestHandler { get; set; }
+
+ /// <summary>
+ /// Gets or sets the web socket handler.
+ /// </summary>
+ /// <value>The web socket handler.</value>
+ Action<WebSocketConnectEventArgs> WebSocketHandler { get; set; }
+
+ /// <summary>
+ /// Starts this instance.
+ /// </summary>
+ /// <param name="urlPrefixes">The URL prefixes.</param>
+ void Start(IEnumerable<string> urlPrefixes);
+
+ /// <summary>
+ /// Stops this instance.
+ /// </summary>
+ void Stop();
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs
index 0f7e94ac5..955c4ed2d 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs
@@ -1,6 +1,5 @@
using MediaBrowser.Model.Logging;
using System;
-using System.Linq;
using System.Net;
using System.Text;
@@ -9,43 +8,22 @@ namespace MediaBrowser.Server.Implementations.HttpServer
public static class LoggerUtils
{
/// <summary>
- /// Logs the request.
- /// </summary>
- /// <param name="logger">The logger.</param>
- /// <param name="request">The request.</param>
- /// <param name="workerIndex">Index of the worker.</param>
- public static void LogRequest(ILogger logger, HttpListenerRequest request, int workerIndex)
- {
- var log = new StringBuilder();
-
- //var headers = string.Join(",", request.Headers.AllKeys.Where(i => !string.Equals(i, "cookie", StringComparison.OrdinalIgnoreCase) && !string.Equals(i, "Referer", StringComparison.OrdinalIgnoreCase)).Select(k => k + "=" + request.Headers[k]));
-
- //log.AppendLine("Ip: " + request.RemoteEndPoint + ". Headers: " + headers);
-
- var type = request.IsWebSocketRequest ? "Web Socket" : "HTTP " + request.HttpMethod;
-
- logger.LogMultiline(type + " " + request.Url, LogSeverity.Debug, log);
- }
-
- /// <summary>
/// Logs the response.
/// </summary>
/// <param name="logger">The logger.</param>
- /// <param name="response">The response.</param>
+ /// <param name="statusCode">The status code.</param>
/// <param name="url">The URL.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="duration">The duration.</param>
- public static void LogResponse(ILogger logger, HttpListenerResponse response, string url, IPEndPoint endPoint, TimeSpan duration)
+ public static void LogResponse(ILogger logger, int statusCode, string url, string endPoint, TimeSpan duration)
{
- var statusCode = response.StatusCode;
-
var log = new StringBuilder();
log.AppendLine(string.Format("Url: {0}", url));
//log.AppendLine("Headers: " + string.Join(",", response.Headers.AllKeys.Select(k => k + "=" + response.Headers[k])));
- var responseTime = string.Format(". Response time: {0} ms", duration.TotalMilliseconds);
+ var responseTime = string.Format(". Response time: {0} ms.", duration.TotalMilliseconds);
var msg = "HTTP Response " + statusCode + " to " + endPoint + responseTime;
diff --git a/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs b/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs
index f89cdac47..c7669fecb 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Events;
+using System.Text;
+using MediaBrowser.Common.Events;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.Logging;
using System;
@@ -36,7 +37,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="socket">The socket.</param>
/// <param name="logger">The logger.</param>
/// <exception cref="System.ArgumentNullException">socket</exception>
- public NativeWebSocket(System.Net.WebSockets.WebSocket socket, ILogger logger)
+ public NativeWebSocket(WebSocket socket, ILogger logger)
{
if (socket == null)
{
@@ -155,6 +156,22 @@ namespace MediaBrowser.Server.Implementations.HttpServer
return WebSocket.SendAsync(new ArraySegment<byte>(bytes), nativeType, true, linkedTokenSource.Token);
}
+ public Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken)
+ {
+ var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationTokenSource.Token);
+
+ return WebSocket.SendAsync(new ArraySegment<byte>(bytes), System.Net.WebSockets.WebSocketMessageType.Binary, true, linkedTokenSource.Token);
+ }
+
+ public Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken)
+ {
+ var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _cancellationTokenSource.Token);
+
+ var bytes = Encoding.UTF8.GetBytes(text);
+
+ return WebSocket.SendAsync(new ArraySegment<byte>(bytes), System.Net.WebSockets.WebSocketMessageType.Text, true, linkedTokenSource.Token);
+ }
+
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
diff --git a/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs b/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs
new file mode 100644
index 000000000..bdc2750fb
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs
@@ -0,0 +1,299 @@
+using MediaBrowser.Common.Net;
+using MediaBrowser.Model.Logging;
+using ServiceStack;
+using ServiceStack.Host.HttpListener;
+using ServiceStack.Web;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.NetListener
+{
+ public class HttpListenerServer : IHttpListener
+ {
+ private readonly ILogger _logger;
+ private HttpListener _listener;
+ private readonly AutoResetEvent _listenForNextRequest = new AutoResetEvent(false);
+
+ public System.Action<Exception, IRequest> ErrorHandler { get; set; }
+ public Action<WebSocketConnectEventArgs> WebSocketHandler { get; set; }
+ public System.Func<IHttpRequest, Uri, Task> RequestHandler { get; set; }
+
+ private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+
+ public HttpListenerServer(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ /// <summary>
+ /// Gets the local end points.
+ /// </summary>
+ /// <value>The local end points.</value>
+ public IEnumerable<string> LocalEndPoints
+ {
+ get { return _localEndPoints.Keys.ToList(); }
+ }
+
+ private List<string> UrlPrefixes { get; set; }
+
+ public void Start(IEnumerable<string> urlPrefixes)
+ {
+ UrlPrefixes = urlPrefixes.ToList();
+
+ if (_listener == null)
+ _listener = new System.Net.HttpListener();
+
+ //HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(UrlPrefixes.First());
+
+ foreach (var prefix in UrlPrefixes)
+ {
+ _logger.Info("Adding HttpListener prefix " + prefix);
+ _listener.Prefixes.Add(prefix);
+ }
+
+ _listener.Start();
+
+ Task.Factory.StartNew(Listen, TaskCreationOptions.LongRunning);
+ }
+
+ private bool IsListening
+ {
+ get { return _listener != null && _listener.IsListening; }
+ }
+
+ // Loop here to begin processing of new requests.
+ private void Listen()
+ {
+ while (IsListening)
+ {
+ if (_listener == null) return;
+
+ try
+ {
+ _listener.BeginGetContext(ListenerCallback, _listener);
+ _listenForNextRequest.WaitOne();
+ }
+ catch (Exception ex)
+ {
+ _logger.Error("Listen()", ex);
+ return;
+ }
+ if (_listener == null) return;
+ }
+ }
+
+ // Handle the processing of a request in here.
+ private void ListenerCallback(IAsyncResult asyncResult)
+ {
+ var listener = asyncResult.AsyncState as HttpListener;
+ HttpListenerContext context;
+
+ if (listener == null) return;
+ var isListening = listener.IsListening;
+
+ try
+ {
+ if (!isListening)
+ {
+ _logger.Debug("Ignoring ListenerCallback() as HttpListener is no longer listening"); return;
+ }
+ // The EndGetContext() method, as with all Begin/End asynchronous methods in the .NET Framework,
+ // blocks until there is a request to be processed or some type of data is available.
+ context = listener.EndGetContext(asyncResult);
+ }
+ catch (Exception ex)
+ {
+ // You will get an exception when httpListener.Stop() is called
+ // because there will be a thread stopped waiting on the .EndGetContext()
+ // method, and again, that is just the way most Begin/End asynchronous
+ // methods of the .NET Framework work.
+ var errMsg = ex + ": " + IsListening;
+ _logger.Warn(errMsg);
+ return;
+ }
+ finally
+ {
+ // Once we know we have a request (or exception), we signal the other thread
+ // so that it calls the BeginGetContext() (or possibly exits if we're not
+ // listening any more) method to start handling the next incoming request
+ // while we continue to process this request on a different thread.
+ _listenForNextRequest.Set();
+ }
+
+ Task.Factory.StartNew(() => InitTask(context));
+ }
+
+ private void InitTask(HttpListenerContext context)
+ {
+ try
+ {
+ var task = this.ProcessRequestAsync(context);
+ task.ContinueWith(x => HandleError(x.Exception, context), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent);
+
+ if (task.Status == TaskStatus.Created)
+ {
+ task.RunSynchronously();
+ }
+ }
+ catch (Exception ex)
+ {
+ HandleError(ex, context);
+ }
+ }
+
+ private Task ProcessRequestAsync(HttpListenerContext context)
+ {
+ var request = context.Request;
+
+ LogHttpRequest(request);
+
+ if (request.IsWebSocketRequest)
+ {
+ return ProcessWebSocketRequest(context);
+ }
+
+ if (string.IsNullOrEmpty(context.Request.RawUrl))
+ return ((object)null).AsTaskResult();
+
+ var operationName = context.Request.GetOperationName();
+
+ var httpReq = GetRequest(context, operationName);
+
+ return RequestHandler(httpReq, request.Url);
+ }
+
+ /// <summary>
+ /// Processes the web socket request.
+ /// </summary>
+ /// <param name="ctx">The CTX.</param>
+ /// <returns>Task.</returns>
+ private async Task ProcessWebSocketRequest(HttpListenerContext ctx)
+ {
+#if !__MonoCS__
+ try
+ {
+ var webSocketContext = await ctx.AcceptWebSocketAsync(null).ConfigureAwait(false);
+
+ if (WebSocketHandler != null)
+ {
+ WebSocketHandler(new WebSocketConnectEventArgs
+ {
+ WebSocket = new NativeWebSocket(webSocketContext.WebSocket, _logger),
+ Endpoint = ctx.Request.RemoteEndPoint.ToString()
+ });
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("AcceptWebSocketAsync error", ex);
+ ctx.Response.StatusCode = 500;
+ ctx.Response.Close();
+ }
+#endif
+ }
+
+ private void HandleError(Exception ex, HttpListenerContext context)
+ {
+ var operationName = context.Request.GetOperationName();
+ var httpReq = GetRequest(context, operationName);
+
+ if (ErrorHandler != null)
+ {
+ ErrorHandler(ex, httpReq);
+ }
+ }
+
+ private static ListenerRequest GetRequest(HttpListenerContext httpContext, string operationName)
+ {
+ var req = new ListenerRequest(httpContext, operationName, RequestAttributes.None);
+ req.RequestAttributes = req.GetAttributes();
+
+ return req;
+ }
+
+ /// <summary>
+ /// Logs the HTTP request.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ private void LogHttpRequest(HttpListenerRequest request)
+ {
+ var endpoint = request.LocalEndPoint;
+
+ if (endpoint != null)
+ {
+ var address = endpoint.ToString();
+
+ _localEndPoints.GetOrAdd(address, address);
+ }
+
+ LogRequest(_logger, request);
+ }
+
+ /// <summary>
+ /// Logs the request.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ /// <param name="request">The request.</param>
+ private static void LogRequest(ILogger logger, HttpListenerRequest request)
+ {
+ var log = new StringBuilder();
+
+ var logHeaders = true;
+
+ if (logHeaders)
+ {
+ var headers = string.Join(",", request.Headers.AllKeys.Where(i => !string.Equals(i, "cookie", StringComparison.OrdinalIgnoreCase) && !string.Equals(i, "Referer", StringComparison.OrdinalIgnoreCase)).Select(k => k + "=" + request.Headers[k]));
+
+ log.AppendLine("Ip: " + request.RemoteEndPoint + ". Headers: " + headers);
+ }
+
+ var type = request.IsWebSocketRequest ? "Web Socket" : "HTTP " + request.HttpMethod;
+
+ logger.LogMultiline(type + " " + request.Url, LogSeverity.Debug, log);
+ }
+
+ public void Stop()
+ {
+ if (_listener != null)
+ {
+ foreach (var prefix in UrlPrefixes)
+ {
+ _listener.Prefixes.Remove(prefix);
+ }
+
+ _listener.Close();
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ private bool _disposed;
+ private readonly object _disposeLock = new object();
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed) return;
+
+ lock (_disposeLock)
+ {
+ if (_disposed) return;
+
+ if (disposing)
+ {
+ Stop();
+ }
+
+ //release unmanaged resources here...
+ _disposed = true;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs b/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs
index 1ff199eb4..657545069 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs
@@ -1,10 +1,10 @@
-using System.Threading;
-using ServiceStack.Web;
+using ServiceStack.Web;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
+using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.HttpServer
@@ -24,6 +24,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer
private long RangeLength { get; set; }
private long TotalContentLength { get; set; }
+ public bool Throttle { get; set; }
+ public long ThrottleLimit { get; set; }
+ public long MinThrottlePosition;
+
/// <summary>
/// The _options
/// </summary>
@@ -159,6 +163,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="responseStream">The response stream.</param>
public void WriteTo(Stream responseStream)
{
+ if (Throttle)
+ {
+ responseStream = new ThrottledStream(responseStream, ThrottleLimit)
+ {
+ MinThrottlePosition = MinThrottlePosition
+ };
+ }
var task = WriteToAsync(responseStream);
Task.WaitAll(task);
@@ -228,5 +239,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
}
public string StatusDescription { get; set; }
+
+ public int PaddingLength { get; set; }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs b/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs
index ac1621709..e0a5764d5 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/ResponseFilter.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Model.Logging;
+using MediaBrowser.Server.Implementations.HttpServer.SocketSharp;
using ServiceStack;
using ServiceStack.Web;
using System;
@@ -66,13 +67,23 @@ namespace MediaBrowser.Server.Implementations.HttpServer
if (length > 0)
{
- var response = (HttpListenerResponse)res.OriginalResponse;
-
- response.ContentLength64 = length;
-
- // Disable chunked encoding. Technically this is only needed when using Content-Range, but
- // anytime we know the content length there's no need for it
- response.SendChunked = false;
+ res.SetContentLength(length);
+
+ var listenerResponse = res.OriginalResponse as HttpListenerResponse;
+
+ if (listenerResponse != null)
+ {
+ // Disable chunked encoding. Technically this is only needed when using Content-Range, but
+ // anytime we know the content length there's no need for it
+ listenerResponse.SendChunked = false;
+ return;
+ }
+
+ var sharpResponse = res as WebSocketSharpResponse;
+ if (sharpResponse != null)
+ {
+ sharpResponse.SendChunked = false;
+ }
}
}
}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
new file mode 100644
index 000000000..19870c435
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
@@ -0,0 +1,164 @@
+using System.Collections.Generic;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller.Session;
+using ServiceStack;
+using ServiceStack.Auth;
+using ServiceStack.Web;
+using System;
+using System.Collections.Specialized;
+using System.Linq;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.Security
+{
+ public class AuthService : IAuthService
+ {
+ private readonly IServerConfigurationManager _config;
+
+ public AuthService(IUserManager userManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext, IServerConfigurationManager config)
+ {
+ AuthorizationContext = authorizationContext;
+ _config = config;
+ SessionManager = sessionManager;
+ UserManager = userManager;
+ }
+
+ public IUserManager UserManager { get; private set; }
+ public ISessionManager SessionManager { get; private set; }
+ public IAuthorizationContext AuthorizationContext { get; private set; }
+
+ /// <summary>
+ /// Restrict authentication to a specific <see cref="IAuthProvider"/>.
+ /// For example, if this attribute should only permit access
+ /// if the user is authenticated with <see cref="BasicAuthProvider"/>,
+ /// you should set this property to <see cref="BasicAuthProvider.Name"/>.
+ /// </summary>
+ public string Provider { get; set; }
+
+ /// <summary>
+ /// Redirect the client to a specific URL if authentication failed.
+ /// If this property is null, simply `401 Unauthorized` is returned.
+ /// </summary>
+ public string HtmlRedirect { get; set; }
+
+ public void Authenticate(IRequest req, IResponse res, object requestDto)
+ {
+ if (HostContext.HasValidAuthSecret(req))
+ return;
+
+ //ExecuteBasic(req, res, requestDto); //first check if session is authenticated
+ //if (res.IsClosed) return; //AuthenticateAttribute already closed the request (ie auth failed)
+
+ ValidateUser(req);
+ }
+
+ // TODO: Remove this when all clients have supported the new sescurity
+ private readonly List<string> _updatedClients = new List<string>(){"Dashboard"};
+
+ private void ValidateUser(IRequest req)
+ {
+ //This code is executed before the service
+ var auth = AuthorizationContext.GetAuthorizationInfo(req);
+
+ if (!string.IsNullOrWhiteSpace(auth.Token)
+ || _config.Configuration.EnableTokenAuthentication
+ || _updatedClients.Contains(auth.Client ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ {
+ SessionManager.ValidateSecurityToken(auth.Token);
+ }
+
+ var user = string.IsNullOrWhiteSpace(auth.UserId)
+ ? null
+ : UserManager.GetUserById(new Guid(auth.UserId));
+
+ if (user == null & !string.IsNullOrWhiteSpace(auth.UserId))
+ {
+ // TODO: Re-enable
+ //throw new ArgumentException("User with Id " + auth.UserId + " not found");
+ }
+
+ if (user != null && user.Configuration.IsDisabled)
+ {
+ throw new AuthenticationException("User account has been disabled.");
+ }
+
+ if (!string.IsNullOrWhiteSpace(auth.DeviceId) &&
+ !string.IsNullOrWhiteSpace(auth.Client) &&
+ !string.IsNullOrWhiteSpace(auth.Device))
+ {
+ SessionManager.LogSessionActivity(auth.Client,
+ auth.Version,
+ auth.DeviceId,
+ auth.Device,
+ req.RemoteIp,
+ user);
+ }
+ }
+
+ private void ExecuteBasic(IRequest req, IResponse res, object requestDto)
+ {
+ if (AuthenticateService.AuthProviders == null)
+ throw new InvalidOperationException(
+ "The AuthService must be initialized by calling AuthService.Init to use an authenticate attribute");
+
+ var matchingOAuthConfigs = AuthenticateService.AuthProviders.Where(x =>
+ this.Provider.IsNullOrEmpty()
+ || x.Provider == this.Provider).ToList();
+
+ if (matchingOAuthConfigs.Count == 0)
+ {
+ res.WriteError(req, requestDto, "No OAuth Configs found matching {0} provider"
+ .Fmt(this.Provider ?? "any"));
+ res.EndRequest();
+ }
+
+ matchingOAuthConfigs.OfType<IAuthWithRequest>()
+ .Each(x => x.PreAuthenticate(req, res));
+
+ var session = req.GetSession();
+ if (session == null || !matchingOAuthConfigs.Any(x => session.IsAuthorized(x.Provider)))
+ {
+ if (this.DoHtmlRedirectIfConfigured(req, res, true)) return;
+
+ AuthProvider.HandleFailedAuth(matchingOAuthConfigs[0], session, req, res);
+ }
+ }
+
+ protected bool DoHtmlRedirectIfConfigured(IRequest req, IResponse res, bool includeRedirectParam = false)
+ {
+ var htmlRedirect = this.HtmlRedirect ?? AuthenticateService.HtmlRedirect;
+ if (htmlRedirect != null && req.ResponseContentType.MatchesContentType(MimeTypes.Html))
+ {
+ DoHtmlRedirect(htmlRedirect, req, res, includeRedirectParam);
+ return true;
+ }
+ return false;
+ }
+
+ public static void DoHtmlRedirect(string redirectUrl, IRequest req, IResponse res, bool includeRedirectParam)
+ {
+ var url = req.ResolveAbsoluteUrl(redirectUrl);
+ if (includeRedirectParam)
+ {
+ var absoluteRequestPath = req.ResolveAbsoluteUrl("~" + req.PathInfo + ToQueryString(req.QueryString));
+ url = url.AddQueryParam(HostContext.ResolveLocalizedString(LocalizedStrings.Redirect), absoluteRequestPath);
+ }
+
+ res.RedirectToUrl(url);
+ }
+
+ private static string ToQueryString(INameValueCollection queryStringCollection)
+ {
+ return ToQueryString((NameValueCollection)queryStringCollection.Original);
+ }
+
+ private static string ToQueryString(NameValueCollection queryStringCollection)
+ {
+ if (queryStringCollection == null || queryStringCollection.Count == 0)
+ return String.Empty;
+
+ return "?" + queryStringCollection.ToFormUrlEncoded();
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
new file mode 100644
index 000000000..94be37e95
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using MediaBrowser.Controller.Net;
+using ServiceStack.Web;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.Security
+{
+ public class AuthorizationContext : IAuthorizationContext
+ {
+ public AuthorizationInfo GetAuthorizationInfo(IRequest requestContext)
+ {
+ return GetAuthorization(requestContext);
+ }
+
+ /// <summary>
+ /// Gets the authorization.
+ /// </summary>
+ /// <param name="httpReq">The HTTP req.</param>
+ /// <returns>Dictionary{System.StringSystem.String}.</returns>
+ private static AuthorizationInfo GetAuthorization(IRequest httpReq)
+ {
+ var auth = GetAuthorizationDictionary(httpReq);
+
+ string userId = null;
+ string deviceId = null;
+ string device = null;
+ string client = null;
+ string version = null;
+
+ if (auth != null)
+ {
+ auth.TryGetValue("UserId", out userId);
+ auth.TryGetValue("DeviceId", out deviceId);
+ auth.TryGetValue("Device", out device);
+ auth.TryGetValue("Client", out client);
+ auth.TryGetValue("Version", out version);
+ }
+
+ var token = httpReq.Headers["X-MediaBrowser-Token"];
+
+ if (string.IsNullOrWhiteSpace(token))
+ {
+ token = httpReq.QueryString["api_key"];
+ }
+
+ return new AuthorizationInfo
+ {
+ Client = client,
+ Device = device,
+ DeviceId = deviceId,
+ UserId = userId,
+ Version = version,
+ Token = token
+ };
+ }
+
+ /// <summary>
+ /// Gets the auth.
+ /// </summary>
+ /// <param name="httpReq">The HTTP req.</param>
+ /// <returns>Dictionary{System.StringSystem.String}.</returns>
+ private static Dictionary<string, string> GetAuthorizationDictionary(IRequest httpReq)
+ {
+ var auth = httpReq.Headers["Authorization"];
+
+ return GetAuthorization(auth);
+ }
+
+ /// <summary>
+ /// Gets the authorization.
+ /// </summary>
+ /// <param name="authorizationHeader">The authorization header.</param>
+ /// <returns>Dictionary{System.StringSystem.String}.</returns>
+ private static Dictionary<string, string> GetAuthorization(string authorizationHeader)
+ {
+ if (authorizationHeader == null) return null;
+
+ var parts = authorizationHeader.Split(' ');
+
+ // There should be at least to parts
+ if (parts.Length < 2) return null;
+
+ // It has to be a digest request
+ if (!string.Equals(parts[0], "MediaBrowser", StringComparison.OrdinalIgnoreCase))
+ {
+ return null;
+ }
+
+ // Remove uptil the first space
+ authorizationHeader = authorizationHeader.Substring(authorizationHeader.IndexOf(' '));
+ parts = authorizationHeader.Split(',');
+
+ var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+
+ foreach (var item in parts)
+ {
+ var param = item.Trim().Split(new[] { '=' }, 2);
+ result.Add(param[0], param[1].Trim(new[] { '"' }));
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/SessionAuthProvider.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/SessionAuthProvider.cs
new file mode 100644
index 000000000..7c3173101
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/Security/SessionAuthProvider.cs
@@ -0,0 +1,35 @@
+using MediaBrowser.Controller.Net;
+using ServiceStack;
+using ServiceStack.Auth;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.Security
+{
+ public class SessionAuthProvider : CredentialsAuthProvider
+ {
+ private readonly ISessionContext _sessionContext;
+
+ public SessionAuthProvider(ISessionContext sessionContext)
+ {
+ _sessionContext = sessionContext;
+ }
+
+ public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
+ {
+ return true;
+ }
+
+ public override bool IsAuthorized(IAuthSession session, IAuthTokens tokens, Authenticate request = null)
+ {
+ return true;
+ }
+
+ protected override void SaveUserAuth(IServiceBase authService, IAuthSession session, IAuthRepository authRepo, IAuthTokens tokens)
+ {
+ }
+
+ public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request)
+ {
+ return base.Authenticate(authService, session, request);
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/SessionContext.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/SessionContext.cs
new file mode 100644
index 000000000..f67c643c8
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/Security/SessionContext.cs
@@ -0,0 +1,36 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller.Session;
+using ServiceStack.Web;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.Security
+{
+ public class SessionContext : ISessionContext
+ {
+ private readonly IUserManager _userManager;
+ private readonly ISessionManager _sessionManager;
+ private readonly IAuthorizationContext _authContext;
+
+ public SessionContext(IUserManager userManager, IAuthorizationContext authContext, ISessionManager sessionManager)
+ {
+ _userManager = userManager;
+ _authContext = authContext;
+ _sessionManager = sessionManager;
+ }
+
+ public SessionInfo GetSession(IRequest requestContext)
+ {
+ var authorization = _authContext.GetAuthorizationInfo(requestContext);
+
+ return _sessionManager.GetSession(authorization.DeviceId, authorization.Client, authorization.Version);
+ }
+
+ public User GetUser(IRequest requestContext)
+ {
+ var session = GetSession(requestContext);
+
+ return session == null || !session.UserId.HasValue ? null : _userManager.GetUserById(session.UserId.Value);
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/Extensions.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/Extensions.cs
new file mode 100644
index 000000000..63d57b6be
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/Extensions.cs
@@ -0,0 +1,28 @@
+using System;
+using MediaBrowser.Model.Logging;
+using WebSocketSharp.Net;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
+{
+ public static class Extensions
+ {
+ public static string GetOperationName(this HttpListenerRequest request)
+ {
+ return request.Url.Segments[request.Url.Segments.Length - 1];
+ }
+
+ public static void CloseOutputStream(this HttpListenerResponse response, ILogger logger)
+ {
+ try
+ {
+ response.OutputStream.Flush();
+ response.OutputStream.Close();
+ response.Close();
+ }
+ catch (Exception ex)
+ {
+ logger.ErrorException("Error in HttpListenerResponseWrapper: " + ex.Message, ex);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs
new file mode 100644
index 000000000..226d97b3c
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/RequestMono.cs
@@ -0,0 +1,918 @@
+using System;
+using System.Collections.Specialized;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using System.Web;
+using ServiceStack.Web;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
+{
+ public partial class WebSocketSharpRequest : IHttpRequest
+ {
+ static internal string GetParameter(string header, string attr)
+ {
+ int ap = header.IndexOf(attr);
+ if (ap == -1)
+ return null;
+
+ ap += attr.Length;
+ if (ap >= header.Length)
+ return null;
+
+ char ending = header[ap];
+ if (ending != '"')
+ ending = ' ';
+
+ int end = header.IndexOf(ending, ap + 1);
+ if (end == -1)
+ return (ending == '"') ? null : header.Substring(ap);
+
+ return header.Substring(ap + 1, end - ap - 1);
+ }
+
+ void LoadMultiPart()
+ {
+ string boundary = GetParameter(ContentType, "; boundary=");
+ if (boundary == null)
+ return;
+
+ var input = GetSubStream(InputStream);
+
+ //DB: 30/01/11 - Hack to get around non-seekable stream and received HTTP request
+ //Not ending with \r\n?
+ var ms = new MemoryStream(32 * 1024);
+ input.CopyTo(ms);
+ input = ms;
+ ms.WriteByte((byte)'\r');
+ ms.WriteByte((byte)'\n');
+
+ input.Position = 0;
+
+ //Uncomment to debug
+ //var content = new StreamReader(ms).ReadToEnd();
+ //Console.WriteLine(boundary + "::" + content);
+ //input.Position = 0;
+
+ var multi_part = new HttpMultipart(input, boundary, ContentEncoding);
+
+ HttpMultipart.Element e;
+ while ((e = multi_part.ReadNextElement()) != null)
+ {
+ if (e.Filename == null)
+ {
+ byte[] copy = new byte[e.Length];
+
+ input.Position = e.Start;
+ input.Read(copy, 0, (int)e.Length);
+
+ form.Add(e.Name, (e.Encoding ?? ContentEncoding).GetString(copy));
+ }
+ else
+ {
+ //
+ // We use a substream, as in 2.x we will support large uploads streamed to disk,
+ //
+ HttpPostedFile sub = new HttpPostedFile(e.Filename, e.ContentType, input, e.Start, e.Length);
+ files.AddFile(e.Name, sub);
+ }
+ }
+ EndSubStream(input);
+ }
+
+ public NameValueCollection Form
+ {
+ get
+ {
+ if (form == null)
+ {
+ form = new WebROCollection();
+ files = new HttpFileCollection();
+
+ if (IsContentType("multipart/form-data", true))
+ LoadMultiPart();
+ else if (
+ IsContentType("application/x-www-form-urlencoded", true))
+ LoadWwwForm();
+
+ form.Protect();
+ }
+
+#if NET_4_0
+ if (validateRequestNewMode && !checked_form) {
+ // Setting this before calling the validator prevents
+ // possible endless recursion
+ checked_form = true;
+ ValidateNameValueCollection ("Form", query_string_nvc, RequestValidationSource.Form);
+ } else
+#endif
+ if (validate_form && !checked_form)
+ {
+ checked_form = true;
+ ValidateNameValueCollection("Form", form);
+ }
+
+ return form;
+ }
+ }
+
+
+ protected bool validate_cookies, validate_query_string, validate_form;
+ protected bool checked_cookies, checked_query_string, checked_form;
+
+ static void ThrowValidationException(string name, string key, string value)
+ {
+ string v = "\"" + value + "\"";
+ if (v.Length > 20)
+ v = v.Substring(0, 16) + "...\"";
+
+ string msg = String.Format("A potentially dangerous Request.{0} value was " +
+ "detected from the client ({1}={2}).", name, key, v);
+
+ throw new HttpRequestValidationException(msg);
+ }
+
+ static void ValidateNameValueCollection(string name, NameValueCollection coll)
+ {
+ if (coll == null)
+ return;
+
+ foreach (string key in coll.Keys)
+ {
+ string val = coll[key];
+ if (val != null && val.Length > 0 && IsInvalidString(val))
+ ThrowValidationException(name, key, val);
+ }
+ }
+
+ internal static bool IsInvalidString(string val)
+ {
+ int validationFailureIndex;
+
+ return IsInvalidString(val, out validationFailureIndex);
+ }
+
+ internal static bool IsInvalidString(string val, out int validationFailureIndex)
+ {
+ validationFailureIndex = 0;
+
+ int len = val.Length;
+ if (len < 2)
+ return false;
+
+ char current = val[0];
+ for (int idx = 1; idx < len; idx++)
+ {
+ char next = val[idx];
+ // See http://secunia.com/advisories/14325
+ if (current == '<' || current == '\xff1c')
+ {
+ if (next == '!' || next < ' '
+ || (next >= 'a' && next <= 'z')
+ || (next >= 'A' && next <= 'Z'))
+ {
+ validationFailureIndex = idx - 1;
+ return true;
+ }
+ }
+ else if (current == '&' && next == '#')
+ {
+ validationFailureIndex = idx - 1;
+ return true;
+ }
+
+ current = next;
+ }
+
+ return false;
+ }
+
+ public void ValidateInput()
+ {
+ validate_cookies = true;
+ validate_query_string = true;
+ validate_form = true;
+ }
+
+ bool IsContentType(string ct, bool starts_with)
+ {
+ if (ct == null || ContentType == null) return false;
+
+ if (starts_with)
+ return StrUtils.StartsWith(ContentType, ct, true);
+
+ return String.Compare(ContentType, ct, true, Helpers.InvariantCulture) == 0;
+ }
+
+
+
+
+
+ void LoadWwwForm()
+ {
+ using (Stream input = GetSubStream(InputStream))
+ {
+ using (StreamReader s = new StreamReader(input, ContentEncoding))
+ {
+ StringBuilder key = new StringBuilder();
+ StringBuilder value = new StringBuilder();
+ int c;
+
+ while ((c = s.Read()) != -1)
+ {
+ if (c == '=')
+ {
+ value.Length = 0;
+ while ((c = s.Read()) != -1)
+ {
+ if (c == '&')
+ {
+ AddRawKeyValue(key, value);
+ break;
+ }
+ else
+ value.Append((char)c);
+ }
+ if (c == -1)
+ {
+ AddRawKeyValue(key, value);
+ return;
+ }
+ }
+ else if (c == '&')
+ AddRawKeyValue(key, value);
+ else
+ key.Append((char)c);
+ }
+ if (c == -1)
+ AddRawKeyValue(key, value);
+
+ EndSubStream(input);
+ }
+ }
+ }
+
+ void AddRawKeyValue(StringBuilder key, StringBuilder value)
+ {
+ string decodedKey = HttpUtility.UrlDecode(key.ToString(), ContentEncoding);
+ form.Add(decodedKey,
+ HttpUtility.UrlDecode(value.ToString(), ContentEncoding));
+
+ key.Length = 0;
+ value.Length = 0;
+ }
+
+ WebROCollection form;
+
+ HttpFileCollection files;
+
+ public sealed class HttpFileCollection : NameObjectCollectionBase
+ {
+ internal HttpFileCollection()
+ {
+ }
+
+ internal void AddFile(string name, HttpPostedFile file)
+ {
+ BaseAdd(name, file);
+ }
+
+ public void CopyTo(Array dest, int index)
+ {
+ /* XXX this is kind of gross and inefficient
+ * since it makes a copy of the superclass's
+ * list */
+ object[] values = BaseGetAllValues();
+ values.CopyTo(dest, index);
+ }
+
+ public string GetKey(int index)
+ {
+ return BaseGetKey(index);
+ }
+
+ public HttpPostedFile Get(int index)
+ {
+ return (HttpPostedFile)BaseGet(index);
+ }
+
+ public HttpPostedFile Get(string key)
+ {
+ return (HttpPostedFile)BaseGet(key);
+ }
+
+ public HttpPostedFile this[string key]
+ {
+ get
+ {
+ return Get(key);
+ }
+ }
+
+ public HttpPostedFile this[int index]
+ {
+ get
+ {
+ return Get(index);
+ }
+ }
+
+ public string[] AllKeys
+ {
+ get
+ {
+ return BaseGetAllKeys();
+ }
+ }
+ }
+ class WebROCollection : NameValueCollection
+ {
+ bool got_id;
+ int id;
+
+ public bool GotID
+ {
+ get { return got_id; }
+ }
+
+ public int ID
+ {
+ get { return id; }
+ set
+ {
+ got_id = true;
+ id = value;
+ }
+ }
+ public void Protect()
+ {
+ IsReadOnly = true;
+ }
+
+ public void Unprotect()
+ {
+ IsReadOnly = false;
+ }
+
+ public override string ToString()
+ {
+ StringBuilder result = new StringBuilder();
+ foreach (string key in AllKeys)
+ {
+ if (result.Length > 0)
+ result.Append('&');
+
+ if (key != null && key.Length > 0)
+ {
+ result.Append(key);
+ result.Append('=');
+ }
+ result.Append(Get(key));
+ }
+
+ return result.ToString();
+ }
+ }
+
+ public sealed class HttpPostedFile
+ {
+ string name;
+ string content_type;
+ Stream stream;
+
+ class ReadSubStream : Stream
+ {
+ Stream s;
+ long offset;
+ long end;
+ long position;
+
+ public ReadSubStream(Stream s, long offset, long length)
+ {
+ this.s = s;
+ this.offset = offset;
+ this.end = offset + length;
+ position = offset;
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override int Read(byte[] buffer, int dest_offset, int count)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException("buffer");
+
+ if (dest_offset < 0)
+ throw new ArgumentOutOfRangeException("dest_offset", "< 0");
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", "< 0");
+
+ int len = buffer.Length;
+ if (dest_offset > len)
+ throw new ArgumentException("destination offset is beyond array size");
+ // reordered to avoid possible integer overflow
+ if (dest_offset > len - count)
+ throw new ArgumentException("Reading would overrun buffer");
+
+ if (count > end - position)
+ count = (int)(end - position);
+
+ if (count <= 0)
+ return 0;
+
+ s.Position = position;
+ int result = s.Read(buffer, dest_offset, count);
+ if (result > 0)
+ position += result;
+ else
+ position = end;
+
+ return result;
+ }
+
+ public override int ReadByte()
+ {
+ if (position >= end)
+ return -1;
+
+ s.Position = position;
+ int result = s.ReadByte();
+ if (result < 0)
+ position = end;
+ else
+ position++;
+
+ return result;
+ }
+
+ public override long Seek(long d, SeekOrigin origin)
+ {
+ long real;
+ switch (origin)
+ {
+ case SeekOrigin.Begin:
+ real = offset + d;
+ break;
+ case SeekOrigin.End:
+ real = end + d;
+ break;
+ case SeekOrigin.Current:
+ real = position + d;
+ break;
+ default:
+ throw new ArgumentException();
+ }
+
+ long virt = real - offset;
+ if (virt < 0 || virt > Length)
+ throw new ArgumentException();
+
+ position = s.Seek(real, SeekOrigin.Begin);
+ return position;
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override bool CanRead
+ {
+ get { return true; }
+ }
+ public override bool CanSeek
+ {
+ get { return true; }
+ }
+ public override bool CanWrite
+ {
+ get { return false; }
+ }
+
+ public override long Length
+ {
+ get { return end - offset; }
+ }
+
+ public override long Position
+ {
+ get
+ {
+ return position - offset;
+ }
+ set
+ {
+ if (value > Length)
+ throw new ArgumentOutOfRangeException();
+
+ position = Seek(value, SeekOrigin.Begin);
+ }
+ }
+ }
+
+ internal HttpPostedFile(string name, string content_type, Stream base_stream, long offset, long length)
+ {
+ this.name = name;
+ this.content_type = content_type;
+ this.stream = new ReadSubStream(base_stream, offset, length);
+ }
+
+ public string ContentType
+ {
+ get
+ {
+ return (content_type);
+ }
+ }
+
+ public int ContentLength
+ {
+ get
+ {
+ return (int)stream.Length;
+ }
+ }
+
+ public string FileName
+ {
+ get
+ {
+ return (name);
+ }
+ }
+
+ public Stream InputStream
+ {
+ get
+ {
+ return (stream);
+ }
+ }
+
+ public void SaveAs(string filename)
+ {
+ byte[] buffer = new byte[16 * 1024];
+ long old_post = stream.Position;
+
+ try
+ {
+ File.Delete(filename);
+ using (FileStream fs = File.Create(filename))
+ {
+ stream.Position = 0;
+ int n;
+
+ while ((n = stream.Read(buffer, 0, 16 * 1024)) != 0)
+ {
+ fs.Write(buffer, 0, n);
+ }
+ }
+ }
+ finally
+ {
+ stream.Position = old_post;
+ }
+ }
+ }
+
+ class Helpers
+ {
+ public static readonly CultureInfo InvariantCulture = CultureInfo.InvariantCulture;
+ }
+
+ internal sealed class StrUtils
+ {
+ StrUtils() { }
+
+ public static bool StartsWith(string str1, string str2)
+ {
+ return StartsWith(str1, str2, false);
+ }
+
+ public static bool StartsWith(string str1, string str2, bool ignore_case)
+ {
+ int l2 = str2.Length;
+ if (l2 == 0)
+ return true;
+
+ int l1 = str1.Length;
+ if (l2 > l1)
+ return false;
+
+ return (0 == String.Compare(str1, 0, str2, 0, l2, ignore_case, Helpers.InvariantCulture));
+ }
+
+ public static bool EndsWith(string str1, string str2)
+ {
+ return EndsWith(str1, str2, false);
+ }
+
+ public static bool EndsWith(string str1, string str2, bool ignore_case)
+ {
+ int l2 = str2.Length;
+ if (l2 == 0)
+ return true;
+
+ int l1 = str1.Length;
+ if (l2 > l1)
+ return false;
+
+ return (0 == String.Compare(str1, l1 - l2, str2, 0, l2, ignore_case, Helpers.InvariantCulture));
+ }
+ }
+
+ class HttpMultipart
+ {
+
+ public class Element
+ {
+ public string ContentType;
+ public string Name;
+ public string Filename;
+ public Encoding Encoding;
+ public long Start;
+ public long Length;
+
+ public override string ToString()
+ {
+ return "ContentType " + ContentType + ", Name " + Name + ", Filename " + Filename + ", Start " +
+ Start.ToString() + ", Length " + Length.ToString();
+ }
+ }
+
+ Stream data;
+ string boundary;
+ byte[] boundary_bytes;
+ byte[] buffer;
+ bool at_eof;
+ Encoding encoding;
+ StringBuilder sb;
+
+ const byte HYPHEN = (byte)'-', LF = (byte)'\n', CR = (byte)'\r';
+
+ // See RFC 2046
+ // In the case of multipart entities, in which one or more different
+ // sets of data are combined in a single body, a "multipart" media type
+ // field must appear in the entity's header. The body must then contain
+ // one or more body parts, each preceded by a boundary delimiter line,
+ // and the last one followed by a closing boundary delimiter line.
+ // After its boundary delimiter line, each body part then consists of a
+ // header area, a blank line, and a body area. Thus a body part is
+ // similar to an RFC 822 message in syntax, but different in meaning.
+
+ public HttpMultipart(Stream data, string b, Encoding encoding)
+ {
+ this.data = data;
+ //DB: 30/01/11: cannot set or read the Position in HttpListener in Win.NET
+ //var ms = new MemoryStream(32 * 1024);
+ //data.CopyTo(ms);
+ //this.data = ms;
+
+ boundary = b;
+ boundary_bytes = encoding.GetBytes(b);
+ buffer = new byte[boundary_bytes.Length + 2]; // CRLF or '--'
+ this.encoding = encoding;
+ sb = new StringBuilder();
+ }
+
+ string ReadLine()
+ {
+ // CRLF or LF are ok as line endings.
+ bool got_cr = false;
+ int b = 0;
+ sb.Length = 0;
+ while (true)
+ {
+ b = data.ReadByte();
+ if (b == -1)
+ {
+ return null;
+ }
+
+ if (b == LF)
+ {
+ break;
+ }
+ got_cr = (b == CR);
+ sb.Append((char)b);
+ }
+
+ if (got_cr)
+ sb.Length--;
+
+ return sb.ToString();
+
+ }
+
+ static string GetContentDispositionAttribute(string l, string name)
+ {
+ int idx = l.IndexOf(name + "=\"");
+ if (idx < 0)
+ return null;
+ int begin = idx + name.Length + "=\"".Length;
+ int end = l.IndexOf('"', begin);
+ if (end < 0)
+ return null;
+ if (begin == end)
+ return "";
+ return l.Substring(begin, end - begin);
+ }
+
+ string GetContentDispositionAttributeWithEncoding(string l, string name)
+ {
+ int idx = l.IndexOf(name + "=\"");
+ if (idx < 0)
+ return null;
+ int begin = idx + name.Length + "=\"".Length;
+ int end = l.IndexOf('"', begin);
+ if (end < 0)
+ return null;
+ if (begin == end)
+ return "";
+
+ string temp = l.Substring(begin, end - begin);
+ byte[] source = new byte[temp.Length];
+ for (int i = temp.Length - 1; i >= 0; i--)
+ source[i] = (byte)temp[i];
+
+ return encoding.GetString(source);
+ }
+
+ bool ReadBoundary()
+ {
+ try
+ {
+ string line = ReadLine();
+ while (line == "")
+ line = ReadLine();
+ if (line[0] != '-' || line[1] != '-')
+ return false;
+
+ if (!StrUtils.EndsWith(line, boundary, false))
+ return true;
+ }
+ catch
+ {
+ }
+
+ return false;
+ }
+
+ string ReadHeaders()
+ {
+ string s = ReadLine();
+ if (s == "")
+ return null;
+
+ return s;
+ }
+
+ bool CompareBytes(byte[] orig, byte[] other)
+ {
+ for (int i = orig.Length - 1; i >= 0; i--)
+ if (orig[i] != other[i])
+ return false;
+
+ return true;
+ }
+
+ long MoveToNextBoundary()
+ {
+ long retval = 0;
+ bool got_cr = false;
+
+ int state = 0;
+ int c = data.ReadByte();
+ while (true)
+ {
+ if (c == -1)
+ return -1;
+
+ if (state == 0 && c == LF)
+ {
+ retval = data.Position - 1;
+ if (got_cr)
+ retval--;
+ state = 1;
+ c = data.ReadByte();
+ }
+ else if (state == 0)
+ {
+ got_cr = (c == CR);
+ c = data.ReadByte();
+ }
+ else if (state == 1 && c == '-')
+ {
+ c = data.ReadByte();
+ if (c == -1)
+ return -1;
+
+ if (c != '-')
+ {
+ state = 0;
+ got_cr = false;
+ continue; // no ReadByte() here
+ }
+
+ int nread = data.Read(buffer, 0, buffer.Length);
+ int bl = buffer.Length;
+ if (nread != bl)
+ return -1;
+
+ if (!CompareBytes(boundary_bytes, buffer))
+ {
+ state = 0;
+ data.Position = retval + 2;
+ if (got_cr)
+ {
+ data.Position++;
+ got_cr = false;
+ }
+ c = data.ReadByte();
+ continue;
+ }
+
+ if (buffer[bl - 2] == '-' && buffer[bl - 1] == '-')
+ {
+ at_eof = true;
+ }
+ else if (buffer[bl - 2] != CR || buffer[bl - 1] != LF)
+ {
+ state = 0;
+ data.Position = retval + 2;
+ if (got_cr)
+ {
+ data.Position++;
+ got_cr = false;
+ }
+ c = data.ReadByte();
+ continue;
+ }
+ data.Position = retval + 2;
+ if (got_cr)
+ data.Position++;
+ break;
+ }
+ else
+ {
+ // state == 1
+ state = 0; // no ReadByte() here
+ }
+ }
+
+ return retval;
+ }
+
+ public Element ReadNextElement()
+ {
+ if (at_eof || ReadBoundary())
+ return null;
+
+ Element elem = new Element();
+ string header;
+ while ((header = ReadHeaders()) != null)
+ {
+ if (StrUtils.StartsWith(header, "Content-Disposition:", true))
+ {
+ elem.Name = GetContentDispositionAttribute(header, "name");
+ elem.Filename = StripPath(GetContentDispositionAttributeWithEncoding(header, "filename"));
+ }
+ else if (StrUtils.StartsWith(header, "Content-Type:", true))
+ {
+ elem.ContentType = header.Substring("Content-Type:".Length).Trim();
+ elem.Encoding = GetEncoding(elem.ContentType);
+ }
+ }
+
+ long start = 0;
+ start = data.Position;
+ elem.Start = start;
+ long pos = MoveToNextBoundary();
+ if (pos == -1)
+ return null;
+
+ elem.Length = pos - start;
+ return elem;
+ }
+
+ static string StripPath(string path)
+ {
+ if (path == null || path.Length == 0)
+ return path;
+
+ if (path.IndexOf(":\\") != 1 && !path.StartsWith("\\\\"))
+ return path;
+ return path.Substring(path.LastIndexOf('\\') + 1);
+ }
+ }
+
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs
new file mode 100644
index 000000000..7ff3a1247
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs
@@ -0,0 +1,165 @@
+using System.Text;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using WebSocketMessageType = MediaBrowser.Model.Net.WebSocketMessageType;
+using WebSocketState = MediaBrowser.Model.Net.WebSocketState;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
+{
+ public class SharpWebSocket : IWebSocket
+ {
+ /// <summary>
+ /// The logger
+ /// </summary>
+ private readonly ILogger _logger;
+
+ public event EventHandler<EventArgs> Closed;
+
+ /// <summary>
+ /// Gets or sets the web socket.
+ /// </summary>
+ /// <value>The web socket.</value>
+ private WebSocketSharp.WebSocket WebSocket { get; set; }
+
+ private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="NativeWebSocket" /> class.
+ /// </summary>
+ /// <param name="socket">The socket.</param>
+ /// <param name="logger">The logger.</param>
+ /// <exception cref="System.ArgumentNullException">socket</exception>
+ public SharpWebSocket(WebSocketSharp.WebSocket socket, ILogger logger)
+ {
+ if (socket == null)
+ {
+ throw new ArgumentNullException("socket");
+ }
+
+ if (logger == null)
+ {
+ throw new ArgumentNullException("logger");
+ }
+
+ _logger = logger;
+ WebSocket = socket;
+
+ socket.OnMessage += socket_OnMessage;
+ socket.OnClose += socket_OnClose;
+ socket.OnError += socket_OnError;
+
+ WebSocket.ConnectAsServer();
+ }
+
+ void socket_OnError(object sender, WebSocketSharp.ErrorEventArgs e)
+ {
+ EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger);
+ }
+
+ void socket_OnClose(object sender, WebSocketSharp.CloseEventArgs e)
+ {
+ EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger);
+ }
+
+ void socket_OnMessage(object sender, WebSocketSharp.MessageEventArgs e)
+ {
+ if (OnReceive != null)
+ {
+ OnReceiveBytes(e.RawData);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the state.
+ /// </summary>
+ /// <value>The state.</value>
+ public WebSocketState State
+ {
+ get
+ {
+ WebSocketState commonState;
+
+ if (!Enum.TryParse(WebSocket.ReadyState.ToString(), true, out commonState))
+ {
+ _logger.Warn("Unrecognized WebSocketState: {0}", WebSocket.ReadyState.ToString());
+ }
+
+ return commonState;
+ }
+ }
+
+ /// <summary>
+ /// Sends the async.
+ /// </summary>
+ /// <param name="bytes">The bytes.</param>
+ /// <param name="endOfMessage">if set to <c>true</c> [end of message].</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ public Task SendAsync(byte[] bytes, bool endOfMessage, CancellationToken cancellationToken)
+ {
+ var completionSource = new TaskCompletionSource<bool>();
+
+ WebSocket.SendAsync(bytes, res => completionSource.TrySetResult(true));
+
+ return completionSource.Task;
+ }
+
+ /// <summary>
+ /// Sends the asynchronous.
+ /// </summary>
+ /// <param name="text">The text.</param>
+ /// <param name="endOfMessage">if set to <c>true</c> [end of message].</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ public Task SendAsync(string text, bool endOfMessage, CancellationToken cancellationToken)
+ {
+ var completionSource = new TaskCompletionSource<bool>();
+
+ WebSocket.SendAsync(text, res => completionSource.TrySetResult(true));
+
+ return completionSource.Task;
+ }
+
+ /// <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)
+ {
+ WebSocket.OnMessage -= socket_OnMessage;
+ WebSocket.OnClose -= socket_OnClose;
+ WebSocket.OnError -= socket_OnError;
+
+ _cancellationTokenSource.Cancel();
+
+ WebSocket.Close();
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the receive action.
+ /// </summary>
+ /// <value>The receive action.</value>
+ public Action<byte[]> OnReceiveBytes { get; set; }
+
+ /// <summary>
+ /// Gets or sets the on receive.
+ /// </summary>
+ /// <value>The on receive.</value>
+ public Action<string> OnReceive { get; set; }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
new file mode 100644
index 000000000..477aa3878
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
@@ -0,0 +1,278 @@
+using MediaBrowser.Common.Net;
+using MediaBrowser.Model.Logging;
+using ServiceStack;
+using ServiceStack.Web;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using WebSocketSharp.Net;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
+{
+ public class WebSocketSharpListener : IHttpListener
+ {
+ private readonly ConcurrentDictionary<string, string> _localEndPoints = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ private WebSocketSharp.Net.HttpListener _listener;
+ private readonly AutoResetEvent _listenForNextRequest = new AutoResetEvent(false);
+
+ private readonly ILogger _logger;
+
+ public WebSocketSharpListener(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ public IEnumerable<string> LocalEndPoints
+ {
+ get { return _localEndPoints.Keys.ToList(); }
+ }
+
+ public Action<Exception, IRequest> ErrorHandler { get; set; }
+
+ public Func<IHttpRequest, Uri, Task> RequestHandler { get; set; }
+
+ public Action<WebSocketConnectEventArgs> WebSocketHandler { get; set; }
+
+ public void Start(IEnumerable<string> urlPrefixes)
+ {
+ if (_listener == null)
+ _listener = new WebSocketSharp.Net.HttpListener();
+
+ foreach (var prefix in urlPrefixes)
+ {
+ _logger.Info("Adding HttpListener prefix " + prefix);
+ _listener.Prefixes.Add(prefix);
+ }
+
+ _listener.Start();
+
+ Task.Factory.StartNew(Listen, TaskCreationOptions.LongRunning);
+ }
+
+ private bool IsListening
+ {
+ get { return _listener != null && _listener.IsListening; }
+ }
+
+ // Loop here to begin processing of new requests.
+ private void Listen()
+ {
+ while (IsListening)
+ {
+ if (_listener == null) return;
+
+ try
+ {
+ _listener.BeginGetContext(ListenerCallback, _listener);
+ _listenForNextRequest.WaitOne();
+ }
+ catch (Exception ex)
+ {
+ _logger.Error("Listen()", ex);
+ return;
+ }
+ if (_listener == null) return;
+ }
+ }
+
+ // Handle the processing of a request in here.
+ private void ListenerCallback(IAsyncResult asyncResult)
+ {
+ var listener = asyncResult.AsyncState as HttpListener;
+ HttpListenerContext context;
+
+ if (listener == null) return;
+ var isListening = listener.IsListening;
+
+ try
+ {
+ if (!isListening)
+ {
+ _logger.Debug("Ignoring ListenerCallback() as HttpListener is no longer listening"); return;
+ }
+ // The EndGetContext() method, as with all Begin/End asynchronous methods in the .NET Framework,
+ // blocks until there is a request to be processed or some type of data is available.
+ context = listener.EndGetContext(asyncResult);
+ }
+ catch (Exception ex)
+ {
+ // You will get an exception when httpListener.Stop() is called
+ // because there will be a thread stopped waiting on the .EndGetContext()
+ // method, and again, that is just the way most Begin/End asynchronous
+ // methods of the .NET Framework work.
+ var errMsg = ex + ": " + IsListening;
+ _logger.Warn(errMsg);
+ return;
+ }
+ finally
+ {
+ // Once we know we have a request (or exception), we signal the other thread
+ // so that it calls the BeginGetContext() (or possibly exits if we're not
+ // listening any more) method to start handling the next incoming request
+ // while we continue to process this request on a different thread.
+ _listenForNextRequest.Set();
+ }
+
+ Task.Factory.StartNew(() => InitTask(context));
+ }
+
+ private void InitTask(HttpListenerContext context)
+ {
+ try
+ {
+ var task = this.ProcessRequestAsync(context);
+ task.ContinueWith(x => HandleError(x.Exception, context), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent);
+
+ if (task.Status == TaskStatus.Created)
+ {
+ task.RunSynchronously();
+ }
+ }
+ catch (Exception ex)
+ {
+ HandleError(ex, context);
+ }
+ }
+
+ private Task ProcessRequestAsync(HttpListenerContext context)
+ {
+ var request = context.Request;
+
+ LogHttpRequest(request);
+
+ if (request.IsWebSocketRequest)
+ {
+ ProcessWebSocketRequest(context);
+ return Task.FromResult(true);
+ }
+
+ if (string.IsNullOrEmpty(context.Request.RawUrl))
+ return ((object)null).AsTaskResult();
+
+ var httpReq = GetRequest(context);
+
+ return RequestHandler(httpReq, request.Url);
+ }
+
+ /// <summary>
+ /// Logs the HTTP request.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ private void LogHttpRequest(HttpListenerRequest request)
+ {
+ var endpoint = request.LocalEndPoint;
+
+ if (endpoint != null)
+ {
+ var address = endpoint.ToString();
+
+ _localEndPoints.GetOrAdd(address, address);
+ }
+
+ LogRequest(_logger, request);
+ }
+
+ private void ProcessWebSocketRequest(HttpListenerContext ctx)
+ {
+ try
+ {
+ var webSocketContext = ctx.AcceptWebSocket(null);
+
+ if (WebSocketHandler != null)
+ {
+ WebSocketHandler(new WebSocketConnectEventArgs
+ {
+ WebSocket = new SharpWebSocket(webSocketContext.WebSocket, _logger),
+ Endpoint = ctx.Request.RemoteEndPoint.ToString()
+ });
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("AcceptWebSocketAsync error", ex);
+ ctx.Response.StatusCode = 500;
+ ctx.Response.Close();
+ }
+ }
+
+ private IHttpRequest GetRequest(HttpListenerContext httpContext)
+ {
+ var operationName = httpContext.Request.GetOperationName();
+
+ var req = new WebSocketSharpRequest(httpContext, operationName, RequestAttributes.None, _logger);
+ req.RequestAttributes = req.GetAttributes();
+
+ return req;
+ }
+
+ /// <summary>
+ /// Logs the request.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ /// <param name="request">The request.</param>
+ private static void LogRequest(ILogger logger, HttpListenerRequest request)
+ {
+ var log = new StringBuilder();
+
+ //var headers = string.Join(",", request.Headers.AllKeys.Where(i => !string.Equals(i, "cookie", StringComparison.OrdinalIgnoreCase) && !string.Equals(i, "Referer", StringComparison.OrdinalIgnoreCase)).Select(k => k + "=" + request.Headers[k]));
+
+ //log.AppendLine("Ip: " + request.RemoteEndPoint + ". Headers: " + headers);
+
+ var type = request.IsWebSocketRequest ? "Web Socket" : "HTTP " + request.HttpMethod;
+
+ logger.LogMultiline(type + " " + request.Url, LogSeverity.Debug, log);
+ }
+
+ private void HandleError(Exception ex, HttpListenerContext context)
+ {
+ var httpReq = GetRequest(context);
+
+ if (ErrorHandler != null)
+ {
+ ErrorHandler(ex, httpReq);
+ }
+ }
+
+ public void Stop()
+ {
+ if (_listener != null)
+ {
+ foreach (var prefix in _listener.Prefixes.ToList())
+ {
+ _listener.Prefixes.Remove(prefix);
+ }
+
+ _listener.Close();
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ private bool _disposed;
+ private readonly object _disposeLock = new object();
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed) return;
+
+ lock (_disposeLock)
+ {
+ if (_disposed) return;
+
+ if (disposing)
+ {
+ Stop();
+ }
+
+ //release unmanaged resources here...
+ _disposed = true;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
new file mode 100644
index 000000000..7a5f6fbdc
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpRequest.cs
@@ -0,0 +1,402 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using Funq;
+using MediaBrowser.Model.Logging;
+using ServiceStack;
+using ServiceStack.Host;
+using ServiceStack.Web;
+using WebSocketSharp.Net;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
+{
+ public partial class WebSocketSharpRequest : IHttpRequest
+ {
+ public Container Container { get; set; }
+ private readonly HttpListenerRequest request;
+ private readonly IHttpResponse response;
+
+ public WebSocketSharpRequest(HttpListenerContext httpContext, string operationName, RequestAttributes requestAttributes, ILogger logger)
+ {
+ this.OperationName = operationName;
+ this.RequestAttributes = requestAttributes;
+ this.request = httpContext.Request;
+ this.response = new WebSocketSharpResponse(logger, httpContext.Response);
+
+ this.RequestPreferences = new RequestPreferences(this);
+ }
+
+ public HttpListenerRequest HttpRequest
+ {
+ get { return request; }
+ }
+
+ public object OriginalRequest
+ {
+ get { return request; }
+ }
+
+ public IResponse Response
+ {
+ get { return response; }
+ }
+
+ public IHttpResponse HttpResponse
+ {
+ get { return response; }
+ }
+
+ public RequestAttributes RequestAttributes { get; set; }
+
+ public IRequestPreferences RequestPreferences { get; private set; }
+
+ public T TryResolve<T>()
+ {
+ if (typeof(T) == typeof(IHttpRequest))
+ throw new Exception("You don't need to use IHttpRequest.TryResolve<IHttpRequest> to resolve itself");
+
+ if (typeof(T) == typeof(IHttpResponse))
+ throw new Exception("Resolve IHttpResponse with 'Response' property instead of IHttpRequest.TryResolve<IHttpResponse>");
+
+ return Container == null
+ ? HostContext.TryResolve<T>()
+ : Container.TryResolve<T>();
+ }
+
+ public string OperationName { get; set; }
+
+ public object Dto { get; set; }
+
+ public string GetRawBody()
+ {
+ if (bufferedStream != null)
+ {
+ return bufferedStream.ToArray().FromUtf8Bytes();
+ }
+
+ using (var reader = new StreamReader(InputStream))
+ {
+ return reader.ReadToEnd();
+ }
+ }
+
+ public string RawUrl
+ {
+ get { return request.RawUrl; }
+ }
+
+ public string AbsoluteUri
+ {
+ get { return request.Url.AbsoluteUri.TrimEnd('/'); }
+ }
+
+ public string UserHostAddress
+ {
+ get { return request.UserHostAddress; }
+ }
+
+ public string XForwardedFor
+ {
+ get
+ {
+ return String.IsNullOrEmpty(request.Headers[HttpHeaders.XForwardedFor]) ? null : request.Headers[HttpHeaders.XForwardedFor];
+ }
+ }
+
+ public int? XForwardedPort
+ {
+ get
+ {
+ return string.IsNullOrEmpty(request.Headers[HttpHeaders.XForwardedPort]) ? (int?)null : int.Parse(request.Headers[HttpHeaders.XForwardedPort]);
+ }
+ }
+
+ public string XForwardedProtocol
+ {
+ get
+ {
+ return string.IsNullOrEmpty(request.Headers[HttpHeaders.XForwardedProtocol]) ? null : request.Headers[HttpHeaders.XForwardedProtocol];
+ }
+ }
+
+ public string XRealIp
+ {
+ get
+ {
+ return String.IsNullOrEmpty(request.Headers[HttpHeaders.XRealIp]) ? null : request.Headers[HttpHeaders.XRealIp];
+ }
+ }
+
+ private string remoteIp;
+ public string RemoteIp
+ {
+ get
+ {
+ return remoteIp ??
+ (remoteIp = XForwardedFor ??
+ (XRealIp ??
+ ((request.RemoteEndPoint != null) ? request.RemoteEndPoint.Address.ToString() : null)));
+ }
+ }
+
+ public bool IsSecureConnection
+ {
+ get { return request.IsSecureConnection || XForwardedProtocol == "https"; }
+ }
+
+ public string[] AcceptTypes
+ {
+ get { return request.AcceptTypes; }
+ }
+
+ private Dictionary<string, object> items;
+ public Dictionary<string, object> Items
+ {
+ get { return items ?? (items = new Dictionary<string, object>()); }
+ }
+
+ private string responseContentType;
+ public string ResponseContentType
+ {
+ get
+ {
+ return responseContentType
+ ?? (responseContentType = this.GetResponseContentType());
+ }
+ set
+ {
+ this.responseContentType = value;
+ HasExplicitResponseContentType = true;
+ }
+ }
+
+ public bool HasExplicitResponseContentType { get; private set; }
+
+ private string pathInfo;
+ public string PathInfo
+ {
+ get
+ {
+ if (this.pathInfo == null)
+ {
+ var mode = HostContext.Config.HandlerFactoryPath;
+
+ var pos = request.RawUrl.IndexOf("?");
+ if (pos != -1)
+ {
+ var path = request.RawUrl.Substring(0, pos);
+ this.pathInfo = HttpRequestExtensions.GetPathInfo(
+ path,
+ mode,
+ mode ?? "");
+ }
+ else
+ {
+ this.pathInfo = request.RawUrl;
+ }
+
+ this.pathInfo = this.pathInfo.UrlDecode();
+ this.pathInfo = NormalizePathInfo(pathInfo, mode);
+ }
+ return this.pathInfo;
+ }
+ }
+
+ private Dictionary<string, System.Net.Cookie> cookies;
+ public IDictionary<string, System.Net.Cookie> Cookies
+ {
+ get
+ {
+ if (cookies == null)
+ {
+ cookies = new Dictionary<string, System.Net.Cookie>();
+ for (var i = 0; i < this.request.Cookies.Count; i++)
+ {
+ var httpCookie = this.request.Cookies[i];
+ cookies[httpCookie.Name] = new System.Net.Cookie(httpCookie.Name, httpCookie.Value, httpCookie.Path, httpCookie.Domain);
+ }
+ }
+
+ return cookies;
+ }
+ }
+
+ public string UserAgent
+ {
+ get { return request.UserAgent; }
+ }
+
+ private NameValueCollectionWrapper headers;
+ public INameValueCollection Headers
+ {
+ get { return headers ?? (headers = new NameValueCollectionWrapper(request.Headers)); }
+ }
+
+ private NameValueCollectionWrapper queryString;
+ public INameValueCollection QueryString
+ {
+ get { return queryString ?? (queryString = new NameValueCollectionWrapper(HttpUtility.ParseQueryString(request.Url.Query))); }
+ }
+
+ private NameValueCollectionWrapper formData;
+ public INameValueCollection FormData
+ {
+ get { return formData ?? (formData = new NameValueCollectionWrapper(this.Form)); }
+ }
+
+ public bool IsLocal
+ {
+ get { return request.IsLocal; }
+ }
+
+ private string httpMethod;
+ public string HttpMethod
+ {
+ get
+ {
+ return httpMethod
+ ?? (httpMethod = Param(HttpHeaders.XHttpMethodOverride)
+ ?? request.HttpMethod);
+ }
+ }
+
+ public string Verb
+ {
+ get { return HttpMethod; }
+ }
+
+ public string Param(string name)
+ {
+ return Headers[name]
+ ?? QueryString[name]
+ ?? FormData[name];
+ }
+
+ public string ContentType
+ {
+ get { return request.ContentType; }
+ }
+
+ public Encoding contentEncoding;
+ public Encoding ContentEncoding
+ {
+ get { return contentEncoding ?? request.ContentEncoding; }
+ set { contentEncoding = value; }
+ }
+
+ public Uri UrlReferrer
+ {
+ get { return request.UrlReferrer; }
+ }
+
+ public static Encoding GetEncoding(string contentTypeHeader)
+ {
+ var param = GetParameter(contentTypeHeader, "charset=");
+ if (param == null) return null;
+ try
+ {
+ return Encoding.GetEncoding(param);
+ }
+ catch (ArgumentException)
+ {
+ return null;
+ }
+ }
+
+ public bool UseBufferedStream
+ {
+ get { return bufferedStream != null; }
+ set
+ {
+ bufferedStream = value
+ ? bufferedStream ?? new MemoryStream(request.InputStream.ReadFully())
+ : null;
+ }
+ }
+
+ private MemoryStream bufferedStream;
+ public Stream InputStream
+ {
+ get { return bufferedStream ?? request.InputStream; }
+ }
+
+ public long ContentLength
+ {
+ get { return request.ContentLength64; }
+ }
+
+ private IHttpFile[] httpFiles;
+ public IHttpFile[] Files
+ {
+ get
+ {
+ if (httpFiles == null)
+ {
+ if (files == null)
+ return httpFiles = new IHttpFile[0];
+
+ httpFiles = new IHttpFile[files.Count];
+ for (var i = 0; i < files.Count; i++)
+ {
+ var reqFile = files[i];
+
+ httpFiles[i] = new HttpFile
+ {
+ ContentType = reqFile.ContentType,
+ ContentLength = reqFile.ContentLength,
+ FileName = reqFile.FileName,
+ InputStream = reqFile.InputStream,
+ };
+ }
+ }
+ return httpFiles;
+ }
+ }
+
+ static Stream GetSubStream(Stream stream)
+ {
+ if (stream is MemoryStream)
+ {
+ var other = (MemoryStream)stream;
+ try
+ {
+ return new MemoryStream(other.GetBuffer(), 0, (int)other.Length, false, true);
+ }
+ catch (UnauthorizedAccessException)
+ {
+ return new MemoryStream(other.ToArray(), 0, (int)other.Length, false, true);
+ }
+ }
+
+ return stream;
+ }
+
+ static void EndSubStream(Stream stream)
+ {
+ }
+
+ public static string GetHandlerPathIfAny(string listenerUrl)
+ {
+ if (listenerUrl == null) return null;
+ var pos = listenerUrl.IndexOf("://", StringComparison.InvariantCultureIgnoreCase);
+ if (pos == -1) return null;
+ var startHostUrl = listenerUrl.Substring(pos + "://".Length);
+ var endPos = startHostUrl.IndexOf('/');
+ if (endPos == -1) return null;
+ var endHostUrl = startHostUrl.Substring(endPos + 1);
+ return String.IsNullOrEmpty(endHostUrl) ? null : endHostUrl.TrimEnd('/');
+ }
+
+ public static string NormalizePathInfo(string pathInfo, string handlerPath)
+ {
+ if (handlerPath != null && pathInfo.TrimStart('/').StartsWith(
+ handlerPath, StringComparison.InvariantCultureIgnoreCase))
+ {
+ return pathInfo.TrimStart('/').Substring(handlerPath.Length);
+ }
+
+ return pathInfo;
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs
new file mode 100644
index 000000000..2e3828512
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpResponse.cs
@@ -0,0 +1,144 @@
+using System;
+using System.IO;
+using System.Net;
+using MediaBrowser.Model.Logging;
+using ServiceStack;
+using ServiceStack.Host;
+using ServiceStack.Web;
+using HttpListenerResponse = WebSocketSharp.Net.HttpListenerResponse;
+
+namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
+{
+ public class WebSocketSharpResponse : IHttpResponse
+ {
+ private readonly ILogger _logger;
+ private readonly HttpListenerResponse response;
+
+ public WebSocketSharpResponse(ILogger logger, HttpListenerResponse response)
+ {
+ _logger = logger;
+ this.response = response;
+ }
+
+ public bool UseBufferedStream { get; set; }
+
+ public object OriginalResponse
+ {
+ get { return response; }
+ }
+
+ public int StatusCode
+ {
+ get { return this.response.StatusCode; }
+ set { this.response.StatusCode = value; }
+ }
+
+ public string StatusDescription
+ {
+ get { return this.response.StatusDescription; }
+ set { this.response.StatusDescription = value; }
+ }
+
+ public string ContentType
+ {
+ get { return response.ContentType; }
+ set { response.ContentType = value; }
+ }
+
+ public ICookies Cookies { get; set; }
+
+ public void AddHeader(string name, string value)
+ {
+ if (string.Equals(name, "Content-Type", StringComparison.OrdinalIgnoreCase))
+ {
+ ContentType = value;
+ return;
+ }
+
+ response.AddHeader(name, value);
+ }
+
+ public void Redirect(string url)
+ {
+ response.Redirect(url);
+ }
+
+ public Stream OutputStream
+ {
+ get { return response.OutputStream; }
+ }
+
+ public object Dto { get; set; }
+
+ public void Write(string text)
+ {
+ try
+ {
+ var bOutput = System.Text.Encoding.UTF8.GetBytes(text);
+ response.ContentLength64 = bOutput.Length;
+
+ var outputStream = response.OutputStream;
+ outputStream.Write(bOutput, 0, bOutput.Length);
+ Close();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Could not WriteTextToResponse: " + ex.Message, ex);
+ throw;
+ }
+ }
+
+ public void Close()
+ {
+ if (!this.IsClosed)
+ {
+ this.IsClosed = true;
+
+ try
+ {
+ this.response.CloseOutputStream(_logger);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error closing HttpListener output stream", ex);
+ }
+ }
+ }
+
+ public void End()
+ {
+ Close();
+ }
+
+ public void Flush()
+ {
+ response.OutputStream.Flush();
+ }
+
+ public bool IsClosed
+ {
+ get;
+ private set;
+ }
+
+ public void SetContentLength(long contentLength)
+ {
+ //you can happily set the Content-Length header in Asp.Net
+ //but HttpListener will complain if you do - you have to set ContentLength64 on the response.
+ //workaround: HttpListener throws "The parameter is incorrect" exceptions when we try to set the Content-Length header
+ response.ContentLength64 = contentLength;
+ }
+
+ public void SetCookie(Cookie cookie)
+ {
+ var cookieStr = cookie.AsHeaderValue();
+ response.Headers.Add(HttpHeaders.SetCookie, cookieStr);
+ }
+
+ public bool SendChunked
+ {
+ get { return response.SendChunked; }
+ set { response.SendChunked = value; }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs b/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs
index a8774f1b7..28fc094f7 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/StreamWriter.cs
@@ -36,6 +36,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer
get { return _options; }
}
+ public bool Throttle { get; set; }
+ public long ThrottleLimit { get; set; }
+ public long MinThrottlePosition;
+
/// <summary>
/// Initializes a new instance of the <see cref="StreamWriter" /> class.
/// </summary>
@@ -77,6 +81,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="responseStream">The response stream.</param>
public void WriteTo(Stream responseStream)
{
+ if (Throttle)
+ {
+ responseStream = new ThrottledStream(responseStream, ThrottleLimit)
+ {
+ MinThrottlePosition = MinThrottlePosition
+ };
+ }
var task = WriteToAsync(responseStream);
Task.WaitAll(task);
@@ -98,7 +109,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
}
catch (Exception ex)
{
- Logger.ErrorException("Error streaming media", ex);
+ Logger.ErrorException("Error streaming data", ex);
throw;
}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/ThrottledStream.cs b/MediaBrowser.Server.Implementations/HttpServer/ThrottledStream.cs
new file mode 100644
index 000000000..067e53571
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/ThrottledStream.cs
@@ -0,0 +1,389 @@
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.HttpServer
+{
+ /// <summary>
+ /// Class for streaming data with throttling support.
+ /// </summary>
+ public class ThrottledStream : Stream
+ {
+ /// <summary>
+ /// A constant used to specify an infinite number of bytes that can be transferred per second.
+ /// </summary>
+ public const long Infinite = 0;
+
+ #region Private members
+ /// <summary>
+ /// The base stream.
+ /// </summary>
+ private readonly Stream _baseStream;
+
+ /// <summary>
+ /// The maximum bytes per second that can be transferred through the base stream.
+ /// </summary>
+ private long _maximumBytesPerSecond;
+
+ /// <summary>
+ /// The number of bytes that has been transferred since the last throttle.
+ /// </summary>
+ private long _byteCount;
+
+ /// <summary>
+ /// The start time in milliseconds of the last throttle.
+ /// </summary>
+ private long _start;
+ #endregion
+
+ #region Properties
+ /// <summary>
+ /// Gets the current milliseconds.
+ /// </summary>
+ /// <value>The current milliseconds.</value>
+ protected long CurrentMilliseconds
+ {
+ get
+ {
+ return Environment.TickCount;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the maximum bytes per second that can be transferred through the base stream.
+ /// </summary>
+ /// <value>The maximum bytes per second.</value>
+ public long MaximumBytesPerSecond
+ {
+ get
+ {
+ return _maximumBytesPerSecond;
+ }
+ set
+ {
+ if (MaximumBytesPerSecond != value)
+ {
+ _maximumBytesPerSecond = value;
+ Reset();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the current stream supports reading.
+ /// </summary>
+ /// <returns>true if the stream supports reading; otherwise, false.</returns>
+ public override bool CanRead
+ {
+ get
+ {
+ return _baseStream.CanRead;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the current stream supports seeking.
+ /// </summary>
+ /// <value></value>
+ /// <returns>true if the stream supports seeking; otherwise, false.</returns>
+ public override bool CanSeek
+ {
+ get
+ {
+ return _baseStream.CanSeek;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the current stream supports writing.
+ /// </summary>
+ /// <value></value>
+ /// <returns>true if the stream supports writing; otherwise, false.</returns>
+ public override bool CanWrite
+ {
+ get
+ {
+ return _baseStream.CanWrite;
+ }
+ }
+
+ /// <summary>
+ /// Gets the length in bytes of the stream.
+ /// </summary>
+ /// <value></value>
+ /// <returns>A long value representing the length of the stream in bytes.</returns>
+ /// <exception cref="T:System.NotSupportedException">The base stream does not support seeking. </exception>
+ /// <exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception>
+ public override long Length
+ {
+ get
+ {
+ return _baseStream.Length;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the position within the current stream.
+ /// </summary>
+ /// <value></value>
+ /// <returns>The current position within the stream.</returns>
+ /// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
+ /// <exception cref="T:System.NotSupportedException">The base stream does not support seeking. </exception>
+ /// <exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception>
+ public override long Position
+ {
+ get
+ {
+ return _baseStream.Position;
+ }
+ set
+ {
+ _baseStream.Position = value;
+ }
+ }
+ #endregion
+
+ public long MinThrottlePosition;
+
+ #region Ctor
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:ThrottledStream"/> class.
+ /// </summary>
+ /// <param name="baseStream">The base stream.</param>
+ /// <param name="maximumBytesPerSecond">The maximum bytes per second that can be transferred through the base stream.</param>
+ /// <exception cref="ArgumentNullException">Thrown when <see cref="baseStream"/> is a null reference.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">Thrown when <see cref="maximumBytesPerSecond"/> is a negative value.</exception>
+ public ThrottledStream(Stream baseStream, long maximumBytesPerSecond)
+ {
+ if (baseStream == null)
+ {
+ throw new ArgumentNullException("baseStream");
+ }
+
+ if (maximumBytesPerSecond < 0)
+ {
+ throw new ArgumentOutOfRangeException("maximumBytesPerSecond",
+ maximumBytesPerSecond, "The maximum number of bytes per second can't be negative.");
+ }
+
+ _baseStream = baseStream;
+ _maximumBytesPerSecond = maximumBytesPerSecond;
+ _start = CurrentMilliseconds;
+ _byteCount = 0;
+ }
+ #endregion
+
+ #region Public methods
+ /// <summary>
+ /// Clears all buffers for this stream and causes any buffered data to be written to the underlying device.
+ /// </summary>
+ /// <exception cref="T:System.IO.IOException">An I/O error occurs.</exception>
+ public override void Flush()
+ {
+ _baseStream.Flush();
+ }
+
+ /// <summary>
+ /// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
+ /// </summary>
+ /// <param name="buffer">An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source.</param>
+ /// <param name="offset">The zero-based byte offset in buffer at which to begin storing the data read from the current stream.</param>
+ /// <param name="count">The maximum number of bytes to be read from the current stream.</param>
+ /// <returns>
+ /// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.
+ /// </returns>
+ /// <exception cref="T:System.ArgumentException">The sum of offset and count is larger than the buffer length. </exception>
+ /// <exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception>
+ /// <exception cref="T:System.NotSupportedException">The base stream does not support reading. </exception>
+ /// <exception cref="T:System.ArgumentNullException">buffer is null. </exception>
+ /// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">offset or count is negative. </exception>
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ Throttle(count);
+
+ return _baseStream.Read(buffer, offset, count);
+ }
+
+ /// <summary>
+ /// Sets the position within the current stream.
+ /// </summary>
+ /// <param name="offset">A byte offset relative to the origin parameter.</param>
+ /// <param name="origin">A value of type <see cref="T:System.IO.SeekOrigin"></see> indicating the reference point used to obtain the new position.</param>
+ /// <returns>
+ /// The new position within the current stream.
+ /// </returns>
+ /// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
+ /// <exception cref="T:System.NotSupportedException">The base stream does not support seeking, such as if the stream is constructed from a pipe or console output. </exception>
+ /// <exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception>
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ return _baseStream.Seek(offset, origin);
+ }
+
+ /// <summary>
+ /// Sets the length of the current stream.
+ /// </summary>
+ /// <param name="value">The desired length of the current stream in bytes.</param>
+ /// <exception cref="T:System.NotSupportedException">The base stream does not support both writing and seeking, such as if the stream is constructed from a pipe or console output. </exception>
+ /// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
+ /// <exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception>
+ public override void SetLength(long value)
+ {
+ _baseStream.SetLength(value);
+ }
+
+ private long _bytesWritten;
+
+ /// <summary>
+ /// Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
+ /// </summary>
+ /// <param name="buffer">An array of bytes. This method copies count bytes from buffer to the current stream.</param>
+ /// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param>
+ /// <param name="count">The number of bytes to be written to the current stream.</param>
+ /// <exception cref="T:System.IO.IOException">An I/O error occurs. </exception>
+ /// <exception cref="T:System.NotSupportedException">The base stream does not support writing. </exception>
+ /// <exception cref="T:System.ObjectDisposedException">Methods were called after the stream was closed. </exception>
+ /// <exception cref="T:System.ArgumentNullException">buffer is null. </exception>
+ /// <exception cref="T:System.ArgumentException">The sum of offset and count is greater than the buffer length. </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">offset or count is negative. </exception>
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ Throttle(count);
+
+ _baseStream.Write(buffer, offset, count);
+
+ _bytesWritten += count;
+ }
+
+ public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ await ThrottleAsync(count, cancellationToken).ConfigureAwait(false);
+
+ await _baseStream.WriteAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
+
+ _bytesWritten += count;
+ }
+
+ /// <summary>
+ /// Returns a <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
+ /// </summary>
+ /// <returns>
+ /// A <see cref="T:System.String"></see> that represents the current <see cref="T:System.Object"></see>.
+ /// </returns>
+ public override string ToString()
+ {
+ return _baseStream.ToString();
+ }
+ #endregion
+
+ #region Protected methods
+ /// <summary>
+ /// Throttles for the specified buffer size in bytes.
+ /// </summary>
+ /// <param name="bufferSizeInBytes">The buffer size in bytes.</param>
+ protected void Throttle(int bufferSizeInBytes)
+ {
+ if (_bytesWritten < MinThrottlePosition)
+ {
+ return;
+ }
+
+ // Make sure the buffer isn't empty.
+ if (_maximumBytesPerSecond <= 0 || bufferSizeInBytes <= 0)
+ {
+ return;
+ }
+
+ _byteCount += bufferSizeInBytes;
+ long elapsedMilliseconds = CurrentMilliseconds - _start;
+
+ if (elapsedMilliseconds > 0)
+ {
+ // Calculate the current bps.
+ long bps = _byteCount * 1000L / elapsedMilliseconds;
+
+ // If the bps are more then the maximum bps, try to throttle.
+ if (bps > _maximumBytesPerSecond)
+ {
+ // Calculate the time to sleep.
+ long wakeElapsed = _byteCount * 1000L / _maximumBytesPerSecond;
+ int toSleep = (int)(wakeElapsed - elapsedMilliseconds);
+
+ if (toSleep > 1)
+ {
+ try
+ {
+ // The time to sleep is more then a millisecond, so sleep.
+ Thread.Sleep(toSleep);
+ }
+ catch (ThreadAbortException)
+ {
+ // Eatup ThreadAbortException.
+ }
+
+ // A sleep has been done, reset.
+ Reset();
+ }
+ }
+ }
+ }
+
+ protected async Task ThrottleAsync(int bufferSizeInBytes, CancellationToken cancellationToken)
+ {
+ if (_bytesWritten < MinThrottlePosition)
+ {
+ return;
+ }
+
+ // Make sure the buffer isn't empty.
+ if (_maximumBytesPerSecond <= 0 || bufferSizeInBytes <= 0)
+ {
+ return;
+ }
+
+ _byteCount += bufferSizeInBytes;
+ long elapsedMilliseconds = CurrentMilliseconds - _start;
+
+ if (elapsedMilliseconds > 0)
+ {
+ // Calculate the current bps.
+ long bps = _byteCount * 1000L / elapsedMilliseconds;
+
+ // If the bps are more then the maximum bps, try to throttle.
+ if (bps > _maximumBytesPerSecond)
+ {
+ // Calculate the time to sleep.
+ long wakeElapsed = _byteCount * 1000L / _maximumBytesPerSecond;
+ int toSleep = (int)(wakeElapsed - elapsedMilliseconds);
+
+ if (toSleep > 1)
+ {
+ // The time to sleep is more then a millisecond, so sleep.
+ await Task.Delay(toSleep, cancellationToken).ConfigureAwait(false);
+
+ // A sleep has been done, reset.
+ Reset();
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Will reset the bytecount to 0 and reset the start time to the current time.
+ /// </summary>
+ protected void Reset()
+ {
+ long difference = CurrentMilliseconds - _start;
+
+ // Only reset counters when a known history is available of more then 1 second.
+ if (difference > 1000)
+ {
+ _byteCount = 0;
+ _start = CurrentMilliseconds;
+ }
+ }
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
index 17118f4b4..7b58dd7c4 100644
--- a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
+++ b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
@@ -14,21 +14,6 @@ namespace MediaBrowser.Server.Implementations.Library
/// </summary>
public class CoreResolutionIgnoreRule : IResolverIgnoreRule
{
- /// <summary>
- /// Any folder named in this list will be ignored - can be added to at runtime for extensibility
- /// </summary>
- private static readonly Dictionary<string, string> IgnoreFolders = new List<string>
- {
- "metadata",
- "ps3_update",
- "ps3_vprm",
- "extrafanart",
- "extrathumbs",
- ".actors",
- ".wd_tv"
-
- }.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
-
private readonly IFileSystem _fileSystem;
public CoreResolutionIgnoreRule(IFileSystem fileSystem)
@@ -78,7 +63,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (args.IsDirectory)
{
// Ignore any folders in our list
- if (IgnoreFolders.ContainsKey(filename))
+ if (EntityResolutionHelper.IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase))
{
return true;
}
@@ -105,7 +90,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (args.Parent != null)
{
// Don't resolve these into audio files
- if (string.Equals(Path.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && EntityResolutionHelper.IsAudioFile(filename))
+ if (string.Equals(_fileSystem.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && EntityResolutionHelper.IsAudioFile(filename))
{
return true;
}
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index 64e0a6662..297d5e032 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -906,7 +906,7 @@ namespace MediaBrowser.Server.Implementations.Library
// Ensure the location is available.
Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath);
- return new PeopleValidator(this, _logger).ValidatePeople(cancellationToken, new MetadataRefreshOptions(), progress);
+ return new PeopleValidator(this, _logger, ConfigurationManager).ValidatePeople(cancellationToken, progress);
}
/// <summary>
@@ -1157,7 +1157,7 @@ namespace MediaBrowser.Server.Implementations.Library
private string GetCollectionType(string path)
{
return new DirectoryInfo(path).EnumerateFiles("*.collection", SearchOption.TopDirectoryOnly)
- .Select(i => Path.GetFileNameWithoutExtension(i.FullName))
+ .Select(i => _fileSystem.GetFileNameWithoutExtension(i))
.FirstOrDefault();
}
@@ -1486,23 +1486,22 @@ namespace MediaBrowser.Server.Implementations.Library
public async Task<UserView> GetNamedView(string name, string type, string sortName, CancellationToken cancellationToken)
{
- var id = "namedview_3_" + name;
- var guid = id.GetMD5();
+ var path = Path.Combine(ConfigurationManager.ApplicationPaths.ItemsByNamePath,
+ "views",
+ _fileSystem.GetValidFilename(type));
- var item = GetItemById(guid) as UserView;
+ var id = (path + "_namedview_" + name).GetMBId(typeof(UserView));
+
+ var item = GetItemById(id) as UserView;
if (item == null)
{
- var path = Path.Combine(ConfigurationManager.ApplicationPaths.ItemsByNamePath,
- "views",
- _fileSystem.GetValidFilename(type));
-
Directory.CreateDirectory(Path.GetDirectoryName(path));
item = new UserView
{
Path = path,
- Id = guid,
+ Id = id,
DateCreated = DateTime.UtcNow,
Name = name,
ViewType = type,
diff --git a/MediaBrowser.Server.Implementations/Library/MusicManager.cs b/MediaBrowser.Server.Implementations/Library/MusicManager.cs
index 9d5826454..7ffbab860 100644
--- a/MediaBrowser.Server.Implementations/Library/MusicManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/MusicManager.cs
@@ -18,15 +18,20 @@ namespace MediaBrowser.Server.Implementations.Library
public IEnumerable<Audio> GetInstantMixFromSong(Audio item, User user)
{
- return GetInstantMixFromGenres(item.Genres, user);
+ var list = new List<Audio>
+ {
+ item
+ };
+
+ return list.Concat(GetInstantMixFromGenres(item.Genres, user));
}
public IEnumerable<Audio> GetInstantMixFromArtist(string name, User user)
{
var artist = _libraryManager.GetArtist(name);
- var genres = _libraryManager.RootFolder
- .RecursiveChildren
+ var genres = user.RootFolder
+ .GetRecursiveChildren(user)
.OfType<Audio>()
.Where(i => i.HasArtist(name))
.SelectMany(i => i.Genres)
@@ -39,7 +44,7 @@ namespace MediaBrowser.Server.Implementations.Library
public IEnumerable<Audio> GetInstantMixFromAlbum(MusicAlbum item, User user)
{
var genres = item
- .RecursiveChildren
+ .GetRecursiveChildren(user, true)
.OfType<Audio>()
.SelectMany(i => i.Genres)
.Concat(item.Genres)
@@ -57,6 +62,7 @@ namespace MediaBrowser.Server.Implementations.Library
return inputItems
.OfType<Audio>()
.Select(i => new Tuple<Audio, int>(i, i.Genres.Count(genresDictionary.ContainsKey)))
+ .Where(i => i.Item2 > 0)
.OrderByDescending(i => i.Item2)
.ThenBy(i => Guid.NewGuid())
.Select(i => i.Item1)
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
index 28d476971..1f9dc56f9 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@@ -6,6 +7,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.IO;
@@ -17,6 +19,15 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
/// </summary>
public class MusicAlbumResolver : ItemResolver<MusicAlbum>
{
+ private readonly ILogger _logger;
+ private readonly IFileSystem _fileSystem;
+
+ public MusicAlbumResolver(ILogger logger, IFileSystem fileSystem)
+ {
+ _logger = logger;
+ _fileSystem = fileSystem;
+ }
+
/// <summary>
/// Gets the priority.
/// </summary>
@@ -45,17 +56,19 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
{
return null;
}
-
+
var collectionType = args.GetCollectionType();
+ var isMusicMediaFolder = string.Equals(collectionType, CollectionType.Music,
+ StringComparison.OrdinalIgnoreCase);
+
// If there's a collection type and it's not music, don't allow it.
- if (!string.IsNullOrEmpty(collectionType) &&
- !string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
+ if (!isMusicMediaFolder)
{
return null;
}
-
- return IsMusicAlbum(args) ? new MusicAlbum() : null;
+
+ return IsMusicAlbum(args, isMusicMediaFolder) ? new MusicAlbum() : null;
}
@@ -63,50 +76,29 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
/// Determine if the supplied file data points to a music album
/// </summary>
/// <param name="path">The path.</param>
+ /// <param name="isMusicMediaFolder">if set to <c>true</c> [is music media folder].</param>
/// <param name="directoryService">The directory service.</param>
+ /// <param name="logger">The logger.</param>
+ /// <param name="fileSystem">The file system.</param>
/// <returns><c>true</c> if [is music album] [the specified data]; otherwise, <c>false</c>.</returns>
- public static bool IsMusicAlbum(string path, IDirectoryService directoryService)
+ public static bool IsMusicAlbum(string path, bool isMusicMediaFolder, IDirectoryService directoryService, ILogger logger, IFileSystem fileSystem)
{
- // If list contains at least 2 audio files or at least one and no video files consider it to contain music
- var foundAudio = 0;
-
- foreach (var file in directoryService.GetFiles(path))
- {
- var fullName = file.FullName;
-
- if (EntityResolutionHelper.IsAudioFile(fullName))
- {
- // Don't resolve these into audio files
- if (string.Equals(Path.GetFileNameWithoutExtension(fullName), BaseItem.ThemeSongFilename) && EntityResolutionHelper.IsAudioFile(fullName))
- {
- continue;
- }
-
- foundAudio++;
- }
- if (foundAudio >= 2)
- {
- return true;
- }
- if (EntityResolutionHelper.IsVideoFile(fullName)) return false;
- }
-
- // or a single audio file and no video files
- return foundAudio > 0;
+ return ContainsMusic(directoryService.GetFileSystemEntries(path), isMusicMediaFolder, true, directoryService, logger, fileSystem);
}
/// <summary>
/// Determine if the supplied resolve args should be considered a music album
/// </summary>
/// <param name="args">The args.</param>
+ /// <param name="isMusicMediaFolder">if set to <c>true</c> [is music media folder].</param>
/// <returns><c>true</c> if [is music album] [the specified args]; otherwise, <c>false</c>.</returns>
- public static bool IsMusicAlbum(ItemResolveArgs args)
+ private bool IsMusicAlbum(ItemResolveArgs args, bool isMusicMediaFolder)
{
// Args points to an album if parent is an Artist folder or it directly contains music
if (args.IsDirectory)
{
//if (args.Parent is MusicArtist) return true; //saves us from testing children twice
- if (ContainsMusic(args.FileSystemChildren)) return true;
+ if (ContainsMusic(args.FileSystemChildren, isMusicMediaFolder, true, args.DirectoryService, _logger, _fileSystem)) return true;
}
return false;
@@ -116,27 +108,86 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
/// Determine if the supplied list contains what we should consider music
/// </summary>
/// <param name="list">The list.</param>
+ /// <param name="isMusicMediaFolder">if set to <c>true</c> [is music media folder].</param>
+ /// <param name="allowSubfolders">if set to <c>true</c> [allow subfolders].</param>
+ /// <param name="directoryService">The directory service.</param>
+ /// <param name="logger">The logger.</param>
+ /// <param name="fileSystem">The file system.</param>
/// <returns><c>true</c> if the specified list contains music; otherwise, <c>false</c>.</returns>
- private static bool ContainsMusic(IEnumerable<FileSystemInfo> list)
+ private static bool ContainsMusic(IEnumerable<FileSystemInfo> list,
+ bool isMusicMediaFolder,
+ bool allowSubfolders,
+ IDirectoryService directoryService,
+ ILogger logger,
+ IFileSystem fileSystem)
{
// If list contains at least 2 audio files or at least one and no video files consider it to contain music
var foundAudio = 0;
- foreach (var file in list)
+ var discSubfolderCount = 0;
+
+ foreach (var fileSystemInfo in list)
{
- var fullName = file.FullName;
+ if ((fileSystemInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
+ {
+ if (isMusicMediaFolder && allowSubfolders && IsAlbumSubfolder(fileSystemInfo, true, directoryService, logger, fileSystem))
+ {
+ discSubfolderCount++;
+ }
+ if (!IsAdditionalSubfolderAllowed(fileSystemInfo))
+ {
+ return false;
+ }
+ }
+
+ var fullName = fileSystemInfo.FullName;
+
+ if (EntityResolutionHelper.IsAudioFile(fullName))
+ {
+ // Don't resolve these into audio files
+ if (string.Equals(fileSystem.GetFileNameWithoutExtension(fullName), BaseItem.ThemeSongFilename))
+ {
+ continue;
+ }
+
+ foundAudio++;
+ }
+ else if (EntityResolutionHelper.IsVideoFile(fullName)) return false;
+ else if (EntityResolutionHelper.IsVideoPlaceHolder(fullName)) return false;
- if (EntityResolutionHelper.IsAudioFile(fullName)) foundAudio++;
if (foundAudio >= 2)
{
return true;
}
- if (EntityResolutionHelper.IsVideoFile(fullName)) return false;
- if (EntityResolutionHelper.IsVideoPlaceHolder(fullName)) return false;
}
// or a single audio file and no video files
- return foundAudio > 0;
+ return foundAudio > 0 || discSubfolderCount > 0;
+ }
+
+ private static bool IsAlbumSubfolder(FileSystemInfo directory, bool isMusicMediaFolder, IDirectoryService directoryService, ILogger logger, IFileSystem fileSystem)
+ {
+ var path = directory.FullName;
+
+ if (IsMultiDiscFolder(path))
+ {
+ logger.Debug("Found multi-disc folder: " + path);
+
+ return ContainsMusic(directoryService.GetFileSystemEntries(path), isMusicMediaFolder, false, directoryService, logger, fileSystem);
+ }
+
+ return false;
+ }
+
+ public static bool IsMultiDiscFolder(string path)
+ {
+ return EntityResolutionHelper.IsMultiDiscAlbumFolder(path);
+ }
+
+ private static bool IsAdditionalSubfolderAllowed(FileSystemInfo directory)
+ {
+ // Resolver will ignore them based on rules engine
+ return true;
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
index 4fa97fc9d..2417d5dcb 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
@@ -1,9 +1,11 @@
-using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
using System;
using System.IO;
using System.Linq;
@@ -15,6 +17,15 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
/// </summary>
public class MusicArtistResolver : ItemResolver<MusicArtist>
{
+ private readonly ILogger _logger;
+ private readonly IFileSystem _fileSystem;
+
+ public MusicArtistResolver(ILogger logger, IFileSystem fileSystem)
+ {
+ _logger = logger;
+ _fileSystem = fileSystem;
+ }
+
/// <summary>
/// Gets the priority.
/// </summary>
@@ -51,9 +62,11 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
var collectionType = args.GetCollectionType();
+ var isMusicMediaFolder = string.Equals(collectionType, CollectionType.Music,
+ StringComparison.OrdinalIgnoreCase);
+
// If there's a collection type and it's not music, it can't be a series
- if (!string.IsNullOrEmpty(collectionType) &&
- !string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
+ if (!isMusicMediaFolder)
{
return null;
}
@@ -61,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
var directoryService = args.DirectoryService;
// If we contain an album assume we are an artist folder
- return args.FileSystemChildren.Where(i => (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory).Any(i => MusicAlbumResolver.IsMusicAlbum(i.FullName, directoryService)) ? new MusicArtist() : null;
+ return args.FileSystemChildren.Where(i => (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory).Any(i => MusicAlbumResolver.IsMusicAlbum(i.FullName, isMusicMediaFolder, directoryService, _logger, _fileSystem)) ? new MusicArtist() : null;
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs
index 594277ef7..166465f72 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Resolvers;
using System;
@@ -12,6 +13,13 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
/// </summary>
public class FolderResolver : FolderResolver<Folder>
{
+ private readonly IFileSystem _fileSystem;
+
+ public FolderResolver(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
/// <summary>
/// Gets the priority.
/// </summary>
@@ -69,7 +77,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
}
})
- .Select(i => Path.GetFileNameWithoutExtension(i.FullName))
+ .Select(i => _fileSystem.GetFileNameWithoutExtension(i))
.FirstOrDefault();
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/LocalTrailerResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/LocalTrailerResolver.cs
index 10ee3586d..b483f7c42 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/LocalTrailerResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/LocalTrailerResolver.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Resolvers;
using System;
@@ -11,6 +12,13 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
/// </summary>
public class LocalTrailerResolver : BaseVideoResolver<Trailer>
{
+ private readonly IFileSystem _fileSystem;
+
+ public LocalTrailerResolver(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
/// <summary>
/// Resolves the specified args.
/// </summary>
@@ -33,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
}
// Support xbmc local trailer convention, but only when looking for local trailers (hence the parent == null check)
- if (args.Parent == null && Path.GetFileNameWithoutExtension(args.Path).EndsWith(BaseItem.XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase))
+ if (args.Parent == null && _fileSystem.GetFileNameWithoutExtension(args.Path).EndsWith(BaseItem.XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase))
{
return base.Resolve(args);
}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
index 905e6e676..215cff22f 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
@@ -6,11 +7,11 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using MediaBrowser.Model.Logging;
namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
{
@@ -22,12 +23,14 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
private readonly IServerApplicationPaths _applicationPaths;
private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger;
+ private readonly IFileSystem _fileSystem;
- public MovieResolver(IServerApplicationPaths appPaths, ILibraryManager libraryManager, ILogger logger)
+ public MovieResolver(IServerApplicationPaths appPaths, ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem)
{
_applicationPaths = appPaths;
_libraryManager = libraryManager;
_logger = logger;
+ _fileSystem = fileSystem;
}
/// <summary>
@@ -79,29 +82,29 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
{
if (string.Equals(collectionType, CollectionType.Trailers, StringComparison.OrdinalIgnoreCase))
{
- return FindMovie<Trailer>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, false, false);
+ return FindMovie<Trailer>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, false, false);
}
if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
{
- return FindMovie<MusicVideo>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, false, false);
+ return FindMovie<MusicVideo>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, false, false);
}
if (string.Equals(collectionType, CollectionType.AdultVideos, StringComparison.OrdinalIgnoreCase))
{
- return FindMovie<AdultVideo>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, true, false);
+ return FindMovie<AdultVideo>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, true, false);
}
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
{
- return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, true, false);
+ return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, true, false);
}
if (string.IsNullOrEmpty(collectionType) ||
string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) ||
string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
{
- return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, true, true);
+ return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, true, true);
}
return null;
@@ -187,7 +190,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
/// <param name="directoryService">The directory service.</param>
/// <param name="supportMultiFileItems">if set to <c>true</c> [support multi file items].</param>
/// <returns>Movie.</returns>
- private T FindMovie<T>(string path, Folder parent, IEnumerable<FileSystemInfo> fileSystemEntries, IDirectoryService directoryService, bool supportMultiFileItems, bool supportsMultipleSources)
+ private T FindMovie<T>(string path, Folder parent, List<FileSystemInfo> fileSystemEntries, IDirectoryService directoryService, bool supportMultiFileItems, bool supportsMultipleSources)
where T : Video, new()
{
var movies = new List<T>();
@@ -407,7 +410,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
if (!string.IsNullOrWhiteSpace(filenamePrefix))
{
- if (sortedMovies.All(i => Path.GetFileNameWithoutExtension(i.Path).StartsWith(filenamePrefix + " - ", StringComparison.OrdinalIgnoreCase)))
+ if (sortedMovies.All(i => _fileSystem.GetFileNameWithoutExtension(i.Path).StartsWith(filenamePrefix + " - ", StringComparison.OrdinalIgnoreCase)))
{
firstMovie.HasLocalAlternateVersions = true;
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
new file mode 100644
index 000000000..2fcfd7086
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
@@ -0,0 +1,39 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace MediaBrowser.Server.Implementations.Library.Resolvers
+{
+ public class PhotoAlbumResolver : FolderResolver<PhotoAlbum>
+ {
+ /// <summary>
+ /// Resolves the specified args.
+ /// </summary>
+ /// <param name="args">The args.</param>
+ /// <returns>Trailer.</returns>
+ protected override PhotoAlbum Resolve(ItemResolveArgs args)
+ {
+ // Must be an image file within a photo collection
+ if (!args.IsRoot && args.IsDirectory && string.Equals(args.GetCollectionType(), CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
+ {
+ if (HasPhotos(args))
+ {
+ return new PhotoAlbum
+ {
+ Path = args.Path
+ };
+ }
+ }
+
+ return null;
+ }
+
+ private static bool HasPhotos(ItemResolveArgs args)
+ {
+ return args.FileSystemChildren.Any(i => ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory) && PhotoResolver.IsImageFile(i.FullName));
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
index cba7aba9a..60e7edfdd 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
@@ -1,24 +1,14 @@
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
using System;
+using System.IO;
using System.Linq;
namespace MediaBrowser.Server.Implementations.Library.Resolvers
{
public class PhotoResolver : ItemResolver<Photo>
{
- private readonly IServerApplicationPaths _applicationPaths;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="PhotoResolver" /> class.
- /// </summary>
- /// <param name="applicationPaths">The application paths.</param>
- public PhotoResolver(IServerApplicationPaths applicationPaths)
- {
- _applicationPaths = applicationPaths;
- }
-
/// <summary>
/// Resolves the specified args.
/// </summary>
@@ -27,7 +17,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
protected override Photo Resolve(ItemResolveArgs args)
{
// Must be an image file within a photo collection
- if (!args.IsDirectory && IsImageFile(args.Path) && string.Equals(args.GetCollectionType(), "photos", StringComparison.OrdinalIgnoreCase))
+ if (!args.IsDirectory && IsImageFile(args.Path) && string.Equals(args.GetCollectionType(), CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
{
return new Photo
{
@@ -39,10 +29,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
}
protected static string[] ImageExtensions = { ".tiff", ".jpeg", ".jpg", ".png", ".aiff" };
- protected bool IsImageFile(string path)
+ internal static bool IsImageFile(string path)
{
- return !path.EndsWith("folder.jpg", StringComparison.OrdinalIgnoreCase)
- && ImageExtensions.Any(p => path.EndsWith(p, StringComparison.OrdinalIgnoreCase));
+ var filename = Path.GetFileName(path);
+
+ return !string.Equals(filename, "folder.jpg", StringComparison.OrdinalIgnoreCase)
+ && ImageExtensions.Contains(Path.GetExtension(path) ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
new file mode 100644
index 000000000..7eff53ce1
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
@@ -0,0 +1,38 @@
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Playlists;
+using System;
+using System.IO;
+
+namespace MediaBrowser.Server.Implementations.Library.Resolvers
+{
+ public class PlaylistResolver : FolderResolver<Playlist>
+ {
+ /// <summary>
+ /// Resolves the specified args.
+ /// </summary>
+ /// <param name="args">The args.</param>
+ /// <returns>BoxSet.</returns>
+ protected override Playlist Resolve(ItemResolveArgs args)
+ {
+ // It's a boxset if all of the following conditions are met:
+ // Is a Directory
+ // Contains [playlist] in the path
+ if (args.IsDirectory)
+ {
+ var filename = Path.GetFileName(args.Path);
+
+ if (string.IsNullOrEmpty(filename))
+ {
+ return null;
+ }
+
+ if (filename.IndexOf("[playlist]", StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ return new Playlist { Path = args.Path };
+ }
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
index 6b376d3b4..d3aad582a 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
@@ -1,9 +1,11 @@
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
using System;
using System.IO;
@@ -14,6 +16,15 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
/// </summary>
public class SeriesResolver : FolderResolver<Series>
{
+ private readonly IFileSystem _fileSystem;
+ private readonly ILogger _logger;
+
+ public SeriesResolver(IFileSystem fileSystem, ILogger logger)
+ {
+ _fileSystem = fileSystem;
+ _logger = logger;
+ }
+
/// <summary>
/// Gets the priority.
/// </summary>
@@ -49,32 +60,18 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
var collectionType = args.GetCollectionType();
+ var isTvShowsFolder = string.Equals(collectionType, CollectionType.TvShows,
+ StringComparison.OrdinalIgnoreCase);
+
// If there's a collection type and it's not tv, it can't be a series
if (!string.IsNullOrEmpty(collectionType) &&
- !string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) &&
+ !isTvShowsFolder &&
!string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
{
return null;
}
-
- // It's a Series if any of the following conditions are met:
- // series.xml exists
- // [tvdbid= is present in the path
- // TVUtils.IsSeriesFolder returns true
- var filename = Path.GetFileName(args.Path);
-
- if (string.IsNullOrEmpty(filename))
- {
- return null;
- }
- // Without these movies that have the name season in them could cause the parent folder to be resolved as a series
- if (filename.IndexOf("[tmdbid=", StringComparison.OrdinalIgnoreCase) != -1)
- {
- return null;
- }
-
- if (args.ContainsMetaFileByName("series.xml") || filename.IndexOf("[tvdbid=", StringComparison.OrdinalIgnoreCase) != -1 || TVUtils.IsSeriesFolder(args.Path, collectionType == CollectionType.TvShows, args.FileSystemChildren, args.DirectoryService))
+ if (TVUtils.IsSeriesFolder(args.Path, isTvShowsFolder, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger))
{
return new Series();
}
diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs
index 4c65fad68..6faa72b81 100644
--- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs
+++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs
@@ -41,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Library
{
var user = _userManager.GetUserById(new Guid(query.UserId));
- inputItems = user.RootFolder.GetRecursiveChildren(user, null);
+ inputItems = user.RootFolder.GetRecursiveChildren(user, true);
}
diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
index 79f126511..d3030f31f 100644
--- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
@@ -125,5 +126,41 @@ namespace MediaBrowser.Server.Implementations.Library
{
return userId + key;
}
+
+ public UserItemDataDto GetUserDataDto(IHasUserData item, User user)
+ {
+ var userData = GetUserData(user.Id, item.GetUserDataKey());
+ var dto = GetUserItemDataDto(userData);
+
+ item.FillUserDataDtoValues(dto, userData, user);
+
+ return dto;
+ }
+
+ /// <summary>
+ /// Converts a UserItemData to a DTOUserItemData
+ /// </summary>
+ /// <param name="data">The data.</param>
+ /// <returns>DtoUserItemData.</returns>
+ /// <exception cref="System.ArgumentNullException"></exception>
+ private UserItemDataDto GetUserItemDataDto(UserItemData data)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("data");
+ }
+
+ return new UserItemDataDto
+ {
+ IsFavorite = data.IsFavorite,
+ Likes = data.Likes,
+ PlaybackPositionTicks = data.PlaybackPositionTicks,
+ PlayCount = data.PlayCount,
+ Rating = data.Rating,
+ Played = data.Played,
+ LastPlayedDate = data.LastPlayedDate,
+ Key = data.Key
+ };
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs
index f9d7479ce..94cc61240 100644
--- a/MediaBrowser.Server.Implementations/Library/UserManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs
@@ -1,14 +1,20 @@
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
+using MediaBrowser.Server.Implementations.Security;
using System;
using System.Collections.Generic;
using System.IO;
@@ -47,20 +53,29 @@ namespace MediaBrowser.Server.Implementations.Library
/// </summary>
/// <value>The user repository.</value>
private IUserRepository UserRepository { get; set; }
+ public event EventHandler<GenericEventArgs<User>> UserPasswordChanged;
private readonly IXmlSerializer _xmlSerializer;
+ private readonly INetworkManager _networkManager;
+
+ private readonly Func<IImageProcessor> _imageProcessorFactory;
+ private readonly Func<IDtoService> _dtoServiceFactory;
+
/// <summary>
/// Initializes a new instance of the <see cref="UserManager" /> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="configurationManager">The configuration manager.</param>
/// <param name="userRepository">The user repository.</param>
- public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer)
+ public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory)
{
_logger = logger;
UserRepository = userRepository;
_xmlSerializer = xmlSerializer;
+ _networkManager = networkManager;
+ _imageProcessorFactory = imageProcessorFactory;
+ _dtoServiceFactory = dtoServiceFactory;
ConfigurationManager = configurationManager;
Users = new List<User>();
}
@@ -118,28 +133,26 @@ namespace MediaBrowser.Server.Implementations.Library
Users = await LoadUsers().ConfigureAwait(false);
}
- /// <summary>
- /// Authenticates a User and returns a result indicating whether or not it succeeded
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="password">The password.</param>
- /// <returns>Task{System.Boolean}.</returns>
- /// <exception cref="System.ArgumentNullException">user</exception>
- public async Task<bool> AuthenticateUser(User user, string password)
+ public async Task<bool> AuthenticateUser(string username, string password, string remoteEndPoint)
{
- if (user == null)
+ if (string.IsNullOrWhiteSpace(username))
{
- throw new ArgumentNullException("user");
+ throw new ArgumentNullException("username");
}
+ var user = Users.First(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
+
if (user.Configuration.IsDisabled)
{
- throw new UnauthorizedAccessException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
+ throw new AuthenticationException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
}
- var existingPasswordString = string.IsNullOrEmpty(user.Password) ? GetSha1String(string.Empty) : user.Password;
+ var success = string.Equals(GetPasswordHash(user), password.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
- var success = string.Equals(existingPasswordString, password.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
+ if (!success && _networkManager.IsInLocalNetwork(remoteEndPoint) && user.Configuration.EnableLocalPassword)
+ {
+ success = string.Equals(GetLocalPasswordHash(user), password.Replace("-", string.Empty), StringComparison.OrdinalIgnoreCase);
+ }
// Update LastActivityDate and LastLoginDate, then save
if (success)
@@ -153,6 +166,25 @@ namespace MediaBrowser.Server.Implementations.Library
return success;
}
+ private string GetPasswordHash(User user)
+ {
+ return string.IsNullOrEmpty(user.Password)
+ ? GetSha1String(string.Empty)
+ : user.Password;
+ }
+
+ private string GetLocalPasswordHash(User user)
+ {
+ return string.IsNullOrEmpty(user.LocalPassword)
+ ? GetSha1String(string.Empty)
+ : user.LocalPassword;
+ }
+
+ private bool IsPasswordEmpty(string passwordHash)
+ {
+ return string.Equals(passwordHash, GetSha1String(string.Empty), StringComparison.OrdinalIgnoreCase);
+ }
+
/// <summary>
/// Gets the sha1 string.
/// </summary>
@@ -192,6 +224,65 @@ namespace MediaBrowser.Server.Implementations.Library
return users;
}
+ public UserDto GetUserDto(User user, string remoteEndPoint = null)
+ {
+ if (user == null)
+ {
+ throw new ArgumentNullException("user");
+ }
+
+ var passwordHash = GetPasswordHash(user);
+
+ var hasConfiguredDefaultPassword = !IsPasswordEmpty(passwordHash);
+
+ var hasPassword = user.Configuration.EnableLocalPassword && !string.IsNullOrEmpty(remoteEndPoint) && _networkManager.IsInLocalNetwork(remoteEndPoint) ?
+ !IsPasswordEmpty(GetLocalPasswordHash(user)) :
+ hasConfiguredDefaultPassword;
+
+ var dto = new UserDto
+ {
+ Id = user.Id.ToString("N"),
+ Name = user.Name,
+ HasPassword = hasPassword,
+ HasConfiguredPassword = hasConfiguredDefaultPassword,
+ LastActivityDate = user.LastActivityDate,
+ LastLoginDate = user.LastLoginDate,
+ Configuration = user.Configuration
+ };
+
+ var image = user.GetImageInfo(ImageType.Primary, 0);
+
+ if (image != null)
+ {
+ dto.PrimaryImageTag = GetImageCacheTag(user, image);
+
+ try
+ {
+ _dtoServiceFactory().AttachPrimaryImageAspectRatio(dto, user);
+ }
+ catch (Exception ex)
+ {
+ // Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions
+ _logger.ErrorException("Error generating PrimaryImageAspectRatio for {0}", ex, user.Name);
+ }
+ }
+
+ return dto;
+ }
+
+ private string GetImageCacheTag(BaseItem item, ItemImageInfo image)
+ {
+ try
+ {
+ return _imageProcessorFactory().GetImageCacheTag(item, image);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error getting {0} image info for {1}", ex, image.Type, image.Path);
+ return null;
+ }
+ }
+
/// <summary>
/// Refreshes metadata for each user
/// </summary>
@@ -278,7 +369,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <exception cref="System.ArgumentException"></exception>
public async Task<User> CreateUser(string name)
{
- if (string.IsNullOrEmpty(name))
+ if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException("name");
}
@@ -386,16 +477,18 @@ namespace MediaBrowser.Server.Implementations.Library
/// <param name="user">The user.</param>
/// <param name="newPassword">The new password.</param>
/// <returns>Task.</returns>
- public Task ChangePassword(User user, string newPassword)
+ public async Task ChangePassword(User user, string newPassword)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
- user.Password = string.IsNullOrEmpty(newPassword) ? string.Empty : GetSha1String(newPassword);
+ user.Password = string.IsNullOrEmpty(newPassword) ? GetSha1String(string.Empty) : GetSha1String(newPassword);
+
+ await UpdateUser(user).ConfigureAwait(false);
- return UpdateUser(user);
+ EventHelper.FireEventIfNotNull(UserPasswordChanged, this, new GenericEventArgs<User>(user), _logger);
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
index fc4b9eb4c..63aa3764c 100644
--- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
@@ -1,4 +1,6 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -7,11 +9,14 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Localization;
+using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Library;
+using MediaBrowser.Model.Querying;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -27,8 +32,10 @@ namespace MediaBrowser.Server.Implementations.Library
private readonly IChannelManager _channelManager;
private readonly ILiveTvManager _liveTvManager;
+ private readonly IServerApplicationPaths _appPaths;
+ private readonly IPlaylistManager _playlists;
- public UserViewManager(ILibraryManager libraryManager, ILocalizationManager localizationManager, IFileSystem fileSystem, IUserManager userManager, IChannelManager channelManager, ILiveTvManager liveTvManager)
+ public UserViewManager(ILibraryManager libraryManager, ILocalizationManager localizationManager, IFileSystem fileSystem, IUserManager userManager, IChannelManager channelManager, ILiveTvManager liveTvManager, IServerApplicationPaths appPaths, IPlaylistManager playlists)
{
_libraryManager = libraryManager;
_localizationManager = localizationManager;
@@ -36,6 +43,8 @@ namespace MediaBrowser.Server.Implementations.Library
_userManager = userManager;
_channelManager = channelManager;
_liveTvManager = liveTvManager;
+ _appPaths = appPaths;
+ _playlists = playlists;
}
public async Task<IEnumerable<Folder>> GetUserViews(UserViewQuery query, CancellationToken cancellationToken)
@@ -62,40 +71,58 @@ namespace MediaBrowser.Server.Implementations.Library
if (recursiveChildren.OfType<Series>().Any())
{
- list.Add(await GetUserView(CollectionType.TvShows, user, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.TvShows, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
if (recursiveChildren.OfType<MusicAlbum>().Any() ||
recursiveChildren.OfType<MusicVideo>().Any())
{
- list.Add(await GetUserView(CollectionType.Music, user, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.Music, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
if (recursiveChildren.OfType<Movie>().Any())
{
- list.Add(await GetUserView(CollectionType.Movies, user, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.Movies, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
if (recursiveChildren.OfType<Game>().Any())
{
- list.Add(await GetUserView(CollectionType.Games, user, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.Games, user, string.Empty, cancellationToken).ConfigureAwait(false));
}
- if (recursiveChildren.OfType<BoxSet>().Any())
+ if (user.Configuration.DisplayCollectionsView &&
+ recursiveChildren.OfType<BoxSet>().Any())
{
- list.Add(await GetUserView(CollectionType.BoxSets, user, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.BoxSets, user, string.Empty, cancellationToken).ConfigureAwait(false));
+ }
+
+ if (recursiveChildren.OfType<Playlist>().Any())
+ {
+ list.Add(_playlists.GetPlaylistsFolder(user.Id.ToString("N")));
+ }
+
+ if (user.Configuration.DisplayFoldersView)
+ {
+ list.Add(await GetUserView(CollectionType.Folders, user, "zz_" + CollectionType.Folders, cancellationToken).ConfigureAwait(false));
}
if (query.IncludeExternalContent)
{
var channelResult = await _channelManager.GetChannels(new ChannelQuery
{
- Limit = 0,
UserId = query.UserId
}, cancellationToken).ConfigureAwait(false);
- if (channelResult.TotalRecordCount > 0)
+ var channels = channelResult.Items;
+
+ var embeddedChannels = channels
+ .Where(i => user.Configuration.DisplayChannelsWithinViews.Contains(i.Id))
+ .ToList();
+
+ list.AddRange(embeddedChannels.Select(i => _channelManager.GetChannel(i.Id)));
+
+ if (channels.Length > embeddedChannels.Count)
{
list.Add(await _channelManager.GetInternalChannelFolder(query.UserId, cancellationToken).ConfigureAwait(false));
}
@@ -106,14 +133,58 @@ namespace MediaBrowser.Server.Implementations.Library
}
}
- return list.OrderBy(i => i.SortName);
+ var sorted = _libraryManager.Sort(list, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList();
+
+ var orders = user.Configuration.OrderedViews.ToList();
+
+ return list
+ .OrderBy(i =>
+ {
+ var index = orders.IndexOf(i.Id.ToString("N"));
+
+ return index == -1 ? int.MaxValue : index;
+ })
+ .ThenBy(sorted.IndexOf)
+ .ThenBy(i => i.SortName);
}
- private Task<UserView> GetUserView(string type, User user, CancellationToken cancellationToken)
+ public Task<UserView> GetUserView(string type, User user, string sortName, CancellationToken cancellationToken)
{
var name = _localizationManager.GetLocalizedString("ViewType" + type);
- return _libraryManager.GetNamedView(name, type, string.Empty, cancellationToken);
+ return _libraryManager.GetNamedView(name, type, sortName, cancellationToken);
+ }
+
+ public async Task<SpecialFolder> GetSpecialFolder(string name, SpecialFolderType type, string itemType, CancellationToken cancellationToken)
+ {
+ var path = Path.Combine(_appPaths.ItemsByNamePath,
+ "specialfolders",
+ _fileSystem.GetValidFilename(name));
+
+ var id = (path + "_specialfolder_" + name).GetMBId(typeof(SpecialFolder));
+
+ var item = _libraryManager.GetItemById(id) as SpecialFolder;
+
+ if (item == null)
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+
+ item = new SpecialFolder
+ {
+ Path = path,
+ Id = id,
+ DateCreated = DateTime.UtcNow,
+ Name = name,
+ SpecialFolderType = type,
+ ItemTypeName = itemType
+ };
+
+ await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
+
+ await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
+ }
+
+ return item;
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs
index 05c972a4e..059ad2481 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs
@@ -1,8 +1,13 @@
using MediaBrowser.Common.Progress;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -23,46 +28,128 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// </summary>
private readonly ILogger _logger;
+ private readonly IServerConfigurationManager _config;
+
/// <summary>
/// Initializes a new instance of the <see cref="PeopleValidator" /> class.
/// </summary>
/// <param name="libraryManager">The library manager.</param>
/// <param name="logger">The logger.</param>
- public PeopleValidator(ILibraryManager libraryManager, ILogger logger)
+ public PeopleValidator(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config)
{
_libraryManager = libraryManager;
_logger = logger;
+ _config = config;
+ }
+
+ private bool DownloadMetadata(PersonInfo i, PeopleMetadataOptions options)
+ {
+ if (i.IsType(PersonType.Actor))
+ {
+ return options.DownloadActorMetadata;
+ }
+ if (i.IsType(PersonType.Director))
+ {
+ return options.DownloadDirectorMetadata;
+ }
+ if (i.IsType(PersonType.Composer))
+ {
+ return options.DownloadComposerMetadata;
+ }
+ if (i.IsType(PersonType.Writer))
+ {
+ return options.DownloadWriterMetadata;
+ }
+ if (i.IsType(PersonType.Producer))
+ {
+ return options.DownloadProducerMetadata;
+ }
+ if (i.IsType(PersonType.GuestStar))
+ {
+ return options.DownloadGuestStarMetadata;
+ }
+
+ return options.DownloadOtherPeopleMetadata;
+ }
+
+ private IEnumerable<PersonInfo> GetPeopleToValidate(BaseItem item, PeopleMetadataOptions options)
+ {
+ return item.People.Where(i =>
+ {
+ if (i.IsType(PersonType.Actor))
+ {
+ return options.DownloadActorMetadata;
+ }
+ if (i.IsType(PersonType.Director))
+ {
+ return options.DownloadDirectorMetadata;
+ }
+ if (i.IsType(PersonType.Composer))
+ {
+ return options.DownloadComposerMetadata;
+ }
+ if (i.IsType(PersonType.Writer))
+ {
+ return options.DownloadWriterMetadata;
+ }
+ if (i.IsType(PersonType.Producer))
+ {
+ return options.DownloadProducerMetadata;
+ }
+ if (i.IsType(PersonType.GuestStar))
+ {
+ return options.DownloadGuestStarMetadata;
+ }
+
+ return options.DownloadOtherPeopleMetadata;
+ });
}
/// <summary>
/// Validates the people.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
- /// <param name="options">The options.</param>
/// <param name="progress">The progress.</param>
/// <returns>Task.</returns>
- public async Task ValidatePeople(CancellationToken cancellationToken, MetadataRefreshOptions options, IProgress<double> progress)
+ public async Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress)
{
var innerProgress = new ActionableProgress<double>();
innerProgress.RegisterAction(pct => progress.Report(pct * .15));
+ var peopleOptions = _config.Configuration.PeopleMetadataOptions;
+
var people = _libraryManager.RootFolder.GetRecursiveChildren()
- .SelectMany(c => c.People)
+ .SelectMany(i => i.People)
.Where(i => !string.IsNullOrWhiteSpace(i.Name))
- .Select(i => i.Name)
- .Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
- var numComplete = 0;
+ var dict = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
foreach (var person in people)
{
+ bool current;
+ if (!dict.TryGetValue(person.Name, out current) || !current)
+ {
+ dict[person.Name] = DownloadMetadata(person, peopleOptions);
+ }
+ }
+
+ var numComplete = 0;
+
+ foreach (var person in dict)
+ {
cancellationToken.ThrowIfCancellationRequested();
try
{
- var item = _libraryManager.GetPerson(person);
+ var item = _libraryManager.GetPerson(person.Key);
+
+ var options = new MetadataRefreshOptions
+ {
+ MetadataRefreshMode = person.Value ? MetadataRefreshMode.Default : MetadataRefreshMode.ValidationOnly,
+ ImageRefreshMode = person.Value ? ImageRefreshMode.Default : ImageRefreshMode.ValidationOnly
+ };
await item.RefreshMetadata(options, cancellationToken).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/LiveTv/CleanDatabaseScheduledTask.cs
index 56e92f82c..bed9458ec 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/CleanDatabaseScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/CleanDatabaseScheduledTask.cs
@@ -41,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
return new ITaskTrigger[]
{
- new IntervalTrigger{ Interval = TimeSpan.FromHours(24)}
+ new IntervalTrigger{ Interval = TimeSpan.FromHours(12)}
};
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs
new file mode 100644
index 000000000..57d1d79e1
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs
@@ -0,0 +1,21 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.LiveTv;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Server.Implementations.LiveTv
+{
+ public class LiveTvConfigurationFactory : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new List<ConfigurationStore>
+ {
+ new ConfigurationStore
+ {
+ ConfigurationType = typeof(LiveTvOptions),
+ Key = "livetv"
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
index 412b2e7bd..9c69e656d 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Logging;
@@ -23,15 +22,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private readonly IUserDataManager _userDataManager;
private readonly IDtoService _dtoService;
- private readonly IItemRepository _itemRepo;
- public LiveTvDtoService(IDtoService dtoService, IUserDataManager userDataManager, IImageProcessor imageProcessor, ILogger logger, IItemRepository itemRepo)
+ public LiveTvDtoService(IDtoService dtoService, IUserDataManager userDataManager, IImageProcessor imageProcessor, ILogger logger)
{
_dtoService = dtoService;
_userDataManager = userDataManager;
_imageProcessor = imageProcessor;
_logger = logger;
- _itemRepo = itemRepo;
}
public TimerInfoDto GetTimerInfoDto(TimerInfo info, ILiveTvService service, LiveTvProgram program, LiveTvChannel channel)
@@ -249,7 +246,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (user != null)
{
- dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, recording.GetUserDataKey()));
+ dto.UserData = _userDataManager.GetUserDataDto(recording, user);
dto.PlayAccess = recording.GetPlayAccess(user);
}
@@ -322,7 +319,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (user != null)
{
- dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, info.GetUserDataKey()));
+ dto.UserData = _userDataManager.GetUserDataDto(info, user);
dto.PlayAccess = info.GetPlayAccess(user);
}
@@ -401,7 +398,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
if (user != null)
{
- dto.UserData = _dtoService.GetUserItemDataDto(_userDataManager.GetUserData(user.Id, item.GetUserDataKey()));
+ dto.UserData = _userDataManager.GetUserDataDto(item, user);
dto.PlayAccess = item.GetPlayAccess(user);
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index 467bedcf1..d072217af 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
@@ -40,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private readonly IUserDataManager _userDataManager;
private readonly ILibraryManager _libraryManager;
private readonly ITaskManager _taskManager;
- private readonly IJsonSerializer _json;
+ private readonly IJsonSerializer _jsonSerializer;
private readonly IDtoService _dtoService;
private readonly ILocalizationManager _localization;
@@ -49,8 +50,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private readonly List<ILiveTvService> _services = new List<ILiveTvService>();
- private readonly ConcurrentDictionary<string, LiveStreamInfo> _openStreams =
- new ConcurrentDictionary<string, LiveStreamInfo>();
+ private readonly ConcurrentDictionary<string, LiveStreamData> _openStreams =
+ new ConcurrentDictionary<string, LiveStreamData>();
private List<Guid> _channelIdList = new List<Guid>();
private Dictionary<Guid, LiveTvProgram> _programs = new Dictionary<Guid, LiveTvProgram>();
@@ -58,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private readonly SemaphoreSlim _refreshSemaphore = new SemaphoreSlim(1, 1);
- public LiveTvManager(IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, IJsonSerializer json, ILocalizationManager localization)
+ public LiveTvManager(IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, IItemRepository itemRepo, IImageProcessor imageProcessor, IUserDataManager userDataManager, IDtoService dtoService, IUserManager userManager, ILibraryManager libraryManager, ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer)
{
_config = config;
_fileSystem = fileSystem;
@@ -67,12 +68,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
_userManager = userManager;
_libraryManager = libraryManager;
_taskManager = taskManager;
- _json = json;
_localization = localization;
+ _jsonSerializer = jsonSerializer;
_dtoService = dtoService;
_userDataManager = userDataManager;
- _tvDtoService = new LiveTvDtoService(dtoService, userDataManager, imageProcessor, logger, _itemRepo);
+ _tvDtoService = new LiveTvDtoService(dtoService, userDataManager, imageProcessor, logger);
}
/// <summary>
@@ -86,6 +87,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public ILiveTvService ActiveService { get; private set; }
+ private LiveTvOptions GetConfiguration()
+ {
+ return _config.GetConfiguration<LiveTvOptions>("livetv");
+ }
+
/// <summary>
/// Adds the parts.
/// </summary>
@@ -94,7 +100,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
_services.AddRange(services);
- SetActiveService(_config.Configuration.LiveTvOptions.ActiveService);
+ SetActiveService(GetConfiguration().ActiveService);
}
private void SetActiveService(string name)
@@ -125,7 +131,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
_taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>();
}
- public async Task<QueryResult<ChannelInfoDto>> GetChannels(LiveTvChannelQuery query, CancellationToken cancellationToken)
+ public async Task<QueryResult<LiveTvChannel>> GetInternalChannels(LiveTvChannelQuery query, CancellationToken cancellationToken)
{
var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId));
@@ -214,9 +220,24 @@ namespace MediaBrowser.Server.Implementations.LiveTv
allEnumerable = allEnumerable.Take(query.Limit.Value);
}
+ var result = new QueryResult<LiveTvChannel>
+ {
+ Items = allEnumerable.ToArray(),
+ TotalRecordCount = allChannels.Count
+ };
+
+ return result;
+ }
+
+ public async Task<QueryResult<ChannelInfoDto>> GetChannels(LiveTvChannelQuery query, CancellationToken cancellationToken)
+ {
+ var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId));
+
+ var internalResult = await GetInternalChannels(query, cancellationToken).ConfigureAwait(false);
+
var returnList = new List<ChannelInfoDto>();
- foreach (var channel in allEnumerable)
+ foreach (var channel in internalResult.Items)
{
var currentProgram = await GetCurrentProgram(channel.ExternalId, cancellationToken).ConfigureAwait(false);
@@ -226,7 +247,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var result = new QueryResult<ChannelInfoDto>
{
Items = returnList.ToArray(),
- TotalRecordCount = allChannels.Count
+ TotalRecordCount = internalResult.TotalRecordCount
};
return result;
@@ -257,12 +278,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return obj;
}
- private async Task RefreshIfNeeded(IEnumerable<LiveTvProgram> programs, CancellationToken cancellationToken)
+ private Task RefreshIfNeeded(IEnumerable<LiveTvProgram> programs, CancellationToken cancellationToken)
{
- foreach (var program in programs)
+ var list = programs.ToList();
+
+ Task.Run(async () =>
{
- await RefreshIfNeeded(program, cancellationToken).ConfigureAwait(false);
- }
+ foreach (var program in list)
+ {
+ await RefreshIfNeeded(program, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ }, cancellationToken);
+
+ return Task.FromResult(true);
}
private async Task RefreshIfNeeded(LiveTvProgram program, CancellationToken cancellationToken)
@@ -272,9 +301,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return;
}
- await program.RefreshMetadata(cancellationToken).ConfigureAwait(false);
-
_refreshedPrograms.TryAdd(program.Id, true);
+
+ await program.RefreshMetadata(cancellationToken).ConfigureAwait(false);
}
public async Task<ILiveTvRecording> GetInternalRecording(string id, CancellationToken cancellationToken)
@@ -292,65 +321,53 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public async Task<LiveStreamInfo> GetRecordingStream(string id, CancellationToken cancellationToken)
{
- await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
-
- try
- {
- var service = ActiveService;
-
- var recordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false);
-
- var recording = recordings.First(i => _tvDtoService.GetInternalRecordingId(service.Name, i.Id) == new Guid(id));
-
- var result = await service.GetRecordingStream(recording.Id, cancellationToken).ConfigureAwait(false);
-
- Sanitize(result);
-
- _logger.Debug("Live stream info: " + _json.SerializeToString(result));
-
- if (!string.IsNullOrEmpty(result.Id))
- {
- _openStreams.AddOrUpdate(result.Id, result, (key, info) => result);
- }
-
- return result;
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error getting recording stream", ex);
-
- throw;
- }
- finally
- {
- _liveStreamSemaphore.Release();
- }
+ return await GetLiveStream(id, false, cancellationToken).ConfigureAwait(false);
}
public async Task<LiveStreamInfo> GetChannelStream(string id, CancellationToken cancellationToken)
{
+ return await GetLiveStream(id, true, cancellationToken).ConfigureAwait(false);
+ }
+
+ private async Task<LiveStreamInfo> GetLiveStream(string id, bool isChannel, CancellationToken cancellationToken)
+ {
await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
var service = ActiveService;
+ LiveStreamInfo info;
- var channel = GetInternalChannel(id);
-
- _logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId);
+ if (isChannel)
+ {
+ var channel = GetInternalChannel(id);
+ _logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId);
- var result = await service.GetChannelStream(channel.ExternalId, cancellationToken).ConfigureAwait(false);
+ info = await service.GetChannelStream(channel.ExternalId, cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ var recordings = await service.GetRecordingsAsync(cancellationToken).ConfigureAwait(false);
+ var recording = recordings.First(i => _tvDtoService.GetInternalRecordingId(service.Name, i.Id) == new Guid(id));
- Sanitize(result);
+ _logger.Info("Opening recording stream from {0}, external recording Id: {1}", service.Name, recording.Id);
+ info = await service.GetRecordingStream(recording.Id, cancellationToken).ConfigureAwait(false);
+ }
- _logger.Debug("Live stream info: " + _json.SerializeToString(result));
+ _logger.Info("Live stream info: {0}", _jsonSerializer.SerializeToString(info));
+ Sanitize(info);
- if (!string.IsNullOrEmpty(result.Id))
+ var data = new LiveStreamData
{
- _openStreams.AddOrUpdate(result.Id, result, (key, info) => result);
- }
+ Info = info,
+ ConsumerCount = 1,
+ IsChannel = isChannel,
+ ItemId = id
+ };
- return result;
+ _openStreams.AddOrUpdate(info.Id, data, (key, i) => data);
+
+ return info;
}
catch (Exception ex)
{
@@ -458,13 +475,27 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
item.ChannelType = channelInfo.ChannelType;
- item.ProviderImageUrl = channelInfo.ImageUrl;
- item.HasProviderImage = channelInfo.HasImage;
- item.ProviderImagePath = channelInfo.ImagePath;
item.ExternalId = channelInfo.Id;
item.ServiceName = serviceName;
item.Number = channelInfo.Number;
+ var replaceImages = new List<ImageType>();
+
+ if (!string.Equals(item.ProviderImageUrl, channelInfo.ImageUrl, StringComparison.OrdinalIgnoreCase))
+ {
+ isNew = true;
+ replaceImages.Add(ImageType.Primary);
+ }
+ if (!string.Equals(item.ProviderImagePath, channelInfo.ImagePath, StringComparison.OrdinalIgnoreCase))
+ {
+ isNew = true;
+ replaceImages.Add(ImageType.Primary);
+ }
+
+ item.ProviderImageUrl = channelInfo.ImageUrl;
+ item.HasProviderImage = channelInfo.HasImage;
+ item.ProviderImagePath = channelInfo.ImagePath;
+
if (string.IsNullOrEmpty(item.Name))
{
item.Name = channelInfo.Name;
@@ -472,7 +503,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
await item.RefreshMetadata(new MetadataRefreshOptions
{
- ForceSave = isNew
+ ForceSave = isNew,
+ ReplaceImages = replaceImages.Distinct().ToList()
}, cancellationToken);
@@ -560,24 +592,28 @@ namespace MediaBrowser.Server.Implementations.LiveTv
};
}
- if (!string.IsNullOrEmpty(info.Path))
- {
- item.Path = info.Path;
- }
- else if (!string.IsNullOrEmpty(info.Url))
- {
- item.Path = info.Url;
- }
-
isNew = true;
}
item.RecordingInfo = info;
item.ServiceName = serviceName;
+ var originalPath = item.Path;
+
+ if (!string.IsNullOrEmpty(info.Path))
+ {
+ item.Path = info.Path;
+ }
+ else if (!string.IsNullOrEmpty(info.Url))
+ {
+ item.Path = info.Url;
+ }
+
+ var pathChanged = !string.Equals(originalPath, item.Path);
+
await item.RefreshMetadata(new MetadataRefreshOptions
{
- ForceSave = isNew
+ ForceSave = isNew || pathChanged
}, cancellationToken);
@@ -1010,9 +1046,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private double GetGuideDays(int channelCount)
{
- if (_config.Configuration.LiveTvOptions.GuideDays.HasValue)
+ var config = GetConfiguration();
+
+ if (config.GuideDays.HasValue)
{
- return _config.Configuration.LiveTvOptions.GuideDays.Value;
+ return config.GuideDays.Value;
}
var programsPerDay = channelCount * 48;
@@ -1032,15 +1070,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return channels.Select(i => new Tuple<string, ChannelInfo>(service.Name, i));
}
- public async Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, CancellationToken cancellationToken)
+ public async Task<QueryResult<BaseItem>> GetInternalRecordings(RecordingQuery query, CancellationToken cancellationToken)
{
var service = ActiveService;
if (service == null)
{
- return new QueryResult<RecordingInfoDto>
+ return new QueryResult<BaseItem>
{
- Items = new RecordingInfoDto[] { }
+ Items = new BaseItem[] { }
};
}
@@ -1125,7 +1163,30 @@ namespace MediaBrowser.Server.Implementations.LiveTv
entities = entities.Take(query.Limit.Value);
}
- var returnArray = entities
+ return new QueryResult<BaseItem>
+ {
+ Items = entities.Cast<BaseItem>().ToArray(),
+ TotalRecordCount = entityList.Count
+ };
+ }
+
+ public async Task<QueryResult<RecordingInfoDto>> GetRecordings(RecordingQuery query, CancellationToken cancellationToken)
+ {
+ var service = ActiveService;
+
+ if (service == null)
+ {
+ return new QueryResult<RecordingInfoDto>
+ {
+ Items = new RecordingInfoDto[] { }
+ };
+ }
+
+ var user = string.IsNullOrEmpty(query.UserId) ? null : _userManager.GetUserById(new Guid(query.UserId));
+
+ var internalResult = await GetInternalRecordings(query, cancellationToken).ConfigureAwait(false);
+
+ var returnArray = internalResult.Items.Cast<ILiveTvRecording>()
.Select(i =>
{
var channel = string.IsNullOrEmpty(i.RecordingInfo.ChannelId) ? null : GetInternalChannel(_tvDtoService.GetInternalChannelId(service.Name, i.RecordingInfo.ChannelId));
@@ -1136,7 +1197,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return new QueryResult<RecordingInfoDto>
{
Items = returnArray,
- TotalRecordCount = entityList.Count
+ TotalRecordCount = internalResult.TotalRecordCount
};
}
@@ -1597,20 +1658,38 @@ namespace MediaBrowser.Server.Implementations.LiveTv
};
}
+ class LiveStreamData
+ {
+ internal LiveStreamInfo Info;
+ internal int ConsumerCount;
+ internal string ItemId;
+ internal bool IsChannel;
+ }
+
public async Task CloseLiveStream(string id, CancellationToken cancellationToken)
{
await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
- var service = ActiveService;
-
- _logger.Info("Closing live stream from {0}, stream Id: {1}", service.Name, id);
-
try
{
- await service.CloseLiveStream(id, cancellationToken).ConfigureAwait(false);
+ var service = ActiveService;
- LiveStreamInfo removed;
- _openStreams.TryRemove(id, out removed);
+ LiveStreamData data;
+ if (_openStreams.TryGetValue(id, out data))
+ {
+ if (data.ConsumerCount > 1)
+ {
+ data.ConsumerCount--;
+ _logger.Info("Decrementing live stream client count.");
+ return;
+ }
+
+ }
+ _openStreams.TryRemove(id, out data);
+
+ _logger.Info("Closing live stream from {0}, stream Id: {1}", service.Name, id);
+
+ await service.CloseLiveStream(id, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -1662,7 +1741,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
foreach (var stream in _openStreams.Values.ToList())
{
- var task = CloseLiveStream(stream.Id, CancellationToken.None);
+ var task = CloseLiveStream(stream.Info.Id, CancellationToken.None);
Task.WaitAll(task);
}
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json
index d9bde2090..91796d5dc 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "\u0627\u064a\u0642\u0627\u0641",
- "OptionOn": "\u062a\u0634\u063a\u064a\u0644",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "My Library",
"SettingsSaved": "\u062a\u0645 \u062d\u0641\u0638 \u0627\u0644\u0627\u0639\u062f\u0627\u062f\u0627\u062a.",
"AddUser": "\u0627\u0636\u0627\u0641\u0629 \u0645\u0633\u062a\u062e\u062f\u0645",
"Users": "\u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645\u064a\u0646",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episode",
"LabelSeries": "Series",
"LabelStopping": "Stopping",
- "ButtonStop": "Stop",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Unknown language",
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
"ButtonPause": "Pause",
"ButtonPlay": "Play",
"ButtonEdit": "Edit",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
+ "ButtonPlayTrailer": "Play trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Previous Track",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
"ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
"HeaderSeriesRecordings": "Series Recordings",
"LabelAnytime": "Any time",
"StatusRecording": "Recording",
@@ -130,7 +123,8 @@
"HeaderMyViews": "My Views",
"HeaderLibraryFolders": "Media Folders",
"HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
"HeaderFavoriteMovies": "Favorite Movies",
"HeaderFavoriteShows": "Favorite Shows",
"HeaderFavoriteEpisodes": "Favorite Episodes",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
"HeaderSelectImagesByNamePath": "Select Images By Name Path",
"HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
"HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Remote access: {0}",
"LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
"HeaderLatestFromChannel": "Latest from {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Unknown language",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "\u0645\u0648\u0627\u0641\u0642",
+ "ButtonCancel": "\u0627\u0644\u063a\u0627\u0621",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "Scenes",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "Name",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Channels",
+ "HeaderMediaFolders": "Media Folders",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "Ended",
+ "OptionContinuing": "Continuing",
+ "OptionOff": "\u0627\u064a\u0642\u0627\u0641",
+ "OptionOn": "\u062a\u0634\u063a\u064a\u0644",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPeople": "People",
+ "OptionRuntime": "\u0632\u0645\u0646 \u0627\u0644\u062a\u0634\u063a\u064a\u0644",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Server",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Advanced",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonScenes": "Scenes",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "Select",
+ "ButtonNew": "New",
+ "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:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Movies",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episodes",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Season number:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Movies",
+ "TabSeries": "Series",
+ "TabEpisodes": "\u0627\u0644\u062d\u0644\u0642\u0627\u062a",
+ "TabTrailers": "Trailers",
+ "TabGames": "Games",
+ "TabAlbums": "\u0627\u0644\u0628\u0648\u0645\u0627\u062a",
+ "TabSongs": "\u0627\u0644\u0627\u063a\u0627\u0646\u0649",
+ "TabMusicVideos": "\u0645\u0648\u0633\u064a\u0642\u0649 \u0627\u0644\u0641\u064a\u062f\u064a\u0648",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json
index b6c67083e..1440a079c 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "Apagat",
- "OptionOn": "Enc\u00e8s",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "My Library",
"SettingsSaved": "Configuraci\u00f3 guardada.",
"AddUser": "Afegir Usuari",
"Users": "Usuaris",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episode",
"LabelSeries": "Series",
"LabelStopping": "Stopping",
- "ButtonStop": "Stop",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Unknown language",
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
"ButtonPause": "Pause",
"ButtonPlay": "Play",
"ButtonEdit": "Edit",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
+ "ButtonPlayTrailer": "Play trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Previous Track",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
"ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
"HeaderSeriesRecordings": "Series Recordings",
"LabelAnytime": "Any time",
"StatusRecording": "Recording",
@@ -130,7 +123,8 @@
"HeaderMyViews": "My Views",
"HeaderLibraryFolders": "Media Folders",
"HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
"HeaderFavoriteMovies": "Favorite Movies",
"HeaderFavoriteShows": "Favorite Shows",
"HeaderFavoriteEpisodes": "Favorite Episodes",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
"HeaderSelectImagesByNamePath": "Select Images By Name Path",
"HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
"HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Remote access: {0}",
"LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
"HeaderLatestFromChannel": "Latest from {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Unknown language",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Cancel",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "Scenes",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "Name",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Channels",
+ "HeaderMediaFolders": "Media Folders",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "Ended",
+ "OptionContinuing": "Continuing",
+ "OptionOff": "Apagat",
+ "OptionOn": "Enc\u00e8s",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPeople": "People",
+ "OptionRuntime": "Runtime",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Server",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Advanced",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonScenes": "Scenes",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "Select",
+ "ButtonNew": "New",
+ "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:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Movies",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episodes",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Season number:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Movies",
+ "TabSeries": "Series",
+ "TabEpisodes": "Episodes",
+ "TabTrailers": "Trailers",
+ "TabGames": "Games",
+ "TabAlbums": "Albums",
+ "TabSongs": "Songs",
+ "TabMusicVideos": "Music Videos",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json
index 6998eaccc..e9e733300 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "Vypnout",
- "OptionOn": "Zapnout",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "My Library",
"SettingsSaved": "Nastaven\u00ed ulo\u017eeno.",
"AddUser": "P\u0159idat u\u017eivatele",
"Users": "U\u017eivatel\u00e9",
@@ -35,20 +27,19 @@
"BrowsePluginCatalogMessage": "Prohl\u00e9dn\u011bte si n\u00e1\u0161 katalog, kde najdete dostupn\u00e9 pluginy.",
"MessageKeyEmailedTo": "Key emailed to {0}.",
"MessageKeysLinked": "Keys linked.",
- "HeaderConfirmation": "Confirmation",
+ "HeaderConfirmation": "Potvrzen\u00ed",
"MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
"MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
"ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
- "HeaderSearch": "Search",
- "LabelArtist": "Artist",
- "LabelMovie": "Movie",
- "LabelMusicVideo": "Music Video",
- "LabelEpisode": "Episode",
- "LabelSeries": "Series",
+ "HeaderSearch": "Vyhled\u00e1v\u00e1n\u00ed",
+ "LabelArtist": "Um\u011blec",
+ "LabelMovie": "Film",
+ "LabelMusicVideo": "Hudebn\u00ed video",
+ "LabelEpisode": "Epizoda",
+ "LabelSeries": "S\u00e9rie",
"LabelStopping": "Stopping",
- "ButtonStop": "Stop",
- "LabelCancelled": "(cancelled)",
- "LabelFailed": "(failed)",
+ "LabelCancelled": "(zru\u0161eno)",
+ "LabelFailed": "(ne\u00fasp\u011b\u0161n\u00e9)",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -66,37 +57,40 @@
"LabelUnknownLanguage": "Unknown language",
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
"ButtonPause": "Pause",
"ButtonPlay": "P\u0159ehr\u00e1t",
"ButtonEdit": "Upravit",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
+ "ButtonPlayTrailer": "Play trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "P\u0159edchod\u00ed stopa",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
"LabelNoUnreadNotifications": "No unread notifications.",
- "ButtonViewNotifications": "View notifications",
- "ButtonMarkTheseRead": "Mark these read",
- "ButtonClose": "Close",
+ "ButtonViewNotifications": "Zobrazit notifikace",
+ "ButtonMarkTheseRead": "Ozna\u010dit jako p\u0159e\u010dten\u00e9",
+ "ButtonClose": "Zav\u0159\u00edt",
"LabelAllPlaysSentToPlayer": "All plays will be sent to the selected player.",
- "MessageInvalidUser": "Invalid user or password.",
+ "MessageInvalidUser": "Neplatn\u00e9 u\u017eivatelsk\u00e9 jm\u00e9no nebo heslo.",
"HeaderAllRecordings": "V\u0161echna nahr\u00e1v\u00e1n\u00ed",
- "RecommendationBecauseYouLike": "Because you like {0}",
- "RecommendationBecauseYouWatched": "Because you watched {0}",
- "RecommendationDirectedBy": "Directed by {0}",
+ "RecommendationBecauseYouLike": "Proto\u017ee se v\u00e1m l\u00edb\u00ed {0}",
+ "RecommendationBecauseYouWatched": "Proto\u017ee jste sledovali {0}",
+ "RecommendationDirectedBy": "Re\u017e\u00edrov\u00e1no {0}",
"RecommendationStarring": "Starring {0}",
"HeaderConfirmRecordingCancellation": "Confirm Recording Cancellation",
"MessageConfirmRecordingCancellation": "Are you sure you wish to cancel this recording?",
"MessageRecordingCancelled": "Recording cancelled.",
"HeaderConfirmSeriesCancellation": "Confirm Series Cancellation",
"MessageConfirmSeriesCancellation": "Are you sure you wish to cancel this series?",
- "MessageSeriesCancelled": "Series cancelled.",
+ "MessageSeriesCancelled": "S\u00e9rie zru\u0161ena.",
"HeaderConfirmRecordingDeletion": "Confirm Recording Deletion",
"MessageConfirmRecordingDeletion": "Are you sure you wish to delete this recording?",
"MessageRecordingDeleted": "Recording deleted.",
- "ButonCancelRecording": "Cancel Recording",
- "MessageRecordingSaved": "Recording saved.",
+ "ButonCancelRecording": "Zru\u0161it nahr\u00e1v\u00e1n\u00ed",
+ "MessageRecordingSaved": "Nahr\u00e1van\u00ed ulo\u017eeno",
"OptionSunday": "Ned\u011ble",
"OptionMonday": "Pond\u011bl\u00ed",
"OptionTuesday": "\u00dater\u00fd",
@@ -104,35 +98,35 @@
"OptionThursday": "\u010ctvrtek",
"OptionFriday": "P\u00e1tek",
"OptionSaturday": "Sobota",
- "HeaderConfirmDeletion": "Confirm Deletion",
+ "HeaderConfirmDeletion": "Potvrdit smaz\u00e1n\u00ed",
"MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
- "LiveTvUpdateAvailable": "(Update available)",
- "LabelVersionUpToDate": "Up to date!",
+ "LiveTvUpdateAvailable": "(Aktualizace dostupn\u00e1)",
+ "LabelVersionUpToDate": "Aktu\u00e1ln\u00ed!",
"ButtonResetTuner": "Reset tuner",
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
"ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
"HeaderSeriesRecordings": "Series Recordings",
"LabelAnytime": "Any time",
- "StatusRecording": "Recording",
+ "StatusRecording": "Nahr\u00e1v\u00e1n\u00ed",
"StatusWatching": "Watching",
"StatusRecordingProgram": "Recording {0}",
"StatusWatchingProgram": "Watching {0}",
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
- "HeaderError": "Error",
+ "HeaderError": "Chyba",
"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": "Media Browser clients will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?",
"HeaderResume": "Pozastavit",
"HeaderMyViews": "My Views",
- "HeaderLibraryFolders": "Media Folders",
+ "HeaderLibraryFolders": "Slo\u017eky m\u00e9di\u00ed",
"HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
- "HeaderFavoriteMovies": "Favorite Movies",
- "HeaderFavoriteShows": "Favorite Shows",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "V\u00edce...",
+ "HeaderFavoriteMovies": "Obl\u00edben\u00e9 filmy",
+ "HeaderFavoriteShows": "Obl\u00edben\u00e9 seri\u00e1ly",
"HeaderFavoriteEpisodes": "Favorite Episodes",
"HeaderFavoriteGames": "Favorite Games",
"HeaderRatingsDownloads": "Rating \/ Downloads",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
"HeaderSelectImagesByNamePath": "Select Images By Name Path",
"HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
"HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
@@ -153,15 +147,15 @@
"ButtonRemove": "Odstranit",
"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.",
- "HeaderFavoriteAlbums": "Favorite Albums",
+ "HeaderFavoriteAlbums": "Obl\u00edben\u00e1 alba",
"HeaderLatestChannelMedia": "Latest Channel Items",
"ButtonOrganizeFile": "Organize File",
- "ButtonDeleteFile": "Delete File",
+ "ButtonDeleteFile": "Smazat soubor",
"HeaderOrganizeFile": "Organize File",
- "HeaderDeleteFile": "Delete File",
- "StatusSkipped": "Skipped",
- "StatusFailed": "Failed",
- "StatusSuccess": "Success",
+ "HeaderDeleteFile": "Smazat soubor",
+ "StatusSkipped": "P\u0159esko\u010deno",
+ "StatusFailed": "Chyba",
+ "StatusSuccess": "\u00dasp\u011bch",
"MessageFileWillBeDeleted": "The following file will be deleted:",
"MessageSureYouWishToProceed": "Are you sure you wish to proceed?",
"MessageDuplicatesWillBeDeleted": "In addition the following dupliates will be deleted:",
@@ -174,7 +168,7 @@
"HeaderShutdown": "Shutdown",
"MessageConfirmRestart": "Are you sure you wish to restart Media Browser Server?",
"MessageConfirmShutdown": "Are you sure you wish to shutdown Media Browser Server?",
- "ButtonUpdateNow": "Update Now",
+ "ButtonUpdateNow": "Aktualizujte te\u010f",
"NewVersionOfSomethingAvailable": "A new version of {0} is available!",
"VersionXIsAvailableForDownload": "Version {0} is now available for download.",
"LabelVersionNumber": "Version {0}",
@@ -185,13 +179,255 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Remote access: {0}",
"LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
"HeaderLatestFromChannel": "Latest from {0}",
- "ButtonDownload": "Download",
+ "ButtonDownload": "St\u00e1hnout",
"LabelUnknownLanaguage": "Unknown language",
"HeaderCurrentSubtitles": "Current Subtitles",
"MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Zru\u0161it",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Otev\u0159\u00edt",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Pokra\u010dovat",
+ "HeaderScenes": "Sc\u00e9ny",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Titulky",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Dom\u016f",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Hl\u00e1\u0161en\u00ed",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "N\u00e1zev",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Um\u011blec",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Kan\u00e1ly",
+ "HeaderMediaFolders": "Slo\u017eky m\u00e9di\u00ed",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "Televizn\u00ed po\u0159ady",
+ "OptionBlockTrailers": "Upout\u00e1vky",
+ "OptionBlockMusic": "Hudba",
+ "OptionBlockMovies": "Filmy",
+ "OptionBlockBooks": "Knihy",
+ "OptionBlockGames": "Hry",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "Ukon\u010deno",
+ "OptionContinuing": "Pokra\u010dov\u00e1n\u00ed",
+ "OptionOff": "Vypnout",
+ "OptionOn": "Zapnout",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Rodi\u010dovsk\u00e9 hodnocen\u00ed",
+ "OptionPeople": "People",
+ "OptionRuntime": "D\u00e9lka",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Server",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Pokro\u010dil\u00e9",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Titulky",
+ "ButtonScenes": "Sc\u00e9ny",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "Vybrat",
+ "ButtonNew": "Nov\u00e9",
+ "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": "Jm\u00e9no:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Filmy",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episody",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "\u010c\u00edslo s\u00e9rie",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "\u010c\u00edslo epizody",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Filmy",
+ "TabSeries": "S\u00e9rie",
+ "TabEpisodes": "Epizody",
+ "TabTrailers": "Uk\u00e1zky\/trailery",
+ "TabGames": "Hry",
+ "TabAlbums": "Alba",
+ "TabSongs": "Skladby",
+ "TabMusicVideos": "Hudebn\u00ed videa",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json
index 0e6fe6a33..4703d6b9f 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "Off",
- "OptionOn": "On",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "Mit bibliotek",
"SettingsSaved": "Indstillinger er gemt",
"AddUser": "Tilf\u00f8j bruger",
"Users": "Brugere",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episode",
"LabelSeries": "Series",
"LabelStopping": "Stopping",
- "ButtonStop": "Stop",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Unknown language",
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
"ButtonPause": "Pause",
"ButtonPlay": "Afspil",
"ButtonEdit": "Rediger",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
+ "ButtonPlayTrailer": "Play trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Previous Track",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
"ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
"HeaderSeriesRecordings": "Series Recordings",
"LabelAnytime": "Any time",
"StatusRecording": "Recording",
@@ -130,7 +123,8 @@
"HeaderMyViews": "My Views",
"HeaderLibraryFolders": "Media Folders",
"HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
"HeaderFavoriteMovies": "Favorite Movies",
"HeaderFavoriteShows": "Favorite Shows",
"HeaderFavoriteEpisodes": "Favorite Episodes",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
"HeaderSelectImagesByNamePath": "Select Images By Name Path",
"HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
"HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Remote access: {0}",
"LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
"HeaderLatestFromChannel": "Latest from {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Unknown language",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Annuller",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "Scenes",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Hjem",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "Name",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Kanaler",
+ "HeaderMediaFolders": "Media Folders",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "F\u00e6rdig",
+ "OptionContinuing": "Fors\u00e6ttes",
+ "OptionOff": "Off",
+ "OptionOn": "On",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPeople": "People",
+ "OptionRuntime": "Varighed",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Server",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Advanceret",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Undertekster",
+ "ButtonScenes": "Scener",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "V\u00e6lg",
+ "ButtonNew": "Ny",
+ "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": "Navn:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Film",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episoder",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Season number:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Film",
+ "TabSeries": "Serier",
+ "TabEpisodes": "Episoder",
+ "TabTrailers": "Trailere",
+ "TabGames": "Spil",
+ "TabAlbums": "Albums",
+ "TabSongs": "Sange",
+ "TabMusicVideos": "Musik Videoer",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json
index b2987fa9c..e671c7da0 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Passwort erstellen",
- "OptionOff": "Aus",
- "OptionOn": "Ein",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "Meine Bibliothek",
"SettingsSaved": "Einstellungen gespeichert",
"AddUser": "Benutzer hinzuf\u00fcgen",
"Users": "Benutzer",
@@ -33,24 +25,23 @@
"NoPluginConfigurationMessage": "Bei diesem Plugin kann nichts eingestellt werden.",
"NoPluginsInstalledMessage": "Sie haben keine Plugins installiert.",
"BrowsePluginCatalogMessage": "Durchsuchen Sie unsere Bibliothek um alle verf\u00fcgbaren Plugins anzuzeigen.",
- "MessageKeyEmailedTo": "Key emailed to {0}.",
+ "MessageKeyEmailedTo": "E-Mail mit Zugangsschl\u00fcssel an: {0}.",
"MessageKeysLinked": "Schl\u00fcssel verkn\u00fcpft.",
"HeaderConfirmation": "Best\u00e4tigung",
"MessageKeyUpdated": "Danke. Ihr Unterst\u00fctzerschl\u00fcssel wurde aktualisiert.",
"MessageKeyRemoved": "Danke. Ihr Unterst\u00fctzerschl\u00fcssel wurde entfernt.",
- "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
+ "ErrorLaunchingChromecast": "W\u00e4hrend des startens von Chromecast ist ein Fehler aufgetreten. Bitte stelle sicher, dass dein Ger\u00e4te mit dem WLAN verbunden ist.",
"HeaderSearch": "Suche",
- "LabelArtist": "K\u00fcnstler",
+ "LabelArtist": "Interpret",
"LabelMovie": "Film",
"LabelMusicVideo": "Musikvideo",
"LabelEpisode": "Episode",
"LabelSeries": "Serie",
- "LabelStopping": "Stopping",
- "ButtonStop": "Stop",
+ "LabelStopping": "Stoppe",
"LabelCancelled": "(abgebrochen)",
"LabelFailed": "(fehlgeschlagen)",
- "LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
- "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
+ "LabelAbortedByServerShutdown": "(Durch herunterfahrenden Server abgebrochen)",
+ "LabelScheduledTaskLastRan": "Zuletzt ausgef\u00fchrt vor: {0}. Ben\u00f6tigte Zeit: {1}.",
"HeaderDeleteTaskTrigger": "Entferne Aufgabenausl\u00f6ser",
"HeaderTaskTriggers": "Aufgabenausl\u00f6ser",
"MessageDeleteTaskTrigger": "Sind Sie sicher, dass sie diesen Aufgabenausl\u00f6ser entfernen wollen?",
@@ -61,42 +52,45 @@
"HeaderSelectAudio": "W\u00e4hle Audio",
"HeaderSelectSubtitles": "W\u00f6hle Untertitel",
"LabelDefaultStream": "(Default)",
- "LabelForcedStream": "(Forced)",
- "LabelDefaultForcedStream": "(Default\/Forced)",
- "LabelUnknownLanguage": "Unknown language",
+ "LabelForcedStream": "(Erzwungen)",
+ "LabelDefaultForcedStream": "(Standard\/Erzwungen)",
+ "LabelUnknownLanguage": "Unbekannte Sprache",
"ButtonMute": "Stumm",
- "ButtonUnmute": "Unmute",
+ "ButtonUnmute": "Ton ein",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "N\u00e4chstes St\u00fcck",
"ButtonPause": "Pause",
"ButtonPlay": "Abspielen",
"ButtonEdit": "Bearbeiten",
- "ButtonQueue": "Queue",
- "ButtonPlayTrailer": "Spiele Trailer",
- "ButtonPlaylist": "Playlist",
- "LabelEnabled": "Enabled",
- "LabelDisabled": "Disabled",
- "ButtonMoreInformation": "More Information",
- "LabelNoUnreadNotifications": "No unread notifications.",
- "ButtonViewNotifications": "View notifications",
- "ButtonMarkTheseRead": "Mark these read",
- "ButtonClose": "Close",
- "LabelAllPlaysSentToPlayer": "All plays will be sent to the selected player.",
- "MessageInvalidUser": "Invalid user or password.",
+ "ButtonQueue": "Warteschlange",
+ "ButtonPlayTrailer": "Trailer abspielen",
+ "ButtonPlaylist": "Wiedergabeliste",
+ "ButtonPreviousTrack": "Vorheriges St\u00fcck",
+ "LabelEnabled": "Aktivieren",
+ "LabelDisabled": "Deaktivieren",
+ "ButtonMoreInformation": "mehr Informationen",
+ "LabelNoUnreadNotifications": "Keine ungelesenen Benachrichtigungen",
+ "ButtonViewNotifications": "Benachrichtigungen anschauen",
+ "ButtonMarkTheseRead": "Als gelesen markieren",
+ "ButtonClose": "Schlie\u00dfen",
+ "LabelAllPlaysSentToPlayer": "Alle Wiedergaben werden zum ausgew\u00e4hlten Abspielger\u00e4t gesendet.",
+ "MessageInvalidUser": "Falscher Benutzername oder Passwort.",
"HeaderAllRecordings": "Alle Aufnahmen",
- "RecommendationBecauseYouLike": "Because you like {0}",
- "RecommendationBecauseYouWatched": "Because you watched {0}",
- "RecommendationDirectedBy": "Directed by {0}",
- "RecommendationStarring": "Starring {0}",
- "HeaderConfirmRecordingCancellation": "Confirm Recording Cancellation",
- "MessageConfirmRecordingCancellation": "Are you sure you wish to cancel this recording?",
- "MessageRecordingCancelled": "Recording cancelled.",
- "HeaderConfirmSeriesCancellation": "Confirm Series Cancellation",
- "MessageConfirmSeriesCancellation": "Are you sure you wish to cancel this series?",
- "MessageSeriesCancelled": "Series cancelled.",
- "HeaderConfirmRecordingDeletion": "Confirm Recording Deletion",
- "MessageConfirmRecordingDeletion": "Are you sure you wish to delete this recording?",
- "MessageRecordingDeleted": "Recording deleted.",
- "ButonCancelRecording": "Cancel Recording",
- "MessageRecordingSaved": "Recording saved.",
+ "RecommendationBecauseYouLike": "Weil du auch {0} magst",
+ "RecommendationBecauseYouWatched": "Weil du auch {0} angesehen hast",
+ "RecommendationDirectedBy": "Unter der Regie von {0}",
+ "RecommendationStarring": "In der Hauptrolle {0}",
+ "HeaderConfirmRecordingCancellation": "Best\u00e4tige Aufzeichnungsabbruch",
+ "MessageConfirmRecordingCancellation": "Bis du dir sicher, diese Aufzeichnung abzubrechen?",
+ "MessageRecordingCancelled": "Aufzeichnung abgebrochen.",
+ "HeaderConfirmSeriesCancellation": "Best\u00e4tige Serienabbruch",
+ "MessageConfirmSeriesCancellation": "Bis du dir sicher, diese Serie abzubrechen?",
+ "MessageSeriesCancelled": "Serie abgebrochen.",
+ "HeaderConfirmRecordingDeletion": "Best\u00e4tige L\u00f6schung der Aufzeichnung",
+ "MessageConfirmRecordingDeletion": "Bis du dir sicher, diese Aufzeichnung zu l\u00f6schen?",
+ "MessageRecordingDeleted": "Aufnahme gel\u00f6scht",
+ "ButonCancelRecording": "Aufnahme abbrechen",
+ "MessageRecordingSaved": "Aufnahme gespeichert",
"OptionSunday": "Sonntag",
"OptionMonday": "Montag",
"OptionTuesday": "Dienstag",
@@ -104,94 +98,336 @@
"OptionThursday": "Donnerstag",
"OptionFriday": "Freitag",
"OptionSaturday": "Samstag",
- "HeaderConfirmDeletion": "Confirm Deletion",
- "MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
- "LiveTvUpdateAvailable": "(Update available)",
+ "HeaderConfirmDeletion": "Best\u00e4tige L\u00f6schung",
+ "MessageConfirmPathSubstitutionDeletion": "Bist du dir sicher die Pfadsubstitution l\u00f6schen zu wollen?",
+ "LiveTvUpdateAvailable": "(Update verf\u00fcgbar)",
"LabelVersionUpToDate": "Auf dem neuesten Stand!",
"ButtonResetTuner": "Tuner zur\u00fccksetzen",
"HeaderResetTuner": "Tuner zur\u00fccksetzen",
"MessageConfirmResetTuner": "sind Sie sicher, dass Sie diesen Tuner zur\u00fccksetzen wollen? Alle aktiven Wiedergaben und Aufnahmen werden sofort beendet.",
- "ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "Alle Channel",
- "HeaderSeriesRecordings": "Series Recordings",
+ "ButtonCancelSeries": "Serien abbrechen",
+ "HeaderSeriesRecordings": "Aufgezeichnete Serien",
"LabelAnytime": "Jederzeit",
- "StatusRecording": "Recording",
- "StatusWatching": "Watching",
- "StatusRecordingProgram": "Recording {0}",
- "StatusWatchingProgram": "Watching {0}",
+ "StatusRecording": "Aufnehmen",
+ "StatusWatching": "Anschauing",
+ "StatusRecordingProgram": "Aufzeichnung {0}",
+ "StatusWatchingProgram": "Gesehen {0}",
"HeaderSplitMedia": "Trenne Medien ab",
"MessageConfirmSplitMedia": "Sind Sie sicher, dass Sie die Medienquellen in seperate Elemente aufteilen wollen?",
"HeaderError": "Fehler",
- "MessagePleaseSelectOneItem": "Please select at least one item.",
- "MessagePleaseSelectTwoItems": "Please select at least two items.",
+ "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:",
- "MessageConfirmItemGrouping": "Media Browser clients will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?",
+ "MessageConfirmItemGrouping": "Media Browser Abspielger\u00e4te werden automatisch die optimale Version, basierend auf dem Endger\u00e4t und der Netzwerkperformance, f\u00fcr die Wiedergabe ausw\u00e4hlen. M\u00f6chtest du fortfahren?",
"HeaderResume": "Fortsetzen",
- "HeaderMyViews": "My Views",
- "HeaderLibraryFolders": "Media Folders",
- "HeaderLatestMedia": "Letzte Medien",
- "ButtonMore": "Mehr...",
- "HeaderFavoriteMovies": "Favorite Movies",
- "HeaderFavoriteShows": "Favorite Shows",
- "HeaderFavoriteEpisodes": "Favorite Episodes",
- "HeaderFavoriteGames": "Favorite Games",
- "HeaderRatingsDownloads": "Rating \/ Downloads",
+ "HeaderMyViews": "Meine Ansichten",
+ "HeaderLibraryFolders": "Medienverzeichnisse",
+ "HeaderLatestMedia": "Neueste Medien",
+ "ButtonMoreItems": "Mehr...",
+ "ButtonMore": "Mehr",
+ "HeaderFavoriteMovies": "Lieblingsfilme",
+ "HeaderFavoriteShows": "Lieblingsserien",
+ "HeaderFavoriteEpisodes": "Lieblingsepisoden",
+ "HeaderFavoriteGames": "Lieblingsspiele",
+ "HeaderRatingsDownloads": "Bewertung \/ Downloads",
"HeaderConfirmProfileDeletion": "Best\u00e4tige Profill\u00f6schung",
"MessageConfirmProfileDeletion": "Sind Sie sicher, dass Sie dieses Profil l\u00f6schen wollen?",
"HeaderSelectServerCachePath": "W\u00e4hle Server Cache Pfad:",
- "HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
+ "HeaderSelectTranscodingPath": "W\u00e4hle Pfad f\u00fcr tempor\u00e4re Transkodierdateien",
"HeaderSelectImagesByNamePath": "W\u00e4hle 'Images By Name' Pfad",
"HeaderSelectMetadataPath": "W\u00e4hle Metadaten Pfad",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
- "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
- "HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
- "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
- "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...",
+ "HeaderSelectServerCachePathHelp": "Suche oder gib den Pfad f\u00fcr die Speicherung von Server Cache Dateien an. Das Verzeichnis muss beschreibbar sein.",
+ "HeaderSelectTranscodingPathHelp": "Suche oder gib den Pfad f\u00fcr die Speicherung von tempor\u00e4ren Transkodierdateien an. Das Verzeichnis muss beschreibbar sein.",
+ "HeaderSelectImagesByNamePathHelp": "Suche oder gib den Pfad f\u00fcr die Speicherung von Namensdaten an. Das Verzeichnis muss beschreibbar sein.",
+ "HeaderSelectMetadataPathHelp": "Suche oder gib den Pfad f\u00fcr die Speicherung von Metadaten an. Das Verzeichnis muss beschreibbar sein.",
+ "HeaderSelectChannelDownloadPath": "W\u00e4hle den Downloadpfad f\u00fcr Channel Plugins",
+ "HeaderSelectChannelDownloadPathHelp": "Suche oder gib den Pfad f\u00fcr die Speicherung von Channel Cache Dateien an. Das Verzeichnis muss beschreibbar sein.",
+ "OptionNewCollection": "Neu...",
"ButtonAdd": "Hinzuf\u00fcgen",
"ButtonRemove": "Entfernen",
- "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.",
- "HeaderFavoriteAlbums": "Favorite Albums",
- "HeaderLatestChannelMedia": "Latest Channel Items",
- "ButtonOrganizeFile": "Organize File",
- "ButtonDeleteFile": "Delete File",
- "HeaderOrganizeFile": "Organize File",
- "HeaderDeleteFile": "Delete File",
- "StatusSkipped": "Skipped",
- "StatusFailed": "Failed",
- "StatusSuccess": "Success",
- "MessageFileWillBeDeleted": "The following file will be deleted:",
- "MessageSureYouWishToProceed": "Are you sure you wish to proceed?",
- "MessageDuplicatesWillBeDeleted": "In addition the following dupliates will be deleted:",
- "MessageFollowingFileWillBeMovedFrom": "The following file will be moved from:",
- "MessageDestinationTo": "to:",
- "HeaderSelectWatchFolder": "Select Watch Folder",
- "HeaderSelectWatchFolderHelp": "Browse or enter the path to your watch folder. The folder must be writeable.",
- "OrganizePatternResult": "Result: {0}",
- "HeaderRestart": "Restart",
- "HeaderShutdown": "Shutdown",
- "MessageConfirmRestart": "Are you sure you wish to restart Media Browser Server?",
- "MessageConfirmShutdown": "Are you sure you wish to shutdown Media Browser Server?",
+ "LabelChapterDownloaders": "Kapitel Downloader:",
+ "LabelChapterDownloadersHelp": "Aktiviere und ordne die Kapitel Downloader nach deinen Pr\u00e4ferenzen. Downloader mit geringer Priorit\u00e4t werden nur genutzt um fehlende Informationen zu erg\u00e4nzen.",
+ "HeaderFavoriteAlbums": "Lieblingsalben",
+ "HeaderLatestChannelMedia": "Neueste Channel Inhalte",
+ "ButtonOrganizeFile": "Organisiere Datei",
+ "ButtonDeleteFile": "L\u00f6sche Datei",
+ "HeaderOrganizeFile": "Organisiere Datei",
+ "HeaderDeleteFile": "L\u00f6sche Datei",
+ "StatusSkipped": "\u00dcbersprungen",
+ "StatusFailed": "Fehlgeschlagen",
+ "StatusSuccess": "Erfolgreich",
+ "MessageFileWillBeDeleted": "Die folgende Datei wird gel\u00f6scht:",
+ "MessageSureYouWishToProceed": "Bis du dir sicher fortfahren zu wollen?",
+ "MessageDuplicatesWillBeDeleted": "Zus\u00e4tzlich werden folgende Duplikate gel\u00f6scht:",
+ "MessageFollowingFileWillBeMovedFrom": "Die folgende Datei wird verschoben von:",
+ "MessageDestinationTo": "nach:",
+ "HeaderSelectWatchFolder": "W\u00e4hle \"Gesehen\" Verzeichnis",
+ "HeaderSelectWatchFolderHelp": "Suche oder gib den Pfad f\u00fcr die Speicherung von \"Gesehen\" Informationen an. Das Verzeichnis muss beschreibbar sein.",
+ "OrganizePatternResult": "Ergebnis: {0}",
+ "HeaderRestart": "Neustart",
+ "HeaderShutdown": "Herunterfahren",
+ "MessageConfirmRestart": "Bist du dir sicher Media Browser Server neustarten zu wollen?",
+ "MessageConfirmShutdown": "Bist du dir sicher Media Browser Server herunterfahren zu wollen?",
"ButtonUpdateNow": "Jetzt aktualisieren",
- "NewVersionOfSomethingAvailable": "A new version of {0} is available!",
- "VersionXIsAvailableForDownload": "Version {0} is now available for download.",
+ "NewVersionOfSomethingAvailable": "Eine neue Version von {0} ist verf\u00fcgbar!",
+ "VersionXIsAvailableForDownload": "Version {0} ist jetzt bereit zum download.",
"LabelVersionNumber": "Version {0}",
- "LabelPlayMethodTranscoding": "Transcoding",
- "LabelPlayMethodDirectStream": "Direct Streaming",
- "LabelPlayMethodDirectPlay": "Direct Playing",
+ "LabelPlayMethodTranscoding": "Transkodieren",
+ "LabelPlayMethodDirectStream": "Direktes Streaming",
+ "LabelPlayMethodDirectPlay": "Direktes Abspielen",
"LabelAudioCodec": "Audio: {0}",
"LabelVideoCodec": "Video: {0}",
- "LabelRemoteAccessUrl": "Remote access: {0}",
- "LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
- "HeaderLatestFromChannel": "Latest from {0}",
+ "LabelRemoteAccessUrl": "Fernzugriff: {0}",
+ "LabelRunningOnPort": "L\u00e4uft \u00fcber Port {0}.",
+ "HeaderLatestFromChannel": "Neuestes von {0}",
"ButtonDownload": "Download",
- "LabelUnknownLanaguage": "Unknown language",
- "HeaderCurrentSubtitles": "Current Subtitles",
- "MessageDownloadQueued": "The download has been queued.",
- "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
- "ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "LabelUnknownLanaguage": "Unbekannte Sprache",
+ "HeaderCurrentSubtitles": "Aktuelle Untertitel",
+ "MessageDownloadQueued": "Der Download wurde in die Warteschlange verschoben.",
+ "MessageAreYouSureDeleteSubtitles": "Bist du dir sicher diese Untertitel Datei l\u00f6schen zu wollen?",
+ "ButtonRemoteControl": "Fernsteuerung",
+ "HeaderLatestTvRecordings": "Neueste Aufnahmen",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Abbrechen",
+ "ButtonRefresh": "Aktualisieren",
+ "LabelCurrentPath": "Aktueller Pfad:",
+ "HeaderSelectMediaPath": "W\u00e4hle einen Medienpfad:",
+ "ButtonNetwork": "Netzwerk",
+ "MessageDirectoryPickerInstruction": "Falls der Netzwerk Button deine Endger\u00e4te nicht automatisch findet, kannst du deren Netzwerkpfade auch manuell eintragen. Zum Beispiel {0} oder {1}.",
+ "HeaderMenu": "Men\u00fc",
+ "ButtonOpen": "\u00d6ffnen",
+ "ButtonOpenInNewTab": "\u00d6ffne in neuem Tab",
+ "ButtonShuffle": "Zufallswiedergabe",
+ "ButtonInstantMix": "Schnellmix",
+ "ButtonResume": "Wiederholen",
+ "HeaderScenes": "Szenen",
+ "HeaderAudioTracks": "Audiospuren",
+ "HeaderSubtitles": "Untertitel",
+ "HeaderVideoQuality": "Videoqualit\u00e4t",
+ "MessageErrorPlayingVideo": "Es gab einen Fehler bei der Videowiedergabe.",
+ "MessageEnsureOpenTuner": "Bitte stelle sicher, dass ein freier Empf\u00e4nger verf\u00fcgbar ist.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Optionsleiste",
+ "ButtonReports": "Meldungen",
+ "ButtonMetadataManager": "Metadaten Manager",
+ "HeaderTime": "Zeit",
+ "HeaderName": "Name",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album-Interpret",
+ "HeaderArtist": "Interpret",
+ "LabelAddedOnDate": "Hinzugef\u00fcgt {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Kan\u00e4le",
+ "HeaderMediaFolders": "Medienverzeichnisse",
+ "HeaderBlockItemsWithNoRating": "Blockiere Elemente ohne Bewertungsinformationen:",
+ "OptionBlockOthers": "Andere",
+ "OptionBlockTvShows": "TV Serien",
+ "OptionBlockTrailers": "Trailer",
+ "OptionBlockMusic": "Musik",
+ "OptionBlockMovies": "Filme",
+ "OptionBlockBooks": "B\u00fccher",
+ "OptionBlockGames": "Spiele",
+ "OptionBlockLiveTvPrograms": "Live-TV Programm",
+ "OptionBlockLiveTvChannels": "Live-TV Kan\u00e4le",
+ "OptionBlockChannelContent": "Internet Channelinhalte",
+ "ButtonRevoke": "Zur\u00fccknehmen",
+ "MessageConfirmRevokeApiKey": "Bist du dir sicher den API Schl\u00fcssel zur\u00fccknehmen zu wollen? Anwendungen die mit Media Browser verbunden sind werden umgehend gestoppt.",
+ "HeaderConfirmRevokeApiKey": "Nehme API Schl\u00fcssel zur\u00fcck",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Bedingungen: {0}",
+ "LabelAll": "Alle",
+ "HeaderDeleteImage": "L\u00f6sche Bild",
+ "MessageFileNotFound": "Datei nicht gefunden.",
+ "MessageFileReadError": "Fehler beim lesen der Datei",
+ "ButtonNextPage": "N\u00e4chste Seite",
+ "ButtonPreviousPage": "Vorherige Seite",
+ "ButtonMoveLeft": "Nach links",
+ "ButtonMoveRight": "Nach rechts",
+ "ButtonBrowseOnlineImages": "Durchsuche Onlinebilder",
+ "HeaderDeleteItem": "L\u00f6sche Element",
+ "ConfirmDeleteItem": "Bist du dir sicher dieses Element aus deiner Bibliothek zu l\u00f6schen?",
+ "MessagePleaseEnterNameOrId": "Bitte gib einen Namen oder eine externe Id an.",
+ "MessageValueNotCorrect": "Der eingegeben Wert ist nicht korrekt. Bitte versuche es noch einmal.",
+ "MessageItemSaved": "Element gespeichert",
+ "OptionEnded": "Beendent",
+ "OptionContinuing": "Fortdauernd",
+ "OptionOff": "Aus",
+ "OptionOn": "Ein",
+ "HeaderFields": "Felder",
+ "HeaderFieldsHelp": "Verschiebe ein Feld zu \"Aus\" um es zu sperren und \u00c4nderungen an dessen Daten zu verhindern.",
+ "HeaderLiveTV": "Live-TV",
+ "MissingLocalTrailer": "Fehlender lokaler Trailer.",
+ "MissingPrimaryImage": "Fehlendes Hauptbild.",
+ "MissingBackdropImage": "Fehlendes Hintergrundbild.",
+ "MissingLogoImage": "Fehlendes Logobild.",
+ "MissingEpisode": "Fehlende Episode",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Hintergr\u00fcnde",
+ "OptionImages": "Bilder",
+ "OptionKeywords": "Stichworte",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "\u00dcbersicht:",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Altersfreigabe",
+ "OptionPeople": "Personen",
+ "OptionRuntime": "Dauer",
+ "OptionProductionLocations": "Produktionsst\u00e4tten",
+ "OptionBirthLocation": "Geburtsort",
+ "LabelAllChannels": "Alle Kan\u00e4le",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEU",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "\u00c4ndere Verzeichnistyp",
+ "HeaderChangeFolderTypeHelp": "Um den Verzeichnistyp zu \u00e4ndern, entferne diesen bitte und erstelle die Bibliothek mit dem neuen Typ erneut.",
+ "HeaderAlert": "Alarm",
+ "MessagePleaseRestart": "Dr\u00fccke auf Neustart um das Update abzuschlie\u00dfen",
+ "ButtonRestart": "Neu starten",
+ "MessagePleaseRefreshPage": "Bitte aktualisiere diese Seite um neue Updates vom Server zu erhalten.",
+ "ButtonHide": "Verstecke",
+ "MessageSettingsSaved": "Einstellungen gespeichert",
+ "ButtonSignOut": "Abmelden",
+ "ButtonMyProfile": "Mein Profil",
+ "ButtonMyPreferences": "Meine Einstellungen",
+ "MessageBrowserDoesNotSupportWebSockets": "Dieser Browser unterst\u00fctzt keine Websockets. Versuche f\u00fcr ein besseres Nutzungserlebnis einen neueren Browser wie beispielsweise Chrome, Firefox, IE10+, Safari (iOS) oder Opera.",
+ "LabelInstallingPackage": "Installiere {0}",
+ "LabelPackageInstallCompleted": "{0} Installation abgeschlossen",
+ "LabelPackageInstallFailed": "{0} Installation fehlgeschlagen",
+ "LabelPackageInstallCancelled": "{0} Installation abgebrochen",
+ "TabServer": "Server",
+ "TabUsers": "Benutzer",
+ "TabLibrary": "Bibliothek",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live-TV",
+ "TabAutoOrganize": "Automatische Organisation",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Erweitert",
+ "TabHelp": "Hilfe",
+ "TabScheduledTasks": "Geplante Aufgaben",
+ "ButtonFullscreen": "Vollbild",
+ "ButtonAudioTracks": "Audiospuren",
+ "ButtonSubtitles": "Untertitel",
+ "ButtonScenes": "Szenen",
+ "ButtonQuality": "Qualit\u00e4t",
+ "HeaderNotifications": "Benachrichtigungen",
+ "HeaderSelectPlayer": "W\u00e4hle Abspielger\u00e4t:",
+ "ButtonSelect": "Ausw\u00e4hlen",
+ "ButtonNew": "Neu",
+ "MessageInternetExplorerWebm": "Installiere f\u00fcr die besten Ergebnisse mit dem Internet Explorer bitte das WebM Playback Plugin.",
+ "HeaderVideoError": "Video Fehler",
+ "ButtonAddToPlaylist": "Hinzuf\u00fcgen zur Wiedergabeliste",
+ "HeaderAddToPlaylist": "Zur Wiedergabeliste hinzuf\u00fcgen",
+ "LabelName": "Name:",
+ "ButtonSubmit": "Best\u00e4tigen",
+ "LabelSelectPlaylist": "Wiedergabeliste",
+ "OptionNewPlaylist": "Neue Wiedergabeliste...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "Zeige Serienaufnahmen an",
+ "ValueOriginalAirDate": "Urspr\u00fcngliches Ausstrahlungsdatum: {0}",
+ "ButtonRemoveFromPlaylist": "Von Wiedergabeliste entfernen",
+ "HeaderSpecials": "Extras",
+ "HeaderTrailers": "Trailer",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Aufl\u00f6sung",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Laufzeit",
+ "HeaderCommunityRating": "Community Bewertung",
+ "HeaderParentalRating": "Alterseinstufung",
+ "HeaderReleaseDate": "Ver\u00f6ffentlichungsdatum",
+ "HeaderDateAdded": "Hinzugef\u00fcgt am",
+ "HeaderSeries": "Serien",
+ "HeaderSeason": "Staffel",
+ "HeaderSeasonNumber": "Staffel Nummer",
+ "HeaderNetwork": "Netzwerk",
+ "HeaderYear": "Jahr",
+ "HeaderGameSystem": "Spielesystem",
+ "HeaderPlayers": "Abspielger\u00e4te",
+ "HeaderEmbeddedImage": "Integriertes Bild",
+ "HeaderTrack": "St\u00fcck",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Filme",
+ "OptionCollections": "Sammlungen",
+ "OptionSeries": "Serien",
+ "OptionSeasons": "Staffeln",
+ "OptionEpisodes": "Episoden",
+ "OptionGames": "Spiele",
+ "OptionGameSystems": "Spielsysteme",
+ "OptionMusicArtists": "Musik-Interpreten",
+ "OptionMusicAlbums": "Musik-Alben",
+ "OptionMusicVideos": "Musik-Videos",
+ "OptionSongs": "Lieder",
+ "OptionHomeVideos": "Heim-Videos",
+ "OptionBooks": "B\u00fccher",
+ "OptionAdultVideos": "Videos f\u00fcr Erwachsene",
+ "ButtonUp": "Hoch",
+ "ButtonDown": "Runter",
+ "LabelMetadataReaders": "Metadatenleser:",
+ "LabelMetadataReadersHelp": "Lege deine bevorzugte lokale Metadatenquelle fest und ordne sie nach Priorit\u00e4ten. Die erste Datei die gefunden wird, wird verwendet.",
+ "LabelMetadataDownloaders": "Metadatendownloader:",
+ "LabelMetadataDownloadersHelp": "Aktiviere und ordne deine bevorzugten Metadatendownloader nach Pr\u00e4ferenzen. Downloader mit niedriger Priorit\u00e4t werden nur genutzt um fehlende Informationen zu erg\u00e4nzen.",
+ "LabelMetadataSavers": "Metadatenspeicherer:",
+ "LabelMetadataSaversHelp": "W\u00e4hle das Dateiformat in dem deine Metadaten gespeichert werden sollen.",
+ "LabelImageFetchers": "Bildquellen",
+ "LabelImageFetchersHelp": "Aktiviere und ordne deine bevorzugten Bildquellen nach Pr\u00e4ferenzen.",
+ "ButtonQueueAllFromHere": "Setze alles von hier auf Warteschlange",
+ "ButtonPlayAllFromHere": "Spiele alles von hier",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identifiziere Element",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Reihenfolge Titeldarstellung:",
+ "OptionSortName": "Sortiername",
+ "OptionReleaseDate": "Ver\u00f6ffentlichungsdatum",
+ "LabelSeasonNumber": "Staffelnummer:",
+ "LabelDiscNumber": "Disc Nummer",
+ "LabelParentNumber": "Ursprungsnummer",
+ "LabelEpisodeNumber": "Episodennummer:",
+ "LabelTrackNumber": "St\u00fcck Nummer:",
+ "LabelNumber": "Nummer:",
+ "LabelReleaseDate": "Ver\u00f6ffentlichungsdatum:",
+ "LabelEndDate": "Endzeit:",
+ "LabelYear": "Jahr:",
+ "LabelDateOfBirth": "Geburtsatum:",
+ "LabelBirthYear": "Geburtsjahr:",
+ "LabelDeathDate": "Todesdatum:",
+ "HeaderRemoveMediaLocation": "Entferne Medienquelle",
+ "MessageConfirmRemoveMediaLocation": "Bist du dir sicher diese Medienquelle entfernen zu wollen?",
+ "HeaderRenameMediaFolder": "Benenne Medienverzeichnis um",
+ "LabelNewName": "Neuer Name:",
+ "HeaderAddMediaFolder": "F\u00fcge Medienverzeichnis hinzu",
+ "HeaderAddMediaFolderHelp": "Name (Filme, Musik, TV, etc):",
+ "HeaderRemoveMediaFolder": "Entferne Medienverzeichnis",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "Die folgenden Medienverzeichnisse werden aus deiner Bibliothek entfernt:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Bist du dir sicher dieses Medienverzeichnis entfernen zu wollen?",
+ "ButtonRename": "Umbenennen",
+ "ButtonChangeType": "\u00c4ndere Typ",
+ "HeaderMediaLocations": "Medienquellen",
+ "LabelFolderTypeValue": "Verzeichnistyp: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Die Pfadersetzung kann Serverpfade zu Netzwerkfreigaben umleiten, die von Endger\u00e4ten f\u00fcr die direkte Wiedergabe genutzt werden k\u00f6nnen.",
+ "FolderTypeMixed": "Filme & Serien gemischt",
+ "FolderTypeMovies": "Filme",
+ "FolderTypeMusic": "Musik",
+ "FolderTypeAdultVideos": "Videos f\u00fcr Erwachsene",
+ "FolderTypePhotos": "Fotos",
+ "FolderTypeMusicVideos": "Musikvideos",
+ "FolderTypeHomeVideos": "Heimvideos",
+ "FolderTypeGames": "Spiele",
+ "FolderTypeBooks": "B\u00fccher",
+ "FolderTypeTvShows": "TV Serien",
+ "TabMovies": "Filme",
+ "TabSeries": "Serie",
+ "TabEpisodes": "Episoden",
+ "TabTrailers": "Trailer",
+ "TabGames": "Spiele",
+ "TabAlbums": "Alben",
+ "TabSongs": "Songs",
+ "TabMusicVideos": "Musikvideos",
+ "BirthPlaceValue": "Geburtsort: {0}",
+ "DeathDateValue": "Gestorben: {0}",
+ "BirthDateValue": "Geboren: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json
index c28e6870d..f961db055 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "\u03c3\u03b2\u03b7\u03c3\u03c4\u03cc\u03c2",
- "OptionOn": "On",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "My Library",
"SettingsSaved": "\u039f\u03b9 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u03b1\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c4\u03b7\u03ba\u03b1\u03bd",
"AddUser": "\u03a0\u03c1\u03bf\u03c3\u03b8\u03ae\u03ba\u03b7 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7",
"Users": "\u039f\u03b9 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b5\u03c2",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episode",
"LabelSeries": "Series",
"LabelStopping": "Stopping",
- "ButtonStop": "Stop",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Unknown language",
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
"ButtonPause": "Pause",
"ButtonPlay": "Play",
"ButtonEdit": "Edit",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
+ "ButtonPlayTrailer": "Play trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Previous Track",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
"ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
"HeaderSeriesRecordings": "Series Recordings",
"LabelAnytime": "Any time",
"StatusRecording": "Recording",
@@ -130,7 +123,8 @@
"HeaderMyViews": "My Views",
"HeaderLibraryFolders": "Media Folders",
"HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
"HeaderFavoriteMovies": "Favorite Movies",
"HeaderFavoriteShows": "Favorite Shows",
"HeaderFavoriteEpisodes": "Favorite Episodes",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
"HeaderSelectImagesByNamePath": "Select Images By Name Path",
"HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
"HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Remote access: {0}",
"LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
"HeaderLatestFromChannel": "Latest from {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Unknown language",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "\u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9",
+ "ButtonCancel": "\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7 ",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "Scenes",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "Name",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Channels",
+ "HeaderMediaFolders": "Media Folders",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "Ended",
+ "OptionContinuing": "Continuing",
+ "OptionOff": "\u03c3\u03b2\u03b7\u03c3\u03c4\u03cc\u03c2",
+ "OptionOn": "On",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPeople": "People",
+ "OptionRuntime": "Runtime",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Server",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Advanced",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonScenes": "Scenes",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "Select",
+ "ButtonNew": "New",
+ "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:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Movies",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episodes",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Season number:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Movies",
+ "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",
+ "TabMusicVideos": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ac \u03b2\u03af\u03bd\u03c4\u03b5\u03bf",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json
index 5e8ffeb02..e8525157d 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "Off",
- "OptionOn": "On",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "My Library",
"SettingsSaved": "Settings saved.",
"AddUser": "Add User",
"Users": "Users",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episode",
"LabelSeries": "Series",
"LabelStopping": "Stopping",
- "ButtonStop": "Stop",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Unknown language",
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
"ButtonPause": "Pause",
"ButtonPlay": "Play",
"ButtonEdit": "Edit",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
+ "ButtonPlayTrailer": "Play trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Previous Track",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
"ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
"HeaderSeriesRecordings": "Series Recordings",
"LabelAnytime": "Any time",
"StatusRecording": "Recording",
@@ -130,11 +123,12 @@
"HeaderMyViews": "My Views",
"HeaderLibraryFolders": "Media Folders",
"HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
- "HeaderFavoriteMovies": "Favorite Movies",
- "HeaderFavoriteShows": "Favorite Shows",
- "HeaderFavoriteEpisodes": "Favorite Episodes",
- "HeaderFavoriteGames": "Favorite Games",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
+ "HeaderFavoriteMovies": "Favourite Movies",
+ "HeaderFavoriteShows": "Favourite Shows",
+ "HeaderFavoriteEpisodes": "Favourite Episodes",
+ "HeaderFavoriteGames": "Favourite Games",
"HeaderRatingsDownloads": "Rating \/ Downloads",
"HeaderConfirmProfileDeletion": "Confirm Profile Deletion",
"MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
"HeaderSelectImagesByNamePath": "Select Images By Name Path",
"HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
"HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
@@ -153,11 +147,11 @@
"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.",
- "HeaderFavoriteAlbums": "Favorite Albums",
+ "HeaderFavoriteAlbums": "Favourite Albums",
"HeaderLatestChannelMedia": "Latest Channel Items",
- "ButtonOrganizeFile": "Organize File",
+ "ButtonOrganizeFile": "Organise File",
"ButtonDeleteFile": "Delete File",
- "HeaderOrganizeFile": "Organize File",
+ "HeaderOrganizeFile": "Organise File",
"HeaderDeleteFile": "Delete File",
"StatusSkipped": "Skipped",
"StatusFailed": "Failed",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Remote access: {0}",
"LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
"HeaderLatestFromChannel": "Latest from {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Unknown language",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Cancel",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "Scenes",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "Name",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Channels",
+ "HeaderMediaFolders": "Media Folders",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "Ended",
+ "OptionContinuing": "Continuing",
+ "OptionOff": "Off",
+ "OptionOn": "On",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPeople": "People",
+ "OptionRuntime": "Runtime",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Server",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organise",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Advanced",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonScenes": "Scenes",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "Select",
+ "ButtonNew": "New",
+ "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:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Movies",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episodes",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Season number:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Movies",
+ "TabSeries": "Series",
+ "TabEpisodes": "Episodes",
+ "TabTrailers": "Trailers",
+ "TabGames": "Games",
+ "TabAlbums": "Albums",
+ "TabSongs": "Songs",
+ "TabMusicVideos": "Music Videos",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json
index 5fafacc78..dd6e416e1 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "Off",
- "OptionOn": "On",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "My Library",
"SettingsSaved": "Settings saved.",
"AddUser": "Add User",
"Users": "Users",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episode",
"LabelSeries": "Series",
"LabelStopping": "Stopping",
- "ButtonStop": "Stop",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Unknown language",
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
"ButtonPause": "Pause",
"ButtonPlay": "Play",
"ButtonEdit": "Edit",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
+ "ButtonPlayTrailer": "Play trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Previous Track",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
"ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
"HeaderSeriesRecordings": "Series Recordings",
"LabelAnytime": "Any time",
"StatusRecording": "Recording",
@@ -130,7 +123,8 @@
"HeaderMyViews": "My Views",
"HeaderLibraryFolders": "Media Folders",
"HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
"HeaderFavoriteMovies": "Favorite Movies",
"HeaderFavoriteShows": "Favorite Shows",
"HeaderFavoriteEpisodes": "Favorite Episodes",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
"HeaderSelectImagesByNamePath": "Select Images By Name Path",
"HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
"HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Remote access: {0}",
"LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
"HeaderLatestFromChannel": "Latest from {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Unknown language",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Cancel",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "Scenes",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "Name",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Channels",
+ "HeaderMediaFolders": "Media Folders",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "Ended",
+ "OptionContinuing": "Continuing",
+ "OptionOff": "Off",
+ "OptionOn": "On",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPeople": "People",
+ "OptionRuntime": "Runtime",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Server",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Advanced",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonScenes": "Scenes",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "Select",
+ "ButtonNew": "New",
+ "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:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Movies",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episodes",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Season number:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Movies",
+ "TabSeries": "Series",
+ "TabEpisodes": "Episodes",
+ "TabTrailers": "Trailers",
+ "TabGames": "Games",
+ "TabAlbums": "Albums",
+ "TabSongs": "Songs",
+ "TabMusicVideos": "Music Videos",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json
index 0d7275354..c05f42914 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Crear Contrase\u00f1a",
- "OptionOff": "Apagado",
- "OptionOn": "Encendido",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Por favor, seleccione dos o m\u00e1s elementos para unir al grupo.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "Mi librer\u00eda",
"SettingsSaved": "Configuraci\u00f3n guardada",
"AddUser": "Agregar usuario",
"Users": "Usuarios",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episodio",
"LabelSeries": "Series",
"LabelStopping": "Deteniendo",
- "ButtonStop": "Detener",
"LabelCancelled": "(cancelado)",
"LabelFailed": "(fracasado)",
"LabelAbortedByServerShutdown": "(Abortado por cierre del servidor)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Idioma desconocido",
"ButtonMute": "Silencio",
"ButtonUnmute": "Activar audio",
+ "ButtonStop": "Detener",
+ "ButtonNextTrack": "Pista siguiente",
"ButtonPause": "Pausa",
"ButtonPlay": "Reproducir",
"ButtonEdit": "Editar",
"ButtonQueue": "En cola",
"ButtonPlayTrailer": "Reproducir trailer",
"ButtonPlaylist": "Lista de reproducci\u00f3n",
+ "ButtonPreviousTrack": "Pista anterior",
"LabelEnabled": "Activado",
"LabelDisabled": "Desactivado",
"ButtonMoreInformation": "M\u00e1s informaci\u00f3n",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reinicio del sintonizador",
"MessageConfirmResetTuner": "\u00bfEst\u00e1 seguro que desea reiniciar este sintonizador? Cualquier reproducci\u00f3n o grabaci\u00f3n activa se detendr\u00e1 inmediatamente.",
"ButtonCancelSeries": "Cancelar serie",
- "LabelAllChannels": "Todos los canales",
"HeaderSeriesRecordings": "Grabaciones de series",
"LabelAnytime": "A cualquier hora",
"StatusRecording": "Grabando",
@@ -127,9 +120,10 @@
"MessageTheFollowingItemsWillBeGrouped": "Los siguientes t\u00edtulos se agrupar\u00e1n en un elemento.",
"MessageConfirmItemGrouping": "Los clientes de Media Browser elegir\u00e1n autom\u00e1ticamente la mejor forma de reproduccion sobre la base de dispositivo y rendimiento de la red. \u00bfEst\u00e1 seguro que desea continuar?",
"HeaderResume": "Continuar",
- "HeaderMyViews": "My Views",
+ "HeaderMyViews": "Mis vistas",
"HeaderLibraryFolders": "Vista de carpeta",
"HeaderLatestMedia": "\u00daltimos medios",
+ "ButtonMoreItems": "More...",
"ButtonMore": "M\u00e1s...",
"HeaderFavoriteMovies": "Pel\u00edculas favoritas",
"HeaderFavoriteShows": "Programas favoritos",
@@ -185,13 +179,255 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Acceso remoto: {0}",
"LabelRunningOnPort": "Ejecut\u00e1ndose en el puerto {0}.",
- "LabelRunningOnPorts": "Ejecut\u00e1ndose en los puertos {0} y {1}.",
"HeaderLatestFromChannel": "Lo \u00faltimo de {0}",
- "ButtonDownload": "Download",
- "LabelUnknownLanaguage": "Unknown language",
- "HeaderCurrentSubtitles": "Current Subtitles",
- "MessageDownloadQueued": "The download has been queued.",
- "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
- "ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "ButtonDownload": "Descargar",
+ "LabelUnknownLanaguage": "Idioma desconocido",
+ "HeaderCurrentSubtitles": "Subt\u00edtulos actuales",
+ "MessageDownloadQueued": "La descarga se ha a\u00f1adido a la cola",
+ "MessageAreYouSureDeleteSubtitles": "\u00bfEst\u00e1 seguro que desea eliminar este archivo de subt\u00edtulos?",
+ "ButtonRemoteControl": "Control remoto",
+ "HeaderLatestTvRecordings": "\u00daltimas grabaciones",
+ "ButtonOk": "OK",
+ "ButtonCancel": "Cancelar",
+ "ButtonRefresh": "Refrescar",
+ "LabelCurrentPath": "Ruta actual:",
+ "HeaderSelectMediaPath": "Seleccionar la ruta para Medios",
+ "ButtonNetwork": "Red",
+ "MessageDirectoryPickerInstruction": "Rutas de red pueden ser introducidas manualmente en el caso de que el bot\u00f3n de la red no pueda localizar sus dispositivos. Por ejemplo, {0} o {1}.",
+ "HeaderMenu": "Men\u00fa",
+ "ButtonOpen": "Abrir",
+ "ButtonOpenInNewTab": "Abrir en nueva pesta\u00f1a",
+ "ButtonShuffle": "Mezclar",
+ "ButtonInstantMix": "Mix instant\u00e1neo",
+ "ButtonResume": "Continuar",
+ "HeaderScenes": "Escenas",
+ "HeaderAudioTracks": "Pistas de audio",
+ "HeaderSubtitles": "Subt\u00edtulos",
+ "HeaderVideoQuality": "Calidad de video",
+ "MessageErrorPlayingVideo": "Ha habido un error reproduciendo el video.",
+ "MessageEnsureOpenTuner": "Aseg\u00farese que hay un sintonizador disponible.",
+ "ButtonHome": "Inicio",
+ "ButtonDashboard": "Panel de control",
+ "ButtonReports": "Informes",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Duraci\u00f3n",
+ "HeaderName": "Nombre",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Artista del album",
+ "HeaderArtist": "Artista",
+ "LabelAddedOnDate": "A\u00f1adido {0}",
+ "ButtonStart": "Inicio",
+ "HeaderChannels": "Canales",
+ "HeaderMediaFolders": "Carpetas de medios",
+ "HeaderBlockItemsWithNoRating": "Bloquear elementos sin informaci\u00f3n de clasificaci\u00f3n:",
+ "OptionBlockOthers": "Otros",
+ "OptionBlockTvShows": "Tv Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "M\u00fasica",
+ "OptionBlockMovies": "Pel\u00edculas",
+ "OptionBlockBooks": "Libros",
+ "OptionBlockGames": "Juegos",
+ "OptionBlockLiveTvPrograms": "Programas de TV en vivo",
+ "OptionBlockLiveTvChannels": "Canales de Tv en vivo",
+ "OptionBlockChannelContent": "Contenido de canales de Internet",
+ "ButtonRevoke": "Revocar",
+ "MessageConfirmRevokeApiKey": "\u00bfEst\u00e1 seguro de que desea revocar esta clave api? La conexi\u00f3n de la aplicaci\u00f3n con Mediabrowser terminar\u00e1 abruptamente.",
+ "HeaderConfirmRevokeApiKey": "Revocar Clave Api",
+ "ValueContainer": "Contenedor: {0}",
+ "ValueAudioCodec": "Codec de audio: {0}",
+ "ValueVideoCodec": "Codec de video: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Condiciones: {0}",
+ "LabelAll": "Todo",
+ "HeaderDeleteImage": "Borrar imagen",
+ "MessageFileNotFound": "Archivo no encontrado.",
+ "MessageFileReadError": "Ha ocurrido un error leyendo este archivo.",
+ "ButtonNextPage": "P\u00e1gina siguiente",
+ "ButtonPreviousPage": "P\u00e1gina anterior",
+ "ButtonMoveLeft": "Mover izquierda",
+ "ButtonMoveRight": "Mover derecha",
+ "ButtonBrowseOnlineImages": "Navegar im\u00e1genes online",
+ "HeaderDeleteItem": "Borrar elemento",
+ "ConfirmDeleteItem": "\u00bfEst\u00e1 seguro que desea borrar este elemento de su biblioteca?",
+ "MessagePleaseEnterNameOrId": "Introduzca un nombre o un identificador externo.",
+ "MessageValueNotCorrect": "El valor introducido no es correcto. Intentelo de nuevo.",
+ "MessageItemSaved": "Elemento grabado.",
+ "OptionEnded": "Finalizado",
+ "OptionContinuing": "Continuando",
+ "OptionOff": "Apagado",
+ "OptionOn": "Encendido",
+ "HeaderFields": "Campos",
+ "HeaderFieldsHelp": "Deslice un campo en 'off' para bloquearlo y evitar que la informaci\u00f3n sea cambiada.",
+ "HeaderLiveTV": "Tv en vivo",
+ "MissingLocalTrailer": "Falta trailer local.",
+ "MissingPrimaryImage": "Falta imagen principal.",
+ "MissingBackdropImage": "Falta imagen de fondo.",
+ "MissingLogoImage": "Falta logo.",
+ "MissingEpisode": "Falta episodio.",
+ "OptionScreenshots": "Capturas del pantalla",
+ "OptionBackdrops": "Im\u00e1genes de fondo",
+ "OptionImages": "Im\u00e1genes",
+ "OptionKeywords": "Palabras clave",
+ "OptionTags": "Etiquetas",
+ "OptionStudios": "Estudios",
+ "OptionName": "Nombre",
+ "OptionOverview": "Sinopsis",
+ "OptionGenres": "G\u00e9neros",
+ "OptionParentalRating": "Clasificaci\u00f3n parental",
+ "OptionPeople": "Gente",
+ "OptionRuntime": "Tiempo",
+ "OptionProductionLocations": "Localizaciones de producci\u00f3n",
+ "OptionBirthLocation": "Lugar de nacimiento",
+ "LabelAllChannels": "Todos los canales",
+ "LabelLiveProgram": "EN VIVO",
+ "LabelNewProgram": "NUEVO",
+ "LabelPremiereProgram": "ESTRENO",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Cambiar tipo de carpeta",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Reiniciar",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Servidor",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Avanzado",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Subt\u00edtulos",
+ "ButtonScenes": "Escenas",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "Seleccionar",
+ "ButtonNew": "Nuevo",
+ "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": "Nombre:",
+ "ButtonSubmit": "Enviar",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Pel\u00edculas",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episodios",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Temporada n\u00famero:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episodio n\u00famero:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Pel\u00edculas",
+ "TabSeries": "Series",
+ "TabEpisodes": "Episodios",
+ "TabTrailers": "Trailers",
+ "TabGames": "Juegos",
+ "TabAlbums": "Albums",
+ "TabSongs": "Canciones",
+ "TabMusicVideos": "Videos Musicales",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_ES.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_ES.json
new file mode 100644
index 000000000..c6efa636a
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_ES.json
@@ -0,0 +1,237 @@
+{
+ "SettingsSaved": "Configuraci\u00f3n guardada",
+ "AddUser": "Agregar usuario",
+ "Users": "Usuarios",
+ "Delete": "Borrar",
+ "Administrator": "Administrador",
+ "Password": "Contrase\u00f1a",
+ "DeleteImage": "Borrar Imagen",
+ "DeleteImageConfirmation": "Est\u00e1 seguro que desea borrar esta imagen?",
+ "FileReadCancelled": "La lectura del archivo se ha cancelado.",
+ "FileNotFound": "Archivo no encontrado.",
+ "FileReadError": "Se encontr\u00f3 un error al leer el archivo.",
+ "DeleteUser": "Borrar Usuario",
+ "DeleteUserConfirmation": "Esta seguro que desea eliminar a {0}?",
+ "PasswordResetHeader": "Restablecer contrase\u00f1a",
+ "PasswordResetComplete": "La contrase\u00f1a se ha restablecido.",
+ "PasswordResetConfirmation": "Esta seguro que desea restablecer la contrase\u00f1a?",
+ "PasswordSaved": "Contrase\u00f1a guardada.",
+ "PasswordMatchError": "La contrase\u00f1a y la confirmaci\u00f3n de la contrase\u00f1a deben de ser iguales.",
+ "OptionRelease": "Release Oficial",
+ "OptionBeta": "Beta",
+ "OptionDev": "Desarrollo",
+ "UninstallPluginHeader": "Desinstalar Plugin",
+ "UninstallPluginConfirmation": "Esta seguro que desea desinstalar {0}?",
+ "NoPluginConfigurationMessage": "El plugin no requiere configuraci\u00f3n",
+ "NoPluginsInstalledMessage": "No tiene plugins instalados.",
+ "BrowsePluginCatalogMessage": "Navegar el catalogo de plugins para ver los plugins disponibles.",
+ "MessageKeyEmailedTo": "Clave enviada por email a {0}.",
+ "MessageKeysLinked": "Claves vinculadas.",
+ "HeaderConfirmation": "Confirmaci\u00f3n",
+ "MessageKeyUpdated": "Gracias. Su clave de seguidor ha sido actualizada.",
+ "MessageKeyRemoved": "Gracias. Su clave de seguidor ha sido eliminada.",
+ "ErrorLaunchingChromecast": "Ha habido un error al lanzar chromecast. Asegurese que su dispositivo est\u00e1 conectado a su red inal\u00e1mbrica.",
+ "HeaderSearch": "Buscar",
+ "LabelArtist": "Artista",
+ "LabelMovie": "Pel\u00edcula",
+ "LabelMusicVideo": "Video Musical",
+ "LabelEpisode": "Episodio",
+ "LabelSeries": "Series",
+ "LabelStopping": "Deteniendo",
+ "ButtonStop": "Detener",
+ "LabelCancelled": "(cancelado)",
+ "LabelFailed": "(fracasado)",
+ "LabelAbortedByServerShutdown": "(Abortado por cierre del servidor)",
+ "LabelScheduledTaskLastRan": "\u00daltima ejecuci\u00f3n {0}, teniendo {1}.",
+ "HeaderDeleteTaskTrigger": "Eliminar tarea de activaci\u00f3n",
+ "HeaderTaskTriggers": "Tareas de activaci\u00f3n",
+ "MessageDeleteTaskTrigger": "\u00bfEst\u00e1 seguro que desea eliminar esta tarea de activaci\u00f3n?",
+ "MessageNoPluginsInstalled": "No tiene plugins instalados.",
+ "LabelVersionInstalled": "{0} instalado",
+ "LabelNumberReviews": "{0} Revisiones",
+ "LabelFree": "Libre",
+ "HeaderSelectAudio": "Seleccionar Audio",
+ "HeaderSelectSubtitles": "Seleccionar Subt\u00edtulos",
+ "LabelDefaultStream": "(Por defecto)",
+ "LabelForcedStream": "(Forzado)",
+ "LabelDefaultForcedStream": "(Por defecto\/Forzado)",
+ "LabelUnknownLanguage": "Idioma desconocido",
+ "ButtonMute": "Silencio",
+ "ButtonUnmute": "Activar audio",
+ "ButtonNextTrack": "Pista siguiente",
+ "ButtonPause": "Pausa",
+ "ButtonPlay": "Reproducir",
+ "ButtonEdit": "Editar",
+ "ButtonQueue": "En cola",
+ "ButtonPlayTrailer": "Reproducir trailer",
+ "ButtonPlaylist": "Lista de reproducci\u00f3n",
+ "ButtonPreviousTrack": "Pista anterior",
+ "LabelEnabled": "Activado",
+ "LabelDisabled": "Desactivado",
+ "ButtonMoreInformation": "M\u00e1s informaci\u00f3n",
+ "LabelNoUnreadNotifications": "No hay notificaciones sin leer.",
+ "ButtonViewNotifications": "Ver notificaciones",
+ "ButtonMarkTheseRead": "Marcar como le\u00eddo",
+ "ButtonClose": "Cerrar",
+ "LabelAllPlaysSentToPlayer": "Todas las reproducciones se enviar\u00e1n al reproductor seleccionado.",
+ "MessageInvalidUser": "Usuario o contrase\u00f1a no v\u00e1lido.",
+ "HeaderAllRecordings": "Todas la grabaciones",
+ "RecommendationBecauseYouLike": "Como le gusta {0}",
+ "RecommendationBecauseYouWatched": "Ya que vi\u00f3 {0}",
+ "RecommendationDirectedBy": "Dirigida por {0}",
+ "RecommendationStarring": "Protagonizada por {0}",
+ "HeaderConfirmRecordingCancellation": "Confirmar la cancelaci\u00f3n de la grabaci\u00f3n",
+ "MessageConfirmRecordingCancellation": "\u00bfEst\u00e1 seguro que desea cancelar esta grabaci\u00f3n?",
+ "MessageRecordingCancelled": "Grabaci\u00f3n cancelada.",
+ "HeaderConfirmSeriesCancellation": "Confirmar cancelaci\u00f3n de serie",
+ "MessageConfirmSeriesCancellation": "\u00bfEst\u00e1 seguro que desea cancelar esta serie?",
+ "MessageSeriesCancelled": "Serie cancelada",
+ "HeaderConfirmRecordingDeletion": "Confirmar borrado de la grabaci\u00f3n",
+ "MessageConfirmRecordingDeletion": "\u00bfEst\u00e1 seguro que desea borrar esta grabaci\u00f3n?",
+ "MessageRecordingDeleted": "Grabaci\u00f3n eliminada.",
+ "ButonCancelRecording": "Cancelar Grabaci\u00f3n",
+ "MessageRecordingSaved": "Grabaci\u00f3n guardada.",
+ "OptionSunday": "Domingo",
+ "OptionMonday": "Lunes",
+ "OptionTuesday": "Martes",
+ "OptionWednesday": "Mi\u00e9rcoles",
+ "OptionThursday": "Jueves",
+ "OptionFriday": "Viernes",
+ "OptionSaturday": "S\u00e1bado",
+ "HeaderConfirmDeletion": "Confirmar borrado",
+ "MessageConfirmPathSubstitutionDeletion": "\u00bfEst\u00e1 seguro que desea borrar esta ruta de sustituci\u00f3n?",
+ "LiveTvUpdateAvailable": "(Actualizaci\u00f3n disponible)",
+ "LabelVersionUpToDate": "\u00a1Actualizado!",
+ "ButtonResetTuner": "Reiniciar sintonizador",
+ "HeaderResetTuner": "Reinicio del sintonizador",
+ "MessageConfirmResetTuner": "\u00bfEst\u00e1 seguro que desea reiniciar este sintonizador? Cualquier reproducci\u00f3n o grabaci\u00f3n activa se detendr\u00e1 inmediatamente.",
+ "ButtonCancelSeries": "Cancelar serie",
+ "LabelAllChannels": "Todos los canales",
+ "HeaderSeriesRecordings": "Grabaciones de series",
+ "LabelAnytime": "A cualquier hora",
+ "StatusRecording": "Grabando",
+ "StatusWatching": "Viendo",
+ "StatusRecordingProgram": "Grabando {0}",
+ "StatusWatchingProgram": "Viendo {0}",
+ "HeaderSplitMedia": "Divisi\u00f3n de medios",
+ "MessageConfirmSplitMedia": "\u00bfEst\u00e1 seguro que desea dividir los medios en partes separadas?",
+ "HeaderError": "Error",
+ "MessagePleaseSelectOneItem": "Seleccione al menos un elemento.",
+ "MessagePleaseSelectTwoItems": "Seleccione al menos dos elementos.",
+ "MessageTheFollowingItemsWillBeGrouped": "Los siguientes t\u00edtulos se agrupar\u00e1n en un elemento.",
+ "MessageConfirmItemGrouping": "Los clientes de Media Browser elegir\u00e1n autom\u00e1ticamente la mejor forma de reproduccion sobre la base de dispositivo y rendimiento de la red. \u00bfEst\u00e1 seguro que desea continuar?",
+ "HeaderResume": "Continuar",
+ "HeaderMyViews": "Mis vistas",
+ "HeaderLibraryFolders": "Vista de carpeta",
+ "HeaderLatestMedia": "\u00daltimos medios",
+ "ButtonMore": "M\u00e1s...",
+ "HeaderFavoriteMovies": "Pel\u00edculas favoritas",
+ "HeaderFavoriteShows": "Programas favoritos",
+ "HeaderFavoriteEpisodes": "Episodios favoritos",
+ "HeaderFavoriteGames": "Juegos favoritos",
+ "HeaderRatingsDownloads": "\nClasificaci\u00f3n \/ Descargas",
+ "HeaderConfirmProfileDeletion": "Confirmar borrado del perfil",
+ "MessageConfirmProfileDeletion": "\u00bfEst\u00e1 seguro que desea eliminar este perfil?",
+ "HeaderSelectServerCachePath": "Seleccione la ruta para el cach\u00e9 del servidor",
+ "HeaderSelectTranscodingPath": "Seleccione la ruta temporal del transcodificador",
+ "HeaderSelectImagesByNamePath": "Seleccione la ruta para im\u00e1genes",
+ "HeaderSelectMetadataPath": "Seleccione la ruta para Metadatos",
+ "HeaderSelectServerCachePathHelp": "Busque o escriba la ruta de acceso que se utilizar\u00e1 para los archivos de cach\u00e9 del servidor. La carpeta debe tener permiso de escritura. La ubicaci\u00f3n de esta carpeta afectar\u00e1 directamente al rendimiento del servidor e idealmente debe ser colocado en una unidad de estado s\u00f3lido.",
+ "HeaderSelectTranscodingPathHelp": "Busque o escriba la ruta de acceso que se utilizar\u00e1 para la transcodificaci\u00f3n de archivos temporales. La carpeta debe tener permiso de escritura.",
+ "HeaderSelectImagesByNamePathHelp": "Busque o escriba la ruta de sus elementos por nombre de carpeta. La carpeta debe tener permisos de escritura.",
+ "HeaderSelectMetadataPathHelp": "Busque o escriba la ruta donde desea almacenar los metadatos. La carpeta debe tener permiso de escritura.",
+ "HeaderSelectChannelDownloadPath": "Seleccione la ruta de descargas de canal",
+ "HeaderSelectChannelDownloadPathHelp": "Navege o escriba la ruta para guardar el los archivos de cach\u00e9 de canales. La carpeta debe tener permisos de escritura.",
+ "OptionNewCollection": "Nuevo...",
+ "ButtonAdd": "A\u00f1adir",
+ "ButtonRemove": "Quitar",
+ "LabelChapterDownloaders": "Downloaders de cap\u00edtulos:",
+ "LabelChapterDownloadersHelp": "Habilitar y clasificar sus descargadores de cap\u00edtulos preferidos en orden de prioridad. Descargadores de menor prioridad s\u00f3lo se utilizar\u00e1n para completar la informaci\u00f3n que falta.",
+ "HeaderFavoriteAlbums": "\u00c1lbumes favoritos",
+ "HeaderLatestChannelMedia": "\u00dcltimos elementos de canal",
+ "ButtonOrganizeFile": "Organizar archivos",
+ "ButtonDeleteFile": "Borrar archivos",
+ "HeaderOrganizeFile": "Organizar archivos",
+ "HeaderDeleteFile": "Borrar archivos",
+ "StatusSkipped": "Saltado",
+ "StatusFailed": "Err\u00f3neo",
+ "StatusSuccess": "\u00c9xito",
+ "MessageFileWillBeDeleted": "El siguiente archivo se eliminar\u00e1:",
+ "MessageSureYouWishToProceed": "\u00bfEst\u00e1 seguro que desea proceder?",
+ "MessageDuplicatesWillBeDeleted": "Adem\u00e1s se eliminar\u00e1n los siguientes duplicados:",
+ "MessageFollowingFileWillBeMovedFrom": "El siguiente archivo se mover\u00e1 desde:",
+ "MessageDestinationTo": "hasta:",
+ "HeaderSelectWatchFolder": "Seleccionar carpeta para el reloj",
+ "HeaderSelectWatchFolderHelp": "Navegue o introduzca la ruta para la carpeta para el reloj. La carpeta debe tener permisos de escritura.",
+ "OrganizePatternResult": "Resultado: {0}",
+ "HeaderRestart": "Reiniciar",
+ "HeaderShutdown": "Apagar",
+ "MessageConfirmRestart": "\u00bfEst\u00e1 seguro que desea reiniciar Media Browser Server?",
+ "MessageConfirmShutdown": "\u00bfEst\u00e1 seguro que desea apagar Media Browser Server?",
+ "ButtonUpdateNow": "Actualizar ahora",
+ "NewVersionOfSomethingAvailable": "\u00a1Hay disponible una nueva versi\u00f3n de {0}!",
+ "VersionXIsAvailableForDownload": "La versi\u00f3n {0} est\u00e1 disponible para su descarga.",
+ "LabelVersionNumber": "Versi\u00f3n {0}",
+ "LabelPlayMethodTranscoding": "Transcodificaci\u00f3n",
+ "LabelPlayMethodDirectStream": "Streaming directo",
+ "LabelPlayMethodDirectPlay": "Reproducci\u00f3n directa",
+ "LabelAudioCodec": "Audio: {0}",
+ "LabelVideoCodec": "Video: {0}",
+ "LabelRemoteAccessUrl": "Acceso remoto: {0}",
+ "LabelRunningOnPort": "Ejecut\u00e1ndose en el puerto {0}.",
+ "LabelRunningOnPorts": "Ejecut\u00e1ndose en los puertos {0} y {1}.",
+ "HeaderLatestFromChannel": "Lo \u00faltimo de {0}",
+ "ButtonDownload": "Descargar",
+ "LabelUnknownLanaguage": "Idioma desconocido",
+ "HeaderCurrentSubtitles": "Subt\u00edtulos actuales",
+ "MessageDownloadQueued": "La descarga se ha a\u00f1adido a la cola",
+ "MessageAreYouSureDeleteSubtitles": "\u00bfEst\u00e1 seguro que desea eliminar este archivo de subt\u00edtulos?",
+ "ButtonRemoteControl": "Control remoto",
+ "HeaderLatestTvRecordings": "\u00daltimas grabaciones",
+ "ButtonOk": "OK",
+ "ButtonCancel": "Cancelar",
+ "ButtonRefresh": "Refrescar",
+ "LabelCurrentPath": "Ruta actual:",
+ "HeaderSelectMediaPath": "Seleccionar la ruta para Medios",
+ "ButtonNetwork": "Red",
+ "MessageDirectoryPickerInstruction": "Rutas de red pueden ser introducidas manualmente en el caso de que el bot\u00f3n de la red no pueda localizar sus dispositivos. Por ejemplo, {0} o {1}.",
+ "HeaderMenu": "Men\u00fa",
+ "ButtonOpen": "Abrir",
+ "ButtonOpenInNewTab": "Abrir en nueva pesta\u00f1a",
+ "ButtonShuffle": "Mezclar",
+ "ButtonInstantMix": "Mix instant\u00e1neo",
+ "ButtonResume": "Continuar",
+ "HeaderScenes": "Escenas",
+ "HeaderAudioTracks": "Pistas de audio",
+ "HeaderSubtitles": "Subt\u00edtulos",
+ "HeaderVideoQuality": "Calidad de video",
+ "MessageErrorPlayingVideo": "Ha habido un error reproduciendo el video.",
+ "MessageEnsureOpenTuner": "Aseg\u00farese que hay un sintonizador disponible.",
+ "ButtonHome": "Inicio",
+ "ButtonDashboard": "Panel de control",
+ "ButtonReports": "Informes",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Duraci\u00f3n",
+ "HeaderName": "Nombre",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Artista del album",
+ "HeaderArtist": "Artista",
+ "LabelAddedOnDate": "A\u00f1adido {0}",
+ "ButtonStart": "Inicio",
+ "HeaderChannels": "Canales",
+ "HeaderMediaFolders": "Carpetas de medios",
+ "HeaderBlockItemsWithNoRating": "Bloquear elementos sin informaci\u00f3n de clasificaci\u00f3n:",
+ "OptionBlockOthers": "Otros",
+ "OptionBlockTvShows": "Tv Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "M\u00fasica",
+ "OptionBlockMovies": "Pel\u00edculas",
+ "OptionBlockBooks": "Libros",
+ "OptionBlockGames": "Juegos",
+ "OptionBlockLiveTvPrograms": "Programas de TV en vivo",
+ "OptionBlockLiveTvChannels": "Canales de Tv en vivo",
+ "OptionBlockChannelContent": "Contenido de canales de Internet",
+ "ButtonRevoke": "Revocar",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key"
+} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json
index d5c854c1a..9db75b4bc 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "No",
- "OptionOn": "Si",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Por favor selecciona dos o mas elementos para agruparlos",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "Mi Biblioteca",
"SettingsSaved": "Configuraci\u00f3n guardada.",
"AddUser": "Agregar usuario",
"Users": "Usuarios",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episodio",
"LabelSeries": "Series",
"LabelStopping": "Deteniendo",
- "ButtonStop": "Detener",
"LabelCancelled": "(cancelado)",
"LabelFailed": "(fall\u00f3)",
"LabelAbortedByServerShutdown": "(Abortada por apagado del servidor)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Idioma Desconocido",
"ButtonMute": "Mudo",
"ButtonUnmute": "Quitar mudo",
+ "ButtonStop": "Detener",
+ "ButtonNextTrack": "Pista Siguiente",
"ButtonPause": "Pausar",
"ButtonPlay": "Reproducir",
"ButtonEdit": "Editar",
"ButtonQueue": "A cola",
- "ButtonPlayTrailer": "Reproducir Trailer",
+ "ButtonPlayTrailer": "Reproducir Avance",
"ButtonPlaylist": "Lista de Reprod.",
+ "ButtonPreviousTrack": "Pista Anterior",
"LabelEnabled": "Habilitado",
"LabelDisabled": "Deshabilitado",
"ButtonMoreInformation": "Mas Informaci\u00f3n",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Resetear Sintonizador",
"MessageConfirmResetTuner": "\u00bfEstas seguro de que deseas restablecer las configuraciones de este sintonizador? Cualquier reproducci\u00f3n o grabaci\u00f3n sera interrumpida abruptamente.",
"ButtonCancelSeries": "Cancelar Series",
- "LabelAllChannels": "Todos los canales",
"HeaderSeriesRecordings": "Grabaciones de Series",
"LabelAnytime": "Cuando sea",
"StatusRecording": "Grabando",
@@ -130,7 +123,8 @@
"HeaderMyViews": "Mis Vistas",
"HeaderLibraryFolders": "Carpetas de Medios",
"HeaderLatestMedia": "Agregados Recientemente",
- "ButtonMore": "M\u00e1s...",
+ "ButtonMoreItems": "M\u00e1s...",
+ "ButtonMore": "M\u00e1s",
"HeaderFavoriteMovies": "Pel\u00edculas Preferidas",
"HeaderFavoriteShows": "Programas Preferidos",
"HeaderFavoriteEpisodes": "Episodios Preferidos",
@@ -142,14 +136,14 @@
"HeaderSelectTranscodingPath": "Seleccionar Ruta para Transcodificaci\u00f3n Temporal",
"HeaderSelectImagesByNamePath": "Seleccionar Ruta para Im\u00e1genes por Nombre",
"HeaderSelectMetadataPath": "Seleccionar Ruta para Metadatos",
- "HeaderSelectServerCachePathHelp": "Explore o capture la ruta a utilizar para los archivos del cach\u00e9 del servidor. La carpeta debe tener permisos de escritura. La ubicaci\u00f3n de esta carpeta impactar\u00e1 directamente el desempe\u00f1o del servidor; idealmente, debe ser ubicada en un disco de estado s\u00f3lido.",
+ "HeaderSelectServerCachePathHelp": "Explore o capture la ruta a utilizar para los archivos del cach\u00e9 del servidor. La carpeta debe tener permisos de escritura.",
"HeaderSelectTranscodingPathHelp": "Explore o capture la ruta a utilizar para los archivos temporales de transcodificaci\u00f3n. La carpeta debe tener permisos de escritura.",
"HeaderSelectImagesByNamePathHelp": "Explore o capture la ruta a utilizar para la carpeta de im\u00e1genes por nombre. La carpeta debe tener permisos de escritura.",
"HeaderSelectMetadataPathHelp": "Explore o capture la ruta donde desea almacenar los metadatos. La carpeta debe tener permisos de escritura.",
"HeaderSelectChannelDownloadPath": "Selecciona una ruta para la descarga del canal",
"HeaderSelectChannelDownloadPathHelp": "Navega o entra en la ruta usada para almacenar los archivos temporales del canal. La carpeta debe tener permisos de escritura.",
"OptionNewCollection": "Nuevo...",
- "ButtonAdd": "A\u00f1adir",
+ "ButtonAdd": "Agregar",
"ButtonRemove": "Eliminar",
"LabelChapterDownloaders": "Descargadores de Cap\u00edtulos:",
"LabelChapterDownloadersHelp": "Habilite y califique sus descargadores de cap\u00edtulos preferidos en orden de prioridad. Los descargadores con menor prioridad s\u00f3lo seran utilizados para completar informaci\u00f3n faltante.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Acceso remoto: {0}",
"LabelRunningOnPort": "Ejecutando en el puerto: {0}.",
- "LabelRunningOnPorts": "Ejecutando en los puertos {0} y {1}.",
"HeaderLatestFromChannel": "M\u00e1s Recientes de {0}",
"ButtonDownload": "Descargar",
"LabelUnknownLanaguage": "Idioma desconocido",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "La descarga se ha agregado a la cola.",
"MessageAreYouSureDeleteSubtitles": "\u00bfEstas seguro de que deseas eliminar este archivo de subtitulos?",
"ButtonRemoteControl": "Control Remoto",
- "HeaderLatestTvRecordings": "\u00daltimas Grabaciones"
+ "HeaderLatestTvRecordings": "\u00daltimas Grabaciones",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Cancelar",
+ "ButtonRefresh": "Actualizar",
+ "LabelCurrentPath": "Ruta actual:",
+ "HeaderSelectMediaPath": "Seleccionar ruta a medios",
+ "ButtonNetwork": "Red",
+ "MessageDirectoryPickerInstruction": "Las rutas de red pueden ser ingresadas manualmente en caso de que el bot\u00f3n de Red no pueda localizar sus dispositivos. Por ejemplo, {0} or {1}.",
+ "HeaderMenu": "Men\u00fa",
+ "ButtonOpen": "Abrir",
+ "ButtonOpenInNewTab": "Abrir en una pesta\u00f1a nueva",
+ "ButtonShuffle": "Mezclar",
+ "ButtonInstantMix": "Mix instant\u00e1neo",
+ "ButtonResume": "Continuar",
+ "HeaderScenes": "Escenas",
+ "HeaderAudioTracks": "Pistas de Audio",
+ "HeaderSubtitles": "Subt\u00edtulos",
+ "HeaderVideoQuality": "Calidad de Video",
+ "MessageErrorPlayingVideo": "Ha ocurrido un error al reproducir el video.",
+ "MessageEnsureOpenTuner": "Por favor aseg\u00farese de que se encuentre disponible un sintonizador abierto.",
+ "ButtonHome": "Inicio",
+ "ButtonDashboard": "Panel de Control",
+ "ButtonReports": "Reportes",
+ "ButtonMetadataManager": "Administrador de Metadatos",
+ "HeaderTime": "Hora",
+ "HeaderName": "Nombre",
+ "HeaderAlbum": "\u00c1lbum",
+ "HeaderAlbumArtist": "Artista del \u00c1lbum",
+ "HeaderArtist": "Artista",
+ "LabelAddedOnDate": "Agregado {0}",
+ "ButtonStart": "Iniciar",
+ "HeaderChannels": "Canales",
+ "HeaderMediaFolders": "Carpetas de Medios",
+ "HeaderBlockItemsWithNoRating": "Bloquear \u00edtems sin informaci\u00f3n de clasificaci\u00f3n",
+ "OptionBlockOthers": "Otros",
+ "OptionBlockTvShows": "Programas de TV",
+ "OptionBlockTrailers": "Avances",
+ "OptionBlockMusic": "M\u00fasica",
+ "OptionBlockMovies": "Pel\u00edculas",
+ "OptionBlockBooks": "Libros",
+ "OptionBlockGames": "Juegos",
+ "OptionBlockLiveTvPrograms": "Programas de TV en Vivo",
+ "OptionBlockLiveTvChannels": "Canales de TV en Vivo",
+ "OptionBlockChannelContent": "Contenido de Canales de Internet",
+ "ButtonRevoke": "Revocar",
+ "MessageConfirmRevokeApiKey": "\u00bfEst\u00e1 seguro de querer revocar esta llave de API?",
+ "HeaderConfirmRevokeApiKey": "Revocar llave de API",
+ "ValueContainer": "Contenedor: {0}",
+ "ValueAudioCodec": "C\u00f3dec de Audio: {0}",
+ "ValueVideoCodec": "C\u00f3dec de Video: {0}",
+ "ValueCodec": "C\u00f3dec: {0}",
+ "ValueConditions": "Condiciones: {0}",
+ "LabelAll": "Todos",
+ "HeaderDeleteImage": "Eliminar Im\u00e1gen",
+ "MessageFileNotFound": "Archivo no encontrado.",
+ "MessageFileReadError": "Ha ocurrido un error al leer este archivo.",
+ "ButtonNextPage": "P\u00e1gina Siguiente",
+ "ButtonPreviousPage": "P\u00e1gina Anterior",
+ "ButtonMoveLeft": "Mover a la izquierda",
+ "ButtonMoveRight": "Mover a la derecha",
+ "ButtonBrowseOnlineImages": "Navegar por im\u00e1genes en l\u00ednea",
+ "HeaderDeleteItem": "Eliminar \u00cdtem",
+ "ConfirmDeleteItem": "\u00bfEsta seguro de querer eleiminar este \u00edtem de su biblioteca?",
+ "MessagePleaseEnterNameOrId": "Por favor ingrese un nombre o id externo.",
+ "MessageValueNotCorrect": "El valor ingresado no es correcto. Intente nuevamente por favor.",
+ "MessageItemSaved": "\u00cdtem guardado.",
+ "OptionEnded": "Finalizado",
+ "OptionContinuing": "Continuando",
+ "OptionOff": "No",
+ "OptionOn": "Si",
+ "HeaderFields": "Campos",
+ "HeaderFieldsHelp": "Deslice un campo hacia \"apagado\" para bloquearlo y evitar que sus datos sean modificados.",
+ "HeaderLiveTV": "TV en Vivo",
+ "MissingLocalTrailer": "Falta avance local.",
+ "MissingPrimaryImage": "Falta im\u00e1gen primaria.",
+ "MissingBackdropImage": "Falta im\u00e1gen de fondo.",
+ "MissingLogoImage": "Falta im\u00e1gen de logo.",
+ "MissingEpisode": "Falta episodio.",
+ "OptionScreenshots": "Capuras de Pantalla",
+ "OptionBackdrops": "Fondos",
+ "OptionImages": "Im\u00e1genes",
+ "OptionKeywords": "Palabras clave",
+ "OptionTags": "Etiquetas",
+ "OptionStudios": "Estudios",
+ "OptionName": "Nombre",
+ "OptionOverview": "Sinopsis",
+ "OptionGenres": "G\u00e9neros",
+ "OptionParentalRating": "Clasificaci\u00f3n Parental",
+ "OptionPeople": "Personas",
+ "OptionRuntime": "Duraci\u00f3n",
+ "OptionProductionLocations": "Lugares de Producci\u00f3n",
+ "OptionBirthLocation": "Lugar de Nacimiento",
+ "LabelAllChannels": "Todos los canales",
+ "LabelLiveProgram": "EN VIVO",
+ "LabelNewProgram": "NUEVO",
+ "LabelPremiereProgram": "ESTRENO",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Cambiar tipo de carpeta",
+ "HeaderChangeFolderTypeHelp": "Para cambiar el tipo de carpeta, por favor elimine y reconstruya la colecci\u00f3n con el nuevo tipo.",
+ "HeaderAlert": "Alerta",
+ "MessagePleaseRestart": "Por favor reinicie para finalizar la actualizaci\u00f3n.",
+ "ButtonRestart": "Reiniciar",
+ "MessagePleaseRefreshPage": "Por favor actualice esta p\u00e1gina para recibir nuevas actualizaciones desde el servidor.",
+ "ButtonHide": "Ocultar",
+ "MessageSettingsSaved": "Configuraciones guardadas",
+ "ButtonSignOut": "Cerrar Sesi\u00f3n",
+ "ButtonMyProfile": "Mi Perf\u00edl",
+ "ButtonMyPreferences": "Mis Preferencias",
+ "MessageBrowserDoesNotSupportWebSockets": "Este navegador no soporta sockets web. Para una mejor experiencia, pruebe con un navegador m\u00e1s nuevo como Chrome, Firefox, IE10+, Safari (iOS) u Opera.",
+ "LabelInstallingPackage": "Instalando {0}",
+ "LabelPackageInstallCompleted": "{0} instalaci\u00f3n completada.",
+ "LabelPackageInstallFailed": "{0} instalaci\u00f3n fallida.",
+ "LabelPackageInstallCancelled": "{0} instalaci\u00f3n cancelada.",
+ "TabServer": "Servidor",
+ "TabUsers": "Usuarios",
+ "TabLibrary": "Biblioteca",
+ "TabMetadata": "Metadatos",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "TV en Vivo",
+ "TabAutoOrganize": "Auto-Organizar",
+ "TabPlugins": "Complementos",
+ "TabAdvanced": "Avanzado",
+ "TabHelp": "Ayuda",
+ "TabScheduledTasks": "Tareas Programadas",
+ "ButtonFullscreen": "Pantalla completa",
+ "ButtonAudioTracks": "Pistas de Sonido",
+ "ButtonSubtitles": "Subt\u00edtulos",
+ "ButtonScenes": "Escenas",
+ "ButtonQuality": "Calidad",
+ "HeaderNotifications": "Notificaciones",
+ "HeaderSelectPlayer": "Seleccionar Reproductor:",
+ "ButtonSelect": "Seleccionar",
+ "ButtonNew": "Nuevo",
+ "MessageInternetExplorerWebm": "Para mejores resultados con Internet Explorer por favor instale el complemento de reproducci\u00f3n WebM.",
+ "HeaderVideoError": "Error de Video",
+ "ButtonAddToPlaylist": "A\u00f1adir a lista de reproducci\u00f3n",
+ "HeaderAddToPlaylist": "A\u00f1adir a Lista de Reproducci\u00f3n",
+ "LabelName": "Nombre:",
+ "ButtonSubmit": "Enviar",
+ "LabelSelectPlaylist": "Lista de Reproducci\u00f3n:",
+ "OptionNewPlaylist": "Nueva lista de reproducci\u00f3n...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "Ver grabaciones de series",
+ "ValueOriginalAirDate": "Fecha de transmisi\u00f3n original: {0}",
+ "ButtonRemoveFromPlaylist": "Eliminar de la lista de reproducci\u00f3n",
+ "HeaderSpecials": "Especiales",
+ "HeaderTrailers": "Avances",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resoluci\u00f3n",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Duraci\u00f3n",
+ "HeaderCommunityRating": "Calificaci\u00f3n de la comunidad",
+ "HeaderParentalRating": "Calificaci\u00f3n parental",
+ "HeaderReleaseDate": "Fecha de estreno",
+ "HeaderDateAdded": "Fecha de adici\u00f3n",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Temporada",
+ "HeaderSeasonNumber": "N\u00famero de temporada",
+ "HeaderNetwork": "Cadena",
+ "HeaderYear": "A\u00f1o",
+ "HeaderGameSystem": "Sistema de juegos",
+ "HeaderPlayers": "Jugadores",
+ "HeaderEmbeddedImage": "Im\u00e1gen embebida",
+ "HeaderTrack": "Pista",
+ "HeaderDisc": "Disco",
+ "OptionMovies": "Pel\u00edculas",
+ "OptionCollections": "Colecciones",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Temporadas",
+ "OptionEpisodes": "Episodios",
+ "OptionGames": "Juegos",
+ "OptionGameSystems": "Sistemas de juegos",
+ "OptionMusicArtists": "Int\u00e9rpretes",
+ "OptionMusicAlbums": "\u00c1lbums musicales",
+ "OptionMusicVideos": "Videos musicales",
+ "OptionSongs": "Canciones",
+ "OptionHomeVideos": "Videos caseros",
+ "OptionBooks": "Libros",
+ "OptionAdultVideos": "Videos para adultos",
+ "ButtonUp": "Arriba",
+ "ButtonDown": "Abajo",
+ "LabelMetadataReaders": "Lectores de metadatos:",
+ "LabelMetadataReadersHelp": "Ordene sus fuentes de metadatos locales por prioridad. El primer archivo encontrado ser\u00e1 le\u00eddo.",
+ "LabelMetadataDownloaders": "Recolectores de metadatos:",
+ "LabelMetadataDownloadersHelp": "Habilite y priorice sus recolectores de metadatos preferidos. Los recolectores de metadatos de menor prioridad solo ser\u00e1n utilizados para llenar informaci\u00f3n faltante.",
+ "LabelMetadataSavers": "Grabadores de metadatos:",
+ "LabelMetadataSaversHelp": "Seleccione los formatos de archivo con los que se guardaran sus metadatos.",
+ "LabelImageFetchers": "Recolectores de im\u00e1genes:",
+ "LabelImageFetchersHelp": "Habilite y priorice sus recolectores de im\u00e1genes preferidos.",
+ "ButtonQueueAllFromHere": "Encolar todos desde aqu\u00ed",
+ "ButtonPlayAllFromHere": "Reproducir todos desde aqu\u00ed",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identificar \u00edtem",
+ "PersonTypePerson": "Persona",
+ "LabelTitleDisplayOrder": "Ordenamiento de despliegue de t\u00edtulos:",
+ "OptionSortName": "Nombre para ordenar",
+ "OptionReleaseDate": "Fecha de estreno",
+ "LabelSeasonNumber": "N\u00famero de temporada:",
+ "LabelDiscNumber": "N\u00famero de disco",
+ "LabelParentNumber": "N\u00famero antecesor",
+ "LabelEpisodeNumber": "N\u00famero de episodio:",
+ "LabelTrackNumber": "N\u00famero de Pista:",
+ "LabelNumber": "N\u00famero",
+ "LabelReleaseDate": "Fecha de estreno:",
+ "LabelEndDate": "Fecha de Fin:",
+ "LabelYear": "A\u00f1o:",
+ "LabelDateOfBirth": "Fecha de nacimiento:",
+ "LabelBirthYear": "A\u00f1o de nacimiento:",
+ "LabelDeathDate": "Fecha de defunci\u00f3n:",
+ "HeaderRemoveMediaLocation": "Eliminar Ubicaci\u00f3n de Medios",
+ "MessageConfirmRemoveMediaLocation": "\u00bfEsta seguro de querer eliminar esta ubicaci\u00f3n?",
+ "HeaderRenameMediaFolder": "Renombrar Carpeta de Medios",
+ "LabelNewName": "Nuevo nombre:",
+ "HeaderAddMediaFolder": "Agregar Carpeta de Medios",
+ "HeaderAddMediaFolderHelp": "Nombre (Pel\u00edculas, M\u00fascia, TV, etc.):",
+ "HeaderRemoveMediaFolder": "Eliminar Carpteta de Medios",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "Las siguientes ubicaciones de medios ser\u00e1n eliminadas de su biblioteca:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "\u00bfEsta seguro de querer eliminar esta carpeta de medios?",
+ "ButtonRename": "Renombrar",
+ "ButtonChangeType": "Cambiar tipo",
+ "HeaderMediaLocations": "Ubicaciones de Medios",
+ "LabelFolderTypeValue": "Tipo de carpeta: {0}",
+ "LabelPathSubstitutionHelp": "Opcional: La sustituci\u00f3n de trayectoras puede mapear trayectorias del servidor a recursos de red comaprtidos que los clientes pueden acceder para reproducir de manera directa.",
+ "FolderTypeMixed": "Pel\u00edculas y TV mezclados",
+ "FolderTypeMovies": "Pel\u00edculas",
+ "FolderTypeMusic": "M\u00fasica",
+ "FolderTypeAdultVideos": "Videos para adultos",
+ "FolderTypePhotos": "Fotos",
+ "FolderTypeMusicVideos": "Videos musicales",
+ "FolderTypeHomeVideos": "Videos caseros",
+ "FolderTypeGames": "Juegos",
+ "FolderTypeBooks": "Libros",
+ "FolderTypeTvShows": "Programas de TV",
+ "TabMovies": "Pel\u00edculas",
+ "TabSeries": "Series",
+ "TabEpisodes": "Episodios",
+ "TabTrailers": "Avances",
+ "TabGames": "Juegos",
+ "TabAlbums": "\u00c1lbums",
+ "TabSongs": "Canciones",
+ "TabMusicVideos": "Videos Musicales",
+ "BirthPlaceValue": "Lugar de nacimiento: {0}",
+ "DeathDateValue": "Fallcimiento: {0}",
+ "BirthDateValue": "Nacimiento: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json
index 6e7f3246a..7b1feb6b3 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Cr\u00e9er mot de passe",
- "OptionOff": "Off",
- "OptionOn": "On",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "Ma biblioth\u00e8que",
"SettingsSaved": "Param\u00e8tres sauvegard\u00e9s.",
"AddUser": "Ajouter utilisateur",
"Users": "Utilisateurs",
@@ -18,7 +10,7 @@
"FileReadCancelled": "La lecture du fichier a \u00e9t\u00e9 annul\u00e9e.",
"FileNotFound": "Fichier non trouv\u00e9",
"FileReadError": "Un erreur est survenue pendant la lecture du fichier.",
- "DeleteUser": "Supprimer utilisateur",
+ "DeleteUser": "Supprimer l'utilisateur",
"DeleteUserConfirmation": "\u00cates-vous s\u00fbr de vouloir supprimer {0}?",
"PasswordResetHeader": "R\u00e9initialisation du mot de passe",
"PasswordResetComplete": "Le mot de passe a \u00e9t\u00e9 r\u00e9initialis\u00e9.",
@@ -38,7 +30,7 @@
"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.",
- "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
+ "ErrorLaunchingChromecast": "Une erreur est rencontr\u00e9e lors du lancement de Chromecast. Assurez-vous bien que votre p\u00e9riph\u00e9rique est bien connect\u00e9 \u00e0 votre r\u00e9seau sans-fil.",
"HeaderSearch": "Recherche",
"LabelArtist": "Artiste",
"LabelMovie": "Film",
@@ -46,14 +38,13 @@
"LabelEpisode": "\u00c9pisode",
"LabelSeries": "S\u00e9ries",
"LabelStopping": "En cours d'arr\u00eat",
- "ButtonStop": "Arr\u00eat",
- "LabelCancelled": "(annull\u00e9)",
+ "LabelCancelled": "(annul\u00e9)",
"LabelFailed": "(\u00e9chou\u00e9)",
"LabelAbortedByServerShutdown": "(Annul\u00e9 par fermeture du serveur)",
"LabelScheduledTaskLastRan": "Derni\u00e8re ex\u00e9cution {0}, dur\u00e9e {1}.",
- "HeaderDeleteTaskTrigger": "Delete Task Trigger",
- "HeaderTaskTriggers": "Task Triggers",
- "MessageDeleteTaskTrigger": "Are you sure you wish to delete this task trigger?",
+ "HeaderDeleteTaskTrigger": "Supprimer le d\u00e9clencheur de t\u00e2che",
+ "HeaderTaskTriggers": "D\u00e9clencheurs de t\u00e2ches",
+ "MessageDeleteTaskTrigger": "\u00cates-vous s\u00fbr de vouloir supprimer ce d\u00e9clencheur de t\u00e2che?",
"MessageNoPluginsInstalled": "Vous n'avez aucun plugin install\u00e9.",
"LabelVersionInstalled": "{0} install\u00e9(s)",
"LabelNumberReviews": "{0} Critique(s)",
@@ -65,13 +56,16 @@
"LabelDefaultForcedStream": "(Par d\u00e9faut\/Forc\u00e9)",
"LabelUnknownLanguage": "Langue inconnue",
"ButtonMute": "Sourdine",
- "ButtonUnmute": "Unmute",
+ "ButtonUnmute": "D\u00e9sactiver sourdine",
+ "ButtonStop": "Arr\u00eat",
+ "ButtonNextTrack": "Piste suivante",
"ButtonPause": "Pause",
"ButtonPlay": "Lire",
"ButtonEdit": "Modifier",
"ButtonQueue": "En file d'attente",
- "ButtonPlayTrailer": "Lire bande-annonce",
+ "ButtonPlayTrailer": "Lire la bande-annonce",
"ButtonPlaylist": "Liste de lecture",
+ "ButtonPreviousTrack": "Piste pr\u00e9c\u00e9dente",
"LabelEnabled": "Activ\u00e9",
"LabelDisabled": "D\u00e9sactiv\u00e9",
"ButtonMoreInformation": "Plus d'information",
@@ -83,9 +77,9 @@
"MessageInvalidUser": "Nom d'utilisateur et mot de passe invalides.",
"HeaderAllRecordings": "Tous les enregistrements",
"RecommendationBecauseYouLike": "Parce-que vous aimez {0}",
- "RecommendationBecauseYouWatched": "Parece-que vous avez regard\u00e9 {0}",
+ "RecommendationBecauseYouWatched": "Parce que vous avez regard\u00e9 {0}",
"RecommendationDirectedBy": "R\u00e9alis\u00e9 par {0}",
- "RecommendationStarring": "Starring {0}",
+ "RecommendationStarring": "Mettant en vedette {0}",
"HeaderConfirmRecordingCancellation": "Confirmer l'annulation de l'enregistrement.",
"MessageConfirmRecordingCancellation": "\u00cates-vous s\u00fbr de vouloir annuler cet enregistrement?",
"MessageRecordingCancelled": "Enregistrement annul\u00e9.",
@@ -110,27 +104,27 @@
"LabelVersionUpToDate": "\u00c0 jour!",
"ButtonResetTuner": "Red\u00e9marrer tuner",
"HeaderResetTuner": "Red\u00e9marrer tuner",
- "MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
+ "MessageConfirmResetTuner": "\u00cates-vous s\u00fbr de vouloir r\u00e9initialiser ce tuner ? Tout les lecteurs ou enregistrements actifs seront brusquement interrompus.",
"ButtonCancelSeries": "Annuler s\u00e9ries",
- "LabelAllChannels": "Toutes les cha\u00eenes",
"HeaderSeriesRecordings": "Enregistrements de s\u00e9ries",
- "LabelAnytime": "Any time",
+ "LabelAnytime": "N'importe quelle heure",
"StatusRecording": "En cours d'enregistrement",
- "StatusWatching": "Watching",
+ "StatusWatching": "En lecture",
"StatusRecordingProgram": "Enregistre {0}",
- "StatusWatchingProgram": "Watching {0}",
- "HeaderSplitMedia": "Split Media Apart",
- "MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
+ "StatusWatchingProgram": "En lecture de {0}",
+ "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",
- "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": "Media Browser clients will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?",
+ "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:",
+ "MessageConfirmItemGrouping": "Les clients Media Browser s\u00e9lectionneront automatiquement la version optimale \u00e0 lire bas\u00e9 sur l'appareil et la performance du r\u00e9seau. \u00cates-vous s\u00fbr de vouloir continuer?",
"HeaderResume": "Reprendre",
- "HeaderMyViews": "My Views",
- "HeaderLibraryFolders": "Media Folders",
+ "HeaderMyViews": "Mes affichages",
+ "HeaderLibraryFolders": "R\u00e9pertoires de m\u00e9dias",
"HeaderLatestMedia": "Derniers m\u00e9dias",
- "ButtonMore": "Plus...",
+ "ButtonMoreItems": "Plus...",
+ "ButtonMore": "Voir la suite",
"HeaderFavoriteMovies": "Films favoris",
"HeaderFavoriteShows": "S\u00e9ries favorites",
"HeaderFavoriteEpisodes": "\u00c9pisodes favoris",
@@ -142,56 +136,298 @@
"HeaderSelectTranscodingPath": "S\u00e9lectionner le chemin d'acc\u00e8s du transcodage temporaire",
"HeaderSelectImagesByNamePath": "S\u00e9lectionner le chemin d'acc\u00e8s du \"Images By Name\"",
"HeaderSelectMetadataPath": "S\u00e9lectionner le chemin d'acc\u00e8s des m\u00e9tadonn\u00e9es",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
- "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
- "HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
- "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
- "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...",
+ "HeaderSelectServerCachePathHelp": "Parcourir ou entrer le chemin d'acc\u00e8s \u00e0 utiliser pour les fichiers caches du serveur. Le dossier doit \u00eatre accessible en \u00e9criture.",
+ "HeaderSelectTranscodingPathHelp": "Parcourir ou saisir le chemin dossier \u00e0 utiliser pour le transcodage des fichiers temporaires. Le dossier devra \u00eatre accessible en \u00e9criture.",
+ "HeaderSelectImagesByNamePathHelp": "Parcourir ou saisir le chemin dossier de vos items par le nom du dossier. Le dossier devra \u00eatre accessible en \u00e9criture.",
+ "HeaderSelectMetadataPathHelp": "Parcourir ou saisir le chemin o\u00f9 vous aimeriez stocker les m\u00e9tadonn\u00e9es. Le r\u00e9pertoire doit \u00eatre accessible en \u00e9criture.",
+ "HeaderSelectChannelDownloadPath": "S\u00e9lectionnez le chemin de t\u00e9l\u00e9chargement des cha\u00eenes.",
+ "HeaderSelectChannelDownloadPathHelp": "Parcourir ou saisir le chemin destin\u00e9 au stockage des fichers cache des cha\u00eenes. Le r\u00e9pertoire doit \u00eatre accessible en \u00e9criture.",
+ "OptionNewCollection": "Nouveau...",
"ButtonAdd": "Ajouter",
"ButtonRemove": "Supprimer",
- "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.",
- "HeaderFavoriteAlbums": "Favorite Albums",
- "HeaderLatestChannelMedia": "Latest Channel Items",
- "ButtonOrganizeFile": "Organize File",
- "ButtonDeleteFile": "Delete File",
- "HeaderOrganizeFile": "Organize File",
- "HeaderDeleteFile": "Delete File",
- "StatusSkipped": "Skipped",
- "StatusFailed": "Failed",
- "StatusSuccess": "Success",
- "MessageFileWillBeDeleted": "The following file will be deleted:",
- "MessageSureYouWishToProceed": "Are you sure you wish to proceed?",
- "MessageDuplicatesWillBeDeleted": "In addition the following dupliates will be deleted:",
- "MessageFollowingFileWillBeMovedFrom": "The following file will be moved from:",
- "MessageDestinationTo": "to:",
- "HeaderSelectWatchFolder": "Select Watch Folder",
- "HeaderSelectWatchFolderHelp": "Browse or enter the path to your watch folder. The folder must be writeable.",
- "OrganizePatternResult": "Result: {0}",
- "HeaderRestart": "Restart",
- "HeaderShutdown": "Shutdown",
- "MessageConfirmRestart": "Are you sure you wish to restart Media Browser Server?",
- "MessageConfirmShutdown": "Are you sure you wish to shutdown Media Browser Server?",
+ "LabelChapterDownloaders": "Agents de t\u00e9l\u00e9chargement de chapitres:",
+ "LabelChapterDownloadersHelp": "Activer et classer vos sources de t\u00e9l\u00e9chargement de chapitre pr\u00e9f\u00e9r\u00e9s dans un ordre de priorit\u00e9. Les sources de t\u00e9l\u00e9chargement ayant une priorit\u00e9 basse, seront seulement utilis\u00e9es pour remplir les informations manquantes.",
+ "HeaderFavoriteAlbums": "Albums favoris",
+ "HeaderLatestChannelMedia": "Derniers items de cha\u00eenes",
+ "ButtonOrganizeFile": "Organiser fichier",
+ "ButtonDeleteFile": "Supprimer fichier",
+ "HeaderOrganizeFile": "Organiser fichier",
+ "HeaderDeleteFile": "Supprimer fichier",
+ "StatusSkipped": "Saut\u00e9s",
+ "StatusFailed": "\u00c9chou\u00e9",
+ "StatusSuccess": "Succ\u00e8s",
+ "MessageFileWillBeDeleted": "Le fichier suivant sera supprim\u00e9:",
+ "MessageSureYouWishToProceed": "\u00cates-vous s\u00fbr de vouloir continuer?",
+ "MessageDuplicatesWillBeDeleted": "De plus, les doubles suivants vont \u00eatre supprim\u00e9s :",
+ "MessageFollowingFileWillBeMovedFrom": "Le fichier suivant sera d\u00e9plac\u00e9 de:",
+ "MessageDestinationTo": "Vers:",
+ "HeaderSelectWatchFolder": "S\u00e9lectionner le r\u00e9pertoire surveill\u00e9",
+ "HeaderSelectWatchFolderHelp": "Parcourir ou saisir le chemin de votre r\u00e9pertoire de surveillance. Le r\u00e9pertoire doit \u00eatre accessible en \u00e9criture.",
+ "OrganizePatternResult": "R\u00e9sultats: {0}",
+ "HeaderRestart": "Red\u00e9marrer",
+ "HeaderShutdown": "\u00c9teindre",
+ "MessageConfirmRestart": "\u00cates-vous s\u00fbr de vouloir red\u00e9marrer le serveur Media Browser?",
+ "MessageConfirmShutdown": "\u00cates-vous s\u00fbr de vouloir \u00e9teindre le serveur Media Browser?",
"ButtonUpdateNow": "Mettre \u00e0 jour maintenant",
- "NewVersionOfSomethingAvailable": "A new version of {0} is available!",
- "VersionXIsAvailableForDownload": "Version {0} is now available for download.",
+ "NewVersionOfSomethingAvailable": "Une nouvelle version de {0} est disponible!",
+ "VersionXIsAvailableForDownload": "La version {0} est maintenant disponible \u00e0 \u00eatre t\u00e9l\u00e9charg\u00e9e.",
"LabelVersionNumber": "Version {0}",
- "LabelPlayMethodTranscoding": "Transcoding",
- "LabelPlayMethodDirectStream": "Direct Streaming",
- "LabelPlayMethodDirectPlay": "Direct Playing",
+ "LabelPlayMethodTranscoding": "Transcodage",
+ "LabelPlayMethodDirectStream": "Direct Stream",
+ "LabelPlayMethodDirectPlay": "Direct Play",
"LabelAudioCodec": "Audio: {0}",
- "LabelVideoCodec": "Video: {0}",
- "LabelRemoteAccessUrl": "Remote access: {0}",
- "LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
- "HeaderLatestFromChannel": "Latest from {0}",
- "ButtonDownload": "Download",
- "LabelUnknownLanaguage": "Unknown language",
- "HeaderCurrentSubtitles": "Current Subtitles",
- "MessageDownloadQueued": "The download has been queued.",
- "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
- "ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "LabelVideoCodec": "Vid\u00e9o: {0}",
+ "LabelRemoteAccessUrl": "Acc\u00e8s distant: {0}",
+ "LabelRunningOnPort": "En ex\u00e9cution sur le port: {0}.",
+ "HeaderLatestFromChannel": "Les plus r\u00e9cents de {0}",
+ "ButtonDownload": "T\u00e9l\u00e9chargement",
+ "LabelUnknownLanaguage": "Langue inconnue",
+ "HeaderCurrentSubtitles": "Sous-titres actuels",
+ "MessageDownloadQueued": "Le t\u00e9l\u00e9chargement a \u00e9t\u00e9 mis en file.",
+ "MessageAreYouSureDeleteSubtitles": "\u00cates-vous s\u00fbr de vouloir supprimer ce fichier de sous-titre?",
+ "ButtonRemoteControl": "Acc\u00e8s distant",
+ "HeaderLatestTvRecordings": "Les plus r\u00e9cents enregistrements",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Annuler",
+ "ButtonRefresh": "Actualiser",
+ "LabelCurrentPath": "Chemin actuel:",
+ "HeaderSelectMediaPath": "S\u00e9lectionner le chemin m\u00e9dia",
+ "ButtonNetwork": "R\u00e9seau",
+ "MessageDirectoryPickerInstruction": "Les chemins r\u00e9seaux seront saisis manuellement dans le cas o\u00f9 le bouton R\u00e9seau ne parvient pas \u00e0 rechercher vos p\u00e9riph\u00e9riques. Par exemple, {0} ou {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Ouvrir",
+ "ButtonOpenInNewTab": "Ouvrir dans un nouvel onglet",
+ "ButtonShuffle": "M\u00e9langer",
+ "ButtonInstantMix": "Instantan\u00e9",
+ "ButtonResume": "Reprendre",
+ "HeaderScenes": "Sc\u00e8nes",
+ "HeaderAudioTracks": "Pistes audio",
+ "HeaderSubtitles": "Sous-titres",
+ "HeaderVideoQuality": "Qualit\u00e9 vid\u00e9o",
+ "MessageErrorPlayingVideo": "La lecture de la vid\u00e9o a rencontr\u00e9 une erreur",
+ "MessageEnsureOpenTuner": "V\u00e9rifiez bien que le tuner est disponible",
+ "ButtonHome": "Portail",
+ "ButtonDashboard": "Tableau de bord",
+ "ButtonReports": "Rapports",
+ "ButtonMetadataManager": "Gestionnaire de m\u00e9tadonn\u00e9es",
+ "HeaderTime": "Heure",
+ "HeaderName": "Nom",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Artiste de l'album",
+ "HeaderArtist": "Artiste",
+ "LabelAddedOnDate": "Ajout\u00e9 {0}",
+ "ButtonStart": "Commencer",
+ "HeaderChannels": "Cha\u00eenes",
+ "HeaderMediaFolders": "R\u00e9pertoires de m\u00e9dias",
+ "HeaderBlockItemsWithNoRating": "Bloquer les items ne comportant aucune information de classement :",
+ "OptionBlockOthers": "Autres",
+ "OptionBlockTvShows": "Emissions TV",
+ "OptionBlockTrailers": "Bandes-annonces",
+ "OptionBlockMusic": "Musiques",
+ "OptionBlockMovies": "Films",
+ "OptionBlockBooks": "Livres",
+ "OptionBlockGames": "Jeux",
+ "OptionBlockLiveTvPrograms": "Programmes TV en direct",
+ "OptionBlockLiveTvChannels": "Cha\u00eenes TV en direct",
+ "OptionBlockChannelContent": "Cha\u00eenes Internet",
+ "ButtonRevoke": "R\u00e9voquer",
+ "MessageConfirmRevokeApiKey": "\u00cates-vous s\u00fbr de vouloir r\u00e9voquer la cl\u00e9 API ? La connexion \u00e0 l'application Media Browser sera brusquement interrompue.",
+ "HeaderConfirmRevokeApiKey": "R\u00e9voquer la cl\u00e9 API",
+ "ValueContainer": "Conteneur : {0}",
+ "ValueAudioCodec": "Codec Audio : {0}",
+ "ValueVideoCodec": "Codec Vid\u00e9o : {0}",
+ "ValueCodec": "Codec : {0}",
+ "ValueConditions": "Conditions : {0}",
+ "LabelAll": "Tout",
+ "HeaderDeleteImage": "Supprimer l'image",
+ "MessageFileNotFound": "Fichier introuvable.",
+ "MessageFileReadError": "Une erreur a \u00e9t\u00e9 rencontr\u00e9e pendant la lecture de ce fichier.",
+ "ButtonNextPage": "Page suivante",
+ "ButtonPreviousPage": "Page pr\u00e9c\u00e9dente",
+ "ButtonMoveLeft": "D\u00e9placer \u00e0 gauche",
+ "ButtonMoveRight": "D\u00e9placer \u00e0 droite",
+ "ButtonBrowseOnlineImages": "Parcourir les images en ligne",
+ "HeaderDeleteItem": "Supprimer l'item",
+ "ConfirmDeleteItem": "\u00cates-vous s\u00fbr de vouloir supprimer cet item de votre biblioth\u00e8que ?",
+ "MessagePleaseEnterNameOrId": "Merci de saisir un nom ou un ID externe.",
+ "MessageValueNotCorrect": "La valeur saisie est incorrecte. Merci de r\u00e9\u00e9ssayer.",
+ "MessageItemSaved": "Item sauvegard\u00e9.",
+ "OptionEnded": "Termin\u00e9",
+ "OptionContinuing": "En cours",
+ "OptionOff": "Off",
+ "OptionOn": "On",
+ "HeaderFields": "Champs",
+ "HeaderFieldsHelp": "Glisser un champ sur \"off\" pour le v\u00e9rouiller et emp\u00eacher les modifications de donn\u00e9es.",
+ "HeaderLiveTV": "TV en direct",
+ "MissingLocalTrailer": "Bande-annonce locale manquante.",
+ "MissingPrimaryImage": "Image principale manquante.",
+ "MissingBackdropImage": "Image d'arri\u00e8re-plan manquante.",
+ "MissingLogoImage": "Image logo manquante.",
+ "MissingEpisode": "Episode manquant.",
+ "OptionScreenshots": "Captures d'\u00e9cran",
+ "OptionBackdrops": "Arri\u00e8re-plans",
+ "OptionImages": "Images",
+ "OptionKeywords": "Mots-cl\u00e9s",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Nom",
+ "OptionOverview": "Aper\u00e7u",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Note d'\u00e9valuation de contr\u00f4le parental",
+ "OptionPeople": "People",
+ "OptionRuntime": "Dur\u00e9e",
+ "OptionProductionLocations": "Sites de production",
+ "OptionBirthLocation": "Lieu de naissance",
+ "LabelAllChannels": "Toutes les cha\u00eenes",
+ "LabelLiveProgram": "DIRECT",
+ "LabelNewProgram": "NOUVEAUTE",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Modifier le type de dossier",
+ "HeaderChangeFolderTypeHelp": "Pour modifier le type de dossier, merci de supprimer et reconstruire la collection avec le nouveau type.",
+ "HeaderAlert": "Alerte",
+ "MessagePleaseRestart": "Merci de red\u00e9marrer pour achever la mise \u00e0 jour.",
+ "ButtonRestart": "Red\u00e9marrer",
+ "MessagePleaseRefreshPage": "Merci de rafra\u00eechir cette page pour recevoir les nouvelles mises \u00e0 jour du serveur.",
+ "ButtonHide": "Cacher",
+ "MessageSettingsSaved": "Param\u00e8tres sauvegard\u00e9s.",
+ "ButtonSignOut": "Se d\u00e9connecter",
+ "ButtonMyProfile": "Mon profil",
+ "ButtonMyPreferences": "Mes pr\u00e9f\u00e9rences",
+ "MessageBrowserDoesNotSupportWebSockets": "Ce navigateur ne supporte pas les sockets Web. Pour un meilleur confort d'utilisation, essayez avec un navigateur moderne tels que Chrome, Firefox, IE10+, Safari (iOS) ou Opera.",
+ "LabelInstallingPackage": "Installation de {0}",
+ "LabelPackageInstallCompleted": "L'installation de {0} est termin\u00e9e.",
+ "LabelPackageInstallFailed": "L'installation de {0} a \u00e9chou\u00e9.",
+ "LabelPackageInstallCancelled": "L'installation de {0} a \u00e9t\u00e9 annul\u00e9e.",
+ "TabServer": "Serveur",
+ "TabUsers": "Utilisateurs",
+ "TabLibrary": "Biblioth\u00e8que",
+ "TabMetadata": "M\u00e9tadonn\u00e9es",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "TV en direct",
+ "TabAutoOrganize": "Auto-Organiser",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Avanc\u00e9",
+ "TabHelp": "Aide",
+ "TabScheduledTasks": "T\u00e2ches planifi\u00e9es",
+ "ButtonFullscreen": "Plein \u00e9cran",
+ "ButtonAudioTracks": "Pistes audio",
+ "ButtonSubtitles": "Sous-titres",
+ "ButtonScenes": "Sc\u00e8nes",
+ "ButtonQuality": "Qualit\u00e9",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "S\u00e9lectionner le lecteur :",
+ "ButtonSelect": "S\u00e9lectionner",
+ "ButtonNew": "Nouveau",
+ "MessageInternetExplorerWebm": "Pour de meilleurs r\u00e9sultats avec Internet Explorer, merci d'installer le plugin WebM pour IE.",
+ "HeaderVideoError": "Erreur vid\u00e9o",
+ "ButtonAddToPlaylist": "Ajouter \u00e0 la liste de lecture",
+ "HeaderAddToPlaylist": "Ajouter \u00e0 la liste de lecture",
+ "LabelName": "Nom:",
+ "ButtonSubmit": "Soumettre",
+ "LabelSelectPlaylist": "Liste de lecture:",
+ "OptionNewPlaylist": "Nouvelle liste de lecture...",
+ "MessageAddedToPlaylistSuccess": "OK",
+ "ButtonViewSeriesRecording": "Voir enregistrements de s\u00e9ries",
+ "ValueOriginalAirDate": "Date de diffusion originale: {0}",
+ "ButtonRemoveFromPlaylist": "Supprimer de la liste de lecture",
+ "HeaderSpecials": "Sp\u00e9ciaux",
+ "HeaderTrailers": "Bandes-annonces",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "R\u00e9solution",
+ "HeaderVideo": "Vid\u00e9o",
+ "HeaderRuntime": "Dur\u00e9e",
+ "HeaderCommunityRating": "Note de communaut\u00e9",
+ "HeaderParentalRating": "Note parentale",
+ "HeaderReleaseDate": "Date de lancement",
+ "HeaderDateAdded": "Date ajout\u00e9e",
+ "HeaderSeries": "S\u00e9ries",
+ "HeaderSeason": "Saison",
+ "HeaderSeasonNumber": "Num\u00e9ro de saison",
+ "HeaderNetwork": "R\u00e9seau",
+ "HeaderYear": "Ann\u00e9e",
+ "HeaderGameSystem": "Plateforme de jeu",
+ "HeaderPlayers": "Lecteurs",
+ "HeaderEmbeddedImage": "Image int\u00e9gr\u00e9e",
+ "HeaderTrack": "Piste",
+ "HeaderDisc": "Disque",
+ "OptionMovies": "Films",
+ "OptionCollections": "Collections",
+ "OptionSeries": "S\u00e9ries",
+ "OptionSeasons": "Saisons",
+ "OptionEpisodes": "\u00c9pisodes",
+ "OptionGames": "Jeux",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Artistes musicaux",
+ "OptionMusicAlbums": "Albums de musique",
+ "OptionMusicVideos": "Vid\u00e9os musicales",
+ "OptionSongs": "Chansons",
+ "OptionHomeVideos": "Vid\u00e9os personnelles",
+ "OptionBooks": "Livres",
+ "OptionAdultVideos": "Vid\u00e9os adultes",
+ "ButtonUp": "Haut",
+ "ButtonDown": "Bas",
+ "LabelMetadataReaders": "Lecteurs de m\u00e9tadonn\u00e9es :",
+ "LabelMetadataReadersHelp": "Classez vos sources locales de m\u00e9tadonn\u00e9es pr\u00e9f\u00e9r\u00e9es dans l'ordre de priorit\u00e9. Le premier fichier trouv\u00e9 sera lu.",
+ "LabelMetadataDownloaders": "T\u00e9l\u00e9chargeurs de m\u00e9tadonn\u00e9es:",
+ "LabelMetadataDownloadersHelp": "Activez et classez vos sources de t\u00e9l\u00e9chargement de m\u00e9tadonn\u00e9es pr\u00e9f\u00e9r\u00e9es dans l'ordre de priorit\u00e9. Les plus basses seront seulement utilis\u00e9s pour remplir les informations manquantes.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Num\u00e9ro de saison",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Num\u00e9ro d'\u00e9pisode",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date de naissance:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Renommer le r\u00e9pertoire de m\u00e9dia",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Supprimer le r\u00e9pertoire de m\u00e9dia",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "\u00cates-vous s\u00fbr de vouloir supprimer ce r\u00e9pertoire de m\u00e9dia?",
+ "ButtonRename": "Renommer",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Films",
+ "FolderTypeMusic": "Musique",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Jeux",
+ "FolderTypeBooks": "Livres",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Films",
+ "TabSeries": "S\u00e9ries",
+ "TabEpisodes": "\u00c9pisodes",
+ "TabTrailers": "Bandes-annonces",
+ "TabGames": "Jeux",
+ "TabAlbums": "Albums",
+ "TabSongs": "Chansons",
+ "TabMusicVideos": "Videos musicales",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json
index c22783249..e81dc5775 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "\u05db\u05d1\u05d5\u05d9",
- "OptionOn": "\u05e4\u05d5\u05e2\u05dc",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "My Library",
"SettingsSaved": "\u05d4\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05e0\u05e9\u05de\u05e8\u05d5.",
"AddUser": "\u05d4\u05d5\u05e1\u05e3 \u05de\u05e9\u05ea\u05de\u05e9",
"Users": "\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episode",
"LabelSeries": "Series",
"LabelStopping": "Stopping",
- "ButtonStop": "Stop",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Unknown language",
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
"ButtonPause": "Pause",
"ButtonPlay": "\u05e0\u05d2\u05df",
"ButtonEdit": "\u05e2\u05e8\u05d5\u05da",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
+ "ButtonPlayTrailer": "Play trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Previous Track",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
"ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
"HeaderSeriesRecordings": "Series Recordings",
"LabelAnytime": "Any time",
"StatusRecording": "Recording",
@@ -130,7 +123,8 @@
"HeaderMyViews": "My Views",
"HeaderLibraryFolders": "Media Folders",
"HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
"HeaderFavoriteMovies": "Favorite Movies",
"HeaderFavoriteShows": "Favorite Shows",
"HeaderFavoriteEpisodes": "Favorite Episodes",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
"HeaderSelectImagesByNamePath": "Select Images By Name Path",
"HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
"HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Remote access: {0}",
"LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
"HeaderLatestFromChannel": "Latest from {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Unknown language",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "\u05d0\u05e9\u05e8",
+ "ButtonCancel": "\u05d1\u05d8\u05dc",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "\u05e1\u05e6\u05e0\u05d5\u05ea",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "\u05e9\u05dd",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "\u05e2\u05e8\u05d5\u05e6\u05d9\u05dd",
+ "HeaderMediaFolders": "\u05e1\u05e4\u05e8\u05d9\u05d5\u05ea \u05de\u05d3\u05d9\u05d4",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "\u05d4\u05e1\u05ea\u05d9\u05d9\u05dd",
+ "OptionContinuing": "\u05de\u05de\u05e9\u05d9\u05da",
+ "OptionOff": "\u05db\u05d1\u05d5\u05d9",
+ "OptionOn": "\u05e4\u05d5\u05e2\u05dc",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "\u05d3\u05d9\u05e8\u05d5\u05d2 \u05d1\u05e7\u05e8\u05ea \u05d4\u05d5\u05e8\u05d9\u05dd",
+ "OptionPeople": "People",
+ "OptionRuntime": "\u05de\u05e9\u05da",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "\u05d4\u05ea\u05d7\u05e8 \u05de\u05d7\u05d3\u05e9",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "\u05e9\u05e8\u05ea",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "\u05de\u05ea\u05e7\u05d3\u05dd",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonScenes": "Scenes",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "\u05d1\u05d7\u05e8",
+ "ButtonNew": "\u05d7\u05d3\u05e9",
+ "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": "\u05e9\u05dd:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "\u05e1\u05e8\u05d8\u05d9\u05dd",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "\u05e4\u05e8\u05e7\u05d9\u05dd",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "\u05de\u05e1\u05e4\u05e8 \u05e2\u05d5\u05e0\u05d4:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "\u05de\u05e1\u05e4\u05e8 \u05e4\u05e8\u05e7:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "\u05e1\u05e8\u05d8\u05d9\u05dd",
+ "TabSeries": "\u05e1\u05d3\u05e8\u05d5\u05ea",
+ "TabEpisodes": "\u05e4\u05e8\u05e7\u05d9\u05dd",
+ "TabTrailers": "\u05d8\u05e8\u05d9\u05d9\u05dc\u05e8\u05d9\u05dd",
+ "TabGames": "\u05de\u05e9\u05d7\u05e7\u05d9\u05dd",
+ "TabAlbums": "\u05d0\u05dc\u05d1\u05d5\u05de\u05d9\u05dd",
+ "TabSongs": "\u05e9\u05d9\u05e8\u05d9\u05dd",
+ "TabMusicVideos": "\u05e7\u05dc\u05d9\u05e4\u05d9\u05dd",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json
index dcd0f73e8..50cc701cf 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Crea Password",
- "OptionOff": "Off",
- "OptionOn": "On",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Si prega di selezionare due o pi\u00f9 elementi al gruppo insieme.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "Mia Libreria",
"SettingsSaved": "Settaggi salvati.",
"AddUser": "Aggiungi utente",
"Users": "Utenti",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episodio",
"LabelSeries": "Serie",
"LabelStopping": "Sto fermando",
- "ButtonStop": "Stop",
"LabelCancelled": "(cancellato)",
"LabelFailed": "(fallito)",
"LabelAbortedByServerShutdown": "(Interrotto dalla chiusura del server)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "(linguaggio sconosciuto)",
"ButtonMute": "Muto",
"ButtonUnmute": "Togli muto",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "traccia Prossima",
"ButtonPause": "Pausa",
"ButtonPlay": "Riproduci",
"ButtonEdit": "Modifica",
"ButtonQueue": "In coda",
- "ButtonPlayTrailer": "Visualizza trailer",
+ "ButtonPlayTrailer": "Visualizza Trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Precedente traccia",
"LabelEnabled": "Abilitato",
"LabelDisabled": "Disabilitato",
"ButtonMoreInformation": "Maggiori informazioni",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Riavvia Scheda TV",
"MessageConfirmResetTuner": "Sei sicuro di voler ripristinare questo sintonizzatore? Tutti i giocatori attivi o registrazioni saranno bruscamente fermato.",
"ButtonCancelSeries": "Serie cancellate",
- "LabelAllChannels": "Tutti i canali",
"HeaderSeriesRecordings": "Serie registrate",
"LabelAnytime": "Qualsiasi ora",
"StatusRecording": "Registrazione",
@@ -128,9 +121,10 @@
"MessageConfirmItemGrouping": "Clienti Media Browser sceglier\u00e0 automaticamente la versione ottimale per giocare sulla base del dispositivo e prestazioni di rete. Sei sicuro di voler continuare?",
"HeaderResume": "Riprendi",
"HeaderMyViews": "Mie viste",
- "HeaderLibraryFolders": "Vista",
+ "HeaderLibraryFolders": "Cartelle dei mediata",
"HeaderLatestMedia": "Ultimi Media",
- "ButtonMore": "Pi\u00f9 info...",
+ "ButtonMoreItems": "Pi\u00f9...",
+ "ButtonMore": "Dettagli",
"HeaderFavoriteMovies": "Film preferiti",
"HeaderFavoriteShows": "Show preferiti",
"HeaderFavoriteEpisodes": "Episodi preferiti",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Selezionare transcodifica Percorso temporaneo",
"HeaderSelectImagesByNamePath": "Selezionare Immagini per nome Path",
"HeaderSelectMetadataPath": "Selezionare metadati Path",
- "HeaderSelectServerCachePathHelp": "Sfoglia o immettere il percorso da utilizzare per i file di cache server. La cartella deve essere scrivibile. La posizione di questa cartella avr\u00e0 un impatto diretto sulle prestazioni del server e dovrebbe idealmente essere collocato su un disco a stato solido.",
+ "HeaderSelectServerCachePathHelp": "Sfoglia o immetti il percorso da utilizzare per i file di cache server. La cartella deve essere scrivibile",
"HeaderSelectTranscodingPathHelp": "Sfoglia o immettere il percorso da utilizzare per la transcodifica dei file temporanei. La cartella deve essere scrivibile.",
"HeaderSelectImagesByNamePathHelp": "Sfoglia oppure immettere il percorso per i vostri articoli per cartella nome. La cartella deve essere scrivibile.",
"HeaderSelectMetadataPathHelp": "Sfoglia o inserire il percorso vuoi archiviare i metadati all'interno. La cartella deve essere scrivibile.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Accesso remoto: {0}",
"LabelRunningOnPort": "Avviato su porta {0}",
- "LabelRunningOnPorts": "Avviato su porte {0} e {1}.",
"HeaderLatestFromChannel": "Ultime da {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "lingua sconosciuta",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "Il download \u00e8 stato accodato.",
"MessageAreYouSureDeleteSubtitles": "Sei sicuro di voler cancellare questo file dei sottotitoli?",
"ButtonRemoteControl": "telecomando",
- "HeaderLatestTvRecordings": "Ultime registrazioni"
+ "HeaderLatestTvRecordings": "Ultime registrazioni",
+ "ButtonOk": "OK",
+ "ButtonCancel": "Annulla",
+ "ButtonRefresh": "Aggiorna",
+ "LabelCurrentPath": "Percorso Corrente:",
+ "HeaderSelectMediaPath": "Seleziona il percorso",
+ "ButtonNetwork": "Rete",
+ "MessageDirectoryPickerInstruction": "Percorsi di rete possono essere inseriti manualmente nel caso in cui il pulsante Rete non riesce a individuare i vostri dispositivi. Ad esempio, {0} o {1}",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Apri",
+ "ButtonOpenInNewTab": "Apri in una nuova finestra",
+ "ButtonShuffle": "A caso",
+ "ButtonInstantMix": "mix istantaneo",
+ "ButtonResume": "Riprendi",
+ "HeaderScenes": "Scene",
+ "HeaderAudioTracks": "tracce audio",
+ "HeaderSubtitles": "Sottotitoli",
+ "HeaderVideoQuality": "Qualit\u00e0 video",
+ "MessageErrorPlayingVideo": "Si \u00e8 verificato un errore riproduzione del video.",
+ "MessageEnsureOpenTuner": "Si prega di assicurarsi che ci sia un sintonizzatore aperto disponibile.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Tempo",
+ "HeaderName": "Nome",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Artista Album",
+ "HeaderArtist": "Artista",
+ "LabelAddedOnDate": "Aggiunto {0}",
+ "ButtonStart": "Avvio",
+ "HeaderChannels": "Canali",
+ "HeaderMediaFolders": "Cartelle dei media",
+ "HeaderBlockItemsWithNoRating": "Blocca gli elementi senza informazioni di valutazione",
+ "OptionBlockOthers": "Altri",
+ "OptionBlockTvShows": "Serie TV",
+ "OptionBlockTrailers": "Trailer",
+ "OptionBlockMusic": "Musica",
+ "OptionBlockMovies": "Film",
+ "OptionBlockBooks": "Libri",
+ "OptionBlockGames": "Giochi",
+ "OptionBlockLiveTvPrograms": "Programmi TV in onda",
+ "OptionBlockLiveTvChannels": "Canali TV in onda",
+ "OptionBlockChannelContent": "Contenuto di Canali Internet",
+ "ButtonRevoke": "Revocare",
+ "MessageConfirmRevokeApiKey": "Sei sicuro che desideri revocare le chiavi api? La connessione dell'applicazione con Media Browser sar\u00e0 improvvisamente terminata.",
+ "HeaderConfirmRevokeApiKey": "Revocare Chiave Api",
+ "ValueContainer": "Contenitore: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Condizioni: {0}",
+ "LabelAll": "Tutti",
+ "HeaderDeleteImage": "Cancella Immagine",
+ "MessageFileNotFound": "File non trovato.",
+ "MessageFileReadError": "Errore leggendo questo file",
+ "ButtonNextPage": "Prossima pagina",
+ "ButtonPreviousPage": "Pagina precedente",
+ "ButtonMoveLeft": "Muovi a sinistra",
+ "ButtonMoveRight": "Muovi a destra",
+ "ButtonBrowseOnlineImages": "Sfoglia le immagini Online",
+ "HeaderDeleteItem": "Elimina elemento",
+ "ConfirmDeleteItem": "Sei sicuro di voler eliminare questo elemento dalla tua libreria?",
+ "MessagePleaseEnterNameOrId": "Inserisci il nome o id esterno.",
+ "MessageValueNotCorrect": "Il valore inserito non \u00e8 corretto.Riprova di nuovo.",
+ "MessageItemSaved": "Elemento salvato.",
+ "OptionEnded": "Finito",
+ "OptionContinuing": "In corso",
+ "OptionOff": "Off",
+ "OptionOn": "On",
+ "HeaderFields": "Campi",
+ "HeaderFieldsHelp": "Far scorrere un campo a 'off' per bloccarlo e impedire che sia i dati vengano modificati.",
+ "HeaderLiveTV": "Tv in diretta",
+ "MissingLocalTrailer": "Trailer locali mancanti",
+ "MissingPrimaryImage": "Immagini principali locali mancanti",
+ "MissingBackdropImage": "Sfondi mancanti",
+ "MissingLogoImage": "Loghi mancanti",
+ "MissingEpisode": "Episodi mancanti",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Sfondi",
+ "OptionImages": "Immagini",
+ "OptionKeywords": "Parole",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Nome",
+ "OptionOverview": "Panoramica",
+ "OptionGenres": "Generi",
+ "OptionParentalRating": "Voto Genitori",
+ "OptionPeople": "Persone",
+ "OptionRuntime": "Durata",
+ "OptionProductionLocations": "Sedi di produzione",
+ "OptionBirthLocation": "Nascita Posizione",
+ "LabelAllChannels": "Tutti i canali",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "Nuovo",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Cambia il tipo di cartella",
+ "HeaderChangeFolderTypeHelp": "Per cambiare il tipo di cartella, rimuovere e ricostruire la collezione con il nuovo tipo.",
+ "HeaderAlert": "Avviso",
+ "MessagePleaseRestart": "Si prega di riavviare per completare l'aggiornamento.",
+ "ButtonRestart": "Riavvia",
+ "MessagePleaseRefreshPage": "Si prega di aggiornare questa pagina per ricevere i nuovi aggiornamenti dal server.",
+ "ButtonHide": "Nascondi",
+ "MessageSettingsSaved": "Settaggi salvati.",
+ "ButtonSignOut": "Esci",
+ "ButtonMyProfile": "Mio Profilo",
+ "ButtonMyPreferences": "Mie preferenze",
+ "MessageBrowserDoesNotSupportWebSockets": "Questo browser non supporta i socket web. Per una migliore esperienza, provare un browser pi\u00f9 recente come Chrome, Firefox, IE10 +, Safari (iOS) o Opera.",
+ "LabelInstallingPackage": "Installazione di {0}",
+ "LabelPackageInstallCompleted": "{0} completamento dell'installazione.",
+ "LabelPackageInstallFailed": "{0} installazione non \u00e8 riuscita.",
+ "LabelPackageInstallCancelled": "{0} installazione annullata.",
+ "TabServer": "Server",
+ "TabUsers": "Utenti",
+ "TabLibrary": "Librerie",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Tv indiretta",
+ "TabAutoOrganize": "Organizza Automaticamente",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Avanzato",
+ "TabHelp": "Aiuto",
+ "TabScheduledTasks": "Operazioni pianificate",
+ "ButtonFullscreen": "Tutto schermo",
+ "ButtonAudioTracks": "Tracce audio",
+ "ButtonSubtitles": "Sottotitoli",
+ "ButtonScenes": "Scene",
+ "ButtonQuality": "Qualit\u00e0",
+ "HeaderNotifications": "Notifiche",
+ "HeaderSelectPlayer": "Utente selezionato:",
+ "ButtonSelect": "Seleziona",
+ "ButtonNew": "Nuovo",
+ "MessageInternetExplorerWebm": "Se utilizzi internet Explorer installa WebM plugin",
+ "HeaderVideoError": "Video Error",
+ "ButtonAddToPlaylist": "Aggiungi alla playlist",
+ "HeaderAddToPlaylist": "Aggiungi alla playlist",
+ "LabelName": "Nome:",
+ "ButtonSubmit": "Invia",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "Nuova playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "Vista delle serie in registrazione",
+ "ValueOriginalAirDate": "Prima messa in onda (originale): {0}",
+ "ButtonRemoveFromPlaylist": "Rimuovi dalla playlist",
+ "HeaderSpecials": "Speciali",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Risoluzione",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Durata",
+ "HeaderCommunityRating": "Voto Comunit\u00e0",
+ "HeaderParentalRating": "Voto genitore",
+ "HeaderReleaseDate": "Data Rilascio",
+ "HeaderDateAdded": "Aggiunto il",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Stagione",
+ "HeaderSeasonNumber": "Stagione Numero",
+ "HeaderNetwork": "Rete",
+ "HeaderYear": "Anno",
+ "HeaderGameSystem": "Gioco Sistema",
+ "HeaderPlayers": "Giocatori",
+ "HeaderEmbeddedImage": "Immagine incorporata",
+ "HeaderTrack": "Traccia",
+ "HeaderDisc": "Disco",
+ "OptionMovies": "Film",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episodi",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Numero Stagione",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Numero Episodio",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Film",
+ "TabSeries": "Serie TV",
+ "TabEpisodes": "Episodi",
+ "TabTrailers": "Trailer",
+ "TabGames": "Giochi",
+ "TabAlbums": "Albums",
+ "TabSongs": "Canzoni",
+ "TabMusicVideos": "Video Musicali",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ 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 6851e0387..c8ce64b83 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
@@ -1,192 +1,440 @@
{
"SettingsSaved": "Settings saved.",
- "AddUser": "Add User",
- "Users": "Users",
- "Delete": "Delete",
- "Administrator": "Administrator",
- "Password": "Password",
- "DeleteImage": "Delete Image",
- "DeleteImageConfirmation": "Are you sure you wish to delete this image?",
- "FileReadCancelled": "The file read has been canceled.",
- "FileNotFound": "File not found.",
- "FileReadError": "An error occurred while reading the file.",
- "DeleteUser": "Delete User",
- "DeleteUserConfirmation": "Are you sure you wish to delete {0}?",
- "PasswordResetHeader": "Password Reset",
- "PasswordResetComplete": "The password has been reset.",
- "PasswordResetConfirmation": "Are you sure you wish to reset the password?",
- "PasswordSaved": "Password saved.",
- "PasswordMatchError": "Password and password confirmation must match.",
- "OptionRelease": "Official Release",
- "OptionBeta": "Beta",
- "OptionDev": "Dev (Unstable)",
- "UninstallPluginHeader": "Uninstall Plugin",
- "UninstallPluginConfirmation": "Are you sure you wish to uninstall {0}?",
- "NoPluginConfigurationMessage": "This plugin has nothing to configure.",
- "NoPluginsInstalledMessage": "You have no plugins installed.",
- "BrowsePluginCatalogMessage": "Browse our plugin catalog to view available plugins.",
- "MessageKeyEmailedTo": "Key emailed to {0}.",
- "MessageKeysLinked": "Keys linked.",
- "HeaderConfirmation": "Confirmation",
- "MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
- "MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
- "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
- "HeaderSearch": "Search",
- "LabelArtist": "Artist",
- "LabelMovie": "Movie",
- "LabelMusicVideo": "Music Video",
- "LabelEpisode": "Episode",
- "LabelSeries": "Series",
- "LabelStopping": "Stopping",
- "ButtonStop": "Stop",
- "LabelCancelled": "(cancelled)",
- "LabelFailed": "(failed)",
- "LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
- "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
- "HeaderDeleteTaskTrigger": "Delete Task Trigger",
- "HeaderTaskTriggers": "Task Triggers",
- "MessageDeleteTaskTrigger": "Are you sure you wish to delete this task trigger?",
- "MessageNoPluginsInstalled": "You have no plugins installed.",
- "LabelVersionInstalled": "{0} installed",
- "LabelNumberReviews": "{0} Reviews",
- "LabelFree": "Free",
- "HeaderSelectAudio": "Select Audio",
- "HeaderSelectSubtitles": "Select Subtitles",
- "LabelDefaultStream": "(Default)",
- "LabelForcedStream": "(Forced)",
- "LabelDefaultForcedStream": "(Default/Forced)",
- "LabelUnknownLanguage": "Unknown language",
- "ButtonMute": "Mute",
- "ButtonUnmute": "Unmute",
- "ButtonStop": "Stop",
- "ButtonNextTrack": "Next Track",
- "ButtonPause": "Pause",
- "ButtonPlay": "Play",
- "ButtonEdit": "Edit",
- "ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
- "ButtonPlaylist": "Playlist",
- "ButtonPreviousTrack": "Previous Track",
- "LabelEnabled": "Enabled",
- "LabelDisabled": "Disabled",
- "ButtonMoreInformation": "More Information",
- "LabelNoUnreadNotifications": "No unread notifications.",
- "ButtonViewNotifications": "View notifications",
- "ButtonMarkTheseRead": "Mark these read",
- "ButtonClose": "Close",
- "LabelAllPlaysSentToPlayer": "All plays will be sent to the selected player.",
- "MessageInvalidUser": "Invalid user or password.",
- "HeaderAllRecordings": "All Recordings",
- "RecommendationBecauseYouLike": "Because you like {0}",
- "RecommendationBecauseYouWatched": "Because you watched {0}",
- "RecommendationDirectedBy": "Directed by {0}",
- "RecommendationStarring": "Starring {0}",
- "HeaderConfirmRecordingCancellation": "Confirm Recording Cancellation",
- "MessageConfirmRecordingCancellation": "Are you sure you wish to cancel this recording?",
- "MessageRecordingCancelled": "Recording cancelled.",
- "HeaderConfirmSeriesCancellation": "Confirm Series Cancellation",
- "MessageConfirmSeriesCancellation": "Are you sure you wish to cancel this series?",
- "MessageSeriesCancelled": "Series cancelled.",
- "HeaderConfirmRecordingDeletion": "Confirm Recording Deletion",
- "MessageConfirmRecordingDeletion": "Are you sure you wish to delete this recording?",
- "MessageRecordingDeleted": "Recording deleted.",
- "ButonCancelRecording": "Cancel Recording",
- "MessageRecordingSaved": "Recording saved.",
- "OptionSunday": "Sunday",
- "OptionMonday": "Monday",
- "OptionTuesday": "Tuesday",
- "OptionWednesday": "Wednesday",
- "OptionThursday": "Thursday",
- "OptionFriday": "Friday",
- "OptionSaturday": "Saturday",
- "HeaderConfirmDeletion": "Confirm Deletion",
- "MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
- "LiveTvUpdateAvailable": "(Update available)",
- "LabelVersionUpToDate": "Up to date!",
- "ButtonResetTuner": "Reset tuner",
- "HeaderResetTuner": "Reset Tuner",
- "MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
- "ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
- "HeaderSeriesRecordings": "Series Recordings",
- "LabelAnytime": "Any time",
- "StatusRecording": "Recording",
- "StatusWatching": "Watching",
- "StatusRecordingProgram": "Recording {0}",
- "StatusWatchingProgram": "Watching {0}",
- "HeaderSplitMedia": "Split Media Apart",
- "MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
- "HeaderError": "Error",
- "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": "Media Browser clients will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?",
- "HeaderResume": "Resume",
- "HeaderMyViews": "My Views",
- "HeaderLibraryFolders": "Media Folders",
- "HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
- "HeaderFavoriteMovies": "Favorite Movies",
- "HeaderFavoriteShows": "Favorite Shows",
- "HeaderFavoriteEpisodes": "Favorite Episodes",
- "HeaderFavoriteGames": "Favorite Games",
- "HeaderRatingsDownloads": "Rating / Downloads",
- "HeaderConfirmProfileDeletion": "Confirm Profile Deletion",
- "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?",
- "HeaderSelectServerCachePath": "Select Server Cache Path",
- "HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
- "HeaderSelectImagesByNamePath": "Select Images By Name Path",
- "HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
- "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
- "HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
- "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
- "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",
+ "AddUser": "Add User",
+ "Users": "Users",
+ "Delete": "Delete",
+ "Administrator": "Administrator",
+ "Password": "Password",
+ "DeleteImage": "Delete Image",
+ "DeleteImageConfirmation": "Are you sure you wish to delete this image?",
+ "FileReadCancelled": "The file read has been canceled.",
+ "FileNotFound": "File not found.",
+ "FileReadError": "An error occurred while reading the file.",
+ "DeleteUser": "Delete User",
+ "DeleteUserConfirmation": "Are you sure you wish to delete {0}?",
+ "PasswordResetHeader": "Password Reset",
+ "PasswordResetComplete": "The password has been reset.",
+ "PasswordResetConfirmation": "Are you sure you wish to reset the password?",
+ "PasswordSaved": "Password saved.",
+ "PasswordMatchError": "Password and password confirmation must match.",
+ "OptionRelease": "Official Release",
+ "OptionBeta": "Beta",
+ "OptionDev": "Dev (Unstable)",
+ "UninstallPluginHeader": "Uninstall Plugin",
+ "UninstallPluginConfirmation": "Are you sure you wish to uninstall {0}?",
+ "NoPluginConfigurationMessage": "This plugin has nothing to configure.",
+ "NoPluginsInstalledMessage": "You have no plugins installed.",
+ "BrowsePluginCatalogMessage": "Browse our plugin catalog to view available plugins.",
+ "MessageKeyEmailedTo": "Key emailed to {0}.",
+ "MessageKeysLinked": "Keys linked.",
+ "HeaderConfirmation": "Confirmation",
+ "MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
+ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
+ "HeaderSearch": "Search",
+ "LabelArtist": "Artist",
+ "LabelMovie": "Movie",
+ "LabelMusicVideo": "Music Video",
+ "LabelEpisode": "Episode",
+ "LabelSeries": "Series",
+ "LabelStopping": "Stopping",
+ "LabelCancelled": "(cancelled)",
+ "LabelFailed": "(failed)",
+ "LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
+ "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
+ "HeaderDeleteTaskTrigger": "Delete Task Trigger",
+ "HeaderTaskTriggers": "Task Triggers",
+ "MessageDeleteTaskTrigger": "Are you sure you wish to delete this task trigger?",
+ "MessageNoPluginsInstalled": "You have no plugins installed.",
+ "LabelVersionInstalled": "{0} installed",
+ "LabelNumberReviews": "{0} Reviews",
+ "LabelFree": "Free",
+ "HeaderSelectAudio": "Select Audio",
+ "HeaderSelectSubtitles": "Select Subtitles",
+ "LabelDefaultStream": "(Default)",
+ "LabelForcedStream": "(Forced)",
+ "LabelDefaultForcedStream": "(Default/Forced)",
+ "LabelUnknownLanguage": "Unknown language",
+ "ButtonMute": "Mute",
+ "ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
+ "ButtonPause": "Pause",
+ "ButtonPlay": "Play",
+ "ButtonEdit": "Edit",
+ "ButtonQueue": "Queue",
+ "ButtonPlayTrailer": "Play trailer",
+ "ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Previous Track",
+ "LabelEnabled": "Enabled",
+ "LabelDisabled": "Disabled",
+ "ButtonMoreInformation": "More Information",
+ "LabelNoUnreadNotifications": "No unread notifications.",
+ "ButtonViewNotifications": "View notifications",
+ "ButtonMarkTheseRead": "Mark these read",
+ "ButtonClose": "Close",
+ "LabelAllPlaysSentToPlayer": "All plays will be sent to the selected player.",
+ "MessageInvalidUser": "Invalid user or password.",
+ "HeaderAllRecordings": "All Recordings",
+ "RecommendationBecauseYouLike": "Because you like {0}",
+ "RecommendationBecauseYouWatched": "Because you watched {0}",
+ "RecommendationDirectedBy": "Directed by {0}",
+ "RecommendationStarring": "Starring {0}",
+ "HeaderConfirmRecordingCancellation": "Confirm Recording Cancellation",
+ "MessageConfirmRecordingCancellation": "Are you sure you wish to cancel this recording?",
+ "MessageRecordingCancelled": "Recording cancelled.",
+ "HeaderConfirmSeriesCancellation": "Confirm Series Cancellation",
+ "MessageConfirmSeriesCancellation": "Are you sure you wish to cancel this series?",
+ "MessageSeriesCancelled": "Series cancelled.",
+ "HeaderConfirmRecordingDeletion": "Confirm Recording Deletion",
+ "MessageConfirmRecordingDeletion": "Are you sure you wish to delete this recording?",
+ "MessageRecordingDeleted": "Recording deleted.",
+ "ButonCancelRecording": "Cancel Recording",
+ "MessageRecordingSaved": "Recording saved.",
+ "OptionSunday": "Sunday",
+ "OptionMonday": "Monday",
+ "OptionTuesday": "Tuesday",
+ "OptionWednesday": "Wednesday",
+ "OptionThursday": "Thursday",
+ "OptionFriday": "Friday",
+ "OptionSaturday": "Saturday",
+ "HeaderConfirmDeletion": "Confirm Deletion",
+ "MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
+ "LiveTvUpdateAvailable": "(Update available)",
+ "LabelVersionUpToDate": "Up to date!",
+ "ButtonResetTuner": "Reset tuner",
+ "HeaderResetTuner": "Reset Tuner",
+ "MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
+ "ButtonCancelSeries": "Cancel Series",
+ "HeaderSeriesRecordings": "Series Recordings",
+ "LabelAnytime": "Any time",
+ "StatusRecording": "Recording",
+ "StatusWatching": "Watching",
+ "StatusRecordingProgram": "Recording {0}",
+ "StatusWatchingProgram": "Watching {0}",
+ "HeaderSplitMedia": "Split Media Apart",
+ "MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
+ "HeaderError": "Error",
+ "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": "Media Browser clients will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?",
+ "HeaderResume": "Resume",
+ "HeaderMyViews": "My Views",
+ "HeaderLibraryFolders": "Media Folders",
+ "HeaderLatestMedia": "Latest Media",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
+ "HeaderFavoriteMovies": "Favorite Movies",
+ "HeaderFavoriteShows": "Favorite Shows",
+ "HeaderFavoriteEpisodes": "Favorite Episodes",
+ "HeaderFavoriteGames": "Favorite Games",
+ "HeaderRatingsDownloads": "Rating / Downloads",
+ "HeaderConfirmProfileDeletion": "Confirm Profile Deletion",
+ "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?",
+ "HeaderSelectServerCachePath": "Select Server Cache Path",
+ "HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
+ "HeaderSelectImagesByNamePath": "Select Images By Name Path",
+ "HeaderSelectMetadataPath": "Select Metadata Path",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
+ "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
+ "HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
+ "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
+ "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",
+ "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.",
+ "HeaderFavoriteAlbums": "Favorite Albums",
+ "HeaderLatestChannelMedia": "Latest Channel Items",
+ "ButtonOrganizeFile": "Organize File",
+ "ButtonDeleteFile": "Delete File",
+ "HeaderOrganizeFile": "Organize File",
+ "HeaderDeleteFile": "Delete File",
+ "StatusSkipped": "Skipped",
+ "StatusFailed": "Failed",
+ "StatusSuccess": "Success",
+ "MessageFileWillBeDeleted": "The following file will be deleted:",
+ "MessageSureYouWishToProceed": "Are you sure you wish to proceed?",
+ "MessageDuplicatesWillBeDeleted": "In addition the following dupliates will be deleted:",
+ "MessageFollowingFileWillBeMovedFrom": "The following file will be moved from:",
+ "MessageDestinationTo": "to:",
+ "HeaderSelectWatchFolder": "Select Watch Folder",
+ "HeaderSelectWatchFolderHelp": "Browse or enter the path to your watch folder. The folder must be writeable.",
+ "OrganizePatternResult": "Result: {0}",
+ "HeaderRestart": "Restart",
+ "HeaderShutdown": "Shutdown",
+ "MessageConfirmRestart": "Are you sure you wish to restart Media Browser Server?",
+ "MessageConfirmShutdown": "Are you sure you wish to shutdown Media Browser Server?",
+ "ButtonUpdateNow": "Update Now",
+ "NewVersionOfSomethingAvailable": "A new version of {0} is available!",
+ "VersionXIsAvailableForDownload": "Version {0} is now available for download.",
+ "LabelVersionNumber": "Version {0}",
+ "LabelPlayMethodTranscoding": "Transcoding",
+ "LabelPlayMethodDirectStream": "Direct Streaming",
+ "LabelPlayMethodDirectPlay": "Direct Playing",
+ "LabelAudioCodec": "Audio: {0}",
+ "LabelVideoCodec": "Video: {0}",
+ "LabelRemoteAccessUrl": "Remote access: {0}",
+ "LabelRunningOnPort": "Running on port {0}.",
+ "HeaderLatestFromChannel": "Latest from {0}",
+ "ButtonDownload": "Download",
+ "LabelUnknownLanaguage": "Unknown language",
+ "HeaderCurrentSubtitles": "Current Subtitles",
+ "MessageDownloadQueued": "The download has been queued.",
+ "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
+ "ButtonRemoteControl": "Remote Control",
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Cancel",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "Scenes",
+ "HeaderAudioTracks": "Audio Tracks",
+ "LabelUnknownLanguage": "Unknown language",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "Name",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Channels",
+ "HeaderMediaFolders": "Media Folders",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "DeleteImageConfirmation": "Are you sure you wish to delete this image?",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "Ended",
+ "OptionContinuing": "Continuing",
+ "OptionOff": "Off",
+ "OptionOn": "On",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "HeaderMediaFolders": "Media Folders",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPeople": "People",
+ "OptionRuntime": "Runtime",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "ButtonRefresh": "Refresh",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Server",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Advanced",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonMute": "Mute",
+ "ButtonUnmute": "Unmute",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonScenes": "Scenes",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "Select",
+ "ButtonNew": "New",
+ "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:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Movies",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episodes",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Season number:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
"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.",
- "HeaderFavoriteAlbums": "Favorite Albums",
- "HeaderLatestChannelMedia": "Latest Channel Items",
- "ButtonOrganizeFile": "Organize File",
- "ButtonDeleteFile": "Delete File",
- "HeaderOrganizeFile": "Organize File",
- "HeaderDeleteFile": "Delete File",
- "StatusSkipped": "Skipped",
- "StatusFailed": "Failed",
- "StatusSuccess": "Success",
- "MessageFileWillBeDeleted": "The following file will be deleted:",
- "MessageSureYouWishToProceed": "Are you sure you wish to proceed?",
- "MessageDuplicatesWillBeDeleted": "In addition the following dupliates will be deleted:",
- "MessageFollowingFileWillBeMovedFrom": "The following file will be moved from:",
- "MessageDestinationTo": "to:",
- "HeaderSelectWatchFolder": "Select Watch Folder",
- "HeaderSelectWatchFolderHelp": "Browse or enter the path to your watch folder. The folder must be writeable.",
- "OrganizePatternResult": "Result: {0}",
- "HeaderRestart": "Restart",
- "HeaderShutdown": "Shutdown",
- "MessageConfirmRestart": "Are you sure you wish to restart Media Browser Server?",
- "MessageConfirmShutdown": "Are you sure you wish to shutdown Media Browser Server?",
- "ButtonUpdateNow": "Update Now",
- "NewVersionOfSomethingAvailable": "A new version of {0} is available!",
- "VersionXIsAvailableForDownload": "Version {0} is now available for download.",
- "LabelVersionNumber": "Version {0}",
- "LabelPlayMethodTranscoding": "Transcoding",
- "LabelPlayMethodDirectStream": "Direct Streaming",
- "LabelPlayMethodDirectPlay": "Direct Playing",
- "LabelAudioCodec": "Audio: {0}",
- "LabelVideoCodec": "Video: {0}",
- "LabelRemoteAccessUrl": "Remote access: {0}",
- "LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
- "HeaderLatestFromChannel": "Latest from {0}",
- "ButtonDownload": "Download",
- "LabelUnknownLanaguage": "Unknown language",
- "HeaderCurrentSubtitles": "Current Subtitles",
- "MessageDownloadQueued": "The download has been queued.",
- "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
- "ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
-} \ No newline at end of file
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Movies",
+ "TabSeries": "Series",
+ "TabEpisodes": "Episodes",
+ "TabTrailers": "Trailers",
+ "TabGames": "Games",
+ "TabAlbums": "Albums",
+ "TabSongs": "Songs",
+ "TabMusicVideos": "Music Videos",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
+}
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json
index 99a9ff6c1..0e07e2f02 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json
@@ -1,13 +1,5 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "\u04e8\u0448\u0456\u0440",
- "OptionOn": "\u049a\u043e\u0441",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "\u0411\u0456\u0440\u0435\u0443 \u043d\u0435 \u043a\u04e9\u0431\u0456\u0440\u0435\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u0431\u0456\u0440\u0433\u0435 \u0442\u043e\u043f\u0442\u0430\u04a3\u044b\u0437.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "\u041c\u0435\u043d\u0456\u04a3 \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043c",
- "SettingsSaved": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0441\u0430\u049b\u0442\u0430\u043b\u0434\u044b.",
+ "SettingsSaved": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440 \u0441\u0430\u049b\u0442\u0430\u043b\u0434\u044b.",
"AddUser": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b \u04af\u0441\u0442\u0435\u0443",
"Users": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440",
"Delete": "\u0416\u043e\u044e",
@@ -32,13 +24,13 @@
"UninstallPluginConfirmation": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d {0} \u043e\u0440\u043d\u0430\u0442\u0443\u044b\u043d \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
"NoPluginConfigurationMessage": "\u0411\u04b1\u043b \u043f\u043b\u0430\u0433\u0438\u043d \u04af\u0448\u0456\u043d \u0435\u0448\u049b\u0430\u043d\u0434\u0430\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u043b\u0430\u0443 \u0436\u043e\u049b.",
"NoPluginsInstalledMessage": "\u041e\u0440\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440 \u0436\u043e\u049b.",
- "BrowsePluginCatalogMessage": "\u049a\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440\u043c\u0435\u043d \u0442\u0430\u043d\u044b\u0441\u0443 \u04af\u0448\u0456\u043d \u043f\u043b\u0430\u0433\u0438\u043d \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0456\u043d \u0448\u0430\u0440\u043b\u0430\u04a3\u044b\u0437.",
+ "BrowsePluginCatalogMessage": "\u049a\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440\u043c\u0435\u043d \u0442\u0430\u043d\u044b\u0441\u0443 \u04af\u0448\u0456\u043d \u043f\u043b\u0430\u0433\u0438\u043d \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0456\u043d \u0448\u043e\u043b\u044b\u04a3\u044b\u0437.",
"MessageKeyEmailedTo": "\u041a\u0456\u043b\u0442 {0} \u04af\u0448\u0456\u043d \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u0434\u044b \u043f\u043e\u0448\u0442\u0430\u043c\u0435\u043d \u0436\u0456\u0431\u0435\u0440\u0456\u043b\u0434\u0456.",
"MessageKeysLinked": "\u041a\u0456\u043b\u0442\u0442\u0435\u0440 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u044b\u043b\u0434\u044b.",
"HeaderConfirmation": "\u0420\u0430\u0441\u0442\u0430\u0443",
"MessageKeyUpdated": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u04a3\u0456\u0437 \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b.",
"MessageKeyRemoved": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u04a3\u0456\u0437 \u0430\u043b\u0430\u0441\u0442\u0430\u043b\u0434\u044b.",
- "ErrorLaunchingChromecast": "Chromecast \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d \u043a\u0435\u0437\u0434\u0435 \u049b\u0430\u0442\u0435 \u043e\u0440\u044b\u043d \u0430\u043b\u0434\u044b. \u0416\u0430\u0431\u0434\u044b\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 \u0442\u0435\u043a\u0441\u0435\u0440\u0456\u04a3\u0456\u0437.",
+ "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. \u0416\u0430\u0431\u0434\u044b\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 \u0442\u0435\u043a\u0441\u0435\u0440\u0456\u04a3\u0456\u0437.",
"HeaderSearch": "\u0406\u0437\u0434\u0435\u0443",
"LabelArtist": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b",
"LabelMovie": "\u0424\u0438\u043b\u044c\u043c",
@@ -46,7 +38,6 @@
"LabelEpisode": "\u042d\u043f\u0438\u0437\u043e\u0434",
"LabelSeries": "\u0421\u0435\u0440\u0438\u0430\u043b",
"LabelStopping": "\u0422\u043e\u049b\u0442\u0430\u0442\u044b\u043b\u0443\u0434\u0430",
- "ButtonStop": "\u0422\u043e\u049b\u0442\u0430\u0442\u0443",
"LabelCancelled": "(\u0431\u043e\u043b\u0434\u044b\u0440\u044b\u043b\u043c\u0430\u0434\u044b)",
"LabelFailed": "(\u0441\u04d9\u0442\u0441\u0456\u0437)",
"LabelAbortedByServerShutdown": "(\u0421\u0435\u0440\u0432\u0435\u0440 \u0436\u04b1\u043c\u044b\u0441\u044b \u0430\u044f\u049b\u0442\u0430\u043b\u0443\u044b\u043d\u0430 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b \u04af\u0437\u0456\u043b\u0434\u0456)",
@@ -55,9 +46,9 @@
"HeaderTaskTriggers": "\u0422\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u043b\u0435\u0440\u0456",
"MessageDeleteTaskTrigger": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0456\u043d \u0436\u043e\u044e \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
"MessageNoPluginsInstalled": "\u041e\u0440\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440 \u0436\u043e\u049b.",
- "LabelVersionInstalled": "{0} \u043d\u04b1\u0441\u049b\u0430\u0441\u044b \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d",
+ "LabelVersionInstalled": "{0} \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d",
"LabelNumberReviews": "{0} \u043f\u0456\u043a\u0456\u0440",
- "LabelFree": "\u0410\u049b\u044b\u0441\u044b\u0437",
+ "LabelFree": "\u0422\u0435\u0433\u0456\u043d",
"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",
"LabelDefaultStream": "(\u04d8\u0434\u0435\u043f\u043a\u0456)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "\u0411\u0435\u043b\u0433\u0456\u0441\u0456\u0437 \u0442\u0456\u043b",
"ButtonMute": "\u0414\u044b\u0431\u044b\u0441\u0442\u044b \u04e9\u0448\u0456\u0440\u0443",
"ButtonUnmute": "\u0414\u044b\u0431\u044b\u0441\u0442\u044b \u049b\u043e\u0441\u0443",
+ "ButtonStop": "\u0422\u043e\u049b\u0442\u0430\u0442\u0443",
+ "ButtonNextTrack": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0436\u043e\u043b\u0448\u044b\u049b",
"ButtonPause": "\u04ae\u0437\u0456\u043b\u0456\u0441",
"ButtonPlay": "\u041e\u0439\u043d\u0430\u0442\u0443",
"ButtonEdit": "\u04e8\u04a3\u0434\u0435\u0443",
"ButtonQueue": "\u041a\u0435\u0437\u0435\u043a",
"ButtonPlayTrailer": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u0434\u0456 \u043e\u0439\u043d\u0430\u0442\u0443",
"ButtonPlaylist": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0456",
+ "ButtonPreviousTrack": "\u0410\u043b\u0434\u044b\u04a3\u0493\u044b \u0436\u043e\u043b\u0448\u044b\u049b",
"LabelEnabled": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d",
"LabelDisabled": "\u0410\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u0493\u0430\u043d",
"ButtonMoreInformation": "\u041a\u04e9\u0431\u0456\u0440\u0435\u043a \u0430\u049b\u043f\u0430\u0440\u0430\u0442",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "\u0422\u044e\u043d\u0435\u0440\u0434\u0456 \u044b\u0441\u044b\u0440\u0443",
"MessageConfirmResetTuner": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u0442\u044e\u043d\u0435\u0440\u0434\u0456 \u044b\u0441\u044b\u0440\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435? \u04d8\u0440 \u0431\u0435\u043b\u0441\u0435\u043d\u0434\u0456 \u043e\u0439\u043d\u0430\u0442\u049b\u044b\u0448\u0442\u0430\u0440 \u043d\u0435\u043c\u0435\u0441\u0435 \u0436\u0430\u0437\u0431\u0430\u043b\u0430\u0440 \u043a\u0435\u043d\u0435\u0442\u0442\u0435\u043d \u0442\u043e\u049b\u0442\u0430\u0442\u044b\u043b\u0430\u0434\u044b.",
"ButtonCancelSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u0434\u044b \u0431\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443",
- "LabelAllChannels": "\u0411\u0430\u0440\u043b\u044b\u049b \u0430\u0440\u043d\u0430\u043b\u0430\u0440",
"HeaderSeriesRecordings": "\u0421\u0435\u0440\u0438\u0430\u043b \u0436\u0430\u0437\u0431\u0430\u043b\u0430\u0440\u044b",
"LabelAnytime": "\u04d8\u0440 \u0443\u0430\u049b\u044b\u0442\u0442\u0430",
"StatusRecording": "\u0416\u0430\u0437\u0431\u0430",
@@ -124,15 +117,16 @@
"HeaderError": "\u049a\u0430\u0442\u0435",
"MessagePleaseSelectOneItem": "\u0415\u04a3 \u043a\u0435\u043c\u0456\u043d\u0434\u0435 \u0431\u0456\u0440 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437.",
"MessagePleaseSelectTwoItems": "\u0415\u04a3 \u043a\u0435\u043c\u0456\u043d\u0434\u0435 \u0435\u043a\u0456 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437.",
- "MessageTheFollowingItemsWillBeGrouped": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0430\u0442\u0430\u0443\u043b\u0430\u0440 \u0431\u0456\u0440 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043a\u0435 \u0442\u043e\u043f\u0442\u0430\u0441\u0442\u044b\u0440\u044b\u043b\u0430\u0434\u044b:",
+ "MessageTheFollowingItemsWillBeGrouped": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0442\u0443\u044b\u043d\u0434\u044b\u043b\u0430\u0440 \u0431\u0456\u0440 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043a\u0435 \u0442\u043e\u043f\u0442\u0430\u0441\u0442\u044b\u0440\u044b\u043b\u0430\u0434\u044b:",
"MessageConfirmItemGrouping": "Media Browser \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440\u0456 \u0436\u0430\u0431\u0434\u044b\u049b \u0436\u04d9\u043d\u0435 \u0436\u0435\u043b\u0456 \u04e9\u043d\u0456\u043c\u0434\u0456\u043b\u0456\u043a\u0442\u0435\u0440\u0456\u043d\u0435 \u043d\u0435\u0433\u0456\u0437\u0434\u0435\u043b\u0456\u043d\u0456\u043f \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u043e\u04a3\u0442\u0430\u0439\u043b\u044b \u043d\u04b1\u0441\u049b\u0430\u0441\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0439\u0434\u044b. \u0428\u044b\u043d\u044b\u043c\u0435\u043d \u0436\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
"HeaderResume": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443",
- "HeaderMyViews": "\u041c\u0435\u043d\u0456\u04a3 \u043a\u04e9\u0440\u0456\u043d\u0456\u0441\u0442\u0435\u0440\u0456\u043c",
+ "HeaderMyViews": "\u041c\u0435\u043d\u0456\u04a3 \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440\u0456\u043c",
"HeaderLibraryFolders": "\u0422\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b",
- "HeaderLatestMedia": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0442\u0430\u0441\u0443\u0448\u044b\u043b\u0430\u0440",
- "ButtonMore": "\u041a\u04e9\u0431\u0456\u0440\u0435\u043a...",
+ "HeaderLatestMedia": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440",
+ "ButtonMoreItems": "\u041a\u04e9\u0431\u0456\u0440\u0435\u043a...",
+ "ButtonMore": "\u041a\u04e9\u0431\u0456\u0440\u0435\u043a",
"HeaderFavoriteMovies": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b \u0444\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
- "HeaderFavoriteShows": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b \u0441\u0435\u0440\u0438\u0430\u043b\u0434\u0430\u0440",
+ "HeaderFavoriteShows": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c\u0434\u0435\u0440",
"HeaderFavoriteEpisodes": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440",
"HeaderFavoriteGames": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b \u043e\u0439\u044b\u043d\u0434\u0430\u0440",
"HeaderRatingsDownloads": "\u0411\u0430\u0493\u0430\u043b\u0430\u0443 \/ \u0416\u04af\u043a\u0442\u0435\u0443\u043b\u0435\u0440",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Transcoding Temporary \u049b\u0430\u043b\u0442\u0430\u0441\u044b \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443",
"HeaderSelectImagesByNamePath": "Images By Name \u049b\u0430\u043b\u0442\u0430\u0441\u044b \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443",
"HeaderSelectMetadataPath": "Metadata \u049b\u0430\u043b\u0442\u0430\u0441\u044b \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443",
- "HeaderSelectServerCachePathHelp": "Server cache \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430\u043d\u044b\u04a3 \u0436\u0430\u0439\u0493\u0430\u0441\u044b\u043c\u044b \u0441\u0435\u0440\u0432\u0435\u0440 \u04e9\u043d\u0456\u043c\u0434\u0456\u043b\u0456\u0433\u0456\u043d\u0435 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u04d9\u0441\u0435\u0440 \u0435\u0442\u0435\u0434\u0456 \u0436\u04d9\u043d\u0435 \u0431\u04b1\u043b \u0438\u0434\u0435\u0430\u043b\u0434\u0430 SSD \u0435\u043d\u0433\u0456\u0437\u0433\u0456\u0441\u0456\u043d\u0434\u0435 \u043e\u0440\u043d\u0430\u043b\u0430\u0441\u0443\u044b \u049b\u0430\u0436\u0435\u0442.",
+ "HeaderSelectServerCachePathHelp": "Server cache \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.",
"HeaderSelectTranscodingPathHelp": "Transcoding temporary \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.",
"HeaderSelectImagesByNamePathHelp": "Items by name \u049b\u0430\u043b\u0442\u0430\u0441\u044b \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.",
"HeaderSelectMetadataPathHelp": "Metadata \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u0441\u0430\u049b\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.",
@@ -152,7 +146,7 @@
"ButtonAdd": "\u04ae\u0441\u0442\u0435\u0443",
"ButtonRemove": "\u0410\u043b\u0430\u0441\u0442\u0430\u0443",
"LabelChapterDownloaders": "\u0421\u0430\u0445\u043d\u0430\u043b\u0430\u0440\u0434\u044b \u0436\u04af\u043a\u0442\u0435\u0443\u0448\u0456\u043b\u0435\u0440:",
- "LabelChapterDownloadersHelp": "\u0421\u0430\u0445\u043d\u0430 \u0436\u04af\u043a\u0442\u0435\u0443\u0448\u0456\u043b\u0435\u0440\u0456\u043d \u049b\u043e\u0441\u044b\u04a3\u044b\u0437 \u0436\u04d9\u043d\u0435 \u0431\u0430\u0441\u044b\u043c\u0434\u044b\u043b\u044b\u049b \u0440\u0435\u0442\u0456 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0434\u04d9\u0440\u0435\u0436\u0435 \u0431\u0435\u0440\u0456\u04a3\u0456\u0437. \u0422\u04e9\u043c\u0435\u043d\u0433\u0456 \u0431\u0430\u0441\u044b\u043c\u0434\u044b\u043b\u044b\u0493\u044b \u0431\u0430\u0440 \u0436\u04af\u043a\u0442\u0435\u0443\u0448\u0456\u043b\u0435\u0440 \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u0436\u043e\u049b \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u0442\u044b \u0442\u043e\u043b\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b.",
+ "LabelChapterDownloadersHelp": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0441\u0430\u0445\u043d\u0430 \u0436\u04af\u043a\u0442\u0435\u0443\u0448\u0456\u043b\u0435\u0440\u0456\u043d \u049b\u043e\u0441\u044b\u04a3\u044b\u0437 \u0436\u04d9\u043d\u0435 \u0431\u0430\u0441\u044b\u043c\u0434\u044b\u043b\u044b\u049b \u0440\u0435\u0442\u0456 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0434\u04d9\u0440\u0435\u0436\u0435 \u0431\u0435\u0440\u0456\u04a3\u0456\u0437. \u0422\u04e9\u043c\u0435\u043d\u0433\u0456 \u0431\u0430\u0441\u044b\u043c\u0434\u044b\u043b\u044b\u0493\u044b \u0431\u0430\u0440 \u0436\u04af\u043a\u0442\u0435\u0443\u0448\u0456\u043b\u0435\u0440 \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u0436\u043e\u049b \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u0442\u044b \u0442\u043e\u043b\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b.",
"HeaderFavoriteAlbums": "\u0422\u0430\u04a3\u0434\u0430\u0443\u043b\u044b \u0430\u043b\u044c\u0431\u043e\u043c\u0434\u0430\u0440",
"HeaderLatestChannelMedia": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u044b\u04a3 \u0435\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440\u0456",
"ButtonOrganizeFile": "\u0424\u0430\u0439\u043b\u0434\u044b \u04b1\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443",
@@ -167,8 +161,8 @@
"MessageDuplicatesWillBeDeleted": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430 \u0440\u0435\u0442\u0456\u043d\u0434\u0435, \u043a\u0435\u043b\u0435\u0441\u0456 \u0442\u0435\u043b\u043d\u04b1\u0441\u049b\u0430\u043b\u0430\u0440 \u0436\u043e\u0439\u044b\u043b\u0430\u0434\u044b:",
"MessageFollowingFileWillBeMovedFrom": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0444\u0430\u0439\u043b \u0436\u044b\u043b\u0436\u044b\u0442\u044b\u043b\u0430\u0434\u044b, \u043c\u044b\u043d\u0430\u0434\u0430\u043d:",
"MessageDestinationTo": "\u043c\u044b\u043d\u0430\u0493\u0430\u043d:",
- "HeaderSelectWatchFolder": "\u0411\u0430\u049b\u044b\u043b\u0430\u0443\u0434\u0430\u0493\u044b \u049b\u0430\u043b\u0442\u0430\u043d\u044b \u0442\u0430\u04a3\u0434\u0430\u0443",
- "HeaderSelectWatchFolderHelp": "\u0411\u0430\u049b\u044b\u043b\u0430\u0443\u0434\u0430\u0493\u044b \u049b\u0430\u043b\u0442\u0430\u0493\u0430 \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.",
+ "HeaderSelectWatchFolder": "\u049a\u0430\u0434\u0430\u0493\u0430\u043b\u0430\u0443\u0434\u0430\u0493\u044b \u049b\u0430\u043b\u0442\u0430\u043d\u044b \u0442\u0430\u04a3\u0434\u0430\u0443",
+ "HeaderSelectWatchFolderHelp": "\u049a\u0430\u0434\u0430\u0493\u0430\u043b\u0430\u0443\u0434\u0430\u0493\u044b \u049b\u0430\u043b\u0442\u0430\u0493\u0430 \u0436\u043e\u043b\u0434\u044b \u0448\u043e\u043b\u044b\u04a3\u044b\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430 \u0436\u0430\u0437\u0443 \u04af\u0448\u0456\u043d \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0431\u043e\u043b\u0443\u044b \u049b\u0430\u0436\u0435\u0442.",
"OrganizePatternResult": "\u041d\u04d9\u0442\u0438\u0436\u0435\u0441\u0456: {0}",
"HeaderRestart": "\u049a\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443",
"HeaderShutdown": "\u0416\u04b1\u043c\u044b\u0441\u0442\u044b \u0430\u044f\u049b\u0442\u0430\u0443",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "\u0411\u0435\u0439\u043d\u0435: {0}",
"LabelRemoteAccessUrl": "\u049a\u0430\u0448\u044b\u049b\u0442\u0430\u043d \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443: {0}",
"LabelRunningOnPort": "{0} \u043f\u043e\u0440\u0442\u044b\u043d\u0434\u0430 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0439\u0434\u0456.",
- "LabelRunningOnPorts": "{0} \u0436\u04d9\u043d\u0435 {1} \u043f\u043e\u0440\u0442\u0442\u0430\u0440\u044b\u043d\u0434\u0430 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0439\u0434\u0456.",
"HeaderLatestFromChannel": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 {0}",
"ButtonDownload": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443",
"LabelUnknownLanaguage": "\u0411\u0435\u043b\u0433\u0456\u0441\u0456\u0437 \u0442\u0456\u043b",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "\u0416\u04af\u043a\u0442\u0435\u0443 \u043a\u0435\u0437\u0435\u043a\u043a\u0435 \u043a\u0456\u0440\u0433\u0456\u0437\u0456\u043b\u0434\u0456.",
"MessageAreYouSureDeleteSubtitles": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 \u0444\u0430\u0439\u043b\u044b\u043d \u0436\u043e\u044e \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
"ButtonRemoteControl": "\u049a\u0430\u0448\u044b\u049b\u0442\u0430\u043d \u0431\u0430\u0441\u049b\u0430\u0440\u0443",
- "HeaderLatestTvRecordings": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0436\u0430\u0437\u0431\u0430\u043b\u0430\u0440"
+ "HeaderLatestTvRecordings": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0436\u0430\u0437\u0431\u0430\u043b\u0430\u0440",
+ "ButtonOk": "\u0416\u0430\u0440\u0430\u0439\u0434\u044b",
+ "ButtonCancel": "\u0411\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443",
+ "ButtonRefresh": "\u041a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443",
+ "LabelCurrentPath": "\u0410\u0493\u044b\u043c\u0434\u044b\u049b \u0436\u043e\u043b:",
+ "HeaderSelectMediaPath": "\u0422\u0430\u0441\u0443\u0448\u044b \u0436\u043e\u043b\u044b\u043d \u0442\u0430\u04a3\u0434\u0430\u0443",
+ "ButtonNetwork": "\u0416\u0435\u043b\u0456",
+ "MessageDirectoryPickerInstruction": "\u0416\u0435\u043b\u0456 \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u0433\u0456 \u0431\u0430\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430 \u0436\u0430\u0431\u0434\u044b\u049b\u0442\u0430\u0440 \u043e\u0440\u043d\u044b \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0441\u0430, \u0436\u0435\u043b\u0456\u043b\u0456\u043a \u0436\u043e\u043b\u0434\u0430\u0440 \u049b\u043e\u043b\u043c\u0435\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u043b\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d. \u041c\u044b\u0441\u0430\u043b\u044b, {0} \u043d\u0435\u043c\u0435\u0441\u0435 {1}.",
+ "HeaderMenu": "\u041c\u04d9\u0437\u0456\u0440",
+ "ButtonOpen": "\u0410\u0448\u0443",
+ "ButtonOpenInNewTab": "\u0416\u0430\u04a3\u0430 \u049b\u043e\u0439\u044b\u043d\u0434\u044b\u0434\u0430 \u0430\u0448\u0443",
+ "ButtonShuffle": "\u0410\u0440\u0430\u043b\u0430\u0441\u0442\u044b\u0440\u0443",
+ "ButtonInstantMix": "\u041b\u0435\u0437\u0434\u0456\u043a \u049b\u043e\u0441\u043f\u0430",
+ "ButtonResume": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443",
+ "HeaderScenes": "\u0421\u0430\u0445\u043d\u0430\u043b\u0430\u0440",
+ "HeaderAudioTracks": "\u0414\u044b\u0431\u044b\u0441 \u0436\u043e\u043b\u0448\u044b\u049b\u0442\u0430\u0440\u044b",
+ "HeaderSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440",
+ "HeaderVideoQuality": "\u0411\u0435\u0439\u043d\u0435 \u0441\u0430\u043f\u0430\u0441\u044b",
+ "MessageErrorPlayingVideo": "\u0411\u0435\u0439\u043d\u0435 \u043e\u0439\u043d\u0430\u0442\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u049b\u0430\u0442\u0435 \u043e\u0440\u044b\u043d \u0430\u043b\u0434\u044b.",
+ "MessageEnsureOpenTuner": "\u049a\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0442\u044e\u043d\u0435\u0440 \u0430\u0448\u044b\u049b \u0435\u043a\u0435\u043d\u0434\u0433\u0456\u043d \u0442\u0435\u043a\u0441\u0435\u0440\u0456\u04a3\u0456\u0437.",
+ "ButtonHome": "\u0411\u0430\u0441\u0442\u044b",
+ "ButtonDashboard": "\u0411\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b",
+ "ButtonReports": "\u0415\u0441\u0435\u043f\u0442\u0435\u0440",
+ "ButtonMetadataManager": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0431\u0430\u0441\u049b\u0430\u0440\u0443\u0448\u044b",
+ "HeaderTime": "\u0423\u0430\u049b\u044b\u0442",
+ "HeaderName": "\u0410\u0442\u044b",
+ "HeaderAlbum": "\u0410\u043b\u044c\u0431\u043e\u043c",
+ "HeaderAlbumArtist": "\u0410\u043b\u044c\u0431\u043e\u043c \u043e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b\u0441\u044b",
+ "HeaderArtist": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b",
+ "LabelAddedOnDate": "\u04ae\u0441\u0442\u0435\u043b\u0433\u0435\u043d\u0456 {0}",
+ "ButtonStart": "\u0411\u0430\u0441\u0442\u0430\u0443",
+ "HeaderChannels": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440",
+ "HeaderMediaFolders": "\u0422\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b",
+ "HeaderBlockItemsWithNoRating": "\u0416\u0430\u0441\u0442\u044b\u049b \u0441\u0430\u043d\u0430\u0442\u044b \u0436\u043e\u049b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440\u0434\u0456 \u049b\u04b1\u0440\u0441\u0430\u0443\u043b\u0430\u0443:",
+ "OptionBlockOthers": "\u0411\u0430\u0441\u049b\u0430\u043b\u0430\u0440",
+ "OptionBlockTvShows": "\u0422\u0414 \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c\u0434\u0435\u0440\u0456",
+ "OptionBlockTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440",
+ "OptionBlockMusic": "\u041c\u0443\u0437\u044b\u043a\u0430",
+ "OptionBlockMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
+ "OptionBlockBooks": "\u041a\u0456\u0442\u0430\u043f\u0442\u0430\u0440",
+ "OptionBlockGames": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440",
+ "OptionBlockLiveTvPrograms": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414 \u0442\u0430\u0440\u0430\u0442\u044b\u043c\u0434\u0430\u0440\u044b",
+ "OptionBlockLiveTvChannels": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414 \u0430\u0440\u043d\u0430\u043b\u0430\u0440\u044b",
+ "OptionBlockChannelContent": "\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0430\u0440\u043d\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b",
+ "ButtonRevoke": "\u0411\u0430\u0441 \u0442\u0430\u0440\u0442\u0443",
+ "MessageConfirmRevokeApiKey": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b API \u043a\u0456\u043b\u0442\u0456\u043d\u0435\u043d \u0431\u0430\u0441 \u0442\u0430\u0440\u0442\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435? \u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430 \u043c\u0435\u043d Media Browser \u0430\u0440\u0430\u0441\u044b\u043d\u0434\u0430\u0493\u044b \u049b\u043e\u0441\u044b\u043b\u044b\u043c \u043a\u0435\u043d\u0435\u0442 \u04af\u0437\u0456\u043b\u0435\u0434\u0456.",
+ "HeaderConfirmRevokeApiKey": "API \u043a\u0456\u043b\u0442\u0456\u043d\u0435\u043d \u0431\u0430\u0441 \u0442\u0430\u0440\u0442\u0443",
+ "ValueContainer": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440: {0}",
+ "ValueAudioCodec": "\u0414\u044b\u0431\u044b\u0441 \u043a\u043e\u0434\u0435\u0433\u0456: {0}",
+ "ValueVideoCodec": "\u0411\u0435\u0439\u043d\u0435 \u043a\u043e\u0434\u0435\u0433\u0456: {0}",
+ "ValueCodec": "\u041a\u043e\u0434\u0435\u043a: {0}",
+ "ValueConditions": "\u0416\u0430\u0493\u0434\u0430\u0439\u043b\u0430\u0440: {0}",
+ "LabelAll": "\u0411\u0430\u0440\u043b\u044b\u049b",
+ "HeaderDeleteImage": "\u0421\u0443\u0440\u0435\u0442\u0442\u0456 \u0436\u043e\u044e",
+ "MessageFileNotFound": "\u0424\u0430\u0439\u043b \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0434\u044b.",
+ "MessageFileReadError": "\u041e\u0441\u044b \u0444\u0430\u0439\u043b\u0434\u044b \u043e\u049b\u044b\u0493\u0430\u043d\u0434\u0430 \u049b\u0430\u0442\u0435 \u043f\u0430\u0439\u0434\u0430 \u0431\u043e\u043b\u0434\u044b.",
+ "ButtonNextPage": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0431\u0435\u0442",
+ "ButtonPreviousPage": "\u0410\u043b\u0434\u044b\u043d\u0493\u044b \u0431\u0435\u0442",
+ "ButtonMoveLeft": "\u0421\u043e\u043b\u0493\u0430 \u0436\u044b\u043b\u0436\u044b\u0442\u0443",
+ "ButtonMoveRight": "\u041e\u04a3\u0493\u0430 \u0436\u044b\u043b\u0436\u044b\u0442\u0443",
+ "ButtonBrowseOnlineImages": "\u0416\u0435\u043b\u0456\u0434\u0435\u0433\u0456 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0448\u043e\u043b\u0443",
+ "HeaderDeleteItem": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u0436\u043e\u044e",
+ "ConfirmDeleteItem": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u0434\u0430\u043d \u0436\u043e\u044e \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
+ "MessagePleaseEnterNameOrId": "\u0410\u0442\u044b\u043d \u043d\u0435\u043c\u0435\u0441\u0435 \u0441\u044b\u0440\u0442\u049b\u044b ID \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437.",
+ "MessageValueNotCorrect": "\u0415\u043d\u0433\u0456\u0437\u0456\u043b\u0433\u0435\u043d \u043c\u04d9\u043d \u0434\u04b1\u0440\u044b\u0441 \u0435\u043c\u0435\u0441. \u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437.",
+ "MessageItemSaved": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u0430\u049b\u0442\u0430\u043b\u0434\u044b.",
+ "OptionEnded": "\u0410\u044f\u049b\u0442\u0430\u043b\u0434\u044b",
+ "OptionContinuing": "\u0416\u0430\u043b\u0493\u0430\u0441\u0443\u0434\u0430",
+ "OptionOff": "\u04e8\u0448\u0456\u0440",
+ "OptionOn": "\u049a\u043e\u0441",
+ "HeaderFields": "\u04e8\u0440\u0456\u0441\u0442\u0435\u0440",
+ "HeaderFieldsHelp": "\u049a\u04b1\u0440\u0441\u0430\u0443\u043b\u0430\u0443 \u04af\u0448\u0456\u043d \u0436\u04d9\u043d\u0435 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u04e9\u0437\u0433\u0435\u0440\u0442\u0443\u0456\u043d\u0435 \u0442\u044b\u0439\u044b\u043c \u0441\u0430\u043b\u0443 \u04af\u0448\u0456\u043d, \u04e9\u0440\u0456\u0441\u0442\u0456 \"\u04e8\u0428\u0406\u0420\" \u0442\u0430\u0440\u0430\u043f\u044b\u043d\u0430 \u0441\u044b\u0440\u0493\u0430\u0442\u044b\u04a3\u044b\u0437.",
+ "HeaderLiveTV": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414",
+ "MissingLocalTrailer": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u0442\u0440\u0435\u0439\u043b\u0435\u0440 \u0436\u043e\u049b.",
+ "MissingPrimaryImage": "\u0411\u0430\u0441\u0442\u0430\u043f\u049b\u044b \u0441\u0443\u0440\u0435\u0442 \u0436\u043e\u049b.",
+ "MissingBackdropImage": "\u0410\u0440\u0442\u049b\u044b \u0441\u0443\u0440\u0435\u0442 \u0436\u043e\u049b.",
+ "MissingLogoImage": "\u041b\u043e\u0433\u043e\u0442\u0438\u043f \u0441\u0443\u0440\u0435\u0442\u0456 \u0436\u043e\u049b.",
+ "MissingEpisode": "\u042d\u043f\u0438\u0437\u043e\u0434 \u0436\u043e\u049b.",
+ "OptionScreenshots": "\u042d\u043a\u0440\u0430\u043d \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456",
+ "OptionBackdrops": "\u0410\u0440\u0442\u049b\u044b \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440",
+ "OptionImages": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u0440",
+ "OptionKeywords": "\u041a\u0456\u043b\u0442 \u0441\u04e9\u0437\u0434\u0435\u0440",
+ "OptionTags": "\u0422\u0435\u0433\u0442\u0435\u0440",
+ "OptionStudios": "\u0421\u0442\u0443\u0434\u0438\u044f\u043b\u0430\u0440",
+ "OptionName": "\u0410\u0442\u044b",
+ "OptionOverview": "\u0416\u0430\u043b\u043f\u044b \u0448\u043e\u043b\u0443",
+ "OptionGenres": "\u0416\u0430\u043d\u0440\u043b\u0430\u0440",
+ "OptionParentalRating": "\u0416\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442",
+ "OptionPeople": "\u0410\u0434\u0430\u043c\u0434\u0430\u0440",
+ "OptionRuntime": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443 \u0443\u0430\u049b\u044b\u0442\u044b",
+ "OptionProductionLocations": "\u04e8\u043d\u0434\u0456\u0440\u0443 \u043e\u0440\u044b\u043d\u0434\u0430\u0440\u044b",
+ "OptionBirthLocation": "\u0422\u0443\u0493\u0430\u043d \u043e\u0440\u043d\u044b",
+ "LabelAllChannels": "\u0411\u0430\u0440\u043b\u044b\u049b \u0430\u0440\u043d\u0430\u043b\u0430\u0440",
+ "LabelLiveProgram": "\u0422\u0406\u041a\u0415\u041b\u0415\u0419 \u042d\u0424\u0418\u0420",
+ "LabelNewProgram": "\u0416\u0410\u04a2\u0410",
+ "LabelPremiereProgram": "\u0422\u04b0\u0421\u0410\u0423\u041a\u0415\u0421\u0415\u0420\u0406",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "\u049a\u0430\u043b\u0442\u0430 \u0442\u04af\u0440\u0456\u043d \u04e9\u0437\u0433\u0435\u0440\u0442\u0443",
+ "HeaderChangeFolderTypeHelp": "\u049a\u0430\u043b\u0442\u0430 \u0442\u04af\u0440\u0456\u043d \u04e9\u0437\u0433\u0435\u0440\u0442\u0443 \u04af\u0448\u0456\u043d, \u0430\u043b\u0430\u0441\u0442\u0430\u04a3\u044b\u0437 \u0436\u04d9\u043d\u0435 \u0436\u0438\u043d\u0430\u049b\u0442\u044b \u0436\u0430\u04a3\u0430 \u0442\u04af\u0440\u0456\u043c\u0435\u043d \u049b\u0430\u0439\u0442\u0430 \u049b\u04b1\u0440\u044b\u04a3\u044b\u0437.",
+ "HeaderAlert": "\u0415\u0441\u043a\u0435\u0440\u0442\u0443",
+ "MessagePleaseRestart": "\u0416\u0430\u04a3\u0430\u0440\u0442\u0443\u0434\u044b \u0430\u044f\u049b\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u049b\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u04a3\u044b\u0437.",
+ "ButtonRestart": "\u049a\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443",
+ "MessagePleaseRefreshPage": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0435\u043d \u0436\u0430\u04a3\u0430 \u0436\u0430\u04a3\u0430\u0440\u0442\u0443\u043b\u0430\u0440\u0434\u044b \u0430\u043b\u0443 \u04af\u0448\u0456\u043d \u043e\u0441\u044b \u0431\u0435\u0442\u0442\u0456 \u043a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0456\u04a3\u0456\u0437.",
+ "ButtonHide": "\u0416\u0430\u0441\u044b\u0440\u0443",
+ "MessageSettingsSaved": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440 \u0441\u0430\u049b\u0442\u0430\u043b\u0434\u044b.",
+ "ButtonSignOut": "\u0428\u044b\u0493\u0443",
+ "ButtonMyProfile": "\u041c\u0435\u043d\u0456\u04a3 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u044b\u043c",
+ "ButtonMyPreferences": "\u041c\u0435\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u043c",
+ "MessageBrowserDoesNotSupportWebSockets": "\u041e\u0441\u044b \u0448\u043e\u043b\u0493\u044b\u0448 \u0432\u0435\u0431-\u0441\u043e\u043a\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u049b\u043e\u043b\u0434\u0430\u043c\u0430\u0439\u0434\u044b. \u0410\u043d\u0430\u0493\u04b1\u0440\u043b\u044b\u043c \u0442\u0438\u0456\u043c\u0434\u0456 \u0436\u04b1\u043c\u044b\u0441 \u04af\u0448\u0456\u043d, \u0436\u0430\u04a3\u0430 \u0448\u043e\u043b\u0493\u044b\u0448 \u0430\u0440\u049b\u044b\u043b\u044b, \u043c\u044b\u0441\u0430\u043b\u044b, Chrome, Firefox, IE10+, Safari (iOS) \u043d\u0435 Opera, \u04d9\u0440\u0435\u043a\u0435\u0442 \u0436\u0430\u0441\u0430\u04a3\u044b\u0437",
+ "LabelInstallingPackage": "{0} \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0443\u0434\u0430",
+ "LabelPackageInstallCompleted": "{0} \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0443\u044b \u0430\u044f\u049b\u0442\u0430\u043b\u0434\u044b.",
+ "LabelPackageInstallFailed": "{0} \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0443\u044b \u0441\u04d9\u0442\u0441\u0456\u0437.",
+ "LabelPackageInstallCancelled": "{0} \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0443\u044b \u0431\u043e\u043b\u0434\u044b\u0440\u044b\u043b\u043c\u0430\u0434\u044b.",
+ "TabServer": "\u0421\u0435\u0440\u0432\u0435\u0440",
+ "TabUsers": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440",
+ "TabLibrary": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430",
+ "TabMetadata": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414",
+ "TabAutoOrganize": "\u0410\u0432\u0442\u043e\u04b1\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443",
+ "TabPlugins": "\u041f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440",
+ "TabAdvanced": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430",
+ "TabHelp": "\u0410\u043d\u044b\u049b\u0442\u0430\u043c\u0430",
+ "TabScheduledTasks": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0443\u0448\u044b",
+ "ButtonFullscreen": "\u0422\u043e\u043b\u044b\u049b \u044d\u043a\u0440\u0430\u043d",
+ "ButtonAudioTracks": "\u0414\u044b\u0431\u044b\u0441 \u0436\u043e\u043b\u0448\u044b\u0493\u044b",
+ "ButtonSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440",
+ "ButtonScenes": "\u0421\u0430\u0445\u043d\u0430\u043b\u0430\u0440",
+ "ButtonQuality": "\u0421\u0430\u043f\u0430",
+ "HeaderNotifications": "\u0425\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443\u043b\u0430\u0440",
+ "HeaderSelectPlayer": "\u041e\u0439\u043d\u0430\u0442\u049b\u044b\u0448\u0442\u044b \u0442\u0430\u04a3\u0434\u0430\u0443:",
+ "ButtonSelect": "\u0411\u04e9\u043b\u0435\u043a\u0442\u0435\u0443",
+ "ButtonNew": "\u0416\u0430\u0441\u0430\u0443",
+ "MessageInternetExplorerWebm": "Internet Explorer \u0430\u0440\u049b\u044b\u043b\u044b \u0435\u04a3 \u0436\u0430\u049b\u0441\u044b \u043d\u04d9\u0442\u0438\u0436\u0435\u043b\u0435\u0440\u0433\u0435 \u0438\u0435 \u0431\u043e\u043b\u0443 \u04af\u0448\u0456\u043d WebM \u043e\u0439\u043d\u0430\u0442\u0443 \u043f\u043b\u0430\u0433\u0438\u043d\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437.",
+ "HeaderVideoError": "\u0411\u0435\u0439\u043d\u0435 \u049b\u0430\u0442\u0435\u0441\u0456",
+ "ButtonAddToPlaylist": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0456\u043d\u0435 \u04af\u0441\u0442\u0435\u0443",
+ "HeaderAddToPlaylist": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0456\u043d\u0435 \u04af\u0441\u0442\u0435\u0443",
+ "LabelName": "\u0410\u0442\u044b:",
+ "ButtonSubmit": "\u0416\u0456\u0431\u0435\u0440\u0443",
+ "LabelSelectPlaylist": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0456:",
+ "OptionNewPlaylist": "\u0416\u0430\u04a3\u0430 \u043e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0456...",
+ "MessageAddedToPlaylistSuccess": "\u0416\u0430\u0440\u0430\u0439\u0434\u044b",
+ "ButtonViewSeriesRecording": "\u0421\u0435\u0440\u0438\u0430\u043b \u0436\u0430\u0437\u0431\u0430\u0441\u044b\u043d \u049b\u0430\u0440\u0430\u0443",
+ "ValueOriginalAirDate": "\u0411\u0430\u0441\u0442\u0430\u043f\u049b\u044b \u044d\u0444\u0438\u0440: {0}",
+ "ButtonRemoveFromPlaylist": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0456\u043d\u0435\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u0443",
+ "HeaderSpecials": "\u0410\u0440\u043d\u0430\u0439\u044b\u043b\u0430\u0440",
+ "HeaderTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440",
+ "HeaderAudio": "\u0414\u044b\u0431\u044b\u0441",
+ "HeaderResolution": "\u0410\u0436\u044b\u0440\u0430\u0442\u044b\u043c\u0434\u044b\u043b\u044b\u0493\u044b",
+ "HeaderVideo": "\u0411\u0435\u0439\u043d\u0435",
+ "HeaderRuntime": "\u04b0\u0437\u0430\u049b\u0442\u044b\u0493\u044b",
+ "HeaderCommunityRating": "\u049a\u0430\u0443\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u049b \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b",
+ "HeaderParentalRating": "\u0416\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442\u044b",
+ "HeaderReleaseDate": "\u0428\u044b\u0493\u0430\u0440\u0443 \u043a\u04af\u043d-\u0430\u0439\u044b",
+ "HeaderDateAdded": "\u04ae\u0441\u0442\u0435\u0443 \u043a\u04af\u043d-\u0430\u0439\u044b",
+ "HeaderSeries": "\u0421\u0435\u0440\u0438\u0430\u043b",
+ "HeaderSeason": "\u041c\u0430\u0443\u0441\u044b\u043c",
+ "HeaderSeasonNumber": "\u041c\u0430\u0443\u0441\u044b\u043c \u043d\u04e9\u043c\u0456\u0440\u0456",
+ "HeaderNetwork": "\u0422\u0435\u043b\u0435\u0436\u0435\u043b\u0456",
+ "HeaderYear": "\u0416\u044b\u043b\u044b",
+ "HeaderGameSystem": "\u041e\u0439\u044b\u043d \u0436\u04af\u0439\u0435\u0441\u0456",
+ "HeaderPlayers": "\u041e\u0439\u044b\u043d\u0448\u044b\u043b\u0430\u0440",
+ "HeaderEmbeddedImage": "\u0415\u043d\u0434\u0456\u0440\u0456\u043b\u0433\u0435\u043d \u0441\u0443\u0440\u0435\u0442",
+ "HeaderTrack": "\u0416\u043e\u043b\u0448\u044b\u049b",
+ "HeaderDisc": "\u0414\u0438\u0441\u043a\u0456",
+ "OptionMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
+ "OptionCollections": "\u0416\u0438\u043d\u0430\u049b\u0442\u0430\u0440",
+ "OptionSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u0434\u0430\u0440",
+ "OptionSeasons": "\u041c\u0430\u0443\u0441\u044b\u043c\u0434\u0430\u0440",
+ "OptionEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440",
+ "OptionGames": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440",
+ "OptionGameSystems": "\u041e\u0439\u044b\u043d \u0436\u04af\u0439\u0435\u043b\u0435\u0440\u0456",
+ "OptionMusicArtists": "\u041c\u0443\u0437\u044b\u043a\u0430 \u043e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b\u043b\u0430\u0440\u044b",
+ "OptionMusicAlbums": "\u041c\u0443\u0437\u044b\u043a\u0430 \u0430\u043b\u044c\u0431\u043e\u043c\u0434\u0430\u0440\u044b",
+ "OptionMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430 \u043a\u043b\u0438\u043f\u0442\u0435\u0440\u0456",
+ "OptionSongs": "\u04d8\u0443\u0435\u043d\u0434\u0435\u0440",
+ "OptionHomeVideos": "\u04ae\u0439 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0456",
+ "OptionBooks": "\u041a\u0456\u0442\u0430\u043f\u0442\u0430\u0440",
+ "OptionAdultVideos": "\u0415\u0440\u0435\u0441\u0435\u043a \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0456",
+ "ButtonUp": "\u0416\u043e\u0493\u0430\u0440\u044b\u0493\u0430",
+ "ButtonDown": "\u0422\u04e9\u043c\u0435\u043d\u0433\u0435",
+ "LabelMetadataReaders": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u043e\u049b\u0443\u0448\u044b\u043b\u0430\u0440\u044b:",
+ "LabelMetadataReadersHelp": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u049b\u0430\u0439\u043d\u0430\u0440 \u043a\u04e9\u0437\u0434\u0435\u0440\u0456\u043d\u0435 \u0431\u0430\u0441\u044b\u043c\u0434\u044b\u043b\u044b\u049b \u0440\u0435\u0442\u0456 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0434\u04d9\u0440\u0435\u0436\u0435 \u0431\u0435\u0440\u0456\u04a3\u0456\u0437. \u0411\u0456\u0440\u0456\u043d\u0448\u0456 \u0442\u0430\u0431\u044b\u043b\u0493\u0430\u043d \u0444\u0430\u0439\u043b \u043e\u049b\u044b\u043b\u0430\u0434\u044b.",
+ "LabelMetadataDownloaders": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0436\u04af\u043a\u0442\u0435\u0443\u0448\u0456\u043b\u0435\u0440\u0456:",
+ "LabelMetadataDownloadersHelp": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0436\u04af\u043a\u0442\u0435\u0443\u0448\u0456\u043b\u0435\u0440\u0456\u043d \u049b\u043e\u0441\u044b\u04a3\u044b\u0437 \u0436\u04d9\u043d\u0435 \u0431\u0430\u0441\u044b\u043c\u0434\u044b\u043b\u044b\u049b \u0440\u0435\u0442\u0456 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0434\u04d9\u0440\u0435\u0436\u0435 \u0431\u0435\u0440\u0456\u04a3\u0456\u0437. \u0422\u04e9\u043c\u0435\u043d\u0433\u0456 \u0431\u0430\u0441\u044b\u043c\u0434\u044b\u043b\u044b\u0493\u044b \u0431\u0430\u0440 \u0436\u04af\u043a\u0442\u0435\u0443\u0448\u0456\u043b\u0435\u0440 \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u0436\u043e\u049b \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u0442\u044b \u0442\u043e\u043b\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b.",
+ "LabelMetadataSavers": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0441\u0430\u049b\u0442\u0430\u0443\u0448\u044b\u043b\u0430\u0440\u044b:",
+ "LabelMetadataSaversHelp": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u049b\u0430\u0439\u0434\u0430 \u0441\u0430\u049b\u0442\u0430\u0439\u0442\u044b\u043d \u0444\u0430\u0439\u043b \u043f\u0456\u0448\u0456\u043c\u0434\u0435\u0440\u0456\u043d \u0442\u0430\u04a3\u0434\u0430\u0443.",
+ "LabelImageFetchers": "\u0421\u0443\u0440\u0435\u0442 \u0456\u0440\u0456\u043a\u0442\u0435\u0443\u0448\u0456\u043b\u0435\u0440\u0456:",
+ "LabelImageFetchersHelp": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0441\u0443\u0440\u0435\u0442 \u0456\u0440\u0456\u043a\u0442\u0435\u0443\u0448\u0456\u043b\u0435\u0440\u0456\u043d \u049b\u043e\u0441\u044b\u04a3\u044b\u0437 \u0436\u04d9\u043d\u0435 \u0431\u0430\u0441\u044b\u043c\u0434\u044b\u043b\u044b\u049b \u0440\u0435\u0442\u0456 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0434\u04d9\u0440\u0435\u0436\u0435 \u0431\u0435\u0440\u0456\u04a3\u0456\u0437.",
+ "ButtonQueueAllFromHere": "\u0411\u04b1\u043b \u0430\u0440\u0430\u0434\u0430\u043d \u0431\u04d9\u0440\u0456\u043d \u043a\u0435\u0437\u0435\u043a\u0442\u0435\u0443",
+ "ButtonPlayAllFromHere": "\u0411\u04b1\u043b \u0430\u0440\u0430\u0434\u0430\u043d \u0431\u04d9\u0440\u0456\u043d \u043e\u0439\u043d\u0430\u0442\u0443",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u0430\u043d\u044b\u049b\u0442\u0430\u0443",
+ "PersonTypePerson": "\u0422\u04b1\u043b\u0493\u0430",
+ "LabelTitleDisplayOrder": "\u0422\u0443\u044b\u043d\u0434\u044b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443 \u0440\u0435\u0442\u0456:",
+ "OptionSortName": "\u0421\u04b1\u0440\u044b\u043f\u0442\u0430\u043b\u0430\u0442\u044b\u043d \u0430\u0442\u044b",
+ "OptionReleaseDate": "\u0428\u044b\u0493\u0430\u0440\u0443 \u043a\u04af\u043d-\u0430\u0439\u044b",
+ "LabelSeasonNumber": "\u041c\u0430\u0443\u0441\u044b\u043c \u043d\u04e9\u043c\u0456\u0440\u0456:",
+ "LabelDiscNumber": "\u0414\u0438\u0441\u043a\u0456 \u043d\u04e9\u043c\u0456\u0440\u0456",
+ "LabelParentNumber": "\u0422\u0435\u043a\u0442\u0456\u043a \u043d\u04e9\u043c\u0456\u0440:",
+ "LabelEpisodeNumber": "\u042d\u043f\u0438\u0437\u043e\u0434 \u043d\u04e9\u043c\u0456\u0440\u0456:",
+ "LabelTrackNumber": "\u0416\u043e\u043b\u0448\u044b\u049b \u043d\u04e9\u043c\u0456\u0440\u0456:",
+ "LabelNumber": "\u041d\u04e9\u043c\u0456\u0440\u0456:",
+ "LabelReleaseDate": "\u0428\u044b\u0493\u0430\u0440\u0443 \u043a\u04af\u043d-\u0430\u0439\u044b:",
+ "LabelEndDate": "\u0410\u044f\u049b\u0442\u0430\u043b\u0443 \u043a\u04af\u043d-\u0430\u0439\u044b:",
+ "LabelYear": "\u0416\u044b\u043b\u044b:",
+ "LabelDateOfBirth": "\u0422\u0443\u0493\u0430\u043d \u043a\u04af\u043d-\u0430\u0439\u044b:",
+ "LabelBirthYear": "\u0422\u0443\u0493\u0430\u043d \u0436\u044b\u043b\u044b:",
+ "LabelDeathDate": "\u04e8\u043b\u0433\u0435\u043d \u0436\u044b\u043b\u044b:",
+ "HeaderRemoveMediaLocation": "\u0422\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u043e\u0440\u043d\u0430\u043b\u0430\u0441\u0443\u044b\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u0443",
+ "MessageConfirmRemoveMediaLocation": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u043e\u0440\u043d\u0430\u043b\u0430\u0441\u0443\u0434\u044b \u0430\u043b\u0430\u0441\u0442\u0430\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
+ "HeaderRenameMediaFolder": "\u0422\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d \u049b\u0430\u0439\u0442\u0430 \u0430\u0442\u0430\u0443",
+ "LabelNewName": "\u0416\u0430\u04a3\u0430 \u0430\u0442\u044b",
+ "HeaderAddMediaFolder": "\u0422\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d \u04af\u0441\u0442\u0435\u0443",
+ "HeaderAddMediaFolderHelp": "\u0410\u0442\u044b (\u041a\u0438\u043d\u043e, \u041c\u0443\u0437\u044b\u043a\u0430, \u0422\u0414, \u0442.\u0431.):",
+ "HeaderRemoveMediaFolder": "\u0422\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u0443",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0442\u0430\u0441\u0443\u0448\u044b \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456\u04a3 \u043e\u0440\u043d\u0430\u043b\u0430\u0441\u0443\u043b\u0430\u0440\u044b \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u0434\u0430\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u043b\u0430\u0434\u044b:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
+ "ButtonRename": "\u049a\u0430\u0439\u0442\u0430 \u0430\u0442\u0430\u0443",
+ "ButtonChangeType": "\u0422\u04af\u0440\u0456\u043d \u04e9\u0437\u0433\u0435\u0440\u0442\u0443",
+ "HeaderMediaLocations": "\u0422\u0430\u0441\u0443\u0448\u044b \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u043e\u0440\u043d\u0430\u043b\u0430\u0441\u0443\u043b\u0430\u0440\u044b",
+ "LabelFolderTypeValue": "\u049a\u0430\u043b\u0442\u0430 \u0442\u04af\u0440\u0456: {0}",
+ "LabelPathSubstitutionHelp": "\u049a\u0430\u043b\u0430\u0443 \u0431\u043e\u0439\u044b\u043d\u0448\u0430: \u0416\u043e\u043b \u0430\u043b\u043c\u0430\u0441\u0442\u044b\u0440\u0443 \u0430\u0440\u049b\u044b\u043b\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0435\u0433\u0456 \u0436\u043e\u043b\u0434\u0430\u0440\u0434\u044b \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0430 \u0430\u043b\u0430\u0442\u044b\u043d \u0436\u0435\u043b\u0456\u043b\u0456\u043a \u049b\u043e\u0440 \u043a\u04e9\u0437\u0434\u0435\u0440\u0456\u043c\u0435\u043d \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.",
+ "FolderTypeMixed": "\u0410\u0440\u0430\u043b\u0430\u0441 (\u043a\u0438\u043d\u043e \u0436\u04d9\u043d\u0435 \u0442\u0434)",
+ "FolderTypeMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
+ "FolderTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430",
+ "FolderTypeAdultVideos": "\u0415\u0440\u0435\u0441\u0435\u043a\u0442\u0456\u043a \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440",
+ "FolderTypePhotos": "\u0424\u043e\u0442\u043e\u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440",
+ "FolderTypeMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044b\u049b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440",
+ "FolderTypeHomeVideos": "\u04ae\u0439 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0456",
+ "FolderTypeGames": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440",
+ "FolderTypeBooks": "\u041a\u0456\u0442\u0430\u043f\u0442\u0430\u0440",
+ "FolderTypeTvShows": "\u0422\u0414 \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c\u0434\u0435\u0440\u0456",
+ "TabMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
+ "TabSeries": "\u0421\u0435\u0440\u0438\u0430\u043b",
+ "TabEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440",
+ "TabTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440",
+ "TabGames": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440",
+ "TabAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u0434\u0435\u0440",
+ "TabSongs": "\u04d8\u0443\u0435\u043d\u0434\u0435\u0440",
+ "TabMusicVideos": "\u0411\u0435\u0439\u043d\u0435\u043a\u043b\u0438\u043f\u0442\u0435\u0440",
+ "BirthPlaceValue": "\u0422\u0443\u0493\u0430\u043d \u043e\u0440\u043d\u044b: {0}",
+ "DeathDateValue": "\u04e8\u043b\u0433\u0435\u043d\u0456: {0}",
+ "BirthDateValue": "\u0422\u0443\u0493\u0430\u043d\u044b: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json
index 51055f880..b6d5e50e5 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "Off",
- "OptionOn": "On",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "My Library",
"SettingsSaved": "Seting Disimpan",
"AddUser": "Tambah Pengguna",
"Users": "Para Pengguna",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episode",
"LabelSeries": "Series",
"LabelStopping": "Stopping",
- "ButtonStop": "Stop",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Unknown language",
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
"ButtonPause": "Pause",
"ButtonPlay": "Play",
"ButtonEdit": "Edit",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
+ "ButtonPlayTrailer": "Play trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Previous Track",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
"ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
"HeaderSeriesRecordings": "Series Recordings",
"LabelAnytime": "Any time",
"StatusRecording": "Recording",
@@ -130,7 +123,8 @@
"HeaderMyViews": "My Views",
"HeaderLibraryFolders": "Media Folders",
"HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
"HeaderFavoriteMovies": "Favorite Movies",
"HeaderFavoriteShows": "Favorite Shows",
"HeaderFavoriteEpisodes": "Favorite Episodes",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
"HeaderSelectImagesByNamePath": "Select Images By Name Path",
"HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
"HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Remote access: {0}",
"LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
"HeaderLatestFromChannel": "Latest from {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Unknown language",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Cancel",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "Scenes",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "Name",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Channels",
+ "HeaderMediaFolders": "Media Folders",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "Ended",
+ "OptionContinuing": "Continuing",
+ "OptionOff": "Off",
+ "OptionOn": "On",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPeople": "People",
+ "OptionRuntime": "Runtime",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Server",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Advanced",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonScenes": "Scenes",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "Select",
+ "ButtonNew": "New",
+ "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:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Movies",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episodes",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Season number:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Movies",
+ "TabSeries": "Series",
+ "TabEpisodes": "Episodes",
+ "TabTrailers": "Trailers",
+ "TabGames": "Games",
+ "TabAlbums": "Albums",
+ "TabSongs": "Songs",
+ "TabMusicVideos": "Music Videos",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json
index 351ab9520..024009e03 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "Av",
- "OptionOn": "P\u00e5",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "Mitt bibliotek",
"SettingsSaved": "Innstillinger lagret",
"AddUser": "Legg til bruker",
"Users": "Brukere",
@@ -15,7 +7,7 @@
"Password": "Passord",
"DeleteImage": "Slett bilde",
"DeleteImageConfirmation": "Er du sikker p\u00e5 at du vil slette bildet?",
- "FileReadCancelled": "Lesing av filen avbrutt",
+ "FileReadCancelled": "Lesing av filen kansellert.",
"FileNotFound": "Fil ikke funnet",
"FileReadError": "Feil oppstod i det filen ble lest",
"DeleteUser": "Slett bruker",
@@ -25,7 +17,7 @@
"PasswordResetConfirmation": "Er du sikker p\u00e5 at du vil resette passordet?",
"PasswordSaved": "Passord lagret",
"PasswordMatchError": "Passord og passord-verifiseringen m\u00e5 matche",
- "OptionRelease": "Sluppet",
+ "OptionRelease": "Offisiell utgivelse",
"OptionBeta": "Beta",
"OptionDev": "Dev (Ustabil)",
"UninstallPluginHeader": "Avinstaller plugin",
@@ -33,70 +25,72 @@
"NoPluginConfigurationMessage": "Denne pluginn-en har intet \u00e5 konfigurere",
"NoPluginsInstalledMessage": "Du har ikke installert noen plugins enn\u00e5",
"BrowsePluginCatalogMessage": "Browse v\u00e5r plugin-katalog for \u00e5 se tilgjengelige plugins",
- "MessageKeyEmailedTo": "Key emailed to {0}.",
- "MessageKeysLinked": "Keys linked.",
- "HeaderConfirmation": "Confirmation",
- "MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
- "MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
- "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
- "HeaderSearch": "Search",
+ "MessageKeyEmailedTo": "N\u00f8kkel sendt til {0}",
+ "MessageKeysLinked": "N\u00f8kkel linket.",
+ "HeaderConfirmation": "Bekreftelse",
+ "MessageKeyUpdated": "Takk. Din supporter n\u00f8kkel har blitt oppdatert.",
+ "MessageKeyRemoved": "Takk. Din supporter n\u00f8kkel har blitt fjernet.",
+ "ErrorLaunchingChromecast": "Det var en error ved \u00e5 starte Chromecast. Vennligst forsikre deg om at enheten har korrekt forbindelse mot ditt tr\u00e5dl\u00f8se nettverk.",
+ "HeaderSearch": "S\u00f8k",
"LabelArtist": "Artist",
- "LabelMovie": "Movie",
- "LabelMusicVideo": "Music Video",
+ "LabelMovie": "Film",
+ "LabelMusicVideo": "Musikk Video",
"LabelEpisode": "Episode",
- "LabelSeries": "Series",
- "LabelStopping": "Stopping",
- "ButtonStop": "Stop",
- "LabelCancelled": "(cancelled)",
- "LabelFailed": "(failed)",
- "LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
- "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
- "HeaderDeleteTaskTrigger": "Delete Task Trigger",
- "HeaderTaskTriggers": "Task Triggers",
- "MessageDeleteTaskTrigger": "Are you sure you wish to delete this task trigger?",
- "MessageNoPluginsInstalled": "You have no plugins installed.",
- "LabelVersionInstalled": "{0} installed",
- "LabelNumberReviews": "{0} Reviews",
- "LabelFree": "Free",
- "HeaderSelectAudio": "Select Audio",
- "HeaderSelectSubtitles": "Select Subtitles",
- "LabelDefaultStream": "(Default)",
- "LabelForcedStream": "(Forced)",
- "LabelDefaultForcedStream": "(Default\/Forced)",
- "LabelUnknownLanguage": "Unknown language",
+ "LabelSeries": "Serier",
+ "LabelStopping": "Stoppe",
+ "LabelCancelled": "(kansellert)",
+ "LabelFailed": "(feilet)",
+ "LabelAbortedByServerShutdown": "(Avbrutt av server shutdown)",
+ "LabelScheduledTaskLastRan": "Sist kj\u00f8rt {0}, tar {1}.",
+ "HeaderDeleteTaskTrigger": "Slett Oppgave Trigger",
+ "HeaderTaskTriggers": "Oppgave Triggers",
+ "MessageDeleteTaskTrigger": "Er du sikker p\u00e5 at du vil slette denne oppgave triggeren?",
+ "MessageNoPluginsInstalled": "Du har ingen plugins installert.",
+ "LabelVersionInstalled": "{0} installert.",
+ "LabelNumberReviews": "{0} Anmeldelser",
+ "LabelFree": "Gratis",
+ "HeaderSelectAudio": "Velg Lyd",
+ "HeaderSelectSubtitles": "Velg Undertekst",
+ "LabelDefaultStream": "(Standard)",
+ "LabelForcedStream": "(Tvunget)",
+ "LabelDefaultForcedStream": "(Standard\/Tvunget)",
+ "LabelUnknownLanguage": "Ukjent spr\u00e5k",
"ButtonMute": "Mute",
- "ButtonUnmute": "Unmute",
+ "ButtonUnmute": "unmute",
+ "ButtonStop": "Stopp",
+ "ButtonNextTrack": "Neste Spor",
"ButtonPause": "Pause",
- "ButtonPlay": "Play",
- "ButtonEdit": "Edit",
- "ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
- "ButtonPlaylist": "Playlist",
- "LabelEnabled": "Enabled",
- "LabelDisabled": "Disabled",
- "ButtonMoreInformation": "More Information",
- "LabelNoUnreadNotifications": "No unread notifications.",
- "ButtonViewNotifications": "View notifications",
- "ButtonMarkTheseRead": "Mark these read",
- "ButtonClose": "Close",
- "LabelAllPlaysSentToPlayer": "All plays will be sent to the selected player.",
- "MessageInvalidUser": "Invalid user or password.",
- "HeaderAllRecordings": "All Recordings",
- "RecommendationBecauseYouLike": "Because you like {0}",
- "RecommendationBecauseYouWatched": "Because you watched {0}",
- "RecommendationDirectedBy": "Directed by {0}",
- "RecommendationStarring": "Starring {0}",
- "HeaderConfirmRecordingCancellation": "Confirm Recording Cancellation",
- "MessageConfirmRecordingCancellation": "Are you sure you wish to cancel this recording?",
- "MessageRecordingCancelled": "Recording cancelled.",
- "HeaderConfirmSeriesCancellation": "Confirm Series Cancellation",
- "MessageConfirmSeriesCancellation": "Are you sure you wish to cancel this series?",
- "MessageSeriesCancelled": "Series cancelled.",
- "HeaderConfirmRecordingDeletion": "Confirm Recording Deletion",
- "MessageConfirmRecordingDeletion": "Are you sure you wish to delete this recording?",
- "MessageRecordingDeleted": "Recording deleted.",
- "ButonCancelRecording": "Cancel Recording",
- "MessageRecordingSaved": "Recording saved.",
+ "ButtonPlay": "Spill",
+ "ButtonEdit": "Rediger",
+ "ButtonQueue": "K\u00f8",
+ "ButtonPlayTrailer": "Spill trailer",
+ "ButtonPlaylist": "Spilleliste",
+ "ButtonPreviousTrack": "Forrige Spor",
+ "LabelEnabled": "Aktivert",
+ "LabelDisabled": "Deaktivert",
+ "ButtonMoreInformation": "Mer Informasjon",
+ "LabelNoUnreadNotifications": "Ingen uleste meldinger.",
+ "ButtonViewNotifications": "Se meldinger.",
+ "ButtonMarkTheseRead": "Maker disse som lest",
+ "ButtonClose": "Lukk",
+ "LabelAllPlaysSentToPlayer": "All avspill vil bli sendt til den valgte spilleren.",
+ "MessageInvalidUser": "Ugyldig bruker eller passord.",
+ "HeaderAllRecordings": "Alle Opptak",
+ "RecommendationBecauseYouLike": "Fordi du liker {0}",
+ "RecommendationBecauseYouWatched": "Fordi du s\u00e5 {0}",
+ "RecommendationDirectedBy": "Regissert av {0}",
+ "RecommendationStarring": "Med {0}",
+ "HeaderConfirmRecordingCancellation": "Bekreft Avbryt Opptak",
+ "MessageConfirmRecordingCancellation": "Er du sikker p\u00e5 at du vil avbryte dette opptaket?",
+ "MessageRecordingCancelled": "Opptak er Avbrutt.",
+ "HeaderConfirmSeriesCancellation": "Bekreft Serier kansellering",
+ "MessageConfirmSeriesCancellation": "Er du sikker p\u00e5 at du vil kansellere denne serien?",
+ "MessageSeriesCancelled": "Serie kansellert.",
+ "HeaderConfirmRecordingDeletion": "Bekreft Sletting av Opptak",
+ "MessageConfirmRecordingDeletion": "Er du sikker p\u00e5 at du vil slette dette opptaket?",
+ "MessageRecordingDeleted": "Opptak slettet.",
+ "ButonCancelRecording": "Avbryt Opptak",
+ "MessageRecordingSaved": "Opptak lagret.",
"OptionSunday": "S\u00f8ndag",
"OptionMonday": "Mandag",
"OptionTuesday": "Tirsdag",
@@ -104,94 +98,336 @@
"OptionThursday": "Torsdag",
"OptionFriday": "Fredag",
"OptionSaturday": "L\u00f8rdag",
- "HeaderConfirmDeletion": "Confirm Deletion",
- "MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
- "LiveTvUpdateAvailable": "(Update available)",
- "LabelVersionUpToDate": "Up to date!",
+ "HeaderConfirmDeletion": "Bekreft Kansellering",
+ "MessageConfirmPathSubstitutionDeletion": "Er du sikker p\u00e5 at du vil slette sti substitusjon?",
+ "LiveTvUpdateAvailable": "(Oppdatering tilgjengelig)",
+ "LabelVersionUpToDate": "Oppdatert!",
"ButtonResetTuner": "Reset tuner",
"HeaderResetTuner": "Reset Tuner",
- "MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
- "ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
- "HeaderSeriesRecordings": "Series Recordings",
- "LabelAnytime": "Any time",
- "StatusRecording": "Recording",
- "StatusWatching": "Watching",
- "StatusRecordingProgram": "Recording {0}",
- "StatusWatchingProgram": "Watching {0}",
- "HeaderSplitMedia": "Split Media Apart",
- "MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
+ "MessageConfirmResetTuner": "Er du sikker p\u00e5 at du vil resette denne tuneren? Alle aktive enheter eller opptak vil br\u00e5tt stoppe.",
+ "ButtonCancelSeries": "Kanseller Serier",
+ "HeaderSeriesRecordings": "Serie Oppdak",
+ "LabelAnytime": "N\u00e5r som helst",
+ "StatusRecording": "Opptak",
+ "StatusWatching": "Ser P\u00e5",
+ "StatusRecordingProgram": "Opptak {0}",
+ "StatusWatchingProgram": "Ser P\u00e5 {0}",
+ "HeaderSplitMedia": "Del Media Fra Hverandre",
+ "MessageConfirmSplitMedia": "Er du sikker at du vil splitte media kilden i separerte elementer?",
"HeaderError": "Error",
- "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": "Media Browser clients will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?",
+ "MessagePleaseSelectOneItem": "Vennligst velg minst ett element.",
+ "MessagePleaseSelectTwoItems": "Vennligst velg minst to elementer.",
+ "MessageTheFollowingItemsWillBeGrouped": "F\u00f8lgende titler vil bli gruppert til ett element:",
+ "MessageConfirmItemGrouping": "Media Browser klienter vil automatisk velge den mest optimale versjonen for avspilling basert p\u00e5 enhet og nettverks ytelse. Er du sikker p\u00e5 at du vil fortsette?",
"HeaderResume": "Fortsett",
- "HeaderMyViews": "My Views",
- "HeaderLibraryFolders": "Media Folders",
- "HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
- "HeaderFavoriteMovies": "Favorite Movies",
- "HeaderFavoriteShows": "Favorite Shows",
- "HeaderFavoriteEpisodes": "Favorite Episodes",
- "HeaderFavoriteGames": "Favorite Games",
- "HeaderRatingsDownloads": "Rating \/ Downloads",
- "HeaderConfirmProfileDeletion": "Confirm Profile Deletion",
- "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?",
- "HeaderSelectServerCachePath": "Select Server Cache Path",
- "HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
- "HeaderSelectImagesByNamePath": "Select Images By Name Path",
- "HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
- "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
- "HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
- "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
- "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",
- "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.",
- "HeaderFavoriteAlbums": "Favorite Albums",
- "HeaderLatestChannelMedia": "Latest Channel Items",
- "ButtonOrganizeFile": "Organize File",
- "ButtonDeleteFile": "Delete File",
- "HeaderOrganizeFile": "Organize File",
- "HeaderDeleteFile": "Delete File",
- "StatusSkipped": "Skipped",
- "StatusFailed": "Failed",
- "StatusSuccess": "Success",
- "MessageFileWillBeDeleted": "The following file will be deleted:",
- "MessageSureYouWishToProceed": "Are you sure you wish to proceed?",
- "MessageDuplicatesWillBeDeleted": "In addition the following dupliates will be deleted:",
- "MessageFollowingFileWillBeMovedFrom": "The following file will be moved from:",
- "MessageDestinationTo": "to:",
- "HeaderSelectWatchFolder": "Select Watch Folder",
- "HeaderSelectWatchFolderHelp": "Browse or enter the path to your watch folder. The folder must be writeable.",
- "OrganizePatternResult": "Result: {0}",
- "HeaderRestart": "Restart",
- "HeaderShutdown": "Shutdown",
- "MessageConfirmRestart": "Are you sure you wish to restart Media Browser Server?",
- "MessageConfirmShutdown": "Are you sure you wish to shutdown Media Browser Server?",
- "ButtonUpdateNow": "Update Now",
- "NewVersionOfSomethingAvailable": "A new version of {0} is available!",
- "VersionXIsAvailableForDownload": "Version {0} is now available for download.",
- "LabelVersionNumber": "Version {0}",
+ "HeaderMyViews": "Mitt Syn",
+ "HeaderLibraryFolders": "Media Mapper",
+ "HeaderLatestMedia": "Siste Media",
+ "ButtonMoreItems": "Mer...",
+ "ButtonMore": "Mer",
+ "HeaderFavoriteMovies": "Favoritt Filmer",
+ "HeaderFavoriteShows": "Favoritt Serier",
+ "HeaderFavoriteEpisodes": "Favoritt Episoder",
+ "HeaderFavoriteGames": "Favoritt Spill",
+ "HeaderRatingsDownloads": "Rangering \/ Nedlasting",
+ "HeaderConfirmProfileDeletion": "Bekreft sletting av profil",
+ "MessageConfirmProfileDeletion": "Er du sikker p\u00e5 at du vil slette denne profilen?",
+ "HeaderSelectServerCachePath": "Velg Server Cache Sti",
+ "HeaderSelectTranscodingPath": "Velg Transcoding Midlertidig Sti",
+ "HeaderSelectImagesByNamePath": "Velg Bilder etter Navn Sti",
+ "HeaderSelectMetadataPath": "Velg Metadata Sti",
+ "HeaderSelectServerCachePathHelp": "Bla eller skriv stien som skal brukes for server cache filer. Mappen m\u00e5 v\u00e6re skrivbar.",
+ "HeaderSelectTranscodingPathHelp": "Bla eller skriv stien som skal brukes for transcoding av midlertidige filer. Mappen m\u00e5 v\u00e6re skrivbar.",
+ "HeaderSelectImagesByNamePathHelp": "Bla eller skriv stien til dine elementer etter navn mappe. Mappen m\u00e5 v\u00e6re skrivbar.",
+ "HeaderSelectMetadataPathHelp": "Bla eller skriv stien som skal brukes for metadata. Mappen m\u00e5 v\u00e6re skrivbar.",
+ "HeaderSelectChannelDownloadPath": "Velg Nedlastingsti For Kanal",
+ "HeaderSelectChannelDownloadPathHelp": "Bla igjennom eller skriv en sti som brukes for lagring av cache filer. Mappen m\u00e5 v\u00e6re skrivbar.",
+ "OptionNewCollection": "Ny...",
+ "ButtonAdd": "Legg Til",
+ "ButtonRemove": "Fjern",
+ "LabelChapterDownloaders": "Kapittel nedlastinger:",
+ "LabelChapterDownloadersHelp": "Aktiver og ranger din foretrukne kapittel nedlasting i f\u00f8lgende prioritet. Lavere prioritet nedlastinger vil kun bli brukt for \u00e5 fylle inn manglende informasjon",
+ "HeaderFavoriteAlbums": "Favoritt Albumer",
+ "HeaderLatestChannelMedia": "Siste Kanal Elementer",
+ "ButtonOrganizeFile": "Organiser Fil",
+ "ButtonDeleteFile": "Slett FIl",
+ "HeaderOrganizeFile": "Organiser Fil",
+ "HeaderDeleteFile": "Slett FIl",
+ "StatusSkipped": "Hoppet over",
+ "StatusFailed": "Feilet",
+ "StatusSuccess": "Sukksess",
+ "MessageFileWillBeDeleted": "F\u00f8lgende fil vil bli slettet:",
+ "MessageSureYouWishToProceed": "Er du sikker p\u00e5 at du vil forsette?",
+ "MessageDuplicatesWillBeDeleted": "I tillegg vil f\u00f8lgende duplisering bli slettet:",
+ "MessageFollowingFileWillBeMovedFrom": "F\u00f8lgende fil har blitt flyttet fra:",
+ "MessageDestinationTo": "til:",
+ "HeaderSelectWatchFolder": "Velg Se Mappe",
+ "HeaderSelectWatchFolderHelp": "S\u00f8k igjennom eller velg sti for din Se mappe. Mappen m\u00e5 v\u00e6re skrivbar.",
+ "OrganizePatternResult": "Resultat: {0}",
+ "HeaderRestart": "Omstart",
+ "HeaderShutdown": "Sl\u00e5 Av",
+ "MessageConfirmRestart": "Er du sikker p\u00e5 at du vil gi Media Browser Server en omstart?",
+ "MessageConfirmShutdown": "Er du sikker p\u00e5 du vil sl\u00e5 av Media Browser Server?",
+ "ButtonUpdateNow": "Oppdater N\u00e5",
+ "NewVersionOfSomethingAvailable": "En ny versjon av {0} er tilgjengelig!",
+ "VersionXIsAvailableForDownload": "Vesjon {0} er n\u00e5 tilgjengelig for nedlasting.",
+ "LabelVersionNumber": "Versjon {0}",
"LabelPlayMethodTranscoding": "Transcoding",
- "LabelPlayMethodDirectStream": "Direct Streaming",
- "LabelPlayMethodDirectPlay": "Direct Playing",
- "LabelAudioCodec": "Audio: {0}",
+ "LabelPlayMethodDirectStream": "Direkte Streaming",
+ "LabelPlayMethodDirectPlay": "Direkte Avspilling",
+ "LabelAudioCodec": "Lyd: {0}",
"LabelVideoCodec": "Video: {0}",
- "LabelRemoteAccessUrl": "Remote access: {0}",
- "LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
- "HeaderLatestFromChannel": "Latest from {0}",
- "ButtonDownload": "Download",
- "LabelUnknownLanaguage": "Unknown language",
- "HeaderCurrentSubtitles": "Current Subtitles",
- "MessageDownloadQueued": "The download has been queued.",
- "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
- "ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "LabelRemoteAccessUrl": "Ekstern tilgang: {0}",
+ "LabelRunningOnPort": "Kj\u00f8rer p\u00e5 port {0}.",
+ "HeaderLatestFromChannel": "Siste fra {0}",
+ "ButtonDownload": "Nedlasting",
+ "LabelUnknownLanaguage": "Ukjent Spr\u00e5k",
+ "HeaderCurrentSubtitles": "N\u00e5v\u00e6rende undertekster",
+ "MessageDownloadQueued": "Nedlastingen har blitt satt i k\u00f8.",
+ "MessageAreYouSureDeleteSubtitles": "Er du sikker p\u00e5 at du vil slette denne undertekst filen?",
+ "ButtonRemoteControl": "Ekstern Kontroll",
+ "HeaderLatestTvRecordings": "Siste Opptak",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "avbryt",
+ "ButtonRefresh": "Oppdater",
+ "LabelCurrentPath": "N\u00e5v\u00e6rende sti:",
+ "HeaderSelectMediaPath": "Velg Media Sti",
+ "ButtonNetwork": "Nettverk",
+ "MessageDirectoryPickerInstruction": "Nettverksti kan skrives inn manuelt i tilfelle Nettverk-knappen ikke klarer \u00e5 lokalisere enhetene dine. For eksempel {0} eller {1}.",
+ "HeaderMenu": "Meny",
+ "ButtonOpen": "\u00c5pne",
+ "ButtonOpenInNewTab": "\u00c5pne i ny fane",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Fortsett",
+ "HeaderScenes": "Scener",
+ "HeaderAudioTracks": "Lydspor",
+ "HeaderSubtitles": "Undertekster",
+ "HeaderVideoQuality": "Video Kvalitet",
+ "MessageErrorPlayingVideo": "Det oppstod en error ved avspilling av vidoen.",
+ "MessageEnsureOpenTuner": "Vennligst s\u00f8rg for at det minst er en \u00e5pen tuner tilgjengelig.",
+ "ButtonHome": "Hjem",
+ "ButtonDashboard": "Dashbord",
+ "ButtonReports": "Rapporter",
+ "ButtonMetadataManager": "Metadata Behandler",
+ "HeaderTime": "Tid",
+ "HeaderName": "Navn",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Lag Til {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Kanaler",
+ "HeaderMediaFolders": "Media Mapper",
+ "HeaderBlockItemsWithNoRating": "Blokker elementer som har ingen rangeringsinformasjon:",
+ "OptionBlockOthers": "Andre",
+ "OptionBlockTvShows": "TV Serier",
+ "OptionBlockTrailers": "Trailere",
+ "OptionBlockMusic": "Musikk",
+ "OptionBlockMovies": "Filmer",
+ "OptionBlockBooks": "B\u00f8ker",
+ "OptionBlockGames": "Spill",
+ "OptionBlockLiveTvPrograms": "Live TV Programmer",
+ "OptionBlockLiveTvChannels": "Live TV Kanaler",
+ "OptionBlockChannelContent": "Internet Kanal Innhold",
+ "ButtonRevoke": "Tilbakekall",
+ "MessageConfirmRevokeApiKey": "Er du sikker p\u00e5 at du vil ta tilbakekalle denne api n\u00f8kkelen? Applikasjonens forbindelse til Media Browser vil bli br\u00e5tt avsluttet.",
+ "HeaderConfirmRevokeApiKey": "Tilbakekall Api N\u00f8kkel",
+ "ValueContainer": "Kontainter: {0}",
+ "ValueAudioCodec": "Lyd Kodek: {0}",
+ "ValueVideoCodec": "Video Kodek: {0}",
+ "ValueCodec": "Koded: {0}",
+ "ValueConditions": "Tilstand: {0}",
+ "LabelAll": "Alle",
+ "HeaderDeleteImage": "Slett bilde",
+ "MessageFileNotFound": "Fant ikke fil.",
+ "MessageFileReadError": "En error oppstod n\u00e5r filen skulle leses",
+ "ButtonNextPage": "Neste Side",
+ "ButtonPreviousPage": "Forrige Side",
+ "ButtonMoveLeft": "Flytt til venstre",
+ "ButtonMoveRight": "Flytt til h\u00f8yre",
+ "ButtonBrowseOnlineImages": "Bla igjennom bilder online",
+ "HeaderDeleteItem": "Slett element",
+ "ConfirmDeleteItem": "Er du sikker p\u00e5 at du vil slette dette elementet fra ditt bibliotek?",
+ "MessagePleaseEnterNameOrId": "Vennligst skriv ett navn eller en ekstern id.",
+ "MessageValueNotCorrect": "Verdien som ble skrevet er ikke korrekt. Vennligst pr\u00f8v igjen.",
+ "MessageItemSaved": "Element lagret.",
+ "OptionEnded": "Avsluttet",
+ "OptionContinuing": "Fortsetter",
+ "OptionOff": "Av",
+ "OptionOn": "P\u00e5",
+ "HeaderFields": "Felt",
+ "HeaderFieldsHelp": "Skyv ett felt til \"av\" for \u00e5 l\u00e5se det og for \u00e5 unng\u00e5 at data blir forandret.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Mangler lokal trailer",
+ "MissingPrimaryImage": "Mangler primary bilde.",
+ "MissingBackdropImage": "Mangler backdrop bilde.",
+ "MissingLogoImage": "Mangler logo bilde.",
+ "MissingEpisode": "Mangler episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Bilder",
+ "OptionKeywords": "N\u00f8kkelord",
+ "OptionTags": "tags",
+ "OptionStudios": "Studioer",
+ "OptionName": "Navn",
+ "OptionOverview": "Oversikt",
+ "OptionGenres": "Sjangere",
+ "OptionParentalRating": "Foreldresensur",
+ "OptionPeople": "Person",
+ "OptionRuntime": "Spilletid",
+ "OptionProductionLocations": "Produksjonsplass",
+ "OptionBirthLocation": "F\u00f8dselsplass",
+ "LabelAllChannels": "Alle kanaler",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NY",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Endre Mappe Type",
+ "HeaderChangeFolderTypeHelp": "For \u00e5 endre mappe type, vennligst fjern og bygg samlingen med en ny type.",
+ "HeaderAlert": "Varsling",
+ "MessagePleaseRestart": "Vennligst utf\u00f8r en omstart for \u00e5 fullf\u00f8re oppdatering.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Vennligst last inn siden p\u00e5 nytt for \u00e5 motta nye oppdateringer fra serveren.",
+ "ButtonHide": "Skjul",
+ "MessageSettingsSaved": "Innstillinger lagret.",
+ "ButtonSignOut": "Logg Ut",
+ "ButtonMyProfile": "Min Profil",
+ "ButtonMyPreferences": "Mine Preferanser",
+ "MessageBrowserDoesNotSupportWebSockets": "Denne nettleseren st\u00f8tter ikke web sockets. For en bedre brukeropplevelse pr\u00f8v en nyere nettleser som eksemepel Chrome, Firefox, IE10+, Safari (IOS) eller Opera.",
+ "LabelInstallingPackage": "Installerer {0}",
+ "LabelPackageInstallCompleted": "{0} installering fullf\u00f8rt.",
+ "LabelPackageInstallFailed": "{0} installasjon feilet.",
+ "LabelPackageInstallCancelled": "{0} installasjon avbrutt.",
+ "TabServer": "Server",
+ "TabUsers": "Brukere",
+ "TabLibrary": "Bibliotek",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-organiser",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Avansert",
+ "TabHelp": "Hjelp",
+ "TabScheduledTasks": "Planlagte Oppgaver",
+ "ButtonFullscreen": "Fullskjerm",
+ "ButtonAudioTracks": "Lydspor",
+ "ButtonSubtitles": "Undertekster",
+ "ButtonScenes": "Scener",
+ "ButtonQuality": "Kvalitet",
+ "HeaderNotifications": "Melding",
+ "HeaderSelectPlayer": "Velg Spiller",
+ "ButtonSelect": "Velg",
+ "ButtonNew": "Ny",
+ "MessageInternetExplorerWebm": "For det beste resultatet med Internet Explorer anbefales det at du installerer WebM avspillings plugin.",
+ "HeaderVideoError": "Video Error",
+ "ButtonAddToPlaylist": "Legg til spilleliste",
+ "HeaderAddToPlaylist": "Legg til Spilleliste",
+ "LabelName": "Navn",
+ "ButtonSubmit": "Send",
+ "LabelSelectPlaylist": "Spilleliste",
+ "OptionNewPlaylist": "Ny spilleliste...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "Se serie opptak",
+ "ValueOriginalAirDate": "Original lanseringsdato: {0}",
+ "ButtonRemoveFromPlaylist": "Fjern fra spilleliste",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Filmer",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episoder",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Sesong nummer",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode nummer",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Filmer",
+ "TabSeries": "Serier",
+ "TabEpisodes": "Episoder",
+ "TabTrailers": "Trailere",
+ "TabGames": "Spill",
+ "TabAlbums": "Album",
+ "TabSongs": "Sanger",
+ "TabMusicVideos": "Musikk-videoer",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json
index 4e045acf3..6b722885a 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Maak wachtwoord",
- "OptionOff": "Uit",
- "OptionOn": "Aan",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Selecteer twee of meer items om te groeperen.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "Mijn Bibliotheek",
"SettingsSaved": "Instellingen opgeslagen.",
"AddUser": "Gebruiker toevoegen",
"Users": "Gebruikers",
@@ -30,9 +22,9 @@
"OptionDev": "Dev (Instabiel)",
"UninstallPluginHeader": "Plug-in de\u00efnstalleren",
"UninstallPluginConfirmation": "Weet u zeker dat u {0} wilt de\u00efnstalleren?",
- "NoPluginConfigurationMessage": "Deze plug-in heeft niets in te stellen",
- "NoPluginsInstalledMessage": "U heeft geen plug-ins ge\u00efnstalleerd",
- "BrowsePluginCatalogMessage": "Bekijk de Plug-in catalogus voor beschikbare plug-ins.",
+ "NoPluginConfigurationMessage": "Deze Plug-in heeft niets in te stellen",
+ "NoPluginsInstalledMessage": "U heeft geen Plug-in ge\u00efnstalleerd",
+ "BrowsePluginCatalogMessage": "Bekijk de Plug-in catalogus voor beschikbare Plug-ins.",
"MessageKeyEmailedTo": "Sleutel gemaild naar {0}.",
"MessageKeysLinked": "Sleutels gekoppeld.",
"HeaderConfirmation": "Bevestiging",
@@ -46,7 +38,6 @@
"LabelEpisode": "Aflevering",
"LabelSeries": "Series",
"LabelStopping": "Stoppen",
- "ButtonStop": "Stop",
"LabelCancelled": "(Geannuleerd)",
"LabelFailed": "(Mislukt)",
"LabelAbortedByServerShutdown": "(Afgebroken door afsluiten van de server)",
@@ -54,7 +45,7 @@
"HeaderDeleteTaskTrigger": "Verwijderen Taak Trigger",
"HeaderTaskTriggers": "Taak Triggers",
"MessageDeleteTaskTrigger": "Weet u zeker dat u deze taak trigger wilt verwijderen?",
- "MessageNoPluginsInstalled": "U heeft geen plug-ins ge\u00efnstalleerd.",
+ "MessageNoPluginsInstalled": "U heeft geen Plug-ins ge\u00efnstalleerd.",
"LabelVersionInstalled": "{0} ge\u00efnstalleerd",
"LabelNumberReviews": "{0} Recensies",
"LabelFree": "Gratis",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Onbekende taal",
"ButtonMute": "Dempen",
"ButtonUnmute": "Dempen opheffen",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Volgend Nummer",
"ButtonPause": "Pauze",
"ButtonPlay": "Afspelen",
"ButtonEdit": "Bewerken",
"ButtonQueue": "Wachtrij",
- "ButtonPlayTrailer": "Trailer Afspelen",
+ "ButtonPlayTrailer": "Trailer afspelen",
"ButtonPlaylist": "Afspeellijst",
+ "ButtonPreviousTrack": "Vorig Nummer",
"LabelEnabled": "Ingeschakeld",
"LabelDisabled": "Uitgeschakeld",
"ButtonMoreInformation": "Meer informatie",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Weet u zeker dat u deze tuner wilt resetten? Alle actieve spelers of opnamen zullen direct worden gestaakt.",
"ButtonCancelSeries": "Annuleren Series",
- "LabelAllChannels": "Alle kanalen",
"HeaderSeriesRecordings": "Serie Opnames",
"LabelAnytime": "Elke keer",
"StatusRecording": "Opname",
@@ -126,11 +119,12 @@
"MessagePleaseSelectTwoItems": "Selecteer ten minste twee items.",
"MessageTheFollowingItemsWillBeGrouped": "De volgende titels worden gegroepeerd in \u00e9\u00e9n item:",
"MessageConfirmItemGrouping": "Media Browser clients zullen automatisch de optimale versie afspelen op basis van het apparaat en de prestaties van het netwerk. Weet u zeker dat u wilt doorgaan?",
- "HeaderResume": "Hervatbaar",
- "HeaderMyViews": "Mijn weergaves",
- "HeaderLibraryFolders": "Mapweergave",
+ "HeaderResume": "Hervatten",
+ "HeaderMyViews": "Mijn Overzichten",
+ "HeaderLibraryFolders": "Media Mappen",
"HeaderLatestMedia": "Nieuw in bibliotheek",
- "ButtonMore": "Meer ...",
+ "ButtonMoreItems": "Meer...",
+ "ButtonMore": "Meer",
"HeaderFavoriteMovies": "Favoriete Films",
"HeaderFavoriteShows": "Favoriete Shows",
"HeaderFavoriteEpisodes": "Favoriete Afleveringen",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Selecteer Tijdelijke Transcodeer Pad",
"HeaderSelectImagesByNamePath": "Selecteer Afbeeldingen op naam Pad",
"HeaderSelectMetadataPath": "Selecteer Metadata Pad",
- "HeaderSelectServerCachePathHelp": "Bladeren of voer het pad in om te gebruiken voor server cache-bestanden. De map moet beschrijfbaar zijn. De locatie van deze map zal een directe invloed prestaties van de server hebben en zou idealiter op een solid state drive worden geplaatst.",
+ "HeaderSelectServerCachePathHelp": "Bladeren of voer het pad in om te gebruiken voor server cache-bestanden. De map moet beschrijfbaar zijn.",
"HeaderSelectTranscodingPathHelp": "Bladeren of voer het pad in om te gebruiken voor het transcoderen van tijdelijke bestanden. De map moet beschrijfbaar zijn.",
"HeaderSelectImagesByNamePathHelp": "Bladeren of voer het pad in naar uw Afbeeldingen op naam Map. De map moet beschrijfbaar zijn.",
"HeaderSelectMetadataPathHelp": "Blader of voer het pad in dat u wilt gebruiken om metadata in op te slaan. De map moet beschrijfbaar zijn.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Toegang op afstand: {0}",
"LabelRunningOnPort": "Draait op poort {0}.",
- "LabelRunningOnPorts": "Draait op poort {0} en {1}.",
"HeaderLatestFromChannel": "Laatste van {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Onbekende taal",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "De download is in de wachtrij geplaatst.",
"MessageAreYouSureDeleteSubtitles": "Weet u zeker dat u dit ondertitelbestand wilt verwijderen?",
"ButtonRemoteControl": "Beheer op afstand",
- "HeaderLatestTvRecordings": "Nieuwste opnames"
+ "HeaderLatestTvRecordings": "Nieuwste opnames",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Annuleren",
+ "ButtonRefresh": "Vernieuwen",
+ "LabelCurrentPath": "Huidige pad:",
+ "HeaderSelectMediaPath": "Selecteer Media Pad",
+ "ButtonNetwork": "Netwerk",
+ "MessageDirectoryPickerInstruction": "Netwerk paden kunnen handmatig worden ingevoerd in het geval de Netwerk knop faalt om uw apparatuur te lokaliseren . Bijvoorbeeld: {0} of {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Openen",
+ "ButtonOpenInNewTab": "Openen in nieuw tabblad",
+ "ButtonShuffle": "Willekeurig",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Hervatten",
+ "HeaderScenes": "Scenes",
+ "HeaderAudioTracks": "Audio sporen",
+ "HeaderSubtitles": "Ondertitels",
+ "HeaderVideoQuality": "Video Kwalitet",
+ "MessageErrorPlayingVideo": "Er ging iets mis bij het afspelen van de video.",
+ "MessageEnsureOpenTuner": "Wees er a.u.b. zeker van dat er een open tuner beschikbaar is.",
+ "ButtonHome": "Start",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Rapporten",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Tijd",
+ "HeaderName": "Naam",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artiest",
+ "HeaderArtist": "Artiest",
+ "LabelAddedOnDate": "Toegevoegd {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Kanalen",
+ "HeaderMediaFolders": "Media Mappen",
+ "HeaderBlockItemsWithNoRating": "Blokkeren van onderdelen zonder classificatiegegevens:",
+ "OptionBlockOthers": "Overigen",
+ "OptionBlockTvShows": "TV Series",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Muziek",
+ "OptionBlockMovies": "Films",
+ "OptionBlockBooks": "Boeken",
+ "OptionBlockGames": "Spellen",
+ "OptionBlockLiveTvPrograms": "Live TV Programma's",
+ "OptionBlockLiveTvChannels": "Live TV Kanalen",
+ "OptionBlockChannelContent": "Internet kanaal Inhoud",
+ "ButtonRevoke": "Herroepen",
+ "MessageConfirmRevokeApiKey": "Weet u zeker dat u deze api-sleutel intrekt? Verbinding van de toepassing met Media Browser zal abrupt worden be\u00ebindigd.",
+ "HeaderConfirmRevokeApiKey": "Intrekken Api Sleutel",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Voorwaarden: {0}",
+ "LabelAll": "Alles",
+ "HeaderDeleteImage": "Afbeelding verwijderen",
+ "MessageFileNotFound": "Bestand niet gevonden.",
+ "MessageFileReadError": "Er is een fout opgetreden bij het lezen van dit bestand.",
+ "ButtonNextPage": "Volgende pagina",
+ "ButtonPreviousPage": "Vorige Pagina",
+ "ButtonMoveLeft": "Verplaats naar links",
+ "ButtonMoveRight": "Verplaats naar rechts",
+ "ButtonBrowseOnlineImages": "Blader door online afbeeldingen",
+ "HeaderDeleteItem": "Item verwijderen",
+ "ConfirmDeleteItem": "Weet u zeker dat u dit item uit uw bibliotheek wilt verwijderen?",
+ "MessagePleaseEnterNameOrId": "Voer een naam of een externe Id in",
+ "MessageValueNotCorrect": "De ingevoerde waarde is niet correct. Probeer het opnieuw.",
+ "MessageItemSaved": "Item opgeslagen.",
+ "OptionEnded": "Gestopt",
+ "OptionContinuing": "Wordt vervolgd...",
+ "OptionOff": "Uit",
+ "OptionOn": "Aan",
+ "HeaderFields": "Velden",
+ "HeaderFieldsHelp": "Schuiven naar 'uit' om het te vergrendelen en om te voorkomen dat het de gegevens worden gewijzigd.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Lokale trailer ontbreekt.",
+ "MissingPrimaryImage": "Primaire afbeelding ontbreekt.",
+ "MissingBackdropImage": "Achtergrondafbeelding ontbreekt.",
+ "MissingLogoImage": "Logo ontbreekt.",
+ "MissingEpisode": "Ontbrekende aflevering.",
+ "OptionScreenshots": "Schermopnamen",
+ "OptionBackdrops": "Achtergronden",
+ "OptionImages": "Afbeeldingen",
+ "OptionKeywords": "Trefwoorden",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Naam",
+ "OptionOverview": "Overzicht",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Kijkwijzer classificatie",
+ "OptionPeople": "Personen",
+ "OptionRuntime": "Speelduur",
+ "OptionProductionLocations": "Productie Locaties",
+ "OptionBirthLocation": "Geboorte Locatie",
+ "LabelAllChannels": "Alle kanalen",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NIEUW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Verander Maptype",
+ "HeaderChangeFolderTypeHelp": "Als u het type map wilt wijzigen, verwijder het dan en maak dan een nieuwe collectie met het nieuwe type.",
+ "HeaderAlert": "Waarschuwing",
+ "MessagePleaseRestart": "Herstart om update te voltooien.",
+ "ButtonRestart": "Herstart",
+ "MessagePleaseRefreshPage": "Vernieuw deze pagina om nieuwe updates te ontvangen van de server.",
+ "ButtonHide": "Verbergen",
+ "MessageSettingsSaved": "Instellingen opgeslagen.",
+ "ButtonSignOut": "Afmelden",
+ "ButtonMyProfile": "Mijn profiel",
+ "ButtonMyPreferences": "Mijn Voorkeuren",
+ "MessageBrowserDoesNotSupportWebSockets": "Deze browser ondersteunt geen web sockets. Voor een betere ervaring, probeer een nieuwere browser zoals Chrome, Firefox, IE10 +, Safari (iOS) of Opera.",
+ "LabelInstallingPackage": "Installeren van {0}",
+ "LabelPackageInstallCompleted": "{0} installatie voltooid.",
+ "LabelPackageInstallFailed": "{0} installatie is mislukt.",
+ "LabelPackageInstallCancelled": "{0} installatie geannuleerd.",
+ "TabServer": "Server",
+ "TabUsers": "Gebruikers",
+ "TabLibrary": "Bibliotheek",
+ "TabMetadata": "Metagegevens",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Automatisch-Organiseren",
+ "TabPlugins": "Plug-ins",
+ "TabAdvanced": "Geavanceerd",
+ "TabHelp": "Hulp",
+ "TabScheduledTasks": "Geplande taken",
+ "ButtonFullscreen": "Volledig scherm",
+ "ButtonAudioTracks": "Audio sporen",
+ "ButtonSubtitles": "Ondertitels",
+ "ButtonScenes": "Scenes",
+ "ButtonQuality": "Kwaliteit",
+ "HeaderNotifications": "Meldingen",
+ "HeaderSelectPlayer": "Selecteer Speler:",
+ "ButtonSelect": "Selecteer",
+ "ButtonNew": "Nieuw",
+ "MessageInternetExplorerWebm": "Voor het beste resultaat met Internet Explorer installeert u de WebM plugin.",
+ "HeaderVideoError": "Video Fout",
+ "ButtonAddToPlaylist": "Toevoegen aan afspeellijst",
+ "HeaderAddToPlaylist": "Toevoegen aan Afspeellijst",
+ "LabelName": "Naam:",
+ "ButtonSubmit": "Uitvoeren",
+ "LabelSelectPlaylist": "Afspeellijst:",
+ "OptionNewPlaylist": "Nieuwe afspeellijst...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "Bekijk serie opnamen",
+ "ValueOriginalAirDate": "Originele uitzenddatum: {0}",
+ "ButtonRemoveFromPlaylist": "Verwijderen uit afspeellijst",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolutie",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Speelduur",
+ "HeaderCommunityRating": "Gemeenschap cijfer",
+ "HeaderParentalRating": "Kijkwijzer classificatie",
+ "HeaderReleaseDate": "Releasedatum ",
+ "HeaderDateAdded": "Datum toegevoegd",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Seizoen",
+ "HeaderSeasonNumber": "Seizoen nummer",
+ "HeaderNetwork": "Zender",
+ "HeaderYear": "Jaar",
+ "HeaderGameSystem": "Spelsysteem",
+ "HeaderPlayers": "Spelers",
+ "HeaderEmbeddedImage": "Ingesloten afbeelding",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Schijf",
+ "OptionMovies": "Films",
+ "OptionCollections": "Verzamelingen",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seizoenen",
+ "OptionEpisodes": "Afleveringen",
+ "OptionGames": "Spellen",
+ "OptionGameSystems": "Spel Systemen",
+ "OptionMusicArtists": "Muziek artiesten",
+ "OptionMusicAlbums": "Muziek albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Nummers ",
+ "OptionHomeVideos": "Home video's",
+ "OptionBooks": "Boeken",
+ "OptionAdultVideos": "Erotische video's",
+ "ButtonUp": "Omhoog",
+ "ButtonDown": "Omlaag",
+ "LabelMetadataReaders": "Metagedata lezers:",
+ "LabelMetadataReadersHelp": "Rangschik de gewenste lokale metadata bronnen in volgorde van prioriteit. Het eerst gevonden bestand zal worden gelezen.",
+ "LabelMetadataDownloaders": "Metadata Downloaders:",
+ "LabelMetadataDownloadersHelp": "Schakelen in en rangschik uw voorkeurs metadata downloader, gerangschikt in volgorde van prioriteit. Lagere prioriteit downloaders zullen alleen worden gebruikt om de ontbrekende informatie in te vullen.",
+ "LabelMetadataSavers": "Metadata Opslag:",
+ "LabelMetadataSaversHelp": "Kies de bestandsindeling om uw metadata op te slaan.",
+ "LabelImageFetchers": "Afbeeldingen Downloaders:",
+ "LabelImageFetchersHelp": "Schakelen in en rangschik uw voorkeurs Afbeeldingen downloader, gerangschikt in volgorde van prioriteit.",
+ "ButtonQueueAllFromHere": "Plaats in de wachtrij vanaf hier",
+ "ButtonPlayAllFromHere": "Speel allemaal vanaf hier",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identificeer item",
+ "PersonTypePerson": "Persoon",
+ "LabelTitleDisplayOrder": "Titel weergave volgorde:",
+ "OptionSortName": "Sorteerbaar",
+ "OptionReleaseDate": "Uitgave datum",
+ "LabelSeasonNumber": "Seizoen:",
+ "LabelDiscNumber": "Disc nummer",
+ "LabelParentNumber": "Bovenliggend nummer",
+ "LabelEpisodeNumber": "Aflevering:",
+ "LabelTrackNumber": "Tracknummer:",
+ "LabelNumber": "Nummer:",
+ "LabelReleaseDate": "Uitgave datum:",
+ "LabelEndDate": "Eind datum|",
+ "LabelYear": "Jaar:",
+ "LabelDateOfBirth": "Geboortedatum:",
+ "LabelBirthYear": "Geboorte jaar:",
+ "LabelDeathDate": "Overlijdens datum:",
+ "HeaderRemoveMediaLocation": "Verwijder media locatie",
+ "MessageConfirmRemoveMediaLocation": "Weet je zeker dat je deze locatie wilt verwijderen?",
+ "HeaderRenameMediaFolder": "Hernoem media map",
+ "LabelNewName": "Nieuwe naam:",
+ "HeaderAddMediaFolder": "Voeg media map toe",
+ "HeaderAddMediaFolderHelp": "Naam (Films, Muziek, TV etc):",
+ "HeaderRemoveMediaFolder": "Verwijder media map",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "De volgende media locaties worden uit de bibliotheek verwijderd:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Weet je zeker dat je deze media map wilt verwijderen?",
+ "ButtonRename": "Hernoem",
+ "ButtonChangeType": "Verander soort",
+ "HeaderMediaLocations": "Media Locaties",
+ "LabelFolderTypeValue": "Map type: {0}",
+ "LabelPathSubstitutionHelp": "Optioneel: Pad vervanging kan server paden naar netwerk locaties verwijzen zodat clients direct kunnen afspelen.",
+ "FolderTypeMixed": "Gemixte films en TV",
+ "FolderTypeMovies": "Films",
+ "FolderTypeMusic": "Muziek",
+ "FolderTypeAdultVideos": "Adult video's",
+ "FolderTypePhotos": "Foto's",
+ "FolderTypeMusicVideos": "Muziek video's",
+ "FolderTypeHomeVideos": "Thuis video's",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Boeken",
+ "FolderTypeTvShows": "TV programma's",
+ "TabMovies": "Films",
+ "TabSeries": "Serie",
+ "TabEpisodes": "Afleveringen",
+ "TabTrailers": "Trailers",
+ "TabGames": "Games",
+ "TabAlbums": "Albums",
+ "TabSongs": "Songs",
+ "TabMusicVideos": "Music Videos",
+ "BirthPlaceValue": "Geboorte plaats: {0})",
+ "DeathDateValue": "Overleden: {0}",
+ "BirthDateValue": "Geboren: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json
new file mode 100644
index 000000000..b9238b554
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json
@@ -0,0 +1,433 @@
+{
+ "SettingsSaved": "Ustawienia zapisane.",
+ "AddUser": "Dodaj u\u017cytkownika",
+ "Users": "U\u017cytkownicy",
+ "Delete": "Usu\u0144",
+ "Administrator": "Administrator",
+ "Password": "Has\u0142o",
+ "DeleteImage": "Usu\u0144 zdj\u0119cie",
+ "DeleteImageConfirmation": "Jeste\u015b pewien \u017ce chcesz usun\u0105\u0107 to zdj\u0119cie?",
+ "FileReadCancelled": "Odczytywanie pliku zosta\u0142o anulowane.",
+ "FileNotFound": "Plik nie znaleziony.",
+ "FileReadError": "Wyst\u0105pi\u0142 b\u0142\u0105d podczas odczytywania pliku.",
+ "DeleteUser": "Usu\u0144 u\u017cytkownika",
+ "DeleteUserConfirmation": "Jeste\u015b pewien \u017ce chcesz usun\u0105\u0107 {0}?",
+ "PasswordResetHeader": "Zresetuj has\u0142o",
+ "PasswordResetComplete": "Has\u0142o zosta\u0142o zresetowane.",
+ "PasswordResetConfirmation": "Jeste\u015b pewien \u017ce chcesz zresetowa\u0107 has\u0142o?",
+ "PasswordSaved": "Has\u0142o zapisane.",
+ "PasswordMatchError": "Has\u0142o i potwierdzenie has\u0142a musz\u0105 si\u0119 zgadza\u0107.",
+ "OptionRelease": "Oficjalne wydanie",
+ "OptionBeta": "Beta",
+ "OptionDev": "Dev (Niestabilne)",
+ "UninstallPluginHeader": "Usu\u0144 wtyczk\u0119",
+ "UninstallPluginConfirmation": "Czy na pewno chcesz usun\u0105\u0107 {0}?",
+ "NoPluginConfigurationMessage": "Ta wtyczka nie ma \u017cadnych ustawie\u0144.",
+ "NoPluginsInstalledMessage": "Nie masz \u017cadnych wtyczek zainstalowanych.",
+ "BrowsePluginCatalogMessage": "Przejrzyj nasz katalog wtyczek \u017ceby zobaczy\u0107 dost\u0119pne wtyczki.",
+ "MessageKeyEmailedTo": "Key emailed to {0}.",
+ "MessageKeysLinked": "Keys linked.",
+ "HeaderConfirmation": "Confirmation",
+ "MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
+ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
+ "HeaderSearch": "Search",
+ "LabelArtist": "Artist",
+ "LabelMovie": "Movie",
+ "LabelMusicVideo": "Music Video",
+ "LabelEpisode": "Episode",
+ "LabelSeries": "Series",
+ "LabelStopping": "Stopping",
+ "LabelCancelled": "(cancelled)",
+ "LabelFailed": "(failed)",
+ "LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
+ "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
+ "HeaderDeleteTaskTrigger": "Delete Task Trigger",
+ "HeaderTaskTriggers": "Task Triggers",
+ "MessageDeleteTaskTrigger": "Are you sure you wish to delete this task trigger?",
+ "MessageNoPluginsInstalled": "You have no plugins installed.",
+ "LabelVersionInstalled": "{0} installed",
+ "LabelNumberReviews": "{0} Reviews",
+ "LabelFree": "Free",
+ "HeaderSelectAudio": "Select Audio",
+ "HeaderSelectSubtitles": "Select Subtitles",
+ "LabelDefaultStream": "(Default)",
+ "LabelForcedStream": "(Forced)",
+ "LabelDefaultForcedStream": "(Default\/Forced)",
+ "LabelUnknownLanguage": "Unknown language",
+ "ButtonMute": "Mute",
+ "ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
+ "ButtonPause": "Pause",
+ "ButtonPlay": "Play",
+ "ButtonEdit": "Edit",
+ "ButtonQueue": "Queue",
+ "ButtonPlayTrailer": "Play trailer",
+ "ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Previous Track",
+ "LabelEnabled": "Enabled",
+ "LabelDisabled": "Disabled",
+ "ButtonMoreInformation": "More Information",
+ "LabelNoUnreadNotifications": "No unread notifications.",
+ "ButtonViewNotifications": "View notifications",
+ "ButtonMarkTheseRead": "Mark these read",
+ "ButtonClose": "Close",
+ "LabelAllPlaysSentToPlayer": "All plays will be sent to the selected player.",
+ "MessageInvalidUser": "Invalid user or password.",
+ "HeaderAllRecordings": "All Recordings",
+ "RecommendationBecauseYouLike": "Because you like {0}",
+ "RecommendationBecauseYouWatched": "Because you watched {0}",
+ "RecommendationDirectedBy": "Directed by {0}",
+ "RecommendationStarring": "Starring {0}",
+ "HeaderConfirmRecordingCancellation": "Confirm Recording Cancellation",
+ "MessageConfirmRecordingCancellation": "Are you sure you wish to cancel this recording?",
+ "MessageRecordingCancelled": "Recording cancelled.",
+ "HeaderConfirmSeriesCancellation": "Confirm Series Cancellation",
+ "MessageConfirmSeriesCancellation": "Are you sure you wish to cancel this series?",
+ "MessageSeriesCancelled": "Series cancelled.",
+ "HeaderConfirmRecordingDeletion": "Confirm Recording Deletion",
+ "MessageConfirmRecordingDeletion": "Are you sure you wish to delete this recording?",
+ "MessageRecordingDeleted": "Recording deleted.",
+ "ButonCancelRecording": "Cancel Recording",
+ "MessageRecordingSaved": "Recording saved.",
+ "OptionSunday": "Niedziela",
+ "OptionMonday": "Poniedzia\u0142ek",
+ "OptionTuesday": "Wtorek",
+ "OptionWednesday": "\u015aroda",
+ "OptionThursday": "Czwartek",
+ "OptionFriday": "Pi\u0105tek",
+ "OptionSaturday": "Sobota",
+ "HeaderConfirmDeletion": "Confirm Deletion",
+ "MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
+ "LiveTvUpdateAvailable": "(Update available)",
+ "LabelVersionUpToDate": "Up to date!",
+ "ButtonResetTuner": "Reset tuner",
+ "HeaderResetTuner": "Reset Tuner",
+ "MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
+ "ButtonCancelSeries": "Cancel Series",
+ "HeaderSeriesRecordings": "Series Recordings",
+ "LabelAnytime": "Any time",
+ "StatusRecording": "Recording",
+ "StatusWatching": "Watching",
+ "StatusRecordingProgram": "Recording {0}",
+ "StatusWatchingProgram": "Watching {0}",
+ "HeaderSplitMedia": "Split Media Apart",
+ "MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
+ "HeaderError": "Error",
+ "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": "Media Browser clients will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?",
+ "HeaderResume": "Wzn\u00f3w",
+ "HeaderMyViews": "My Views",
+ "HeaderLibraryFolders": "Media Folders",
+ "HeaderLatestMedia": "Latest Media",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
+ "HeaderFavoriteMovies": "Favorite Movies",
+ "HeaderFavoriteShows": "Favorite Shows",
+ "HeaderFavoriteEpisodes": "Favorite Episodes",
+ "HeaderFavoriteGames": "Favorite Games",
+ "HeaderRatingsDownloads": "Rating \/ Downloads",
+ "HeaderConfirmProfileDeletion": "Confirm Profile Deletion",
+ "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?",
+ "HeaderSelectServerCachePath": "Select Server Cache Path",
+ "HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
+ "HeaderSelectImagesByNamePath": "Select Images By Name Path",
+ "HeaderSelectMetadataPath": "Select Metadata Path",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
+ "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
+ "HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
+ "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
+ "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",
+ "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.",
+ "HeaderFavoriteAlbums": "Favorite Albums",
+ "HeaderLatestChannelMedia": "Latest Channel Items",
+ "ButtonOrganizeFile": "Organize File",
+ "ButtonDeleteFile": "Delete File",
+ "HeaderOrganizeFile": "Organize File",
+ "HeaderDeleteFile": "Delete File",
+ "StatusSkipped": "Skipped",
+ "StatusFailed": "Failed",
+ "StatusSuccess": "Success",
+ "MessageFileWillBeDeleted": "The following file will be deleted:",
+ "MessageSureYouWishToProceed": "Are you sure you wish to proceed?",
+ "MessageDuplicatesWillBeDeleted": "In addition the following dupliates will be deleted:",
+ "MessageFollowingFileWillBeMovedFrom": "The following file will be moved from:",
+ "MessageDestinationTo": "to:",
+ "HeaderSelectWatchFolder": "Select Watch Folder",
+ "HeaderSelectWatchFolderHelp": "Browse or enter the path to your watch folder. The folder must be writeable.",
+ "OrganizePatternResult": "Result: {0}",
+ "HeaderRestart": "Restart",
+ "HeaderShutdown": "Shutdown",
+ "MessageConfirmRestart": "Are you sure you wish to restart Media Browser Server?",
+ "MessageConfirmShutdown": "Are you sure you wish to shutdown Media Browser Server?",
+ "ButtonUpdateNow": "Update Now",
+ "NewVersionOfSomethingAvailable": "A new version of {0} is available!",
+ "VersionXIsAvailableForDownload": "Version {0} is now available for download.",
+ "LabelVersionNumber": "Version {0}",
+ "LabelPlayMethodTranscoding": "Transcoding",
+ "LabelPlayMethodDirectStream": "Direct Streaming",
+ "LabelPlayMethodDirectPlay": "Direct Playing",
+ "LabelAudioCodec": "Audio: {0}",
+ "LabelVideoCodec": "Video: {0}",
+ "LabelRemoteAccessUrl": "Remote access: {0}",
+ "LabelRunningOnPort": "Running on port {0}.",
+ "HeaderLatestFromChannel": "Latest from {0}",
+ "ButtonDownload": "Download",
+ "LabelUnknownLanaguage": "Unknown language",
+ "HeaderCurrentSubtitles": "Current Subtitles",
+ "MessageDownloadQueued": "The download has been queued.",
+ "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
+ "ButtonRemoteControl": "Remote Control",
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Anuluj",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "Scenes",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "Name",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Channels",
+ "HeaderMediaFolders": "Media Folders",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "Ended",
+ "OptionContinuing": "Continuing",
+ "OptionOff": "Off",
+ "OptionOn": "On",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Ocena rodzicielska",
+ "OptionPeople": "People",
+ "OptionRuntime": "D\u0142ugo\u015b\u0107 filmu",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Server",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Zaawansowane",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonScenes": "Scenes",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "Select",
+ "ButtonNew": "New",
+ "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:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Filmy",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Odcinki",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Season number:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Filmy",
+ "TabSeries": "Series",
+ "TabEpisodes": "Odcinki",
+ "TabTrailers": "Zwiastuny",
+ "TabGames": "Gry",
+ "TabAlbums": "Albumy",
+ "TabSongs": "Utwory",
+ "TabMusicVideos": "Teledyski",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
+} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json
index 609c8e477..db6012513 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Criar Senha",
- "OptionOff": "Off",
- "OptionOn": "On",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Por favor, selecione dois ou mais itens para agrupar.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "Minha Biblioteca",
"SettingsSaved": "Ajustes salvos.",
"AddUser": "Adicionar Usu\u00e1rio",
"Users": "Usu\u00e1rios",
@@ -14,7 +6,7 @@
"Administrator": "Administrador",
"Password": "Senha",
"DeleteImage": "Apagar Imagem",
- "DeleteImageConfirmation": "Tem certeza que deseja apagar esta imagem?",
+ "DeleteImageConfirmation": "Deseja realmente apagar esta imagem?",
"FileReadCancelled": "A leitura do arquivo foi cancelada.",
"FileNotFound": "Arquivo n\u00e3o encontrado.",
"FileReadError": "Ocorreu um erro ao ler o arquivo.",
@@ -46,14 +38,13 @@
"LabelEpisode": "Epis\u00f3dio",
"LabelSeries": "S\u00e9ries",
"LabelStopping": "Parando",
- "ButtonStop": "Parar",
"LabelCancelled": "(cancelado)",
"LabelFailed": "(falhou)",
"LabelAbortedByServerShutdown": "(Abortada pelo desligamento do servidor)",
"LabelScheduledTaskLastRan": "\u00daltima execu\u00e7\u00e3o {0}, demorando {1}.",
"HeaderDeleteTaskTrigger": "Excluir Disparador da Tarefa",
"HeaderTaskTriggers": "Disparadores de Tarefa",
- "MessageDeleteTaskTrigger": "Tem certeza que deseja excluir este disparador de tarefa?",
+ "MessageDeleteTaskTrigger": "Deseja realmente excluir este disparador de tarefa?",
"MessageNoPluginsInstalled": "Voc\u00ea n\u00e3o possui plugins instalados.",
"LabelVersionInstalled": "{0} instalado",
"LabelNumberReviews": "{0} Cr\u00edticas",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Idioma desconhecido",
"ButtonMute": "Mudo",
"ButtonUnmute": "Remover Mudo",
+ "ButtonStop": "Parar",
+ "ButtonNextTrack": "Faixa seguinte",
"ButtonPause": "Pausar",
"ButtonPlay": "Reproduzir",
"ButtonEdit": "Editar",
- "ButtonQueue": "Fila",
- "ButtonPlayTrailer": "Reproduzir Trailer",
- "ButtonPlaylist": "Lista reprodu\u00e7\u00e3o",
+ "ButtonQueue": "Adicionar \u00e0 fila",
+ "ButtonPlayTrailer": "Reproduzir trailer",
+ "ButtonPlaylist": "Lista de reprodu\u00e7\u00e3o",
+ "ButtonPreviousTrack": "Faixa anterior",
"LabelEnabled": "Ativada",
"LabelDisabled": "Desativada",
"ButtonMoreInformation": "Mais informa\u00e7\u00f5es",
@@ -87,13 +81,13 @@
"RecommendationDirectedBy": "Dirigido por {0}",
"RecommendationStarring": "Estrelando {0}",
"HeaderConfirmRecordingCancellation": "Confirmar Cancelamento da Grava\u00e7\u00e3o",
- "MessageConfirmRecordingCancellation": "Tem certeza que deseja cancelar esta grava\u00e7\u00e3o?",
+ "MessageConfirmRecordingCancellation": "Deseja realmente cancelar esta grava\u00e7\u00e3o?",
"MessageRecordingCancelled": "Grava\u00e7\u00e3o cancelada.",
"HeaderConfirmSeriesCancellation": "Confirmar Cancelamento da S\u00e9rie",
- "MessageConfirmSeriesCancellation": "Tem certeza que deseja cancelar esta s\u00e9rie?",
+ "MessageConfirmSeriesCancellation": "Deseja realmente cancelar esta s\u00e9rie?",
"MessageSeriesCancelled": "S\u00e9rie cancelada.",
"HeaderConfirmRecordingDeletion": "Confirmar Exclus\u00e3o da Grava\u00e7\u00e3o",
- "MessageConfirmRecordingDeletion": "Tem certeza que deseja excluir esta grava\u00e7\u00e3o?",
+ "MessageConfirmRecordingDeletion": "Deseja realmente excluir esta grava\u00e7\u00e3o?",
"MessageRecordingDeleted": "Grava\u00e7\u00e3o exclu\u00edda.",
"ButonCancelRecording": "Cancelar Grava\u00e7\u00e3o",
"MessageRecordingSaved": "Grava\u00e7\u00e3o salva.",
@@ -105,14 +99,13 @@
"OptionFriday": "Sexta-feira",
"OptionSaturday": "S\u00e1bado",
"HeaderConfirmDeletion": "Confirmar Exclus\u00e3o",
- "MessageConfirmPathSubstitutionDeletion": "Tem certeza que deseja excluir esta substitui\u00e7\u00e3o de caminho?",
+ "MessageConfirmPathSubstitutionDeletion": "Deseja realmente excluir esta substitui\u00e7\u00e3o de caminho?",
"LiveTvUpdateAvailable": "(Atualiza\u00e7\u00e3o dispon\u00edvel)",
"LabelVersionUpToDate": "Atualizado!",
"ButtonResetTuner": "Reiniciar sintonizador",
"HeaderResetTuner": "Reiniciar Sintonizador",
- "MessageConfirmResetTuner": "Tem certeza que deseja reiniciar este sintonizador? Qualquer reprodutor ativo ser\u00e1 abruptamente parado.",
+ "MessageConfirmResetTuner": "Deseja realmente reiniciar este sintonizador? Qualquer reprodutor ativo ser\u00e1 abruptamente parado.",
"ButtonCancelSeries": "Cancelar S\u00e9rie",
- "LabelAllChannels": "Todos os canais",
"HeaderSeriesRecordings": "Grava\u00e7\u00f5es de S\u00e9ries",
"LabelAnytime": "Qualquer hora",
"StatusRecording": "Gravando",
@@ -120,50 +113,51 @@
"StatusRecordingProgram": "Gravando {0}",
"StatusWatchingProgram": "Assistindo {0}",
"HeaderSplitMedia": "Separar M\u00eddia",
- "MessageConfirmSplitMedia": "Tem certeza que deseja dividir as fontes de m\u00eddia em itens separados?",
+ "MessageConfirmSplitMedia": "Deseja realmente dividir as fontes de m\u00eddia em itens separados?",
"HeaderError": "Erro",
"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:",
- "MessageConfirmItemGrouping": "Os clientes do Media Browser escolher\u00e3o automaticamente a vers\u00e3o ideal para reproduzir com base no performance do dispositivo e da rede. Tem certeza que deseja continuar?",
+ "MessageConfirmItemGrouping": "Os clientes do Media Browser escolher\u00e3o automaticamente a vers\u00e3o ideal para reproduzir com base no performance do dispositivo e da rede. Deseja realmente continuar?",
"HeaderResume": "Retomar",
- "HeaderMyViews": "My Views",
- "HeaderLibraryFolders": "Visualiza\u00e7\u00e3o da Pasta",
+ "HeaderMyViews": "Minhas Visualiza\u00e7\u00f5es",
+ "HeaderLibraryFolders": "Pastas de M\u00eddias",
"HeaderLatestMedia": "M\u00eddias Recentes",
- "ButtonMore": "Mais...",
+ "ButtonMoreItems": "Mais...",
+ "ButtonMore": "Mais",
"HeaderFavoriteMovies": "Filmes Favoritos",
"HeaderFavoriteShows": "S\u00e9ries Favoritas",
"HeaderFavoriteEpisodes": "Epis\u00f3dios Favoritos",
"HeaderFavoriteGames": "Jogos Favoritos",
- "HeaderRatingsDownloads": "Critica \/ Downloads",
+ "HeaderRatingsDownloads": "Avalia\u00e7\u00e3o \/ Downloads",
"HeaderConfirmProfileDeletion": "Confirmar Exclus\u00e3o do Perfil",
- "MessageConfirmProfileDeletion": "Tem certeza que deseja excluir este perfil?",
+ "MessageConfirmProfileDeletion": "Deseja realmente excluir este perfil?",
"HeaderSelectServerCachePath": "Selecione o Caminho do Cache do Servidor",
"HeaderSelectTranscodingPath": "Selecione o Caminho Tempor\u00e1rio da Transcodifica\u00e7\u00e3o",
"HeaderSelectImagesByNamePath": "Selecione o Caminho da Images By Name",
"HeaderSelectMetadataPath": "Selecione o Caminho dos Metadados",
- "HeaderSelectServerCachePathHelp": "Localize ou digite o caminho para armazenar os arquivos de cache do servidor. A pasta deve ser grav\u00e1vel. A localiza\u00e7\u00e3o desta pasta impactar\u00e1 a performance do servidor diretamente e dever\u00e1 ser colocada, preferencialmente, em um drive de estado s\u00f3lido.",
+ "HeaderSelectServerCachePathHelp": "Localize ou digite o caminho para armazenar os arquivos de cache do servidor. A pasta deve permitir grava\u00e7\u00e3o.",
"HeaderSelectTranscodingPathHelp": "Localize ou digite o caminho para usar para arquivos tempor\u00e1rios de transcodifica\u00e7\u00e3o. A pasta deve ser grav\u00e1vel.",
"HeaderSelectImagesByNamePathHelp": "Localize ou digite o caminho de sua pasta de itens por nome. A pasta deve ser grav\u00e1vel.",
"HeaderSelectMetadataPathHelp": "Localize ou digite o caminho que voc\u00ea gostaria de armazenar os metadados. A pasta deve ser grav\u00e1vel.",
"HeaderSelectChannelDownloadPath": "Selecione o Caminho para Download do Canal.",
"HeaderSelectChannelDownloadPathHelp": "Localize ou digite o caminho a ser usado para armazenamento de arquivos de cache do canal. A pasta deve permitir escrita.",
- "OptionNewCollection": "Novo...",
+ "OptionNewCollection": "Nova...",
"ButtonAdd": "Adicionar",
"ButtonRemove": "Remover",
"LabelChapterDownloaders": "Downloaders de cap\u00edtulos:",
- "LabelChapterDownloadersHelp": "Habilite e classifique seus downloaders de cap\u00edtulos preferidos em ordem de prioridade. Downloaders de menor prioridade s\u00f3 ser\u00e3o usados para preencher informa\u00e7\u00f5es faltantes.",
+ "LabelChapterDownloadersHelp": "Habilite e classifique seus downloaders de cap\u00edtulos preferidos em ordem de prioridade. Downloaders de menor prioridade s\u00f3 ser\u00e3o usados para preencher informa\u00e7\u00f5es que ainda n\u00e3o existam.",
"HeaderFavoriteAlbums": "\u00c1lbuns Favoritos",
"HeaderLatestChannelMedia": "Itens de Canais Recentes",
"ButtonOrganizeFile": "Organizar Arquivo",
"ButtonDeleteFile": "Excluir Arquivo",
"HeaderOrganizeFile": "Organizar Arquivo",
"HeaderDeleteFile": "Excluir Arquivo",
- "StatusSkipped": "Ignorado",
+ "StatusSkipped": "Ignorada",
"StatusFailed": "Com Falha",
"StatusSuccess": "Sucesso",
"MessageFileWillBeDeleted": "Ser\u00e1 exclu\u00eddo o seguinte arquivo:",
- "MessageSureYouWishToProceed": "Tem certeza de que deseja prosseguir?",
+ "MessageSureYouWishToProceed": "Deseja realmente prosseguir?",
"MessageDuplicatesWillBeDeleted": "Adicionalmente as seguintes c\u00f3pias ser\u00e3o exclu\u00eddas:",
"MessageFollowingFileWillBeMovedFrom": "Os seguintes arquivos ser\u00e3o movidos de:",
"MessageDestinationTo": "para:",
@@ -171,9 +165,9 @@
"HeaderSelectWatchFolderHelp": "Localize ou digite o caminho para a sua pasta de monitora\u00e7\u00e3o. A pasta deve permitir escrita.",
"OrganizePatternResult": "Resultado: {0}",
"HeaderRestart": "Reiniciar",
- "HeaderShutdown": "Terminar",
- "MessageConfirmRestart": "Tem certeza de que deseja reiniciar o Servidor Media Browser?",
- "MessageConfirmShutdown": "Tem certeza de que deseja terminar o Servidor Media Browser?",
+ "HeaderShutdown": "Desligar",
+ "MessageConfirmRestart": "Deseja realmente reiniciar o Servidor Media Browser?",
+ "MessageConfirmShutdown": "Deseja realmente desligar o Servidor Media Browser?",
"ButtonUpdateNow": "Atualizar Agora",
"NewVersionOfSomethingAvailable": "Est\u00e1 dispon\u00edvel uma nova vers\u00e3o de {0}!",
"VersionXIsAvailableForDownload": "A vers\u00e3o {0} est\u00e1 dispon\u00edvel para download.",
@@ -184,14 +178,256 @@
"LabelAudioCodec": "\u00c1udio: {0}",
"LabelVideoCodec": "V\u00eddeo: {0}",
"LabelRemoteAccessUrl": "Acesso Remoto: {0}",
- "LabelRunningOnPort": "Dispon\u00edvel na porta {0}.",
- "LabelRunningOnPorts": "Dispon\u00edvel nas portas {0} e {1}.",
- "HeaderLatestFromChannel": "\u00daltimo desde {0}",
+ "LabelRunningOnPort": "Executando na porta {0}.",
+ "HeaderLatestFromChannel": "Mais recentes de {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Idioma desconhecido",
"HeaderCurrentSubtitles": "Legendas Atuais",
"MessageDownloadQueued": "O download foi enfileirado.",
- "MessageAreYouSureDeleteSubtitles": "Tem certeza que deseja excluir este arquivo de legendas?",
- "ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "MessageAreYouSureDeleteSubtitles": "Deseja realmente excluir este arquivo de legendas?",
+ "ButtonRemoteControl": "Controle Remoto",
+ "HeaderLatestTvRecordings": "\u00daltimas Grava\u00e7\u00f5es",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Cancelar",
+ "ButtonRefresh": "Atualizar",
+ "LabelCurrentPath": "Caminho atual:",
+ "HeaderSelectMediaPath": "Selecionar o Caminho da M\u00eddia",
+ "ButtonNetwork": "Rede",
+ "MessageDirectoryPickerInstruction": "Os caminhos da rede podem ser digitados manualmente caso o bot\u00e3o de Rede n\u00e3o consiga localizar seus dispositivos. Por exemplo, {0} ou {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Abrir",
+ "ButtonOpenInNewTab": "Abrir em uma nova aba",
+ "ButtonShuffle": "Aleat\u00f3rio",
+ "ButtonInstantMix": "Mix inst\u00e2ntaneo",
+ "ButtonResume": "Retomar",
+ "HeaderScenes": "Cenas",
+ "HeaderAudioTracks": "Faixas de Audio",
+ "HeaderSubtitles": "Legendas",
+ "HeaderVideoQuality": "Qualidade do V\u00eddeo",
+ "MessageErrorPlayingVideo": "Houve um erro na reprodu\u00e7\u00e3o do v\u00eddeo.",
+ "MessageEnsureOpenTuner": "Por favor, cetifique-se que existe um sintonizador aberto.",
+ "ButtonHome": "In\u00edcio",
+ "ButtonDashboard": "Painel",
+ "ButtonReports": "Relat\u00f3rios",
+ "ButtonMetadataManager": "Gerenciador de Metadados",
+ "HeaderTime": "Tempo",
+ "HeaderName": "Nome",
+ "HeaderAlbum": "\u00c1lbum",
+ "HeaderAlbumArtist": "Artista do \u00c1lbum",
+ "HeaderArtist": "Artista",
+ "LabelAddedOnDate": "Adicionado {0}",
+ "ButtonStart": "Iniciar",
+ "HeaderChannels": "Canais",
+ "HeaderMediaFolders": "Pastas de M\u00eddia",
+ "HeaderBlockItemsWithNoRating": "Bloquear itens sem informa\u00e7\u00e3o de classifica\u00e7\u00e3o:",
+ "OptionBlockOthers": "Outros",
+ "OptionBlockTvShows": "S\u00e9ries de TV",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "M\u00fasica",
+ "OptionBlockMovies": "Filmes",
+ "OptionBlockBooks": "Livros",
+ "OptionBlockGames": "Jogos",
+ "OptionBlockLiveTvPrograms": "Programas de TV ao vivo",
+ "OptionBlockLiveTvChannels": "Canais de TV ao vivo",
+ "OptionBlockChannelContent": "Conte\u00fado do Canal de Internet",
+ "ButtonRevoke": "Revogar",
+ "MessageConfirmRevokeApiKey": "Deseja realmente revogar esta chave da api? A conex\u00e3o da aplica\u00e7\u00e3o com o Media Browser ser\u00e1 abruptamente encerrada.",
+ "HeaderConfirmRevokeApiKey": "Revogar Chave da Api",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Codec de \u00c1udio: {0}",
+ "ValueVideoCodec": "Codec de V\u00eddeo: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Condi\u00e7\u00f5es: {0}",
+ "LabelAll": "Todos",
+ "HeaderDeleteImage": "Apagar Imagem",
+ "MessageFileNotFound": "Arquivo n\u00e3o encontrado.",
+ "MessageFileReadError": "Ocorreu um erro ao ler este arquivo.",
+ "ButtonNextPage": "Pr\u00f3xima P\u00e1gina",
+ "ButtonPreviousPage": "P\u00e1gina Anterior",
+ "ButtonMoveLeft": "Mover \u00e0 esquerda",
+ "ButtonMoveRight": "Mover \u00e0 direita",
+ "ButtonBrowseOnlineImages": "Procurar imagens online",
+ "HeaderDeleteItem": "Apagar item",
+ "ConfirmDeleteItem": "Deseja realmente apagar este item de sua biblioteca?",
+ "MessagePleaseEnterNameOrId": "Por favor, digite um nome ou Id externo.",
+ "MessageValueNotCorrect": "O valor digitado n\u00e3o est\u00e1 correto. Por favor, tente novamente.",
+ "MessageItemSaved": "Item salvo.",
+ "OptionEnded": "Finalizada",
+ "OptionContinuing": "Em Exibi\u00e7\u00e3o",
+ "OptionOff": "Off",
+ "OptionOn": "On",
+ "HeaderFields": "Campos",
+ "HeaderFieldsHelp": "Deslize um campo para 'off' para bloquear e evitar que seus dados sejam alterados.",
+ "HeaderLiveTV": "TV ao Vivo",
+ "MissingLocalTrailer": "Faltando trailer local.",
+ "MissingPrimaryImage": "Faltando imagem prim\u00e1ria.",
+ "MissingBackdropImage": "Faltando imagem de fundo.",
+ "MissingLogoImage": "Faltando imagem do logo.",
+ "MissingEpisode": "Faltando epis\u00f3dio.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Imagens de Fundo",
+ "OptionImages": "Imagens",
+ "OptionKeywords": "Palavras-chave",
+ "OptionTags": "Tags",
+ "OptionStudios": "Est\u00fadios",
+ "OptionName": "Nome",
+ "OptionOverview": "Descri\u00e7\u00e3o",
+ "OptionGenres": "G\u00eaneros",
+ "OptionParentalRating": "Classifica\u00e7\u00e3o Parental",
+ "OptionPeople": "Pessoas",
+ "OptionRuntime": "Dura\u00e7\u00e3o",
+ "OptionProductionLocations": "Locais de Produ\u00e7\u00e3o",
+ "OptionBirthLocation": "Local de Nascimento",
+ "LabelAllChannels": "Todos os canais",
+ "LabelLiveProgram": "AO VIVO",
+ "LabelNewProgram": "NOVO",
+ "LabelPremiereProgram": "ESTR\u00c9IA",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Alterar Tipo de Pasta",
+ "HeaderChangeFolderTypeHelp": "Para alterar o tipo de pasta, por favor remova e reconstrua a cole\u00e7\u00e3o com o novo tipo.",
+ "HeaderAlert": "Alerta",
+ "MessagePleaseRestart": "Por favor, reinicie para finalizar a atualiza\u00e7\u00e3o.",
+ "ButtonRestart": "Reiniciar",
+ "MessagePleaseRefreshPage": "Por favor, atualize esta p\u00e1gina para receber novas atualiza\u00e7\u00f5es do servidor.",
+ "ButtonHide": "Ocultar",
+ "MessageSettingsSaved": "Ajustes salvos.",
+ "ButtonSignOut": "Sair",
+ "ButtonMyProfile": "Meu Perfil",
+ "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.",
+ "LabelPackageInstallFailed": "Instala\u00e7\u00e3o de {0} falhou.",
+ "LabelPackageInstallCancelled": "Instala\u00e7\u00e3o de {0} cancelada.",
+ "TabServer": "Servidor",
+ "TabUsers": "Usu\u00e1rios",
+ "TabLibrary": "Biblioteca",
+ "TabMetadata": "Metadados",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "TV ao Vivo",
+ "TabAutoOrganize": "Auto-Organizar",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Avan\u00e7ado",
+ "TabHelp": "Ajuda",
+ "TabScheduledTasks": "Tarefas Agendadas",
+ "ButtonFullscreen": "Tela Cheia",
+ "ButtonAudioTracks": "Faixas de \u00c1udio",
+ "ButtonSubtitles": "Legendas",
+ "ButtonScenes": "Cenas",
+ "ButtonQuality": "Qualidade",
+ "HeaderNotifications": "Avisos",
+ "HeaderSelectPlayer": "Selecione onde reproduzir:",
+ "ButtonSelect": "Selecionar",
+ "ButtonNew": "Nova",
+ "MessageInternetExplorerWebm": "Para melhores resultados com o Internet Explorer, por favor instale o plugin de reprodu\u00e7\u00e3o WebM.",
+ "HeaderVideoError": "Erro de V\u00eddeo",
+ "ButtonAddToPlaylist": "Adicionar \u00e0 lista de reprodu\u00e7\u00e3o",
+ "HeaderAddToPlaylist": "Adicionar \u00e0 Lista de Reprodu\u00e7\u00e3o",
+ "LabelName": "Nome:",
+ "ButtonSubmit": "Enviar",
+ "LabelSelectPlaylist": "Lista de Reprodu\u00e7\u00e3o:",
+ "OptionNewPlaylist": "Nova lista de reprodu\u00e7\u00e3o",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "Visualizar grava\u00e7\u00e3o de s\u00e9ries",
+ "ValueOriginalAirDate": "Data original de exibi\u00e7\u00e3o: {0}",
+ "ButtonRemoveFromPlaylist": "Remover da lista de reprodu\u00e7\u00e3o",
+ "HeaderSpecials": "Especiais",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "\u00c1udio",
+ "HeaderResolution": "Resolu\u00e7\u00e3o",
+ "HeaderVideo": "V\u00eddeo",
+ "HeaderRuntime": "Dura\u00e7\u00e3o",
+ "HeaderCommunityRating": "Avalia\u00e7\u00e3o da Comunidade",
+ "HeaderParentalRating": "Classifica\u00e7\u00e3o parental",
+ "HeaderReleaseDate": "Data de lan\u00e7amento",
+ "HeaderDateAdded": "Data de adi\u00e7\u00e3o",
+ "HeaderSeries": "S\u00e9rie",
+ "HeaderSeason": "Temporada",
+ "HeaderSeasonNumber": "N\u00famero da temporada",
+ "HeaderNetwork": "Rede de TV",
+ "HeaderYear": "Ano",
+ "HeaderGameSystem": "Sistema do jogo",
+ "HeaderPlayers": "Jogadores",
+ "HeaderEmbeddedImage": "Imagem incorporada",
+ "HeaderTrack": "Faixa",
+ "HeaderDisc": "Disco",
+ "OptionMovies": "Filmes",
+ "OptionCollections": "Cole\u00e7\u00f5es",
+ "OptionSeries": "S\u00e9ries",
+ "OptionSeasons": "Temporadas",
+ "OptionEpisodes": "Epis\u00f3dios",
+ "OptionGames": "Jogos",
+ "OptionGameSystems": "Sistemas de jogos",
+ "OptionMusicArtists": "Artistas da M\u00fasica",
+ "OptionMusicAlbums": "\u00c1lbuns de m\u00fasica",
+ "OptionMusicVideos": "V\u00eddeos Musicais",
+ "OptionSongs": "M\u00fasicas",
+ "OptionHomeVideos": "V\u00eddeos caseiros",
+ "OptionBooks": "Livros",
+ "OptionAdultVideos": "V\u00eddeos adultos",
+ "ButtonUp": "Para cima",
+ "ButtonDown": "Para baixo",
+ "LabelMetadataReaders": "Leitores de metadados:",
+ "LabelMetadataReadersHelp": "Classifique por ordem de prioridade suas fontes de metadados locais preferidas. O primeiro arquivo encontrado ser\u00e1 lido.",
+ "LabelMetadataDownloaders": "Downloaders de metadados:",
+ "LabelMetadataDownloadersHelp": "Ative e classifique por ordem de prioridade seus downloaders de metadados preferidos. Downloaders com prioridade mais baixa s\u00f3 ser\u00e3o usados para baixar informa\u00e7\u00f5es que ainda n\u00e3o existam.",
+ "LabelMetadataSavers": "Gravadores de metadados:",
+ "LabelMetadataSaversHelp": "Escolha os formatos de arquivos nos quais deseja gravar seus metadados.",
+ "LabelImageFetchers": "Buscadores de imagem:",
+ "LabelImageFetchersHelp": "Ative e classifique por ordem de prioridade seus buscadores de imagem preferidos.",
+ "ButtonQueueAllFromHere": "Enfileirar todas a partir daqui",
+ "ButtonPlayAllFromHere": "Reproduzir todas a partir daqui",
+ "LabelDynamicExternalId": "Id de {0}:",
+ "HeaderIdentify": "Identificar Item",
+ "PersonTypePerson": "Pessoa",
+ "LabelTitleDisplayOrder": "Ordem de exibi\u00e7\u00e3o do t\u00edtulo: ",
+ "OptionSortName": "Nome para ordena\u00e7\u00e3o",
+ "OptionReleaseDate": "Data de lan\u00e7amento",
+ "LabelSeasonNumber": "N\u00famero da temporada:",
+ "LabelDiscNumber": "N\u00famero do disco",
+ "LabelParentNumber": "N\u00famero do superior",
+ "LabelEpisodeNumber": "N\u00famero do epis\u00f3dio:",
+ "LabelTrackNumber": "N\u00famero da faixa:",
+ "LabelNumber": "N\u00famero:",
+ "LabelReleaseDate": "Data do lan\u00e7amento:",
+ "LabelEndDate": "Data final:",
+ "LabelYear": "Ano:",
+ "LabelDateOfBirth": "Data de nascimento:",
+ "LabelBirthYear": "Ano de nascimento:",
+ "LabelDeathDate": "Data da morte:",
+ "HeaderRemoveMediaLocation": "Remover Localiza\u00e7\u00e3o da M\u00eddia",
+ "MessageConfirmRemoveMediaLocation": "Deseja realmente remover esta localiza\u00e7\u00e3o?",
+ "HeaderRenameMediaFolder": "Renomear Pasta de M\u00eddia",
+ "LabelNewName": "Novo nome:",
+ "HeaderAddMediaFolder": "Adicionar Pasta de M\u00eddia",
+ "HeaderAddMediaFolderHelp": "Nome (Filmes, M\u00fasica, TV, etc):",
+ "HeaderRemoveMediaFolder": "Excluir Pasta de M\u00eddia",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "As localiza\u00e7\u00f5es de m\u00eddia abaixo ser\u00e3o exclu\u00eddas de sua biblioteca:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Deseja realmente excluir esta pasta de m\u00eddia?",
+ "ButtonRename": "Renomear",
+ "ButtonChangeType": "Alterar tipo",
+ "HeaderMediaLocations": "Localiza\u00e7\u00f5es de M\u00eddia",
+ "LabelFolderTypeValue": "Tipo de pasta: {0}",
+ "LabelPathSubstitutionHelp": "Opcional: Substitui\u00e7\u00e3o de caminho pode mapear caminhos do servidor para compartilhamentos de rede de forma a que os clientes possam acessar para reprodu\u00e7\u00e3o direta.",
+ "FolderTypeMixed": "Filmes & tv misturados",
+ "FolderTypeMovies": "Filmes",
+ "FolderTypeMusic": "M\u00fasica",
+ "FolderTypeAdultVideos": "V\u00eddeos adultos",
+ "FolderTypePhotos": "Fotos",
+ "FolderTypeMusicVideos": "V\u00eddeos musicais",
+ "FolderTypeHomeVideos": "V\u00eddeos caseiros",
+ "FolderTypeGames": "Jogos",
+ "FolderTypeBooks": "Livros",
+ "FolderTypeTvShows": "S\u00e9ries de TV",
+ "TabMovies": "Filmes",
+ "TabSeries": "S\u00e9ries",
+ "TabEpisodes": "Epis\u00f3dios",
+ "TabTrailers": "Trailers",
+ "TabGames": "Jogos",
+ "TabAlbums": "\u00c1lbuns",
+ "TabSongs": "M\u00fasicas",
+ "TabMusicVideos": "V\u00eddeos Musicais",
+ "BirthPlaceValue": "Local de nascimento: {0}",
+ "DeathDateValue": "Morte: {0}",
+ "BirthDateValue": "Nascimento: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json
index 89d5c217b..6f3146bfd 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Criar Senha",
- "OptionOff": "Desligado",
- "OptionOn": "Ligado",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "My Library",
"SettingsSaved": "Configura\u00e7\u00f5es guardadas.",
"AddUser": "Adicionar Utilizador",
"Users": "Utilizadores",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episode",
"LabelSeries": "Series",
"LabelStopping": "Stopping",
- "ButtonStop": "Parar",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Unknown language",
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
+ "ButtonStop": "Parar",
+ "ButtonNextTrack": "Pr\u00f3xima Faixa",
"ButtonPause": "Pausar",
"ButtonPlay": "Reproduzir",
"ButtonEdit": "Editar",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
+ "ButtonPlayTrailer": "Play trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Faixa Anterior",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
"ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
"HeaderSeriesRecordings": "Series Recordings",
"LabelAnytime": "Any time",
"StatusRecording": "Recording",
@@ -130,7 +123,8 @@
"HeaderMyViews": "My Views",
"HeaderLibraryFolders": "Media Folders",
"HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
"HeaderFavoriteMovies": "Favorite Movies",
"HeaderFavoriteShows": "Favorite Shows",
"HeaderFavoriteEpisodes": "Favorite Episodes",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
"HeaderSelectImagesByNamePath": "Select Images By Name Path",
"HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
"HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Remote access: {0}",
"LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
"HeaderLatestFromChannel": "Latest from {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Unknown language",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Cancelar",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "Cenas",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "In\u00edcio",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "Nome",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Canais",
+ "HeaderMediaFolders": "Pastas Multim\u00e9dia",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "Terminado",
+ "OptionContinuing": "A Continuar",
+ "OptionOff": "Desligado",
+ "OptionOn": "Ligado",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Classifica\u00e7\u00e3o Parental",
+ "OptionPeople": "People",
+ "OptionRuntime": "Dura\u00e7\u00e3o",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Reiniciar",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Servidor",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadados",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Avan\u00e7ado",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Legendas",
+ "ButtonScenes": "Cenas",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifica\u00e7\u00f5es",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "Selecionar",
+ "ButtonNew": "Novo",
+ "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": "Nome:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Filmes",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Epis\u00f3dios",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "N\u00famero da temporada",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "N\u00famero do epis\u00f3dio",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Filmes",
+ "TabSeries": "S\u00e9ries",
+ "TabEpisodes": "Epis\u00f3dios",
+ "TabTrailers": "Trailers",
+ "TabGames": "Jogos",
+ "TabAlbums": "\u00c1lbuns",
+ "TabSongs": "M\u00fasicas",
+ "TabMusicVideos": "Videos Musicais",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json
index e64ac3606..b00872075 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json
@@ -1,13 +1,5 @@
{
- "CreatePassword": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c",
- "OptionOff": "\u0412\u044b\u043a\u043b",
- "OptionOn": "\u0412\u043a\u043b",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\u0432\u0430 \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432\u043c\u0435\u0441\u0442\u0435.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "\u041c\u043e\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430",
- "SettingsSaved": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0431\u044b\u043b\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b.",
+ "SettingsSaved": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b.",
"AddUser": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f",
"Users": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438",
"Delete": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c",
@@ -32,12 +24,12 @@
"UninstallPluginConfirmation": "\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 {0}?",
"NoPluginConfigurationMessage": "\u041d\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430.",
"NoPluginsInstalledMessage": "\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430.",
- "BrowsePluginCatalogMessage": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433, \u0447\u0442\u043e\u0431\u044b \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c\u0438.",
- "MessageKeyEmailedTo": "\u041a\u043b\u044e\u0447 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u043e\u044e \u0434\u043b\u044f {0}.",
+ "BrowsePluginCatalogMessage": "\u041f\u0440\u043e\u043b\u0438\u0441\u0442\u0430\u0439\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c\u0438.",
+ "MessageKeyEmailedTo": "\u041a\u043b\u044e\u0447 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u042d-\u043f\u043e\u0447\u0442\u043e\u044e \u0434\u043b\u044f {0}.",
"MessageKeysLinked": "\u041a\u043b\u044e\u0447\u0438 \u0431\u044b\u043b\u0438 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u044b.",
"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\u0431\u0440\u0430\u043d.",
+ "MessageKeyRemoved": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u0431\u044b\u043b \u0443\u0434\u0430\u043b\u0451\u043d.",
"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.",
"HeaderSearch": "\u041f\u043e\u0438\u0441\u043a",
"LabelArtist": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c",
@@ -46,7 +38,6 @@
"LabelEpisode": "\u042d\u043f\u0438\u0437\u043e\u0434",
"LabelSeries": "\u0421\u0435\u0440\u0438\u0430\u043b",
"LabelStopping": "\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e",
- "ButtonStop": "\u0421\u0442\u043e\u043f",
"LabelCancelled": "(\u043e\u0442\u043c\u0435\u043d\u0435\u043d\u043e)",
"LabelFailed": "(\u043d\u0435\u0443\u0434\u0430\u0447\u043d\u043e)",
"LabelAbortedByServerShutdown": "(\u041f\u0440\u0435\u0440\u0432\u0430\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430)",
@@ -55,43 +46,46 @@
"HeaderTaskTriggers": "\u0422\u0440\u0438\u0433\u0433\u0435\u0440\u044b \u0437\u0430\u0434\u0430\u043d\u0438\u044f",
"MessageDeleteTaskTrigger": "\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\u044b\u0439 \u0442\u0440\u0438\u0433\u0433\u0435\u0440 \u0437\u0430\u0434\u0430\u043d\u0438\u044f?",
"MessageNoPluginsInstalled": "\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430.",
- "LabelVersionInstalled": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f: {0}",
- "LabelNumberReviews": "\u041e\u0442\u0437\u044b\u0432\u043e\u0432: {0}",
- "LabelFree": "\u0411\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e",
+ "LabelVersionInstalled": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430: {0}",
+ "LabelNumberReviews": "\u041e\u0442\u0437\u044b\u0432\u044b: {0}",
+ "LabelFree": "\u0411\u0435\u0441\u043f\u043b.",
"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",
- "LabelDefaultStream": "(\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e)",
+ "LabelDefaultStream": "(\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435)",
"LabelForcedStream": "(\u0424\u043e\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435))",
- "LabelDefaultForcedStream": "(\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e\/\u0424\u043e\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435)",
+ "LabelDefaultForcedStream": "(\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435\/\u0424\u043e\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435)",
"LabelUnknownLanguage": "\u041d\u0435\u043e\u043f\u043e\u0437\u043d\u0430\u043d\u043d\u044b\u0439 \u044f\u0437\u044b\u043a",
"ButtonMute": "\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u0432\u0443\u043a",
"ButtonUnmute": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u0432\u0443\u043a",
+ "ButtonStop": "\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c",
+ "ButtonNextTrack": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430",
"ButtonPause": "\u041f\u0430\u0443\u0437\u0430",
- "ButtonPlay": "\u0412\u043e\u0441\u043f\u0440",
+ "ButtonPlay": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438",
"ButtonEdit": "\u041f\u0440\u0430\u0432\u0438\u0442\u044c",
"ButtonQueue": "\u041e\u0447\u0435\u0440\u0435\u0434\u044c",
"ButtonPlayTrailer": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0442\u0440\u0435\u0439\u043b\u0435\u0440",
"ButtonPlaylist": "\u0421\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
+ "ButtonPreviousTrack": "\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430",
"LabelEnabled": "\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u043e",
"LabelDisabled": "\u0412\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043e",
- "ButtonMoreInformation": "\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
+ "ButtonMoreInformation": "\u0415\u0449\u0451 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
"LabelNoUnreadNotifications": "\u041d\u0435\u0442 \u043d\u0435\u043f\u0440\u043e\u0447\u0442\u0451\u043d\u043d\u044b\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.",
"ButtonViewNotifications": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f",
"ButtonMarkTheseRead": "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0430\u043a \u043f\u0440\u043e\u0447\u0442\u0451\u043d\u043d\u044b\u0435",
"ButtonClose": "\u0417\u0430\u043a\u0440\u044b\u0442\u044c",
- "LabelAllPlaysSentToPlayer": "\u0412\u0441\u0451 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e \u043d\u0430 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043b\u0435\u0439\u0435\u0440",
+ "LabelAllPlaysSentToPlayer": "\u0412\u0441\u0451 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043f\u043b\u0435\u0439\u0435\u0440",
"MessageInvalidUser": "\u041d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c.",
"HeaderAllRecordings": "\u0412\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438",
- "RecommendationBecauseYouLike": "\u0422\u0430\u043a \u043a\u0430\u043a \u0432\u0430\u043c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f {0}",
- "RecommendationBecauseYouWatched": "\u0422\u0430\u043a \u043a\u0430\u043a \u0432\u044b \u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 {0}",
+ "RecommendationBecauseYouLike": "\u0418\u0431\u043e \u0432\u0430\u043c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u00ab{0}\u00bb",
+ "RecommendationBecauseYouWatched": "\u0418\u0431\u043e \u0432\u044b \u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u00ab{0}\u00bb",
"RecommendationDirectedBy": "\u041f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0449\u0438\u043a {0}",
"RecommendationStarring": "\u0412 \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0440\u043e\u043b\u0438 {0}",
"HeaderConfirmRecordingCancellation": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043e\u0442\u043c\u0435\u043d\u044b \u0437\u0430\u043f\u0438\u0441\u0438",
"MessageConfirmRecordingCancellation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c?",
"MessageRecordingCancelled": "\u0417\u0430\u043f\u0438\u0441\u044c \u0431\u044b\u043b\u0430 \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u0430.",
"HeaderConfirmSeriesCancellation": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043e\u0442\u043c\u0435\u043d\u044b \u0441\u0435\u0440\u0438\u0438",
- "MessageConfirmSeriesCancellation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0435\u0440\u0438\u044e?",
- "MessageSeriesCancelled": "\u0421\u0435\u0440\u0438\u044f \u0431\u044b\u043b\u0430 \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u0430.",
+ "MessageConfirmSeriesCancellation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0438\u0430\u043b?",
+ "MessageSeriesCancelled": "\u0421\u0435\u0440\u0438\u0430\u043b \u0431\u044b\u043b \u043e\u0442\u043c\u0435\u043d\u0451\u043d.",
"HeaderConfirmRecordingDeletion": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438",
"MessageConfirmRecordingDeletion": "\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 \u0437\u0430\u043f\u0438\u0441\u044c?",
"MessageRecordingDeleted": "\u0417\u0430\u043f\u0438\u0441\u044c \u0431\u044b\u043b\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0430.",
@@ -111,28 +105,28 @@
"ButtonResetTuner": "\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0442\u044e\u043d\u0435\u0440",
"HeaderResetTuner": "\u0421\u0431\u0440\u043e\u0441 \u0442\u044e\u043d\u0435\u0440\u0430",
"MessageConfirmResetTuner": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0442\u044e\u043d\u0435\u0440? \u041b\u044e\u0431\u044b\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u043f\u043b\u0435\u0439\u0435\u0440\u044b \u0438\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u0431\u0443\u0434\u0443\u0442 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b.",
- "ButtonCancelSeries": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0435\u0440\u0438\u044e",
- "LabelAllChannels": "\u0412\u0441\u0435 \u043a\u0430\u043d\u0430\u043b\u044b",
- "HeaderSeriesRecordings": "\u0417\u0430\u043f\u0438\u0441\u0438 \u0441\u0435\u0440\u0438\u0439",
+ "ButtonCancelSeries": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0435\u0440\u0438\u0430\u043b",
+ "HeaderSeriesRecordings": "\u0417\u0430\u043f\u0438\u0441\u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u043e\u0432",
"LabelAnytime": "\u041b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f",
- "StatusRecording": "\u0417\u0430\u043f\u0438\u0441\u044c",
- "StatusWatching": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440",
+ "StatusRecording": "\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f",
+ "StatusWatching": "\u041f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u0442\u0441\u044f",
"StatusRecordingProgram": "\u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f {0}",
"StatusWatchingProgram": "\u041f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u0442\u0441\u044f {0}",
- "HeaderSplitMedia": "\u0420\u0430\u0437\u0431\u0438\u0442\u044c \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u0438 \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438",
- "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 \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b?",
+ "HeaderSplitMedia": "\u0420\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438",
+ "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\u0434\u0435\u043b\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",
"MessagePleaseSelectOneItem": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435, \u043e\u0434\u0438\u043d \u044d\u043b\u0435\u043c\u0435\u043d\u0442.",
"MessagePleaseSelectTwoItems": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435, \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 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f :",
- "MessageConfirmItemGrouping": "\u041a\u043b\u0438\u0435\u043d\u0442\u044b Media Browser \u0431\u0443\u0434\u0443\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 \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?",
+ "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": "\u041a\u043b\u0438\u0435\u043d\u0442\u044b Media Browser \u0431\u0443\u0434\u0443\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \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",
- "HeaderMyViews": "\u041c\u043e\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f",
+ "HeaderMyViews": "\u041c\u043e\u0438 \u0430\u0441\u043f\u0435\u043a\u0442\u044b",
"HeaderLibraryFolders": "\u041c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438",
- "HeaderLatestMedia": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043c\u0435\u0434\u0438\u0430\u0444\u0430\u0439\u043b\u043e\u0432",
- "ButtonMore": "\u0411\u043e\u043b\u0435\u0435...",
+ "HeaderLatestMedia": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
+ "ButtonMoreItems": "\u0415\u0449\u0451...",
+ "ButtonMore": "\u0415\u0449\u0451",
"HeaderFavoriteMovies": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0444\u0438\u043b\u044c\u043c\u044b",
- "HeaderFavoriteShows": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0441\u0435\u0440\u0438\u0430\u043b\u044b",
+ "HeaderFavoriteShows": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0446\u0438\u043a\u043b\u044b",
"HeaderFavoriteEpisodes": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b",
"HeaderFavoriteGames": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0438\u0433\u0440\u044b",
"HeaderRatingsDownloads": "\u041e\u0446\u0435\u043d\u043a\u0430 \/ \u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0438",
@@ -142,17 +136,17 @@
"HeaderSelectTranscodingPath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u0434\u043b\u044f \u043f\u0430\u043f\u043a\u0438 Transcoding Temporary",
"HeaderSelectImagesByNamePath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u0434\u043b\u044f \u043f\u0430\u043f\u043a\u0438 Images By Name",
"HeaderSelectMetadataPath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u0434\u043b\u044f \u043f\u0430\u043f\u043a\u0438 Metadata",
- "HeaderSelectServerCachePathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 server cache. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438. \u0420\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0438 \u043f\u0440\u044f\u043c\u043e \u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u0432 \u0438\u0434\u0435\u0430\u043b\u0435 \u043e\u043d\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f \u043d\u0430 SSD.",
- "HeaderSelectTranscodingPathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 transcoding temporary. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.",
- "HeaderSelectImagesByNamePathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 items by name. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.",
- "HeaderSelectMetadataPathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c, \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0444\u0430\u0439\u043b\u044b metadata. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.",
+ "HeaderSelectServerCachePathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 server cache. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.",
+ "HeaderSelectTranscodingPathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 transcoding temporary. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.",
+ "HeaderSelectImagesByNamePathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 items by name. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.",
+ "HeaderSelectMetadataPathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u0430\u0439\u043b\u043e\u0432 metadata. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.",
"HeaderSelectChannelDownloadPath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u043e\u0432",
- "HeaderSelectChannelDownloadPathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u043a\u0435\u0448\u0430 \u043a\u0430\u043d\u0430\u043b\u043e\u0432. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.",
+ "HeaderSelectChannelDownloadPathHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u043a\u0435\u0448\u0430 \u043a\u0430\u043d\u0430\u043b\u043e\u0432. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.",
"OptionNewCollection": "\u041d\u043e\u0432\u0430\u044f...",
"ButtonAdd": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c",
- "ButtonRemove": "\u0423\u0431\u0440\u0430\u0442\u044c",
+ "ButtonRemove": "\u0418\u0437\u044a\u044f\u0442\u044c",
"LabelChapterDownloaders": "\u0417\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0438 \u0441\u0446\u0435\u043d:",
- "LabelChapterDownloadersHelp": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0438 \u0440\u0430\u043d\u0436\u0438\u0440\u0443\u0439\u0442\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0438 \u0441\u0446\u0435\u043d \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430. \u0417\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0438 \u043d\u0438\u0437\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u0439.",
+ "LabelChapterDownloadersHelp": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0438 \u0440\u0430\u043d\u0436\u0438\u0440\u0443\u0439\u0442\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0438 \u0441\u0446\u0435\u043d \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430. \u0417\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0438 \u043d\u0438\u0437\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u044e\u0449\u0435\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438.",
"HeaderFavoriteAlbums": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0430\u043b\u044c\u0431\u043e\u043c\u044b",
"HeaderLatestChannelMedia": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u043e\u0432",
"ButtonOrganizeFile": "\u0420\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b",
@@ -168,30 +162,272 @@
"MessageFollowingFileWillBeMovedFrom": "\u0411\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0451\u043d \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0444\u0430\u0439\u043b \u0438\u0437:",
"MessageDestinationTo": "\u0432:",
"HeaderSelectWatchFolder": "\u0412\u044b\u0431\u043e\u0440 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u0439 \u043f\u0430\u043f\u043a\u0438",
- "HeaderSelectWatchFolderHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c \u043a \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u0439 \u043f\u0430\u043f\u043a\u0435. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.",
+ "HeaderSelectWatchFolderHelp": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 \u0438\u043b\u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f. \u041f\u0430\u043f\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438.",
"OrganizePatternResult": "\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442: {0}",
"HeaderRestart": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a",
"HeaderShutdown": "\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u044b",
"MessageConfirmRestart": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Media Browser Server?",
"MessageConfirmShutdown": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 Media Browser Server?",
- "ButtonUpdateNow": "\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441",
+ "ButtonUpdateNow": "\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e",
"NewVersionOfSomethingAvailable": "\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f {0}!",
"VersionXIsAvailableForDownload": "\u0412\u0435\u0440\u0441\u0438\u044f {0} \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438.",
"LabelVersionNumber": "\u0412\u0435\u0440\u0441\u0438\u044f {0}",
"LabelPlayMethodTranscoding": "\u041f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430",
- "LabelPlayMethodDirectStream": "\u041f\u0440\u044f\u043c\u043e\u0439 \u043f\u043e\u0442\u043e\u043a",
+ "LabelPlayMethodDirectStream": "\u041f\u0440\u044f\u043c\u0430\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0430\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430",
"LabelPlayMethodDirectPlay": "\u041f\u0440\u044f\u043c\u043e\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435",
"LabelAudioCodec": "\u0410\u0443\u0434\u0438\u043e: {0}",
"LabelVideoCodec": "\u0412\u0438\u0434\u0435\u043e: {0}",
- "LabelRemoteAccessUrl": "\u0423\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f: {0}",
+ "LabelRemoteAccessUrl": "\u0412\u043d\u0435\u0448\u043d\u0438\u0439 \u0434\u043e\u0441\u0442\u0443\u043f: {0}",
"LabelRunningOnPort": "\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043f\u043e\u0440\u0442\u0443 {0}.",
- "LabelRunningOnPorts": "\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u043f\u043e\u0440\u0442\u0430\u0445 {0} \u0438 {1}.",
"HeaderLatestFromChannel": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u0438\u0437 {0}",
"ButtonDownload": "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c",
"LabelUnknownLanaguage": "\u041d\u0435\u043e\u043f\u043e\u0437\u043d\u0430\u043d\u043d\u044b\u0439 \u044f\u0437\u044b\u043a",
- "HeaderCurrentSubtitles": "\u0422\u0435\u043a\u0443\u0449\u0438\u0435 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b",
+ "HeaderCurrentSubtitles": "\u0418\u043c\u0435\u044e\u0449\u0438\u0435\u0441\u044f \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b",
"MessageDownloadQueued": "\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c.",
"MessageAreYouSureDeleteSubtitles": "\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\u044b\u0439 \u0444\u0430\u0439\u043b \u0441\u0443\u0431\u0438\u0442\u0440\u043e\u0432?",
"ButtonRemoteControl": "\u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e",
- "HeaderLatestTvRecordings": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439"
+ "HeaderLatestTvRecordings": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439",
+ "ButtonOk": "\u041e\u041a",
+ "ButtonCancel": "\u041e\u0442\u043c\u0435\u043d\u0430",
+ "ButtonRefresh": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c",
+ "LabelCurrentPath": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0443\u0442\u044c:",
+ "HeaderSelectMediaPath": "\u0412\u044b\u0431\u043e\u0440 \u043f\u0443\u0442\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
+ "ButtonNetwork": "\u0421\u0435\u0442\u044c",
+ "MessageDirectoryPickerInstruction": "\u0421\u0435\u0442\u0435\u0432\u044b\u0435 \u043f\u0443\u0442\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u0432\u043e\u0434\u0438\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u0421\u0435\u0442\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u0431\u043e\u0439 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: {0} \u0438\u043b\u0438 {1}.",
+ "HeaderMenu": "\u041c\u0435\u043d\u044e",
+ "ButtonOpen": "\u041e\u0442\u043a\u0440\u044b\u0442\u044c",
+ "ButtonOpenInNewTab": "\u0412 \u043d\u043e\u0432\u043e\u0439 \u0432\u043a\u043b\u0430\u0434\u043a\u0435",
+ "ButtonShuffle": "\u041f\u0435\u0440\u0435\u043c\u0435\u0448\u0430\u0442\u044c",
+ "ButtonInstantMix": "\u0410\u0432\u0442\u043e\u043c\u0438\u043a\u0441",
+ "ButtonResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c",
+ "HeaderScenes": "\u0421\u0446\u0435\u043d\u044b",
+ "HeaderAudioTracks": "\u0410\u0443\u0434\u0438\u043e\u0434\u043e\u0440\u043e\u0436\u043a\u0438",
+ "HeaderSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b",
+ "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 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u044e\u043d\u0435\u0440.",
+ "ButtonHome": "\u0413\u043b\u0430\u0432\u043d\u0430\u044f",
+ "ButtonDashboard": "\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c",
+ "ButtonReports": "\u041e\u0442\u0447\u0451\u0442\u044b",
+ "ButtonMetadataManager": "\u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
+ "HeaderTime": "\u0412\u0440\u0435\u043c\u044f",
+ "HeaderName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435",
+ "HeaderAlbum": "\u0410\u043b\u044c\u0431\u043e\u043c",
+ "HeaderAlbumArtist": "\u0410\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c",
+ "HeaderArtist": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c",
+ "LabelAddedOnDate": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e {0}",
+ "ButtonStart": "\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c",
+ "HeaderChannels": "\u041a\u0430\u043d\u0430\u043b\u044b",
+ "HeaderMediaFolders": "\u041c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438",
+ "HeaderBlockItemsWithNoRating": "\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0431\u0435\u0437 \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u043e\u0439 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438:",
+ "OptionBlockOthers": "\u0414\u0440\u0443\u0433\u0438\u0435",
+ "OptionBlockTvShows": "\u0422\u0412 \u0446\u0438\u043a\u043b\u044b",
+ "OptionBlockTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b",
+ "OptionBlockMusic": "\u041c\u0443\u0437\u044b\u043a\u0430",
+ "OptionBlockMovies": "\u0424\u0438\u043b\u044c\u043c\u044b",
+ "OptionBlockBooks": "\u041a\u043d\u0438\u0433\u0438",
+ "OptionBlockGames": "\u0418\u0433\u0440\u044b",
+ "OptionBlockLiveTvPrograms": "\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u044d\u0444\u0438\u0440\u043d\u043e\u0433\u043e \u0422\u0412",
+ "OptionBlockLiveTvChannels": "\u041a\u0430\u043d\u0430\u043b\u044b \u044d\u0444\u0438\u0440\u043d\u043e\u0433\u043e \u0422\u0412",
+ "OptionBlockChannelContent": "\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043a\u0430\u043d\u0430\u043b\u043e\u0432",
+ "ButtonRevoke": "\u041e\u0442\u043e\u0437\u0432\u0430\u0442\u044c",
+ "MessageConfirmRevokeApiKey": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0442\u043e\u0437\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 API? \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a Media Browser \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0437\u043a\u043e \u043e\u0431\u043e\u0440\u0432\u0430\u043d\u043e.",
+ "HeaderConfirmRevokeApiKey": "\u041e\u0442\u0437\u044b\u0432\u0430\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0430 API",
+ "ValueContainer": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440: {0}",
+ "ValueAudioCodec": "\u0410\u0443\u0434\u0438\u043e \u043a\u043e\u0434\u0435\u043a: {0}",
+ "ValueVideoCodec": "\u0412\u0438\u0434\u0435\u043e \u043a\u043e\u0434\u0435\u043a: {0}",
+ "ValueCodec": "\u041a\u043e\u0434\u0435\u043a: {0}",
+ "ValueConditions": "\u041e\u0431\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430: {0}",
+ "LabelAll": "\u0412\u0441\u0435",
+ "HeaderDeleteImage": "\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0430",
+ "MessageFileNotFound": "\u0424\u0430\u0439\u043b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d.",
+ "MessageFileReadError": "\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430.",
+ "ButtonNextPage": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430",
+ "ButtonPreviousPage": "\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430",
+ "ButtonMoveLeft": "\u0414\u0432\u0438\u0433\u0430\u0442\u044c \u0432\u043b\u0435\u0432\u043e",
+ "ButtonMoveRight": "\u0414\u0432\u0438\u0433\u0430\u0442\u044c \u0432\u043f\u0440\u0430\u0432\u043e",
+ "ButtonBrowseOnlineImages": "\u041f\u0440\u043e\u043b\u0438\u0441\u0442\u0430\u0442\u044c \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0432 \u0441\u0435\u0442\u0438",
+ "HeaderDeleteItem": "\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430",
+ "ConfirmDeleteItem": "\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\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438\u0437 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438?",
+ "MessagePleaseEnterNameOrId": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0438\u043b\u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 ID.",
+ "MessageValueNotCorrect": "\u0412\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443.",
+ "MessageItemSaved": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0431\u044b\u043b \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d.",
+ "OptionEnded": "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0441\u044f",
+ "OptionContinuing": "\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442\u0441\u044f",
+ "OptionOff": "\u0412\u044b\u043a\u043b",
+ "OptionOn": "\u0412\u043a\u043b",
+ "HeaderFields": "\u041f\u043e\u043b\u044f",
+ "HeaderFieldsHelp": "\u041f\u0435\u0440\u0435\u0434\u0432\u0438\u043d\u044c\u0442\u0435 \u043f\u043e\u043b\u0435 \u043d\u0430 \"\u0412\u042b\u041a\u041b\", \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0438 \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u043e\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0435\u0433\u043e \u0434\u0430\u043d\u043d\u044b\u0445.",
+ "HeaderLiveTV": "\u042d\u0444\u0438\u0440\u043d\u043e\u0435 \u0422\u0412",
+ "MissingLocalTrailer": "\u041d\u0435\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u0430.",
+ "MissingPrimaryImage": "\u041d\u0435\u0442 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u043e\u0433\u043e \u0440\u0438\u0441\u0443\u043d\u043a\u0430.",
+ "MissingBackdropImage": "\u041d\u0435\u0442 \u0440\u0438\u0441\u0443\u043d\u043a\u0430 \u0437\u0430\u0434\u043d\u0438\u043a\u0430.",
+ "MissingLogoImage": "\u041d\u0435\u0442 \u0440\u0438\u0441\u0443\u043d\u043a\u0430 \u043b\u043e\u0433\u043e\u0442\u0438\u043f\u0430.",
+ "MissingEpisode": "\u041d\u0435\u0442 \u044d\u043f\u0438\u0437\u043e\u0434\u0430.",
+ "OptionScreenshots": "\u0421\u043d\u0438\u043c\u043a\u0438 \u044d\u043a\u0440\u0430\u043d\u0430",
+ "OptionBackdrops": "\u0417\u0430\u0434\u043d\u0438\u043a\u0438",
+ "OptionImages": "\u0420\u0438\u0441\u0443\u043d\u043a\u0438",
+ "OptionKeywords": "\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430",
+ "OptionTags": "\u0422\u0435\u0433\u0438",
+ "OptionStudios": "\u0421\u0442\u0443\u0434\u0438\u0438",
+ "OptionName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435",
+ "OptionOverview": "\u041e\u0431\u043e\u0437\u0440\u0435\u043d\u0438\u0435",
+ "OptionGenres": "\u0416\u0430\u043d\u0440\u044b",
+ "OptionParentalRating": "\u0412\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f",
+ "OptionPeople": "\u041b\u044e\u0434\u0438",
+ "OptionRuntime": "\u0414\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c",
+ "OptionProductionLocations": "\u041c\u0435\u0441\u0442\u0430 \u0441\u044a\u0451\u043c\u043e\u043a",
+ "OptionBirthLocation": "\u041c\u0435\u0441\u0442\u043e \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f",
+ "LabelAllChannels": "\u0412\u0441\u0435 \u043a\u0430\u043d\u0430\u043b\u044b",
+ "LabelLiveProgram": "\u041f\u0420\u042f\u041c\u041e\u0419 \u042d\u0424\u0418\u0420",
+ "LabelNewProgram": "\u041d\u041e\u0412\u041e\u0415",
+ "LabelPremiereProgram": "\u041f\u0420\u0415\u041c\u042c\u0415\u0420\u0410",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 \u043f\u0430\u043f\u043a\u0438",
+ "HeaderChangeFolderTypeHelp": "\u0414\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430 \u043f\u0430\u043f\u043a\u0438, \u0443\u0434\u0430\u043b\u0438\u0442\u0435 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0443 \u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0435\u0451 \u0441 \u043d\u043e\u0432\u044b\u043c \u0442\u0438\u043f\u043e\u043c.",
+ "HeaderAlert": "\u041e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u0435",
+ "MessagePleaseRestart": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435.",
+ "ButtonRestart": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c",
+ "MessagePleaseRefreshPage": "\u041f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0435 \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.",
+ "ButtonHide": "\u0421\u043a\u0440\u044b\u0442\u044c",
+ "MessageSettingsSaved": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b.",
+ "ButtonSignOut": "\u0412\u044b\u0439\u0442\u0438",
+ "ButtonMyProfile": "\u041c\u043e\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c",
+ "ButtonMyPreferences": "\u041c\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438",
+ "MessageBrowserDoesNotSupportWebSockets": "\u0414\u0430\u043d\u043d\u044b\u0439 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0435\u0431-\u0441\u043e\u043a\u0435\u0442\u044b. \u0414\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u0441 \u0431\u043e\u043b\u0435\u0435 \u043d\u043e\u0432\u044b\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Chrome, Firefox, IE10+, Safari (iOS) \u0438\u043b\u0438 Opera.",
+ "LabelInstallingPackage": "\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f {0}",
+ "LabelPackageInstallCompleted": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 {0} \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430.",
+ "LabelPackageInstallFailed": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 {0} \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u0430.",
+ "LabelPackageInstallCancelled": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 {0} \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u0430.",
+ "TabServer": "\u0421\u0435\u0440\u0432\u0435\u0440",
+ "TabUsers": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438",
+ "TabLibrary": "\u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430",
+ "TabMetadata": "\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "\u042d\u0444\u0438\u0440\u043d\u043e\u0435 \u0422\u0412",
+ "TabAutoOrganize": "\u0410\u0432\u0442\u043e\u0440\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f",
+ "TabPlugins": "\u041f\u043b\u0430\u0433\u0438\u043d\u044b",
+ "TabAdvanced": "\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e",
+ "TabHelp": "\u0421\u043f\u0440\u0430\u0432\u043a\u0430",
+ "TabScheduledTasks": "\u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a",
+ "ButtonFullscreen": "\u041f\u043e\u043b\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d",
+ "ButtonAudioTracks": "\u0410\u0443\u0434\u0438\u043e \u0434\u043e\u0440\u043e\u0436\u043a\u0438",
+ "ButtonSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b",
+ "ButtonScenes": "\u0421\u0446\u0435\u043d\u044b",
+ "ButtonQuality": "\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e",
+ "HeaderNotifications": "\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f",
+ "HeaderSelectPlayer": "\u0412\u044b\u0431\u043e\u0440 \u043f\u043b\u0435\u0439\u0435\u0440\u0430:",
+ "ButtonSelect": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c",
+ "ButtonNew": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c",
+ "MessageInternetExplorerWebm": "\u0414\u043b\u044f \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0438\u043b\u0443\u0447\u0448\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0432 Internet Explorer, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u043b\u0430\u0433\u0438\u043d \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f WebM.",
+ "HeaderVideoError": "\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0438\u0434\u0435\u043e",
+ "ButtonAddToPlaylist": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440-\u0438\u044f",
+ "HeaderAddToPlaylist": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440-\u0438\u044f",
+ "LabelName": "\u0418\u043c\u044f (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435):",
+ "ButtonSubmit": "\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c",
+ "LabelSelectPlaylist": "\u0421\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440-\u0438\u044f:",
+ "OptionNewPlaylist": "\u041d\u043e\u0432\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440-\u0438\u044f...",
+ "MessageAddedToPlaylistSuccess": "\u041e\u041a",
+ "ButtonViewSeriesRecording": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c \u0441\u0435\u0440\u0438\u0430\u043b\u0430",
+ "ValueOriginalAirDate": "\u041f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u044d\u0444\u0438\u0440: {0}",
+ "ButtonRemoveFromPlaylist": "\u0418\u0437\u044a\u044f\u0442\u044c \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430 \u0432\u043e\u0441\u043f\u0440-\u0438\u044f",
+ "HeaderSpecials": "\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435",
+ "HeaderTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b",
+ "HeaderAudio": "\u0410\u0443\u0434\u0438\u043e",
+ "HeaderResolution": "\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435",
+ "HeaderVideo": "\u0412\u0438\u0434\u0435\u043e",
+ "HeaderRuntime": "\u0414\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c",
+ "HeaderCommunityRating": "\u041e\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u043e\u0446\u0435\u043d\u043a\u0430",
+ "HeaderParentalRating": "\u0412\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f",
+ "HeaderReleaseDate": "\u0414\u0430\u0442\u0430 \u0432\u044b\u043f\u0443\u0441\u043a\u0430",
+ "HeaderDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f",
+ "HeaderSeries": "\u0421\u0435\u0440\u0438\u0430\u043b",
+ "HeaderSeason": "\u0421\u0435\u0437\u043e\u043d",
+ "HeaderSeasonNumber": "\u041d\u043e\u043c\u0435\u0440 \u0441\u0435\u0437\u043e\u043d\u0430",
+ "HeaderNetwork": "\u0422\u0435\u043b\u0435\u0441\u0435\u0442\u044c",
+ "HeaderYear": "\u0413\u043e\u0434",
+ "HeaderGameSystem": "\u0418\u0433\u0440\u043e\u0432\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430",
+ "HeaderPlayers": "\u0418\u0433\u0440\u043e\u043a\u0438",
+ "HeaderEmbeddedImage": "\u0412\u043d\u0435\u0434\u0440\u0451\u043d\u043d\u044b\u0439 \u0440\u0438\u0441\u0443\u043d\u043e\u043a",
+ "HeaderTrack": "\u0414\u043e\u0440\u043e\u0436\u043a\u0430",
+ "HeaderDisc": "\u0414\u0438\u0441\u043a",
+ "OptionMovies": "\u0424\u0438\u043b\u044c\u043c\u044b",
+ "OptionCollections": "\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438",
+ "OptionSeries": "\u0422\u0412 \u0441\u0435\u0440\u0438\u0430\u043b\u044b",
+ "OptionSeasons": "\u0422\u0412 \u0441\u0435\u0437\u043e\u043d\u044b",
+ "OptionEpisodes": "\u0422\u0412 \u044d\u043f\u0438\u0437\u043e\u0434\u044b",
+ "OptionGames": "\u0418\u0433\u0440\u044b",
+ "OptionGameSystems": "\u0418\u0433\u0440\u043e\u0432\u044b\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b",
+ "OptionMusicArtists": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438",
+ "OptionMusicAlbums": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0430\u043b\u044c\u0431\u043e\u043c\u044b",
+ "OptionMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0438\u043f\u044b",
+ "OptionSongs": "\u041c\u0435\u043b\u043e\u0434\u0438\u0438",
+ "OptionHomeVideos": "\u0414\u043e\u043c\u0430\u0448\u043d\u0435\u0435 \u0432\u0438\u0434\u0435\u043e",
+ "OptionBooks": "\u041a\u043d\u0438\u0433\u0438",
+ "OptionAdultVideos": "\u0412\u0437\u0440\u043e\u0441\u043b\u043e\u0435 \u0432\u0438\u0434\u0435\u043e",
+ "ButtonUp": "\u0412\u0432\u0435\u0440\u0445",
+ "ButtonDown": "\u0412\u043d\u0438\u0437",
+ "LabelMetadataReaders": "\u0421\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445:",
+ "LabelMetadataReadersHelp": "\u0420\u0430\u043d\u0436\u0438\u0440\u0443\u0439\u0442\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430. \u0411\u0443\u0434\u0435\u0442 \u0441\u0447\u0438\u0442\u0430\u043d \u043f\u0435\u0440\u0432\u044b\u0439 \u0436\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b.",
+ "LabelMetadataDownloaders": "\u0417\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445:",
+ "LabelMetadataDownloadersHelp": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0438 \u0440\u0430\u043d\u0436\u0438\u0440\u0443\u0439\u0442\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430. \u0417\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u0438 \u0441 \u043d\u0438\u0437\u043a\u0438\u043c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u044e\u0449\u0435\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438.",
+ "LabelMetadataSavers": "\u0425\u0440\u0430\u043d\u0438\u0442\u0435\u043b\u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445:",
+ "LabelMetadataSaversHelp": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0444\u0430\u0439\u043b\u043e\u0432, \u043a\u0443\u0434\u0430 \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435.",
+ "LabelImageFetchers": "\u041e\u0442\u0431\u043e\u0440\u0449\u0438\u043a\u0438 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432:",
+ "LabelImageFetchersHelp": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0438 \u0440\u0430\u043d\u0436\u0438\u0440\u0443\u0439\u0442\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043e\u0442\u0431\u043e\u0440\u0449\u0438\u043a\u0438 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u0430.",
+ "ButtonQueueAllFromHere": "\u041f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u0441\u0435 \u043e\u0442\u0441\u044e\u0434\u0430",
+ "ButtonPlayAllFromHere": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0432\u0441\u0435 \u043e\u0442\u0441\u044e\u0434\u0430",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430",
+ "PersonTypePerson": "\u041f\u0435\u0440\u0441\u043e\u043d\u0430",
+ "LabelTitleDisplayOrder": "\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0439:",
+ "OptionSortName": "\u0421\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435",
+ "OptionReleaseDate": "\u0414\u0430\u0442\u0430 \u0432\u044b\u043f\u0443\u0441\u043a\u0430",
+ "LabelSeasonNumber": "\u041d\u043e\u043c\u0435\u0440 \u0441\u0435\u0437\u043e\u043d\u0430:",
+ "LabelDiscNumber": "\u041d\u043e\u043c\u0435\u0440 \u0434\u0438\u0441\u043a\u0430",
+ "LabelParentNumber": "\u0420\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043d\u043e\u043c\u0435\u0440",
+ "LabelEpisodeNumber": "\u041d\u043e\u043c\u0435\u0440 \u044d\u043f\u0438\u0437\u043e\u0434\u0430:",
+ "LabelTrackNumber": "\u041d\u043e\u043c\u0435\u0440 \u0434\u043e\u0440\u043e\u0436\u043a\u0438:",
+ "LabelNumber": "\u041d\u043e\u043c\u0435\u0440:",
+ "LabelReleaseDate": "\u0414\u0430\u0442\u0430 \u0432\u044b\u043f\u0443\u0441\u043a\u0430:",
+ "LabelEndDate": "\u041a\u043e\u043d\u0435\u0447\u043d\u0430\u044f \u0434\u0430\u0442\u0430:",
+ "LabelYear": "\u0413\u043e\u0434:",
+ "LabelDateOfBirth": "\u0414\u0430\u0442\u0430 \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f:",
+ "LabelBirthYear": "\u0413\u043e\u0434 \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f:",
+ "LabelDeathDate": "\u0413\u043e\u0434 \u0441\u043c\u0435\u0440\u0442\u0438:",
+ "HeaderRemoveMediaLocation": "\u0418\u0437\u044a\u044f\u0442\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
+ "MessageConfirmRemoveMediaLocation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0438\u0437\u044a\u044f\u0442\u044c \u044d\u0442\u043e \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0435?",
+ "HeaderRenameMediaFolder": "\u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438",
+ "LabelNewName": "\u041d\u043e\u0432\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435:",
+ "HeaderAddMediaFolder": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438",
+ "HeaderAddMediaFolderHelp": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 (\u041a\u0438\u043d\u043e, \u041c\u0443\u0437\u044b\u043a\u0430, \u0422\u0412 \u0438 \u0442.\u043f.).",
+ "HeaderRemoveMediaFolder": "\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "\u0418\u0437 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u044a\u044f\u0442\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 :",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0438\u0437\u044a\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0443?",
+ "ButtonRename": "\u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u0442\u044c",
+ "ButtonChangeType": "\u0421\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0438\u043f",
+ "HeaderMediaLocations": "\u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
+ "LabelFolderTypeValue": "\u0422\u0438\u043f \u043f\u0430\u043f\u043a\u0438: {0}",
+ "LabelPathSubstitutionHelp": "\u041d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e: \u041f\u0440\u0438 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u043f\u0443\u0442\u0435\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u0441 \u0441\u0435\u0442\u0435\u0432\u044b\u043c\u0438 \u043e\u0431\u0449\u0438\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438, \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u044b \u0441\u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u0434\u043b\u044f \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f.",
+ "FolderTypeMixed": "\u0421\u043c\u0435\u0448\u0430\u043d\u043d\u044b\u0439 (\u0444\u0438\u043b\u044c\u043c\u044b \u0438 \u0422\u0412)",
+ "FolderTypeMovies": "\u0424\u0438\u043b\u044c\u043c\u044b",
+ "FolderTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430",
+ "FolderTypeAdultVideos": "\u0412\u0437\u0440\u043e\u0441\u043b\u043e\u0435 \u0432\u0438\u0434\u0435\u043e",
+ "FolderTypePhotos": "\u0424\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438",
+ "FolderTypeMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u0438\u0434\u0435\u043e",
+ "FolderTypeHomeVideos": "\u0414\u043e\u043c\u0430\u0448\u043d\u0435\u0435 \u0432\u0438\u0434\u0435\u043e",
+ "FolderTypeGames": "\u0418\u0433\u0440\u044b",
+ "FolderTypeBooks": "\u041a\u043d\u0438\u0433\u0438",
+ "FolderTypeTvShows": "\u0422\u0412 \u0446\u0438\u043a\u043b\u044b",
+ "TabMovies": "\u0424\u0438\u043b\u044c\u043c\u044b",
+ "TabSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u044b",
+ "TabEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u044b",
+ "TabTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b",
+ "TabGames": "\u0418\u0433\u0440\u044b",
+ "TabAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u044b",
+ "TabSongs": "\u041c\u0435\u043b\u043e\u0434\u0438\u0438",
+ "TabMusicVideos": "\u041a\u043b\u0438\u043f\u044b",
+ "BirthPlaceValue": "\u041c\u0435\u0441\u0442\u043e \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f: {0}",
+ "DeathDateValue": "\u041a\u043e\u043d\u0447\u0438\u043d\u0430: {0}",
+ "BirthDateValue": "\u0420\u043e\u0436\u0434\u0435\u043d\u0438\u0435: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json
index 47f2b8fdb..50d24dae5 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "Av",
- "OptionOn": "P\u00e5",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "V\u00e4lj tv\u00e5 eller flera objekt att gruppera.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "Mitt bibliotek",
"SettingsSaved": "Inst\u00e4llningarna sparade.",
"AddUser": "Skapa anv\u00e4ndare",
"Users": "Anv\u00e4ndare",
@@ -46,7 +38,6 @@
"LabelEpisode": "Avsnitt",
"LabelSeries": "Serie",
"LabelStopping": "Avbryter",
- "ButtonStop": "Stopp",
"LabelCancelled": "(avbr\u00f6ts)",
"LabelFailed": "(misslyckades)",
"LabelAbortedByServerShutdown": "(avbr\u00f6ts eftersom servern st\u00e4ngdes av)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Ok\u00e4nt spr\u00e5k",
"ButtonMute": "Tyst",
"ButtonUnmute": "Muting av",
+ "ButtonStop": "Stopp",
+ "ButtonNextTrack": "N\u00e4sta sp\u00e5r",
"ButtonPause": "Paus",
"ButtonPlay": "Spela upp",
"ButtonEdit": "\u00c4ndra",
"ButtonQueue": "K\u00f6",
"ButtonPlayTrailer": "Spela upp trailer",
"ButtonPlaylist": "Spellista",
+ "ButtonPreviousTrack": "F\u00f6reg\u00e5ende sp\u00e5r",
"LabelEnabled": "Aktiverad",
"LabelDisabled": "Avaktiverad",
"ButtonMoreInformation": "Mer information",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "\u00c5terst\u00e4ll mottagare",
"MessageConfirmResetTuner": "Vill du verkligen \u00e5terst\u00e4lla den h\u00e4r mottagaren? Alla aktiva uppspelare och inspelningar kommer att avbrytas utan f\u00f6rvarning.",
"ButtonCancelSeries": "Avbryt serieinspelning",
- "LabelAllChannels": "Alla kanaler",
"HeaderSeriesRecordings": "Serieinspelningar",
"LabelAnytime": "N\u00e4r som helst",
"StatusRecording": "Inspelning p\u00e5g\u00e5r",
@@ -130,6 +123,7 @@
"HeaderMyViews": "Mina vyer",
"HeaderLibraryFolders": "Mappvy",
"HeaderLatestMedia": "Nytillkommet",
+ "ButtonMoreItems": "More...",
"ButtonMore": "Mer...",
"HeaderFavoriteMovies": "Favoritfilmer",
"HeaderFavoriteShows": "Favoritserier",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Fj\u00e4rranslutning: {0}",
"LabelRunningOnPort": "Anv\u00e4nder port {0}.",
- "LabelRunningOnPorts": "Anv\u00e4nder port {0} och {1}.",
"HeaderLatestFromChannel": "Senaste fr\u00e5n {0}",
"ButtonDownload": "Ladda ned",
"LabelUnknownLanaguage": "Ok\u00e4nt spr\u00e5k",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "Nedladdningen har lagts i k\u00f6n.",
"MessageAreYouSureDeleteSubtitles": "\u00c4r du s\u00e4ker p\u00e5 att du vill radera den h\u00e4r undertextfilen?",
"ButtonRemoteControl": "Fj\u00e4rrkontroll",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Senaste inspelningar",
+ "ButtonOk": "OK",
+ "ButtonCancel": "Avbryt",
+ "ButtonRefresh": "Uppdatera",
+ "LabelCurrentPath": "Aktuell s\u00f6kv\u00e4g:",
+ "HeaderSelectMediaPath": "V\u00e4lj s\u00f6kv\u00e4g till media",
+ "ButtonNetwork": "N\u00e4tverk",
+ "MessageDirectoryPickerInstruction": "N\u00e4tverkss\u00f6kv\u00e4gar kan anges manuellt om \"N\u00e4tverk\" inte hittar dina enheter. T ex {0} eller {1}.",
+ "HeaderMenu": "Meny",
+ "ButtonOpen": "\u00d6ppna",
+ "ButtonOpenInNewTab": "\u00d6ppna i ny flik",
+ "ButtonShuffle": "Blanda",
+ "ButtonInstantMix": "Omedelbar mix",
+ "ButtonResume": "\u00c5teruppta",
+ "HeaderScenes": "Kapitel",
+ "HeaderAudioTracks": "Ljudsp\u00e5r",
+ "HeaderSubtitles": "Undertexter",
+ "HeaderVideoQuality": "Videokvalitet",
+ "MessageErrorPlayingVideo": "Ett fel uppstod vid uppspelning av videon.",
+ "MessageEnsureOpenTuner": "V\u00e4nligen kontrollera att det finns en ledig mottagare.",
+ "ButtonHome": "Hem",
+ "ButtonDashboard": "Kontrollpanel",
+ "ButtonReports": "Rapporter",
+ "ButtonMetadataManager": "Metadatahanteraren",
+ "HeaderTime": "Tid",
+ "HeaderName": "Namn",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Albumartist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "{0} tillagd",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Kanaler",
+ "HeaderMediaFolders": "Mediamappar",
+ "HeaderBlockItemsWithNoRating": "Blockera objekt utan \u00e5ldersgr\u00e4ns:",
+ "OptionBlockOthers": "\u00d6vrigt",
+ "OptionBlockTvShows": "TV-serier",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Musik",
+ "OptionBlockMovies": "Filmer",
+ "OptionBlockBooks": "B\u00f6cker",
+ "OptionBlockGames": "Spel",
+ "OptionBlockLiveTvPrograms": "TV-program",
+ "OptionBlockLiveTvChannels": "TV-kanaler",
+ "OptionBlockChannelContent": "Kanalinneh\u00e5ll fr\u00e5n Internet",
+ "ButtonRevoke": "\u00c5terkalla",
+ "MessageConfirmRevokeApiKey": "\u00c4r du s\u00e4ker p\u00e5 att du vill \u00e5terkalla den h\u00e4r API-nyckeln? Programmets anslutning till Media Browser kommer att avbrytas omg\u00e5ende.",
+ "HeaderConfirmRevokeApiKey": "\u00c5terkalla API-nyckel",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audiocodec: {0}",
+ "ValueVideoCodec": "Videocodec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Villkor: {0}",
+ "LabelAll": "Alla",
+ "HeaderDeleteImage": "Radera bild",
+ "MessageFileNotFound": "Filen hittades ej.",
+ "MessageFileReadError": "Ett fel uppstod vid l\u00e4sning av filen.",
+ "ButtonNextPage": "N\u00e4sta sida",
+ "ButtonPreviousPage": "F\u00f6reg\u00e5ende sida",
+ "ButtonMoveLeft": "V\u00e4nster",
+ "ButtonMoveRight": "H\u00f6ger",
+ "ButtonBrowseOnlineImages": "Bl\u00e4ddra bland bilder online",
+ "HeaderDeleteItem": "Radera objekt",
+ "ConfirmDeleteItem": "\u00c4r du s\u00e4ker p\u00e5 att du vill radera det h\u00e4r objektet fr\u00e5n biblioteket?",
+ "MessagePleaseEnterNameOrId": "Ange ett namn eller externt id.",
+ "MessageValueNotCorrect": "Det angivna v\u00e4rdet \u00e4r felaktigt. Var god f\u00f6rs\u00f6k igen.",
+ "MessageItemSaved": "Objektet har sparats.",
+ "OptionEnded": "Avslutad",
+ "OptionContinuing": "P\u00e5g\u00e5ende",
+ "OptionOff": "Av",
+ "OptionOn": "P\u00e5",
+ "HeaderFields": "F\u00e4lt",
+ "HeaderFieldsHelp": "Dra ett f\u00e4lt till \"av\" f\u00f6r att l\u00e5sa det och f\u00f6rhindra att dess data \u00e4ndras.",
+ "HeaderLiveTV": "Live-TV",
+ "MissingLocalTrailer": "Lokalt sparad trailer saknas.",
+ "MissingPrimaryImage": "Huvudbild saknas.",
+ "MissingBackdropImage": "Fondbild saknas.",
+ "MissingLogoImage": "Logo saknas.",
+ "MissingEpisode": "Avsnitt saknas.",
+ "OptionScreenshots": "Sk\u00e4rmklipp",
+ "OptionBackdrops": "Fondbilder",
+ "OptionImages": "Bilder",
+ "OptionKeywords": "Nyckelord",
+ "OptionTags": "Etiketter",
+ "OptionStudios": "Studior",
+ "OptionName": "Namn",
+ "OptionOverview": "\u00d6versikt",
+ "OptionGenres": "Genrer",
+ "OptionParentalRating": "F\u00f6r\u00e4ldraklassning",
+ "OptionPeople": "Personer",
+ "OptionRuntime": "Speltid",
+ "OptionProductionLocations": "Produktionsplatser",
+ "OptionBirthLocation": "F\u00f6delseort",
+ "LabelAllChannels": "Alla kanaler",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NY",
+ "LabelPremiereProgram": "PREMI\u00c4R",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "\u00c4ndra mapptyp",
+ "HeaderChangeFolderTypeHelp": "F\u00f6r att \u00e4ndra mapptyp, ta bort den existerande och skapa en ny av den \u00f6nskade typen.",
+ "HeaderAlert": "Varning",
+ "MessagePleaseRestart": "V\u00e4nligen starta om f\u00f6r att slutf\u00f6ra uppdateringarna.",
+ "ButtonRestart": "Starta om",
+ "MessagePleaseRefreshPage": "V\u00e4nligen ladda om den h\u00e4r sidan f\u00f6r att ta emot nya uppdateringar fr\u00e5n servern.",
+ "ButtonHide": "D\u00f6lj",
+ "MessageSettingsSaved": "Inst\u00e4llningarna har sparats.",
+ "ButtonSignOut": "Logga ut",
+ "ButtonMyProfile": "Min profil",
+ "ButtonMyPreferences": "Mina inst\u00e4llningar",
+ "MessageBrowserDoesNotSupportWebSockets": "Den h\u00e4r webbl\u00e4saren st\u00f6djer inte web sockets. F\u00f6r att f\u00e5 en b\u00e4ttre upplevelse, prova en nyare webbl\u00e4sare, t ex Chrome, Firefox, IE10+, Safari (iOS) eller Opera.",
+ "LabelInstallingPackage": "Installerar {0}",
+ "LabelPackageInstallCompleted": "Installationen av {0} slutf\u00f6rdes.",
+ "LabelPackageInstallFailed": "Installationen av {0} misslyckades.",
+ "LabelPackageInstallCancelled": "Installationen av {0} avbr\u00f6ts.",
+ "TabServer": "Server",
+ "TabUsers": "Anv\u00e4ndare",
+ "TabLibrary": "Bibliotek",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live-TV",
+ "TabAutoOrganize": "Katalogisera automatiskt",
+ "TabPlugins": "Till\u00e4gg",
+ "TabAdvanced": "Avancerat",
+ "TabHelp": "Hj\u00e4lp",
+ "TabScheduledTasks": "Schemalagda aktiviteter",
+ "ButtonFullscreen": "Fullsk\u00e4rm",
+ "ButtonAudioTracks": "Ljudsp\u00e5r",
+ "ButtonSubtitles": "Undertexter",
+ "ButtonScenes": "Scener",
+ "ButtonQuality": "Kvalitet",
+ "HeaderNotifications": "Meddelanden",
+ "HeaderSelectPlayer": "V\u00e4lj uppspelare:",
+ "ButtonSelect": "V\u00e4lj",
+ "ButtonNew": "Nytillkommet",
+ "MessageInternetExplorerWebm": "F\u00f6r b\u00e4sta resultat med Internet Explorer, installera WebM-till\u00e4gget f\u00f6r IE.",
+ "HeaderVideoError": "Videofel",
+ "ButtonAddToPlaylist": "L\u00e4gg till i spellista",
+ "HeaderAddToPlaylist": "L\u00e4gg till i Spellista",
+ "LabelName": "Namn:",
+ "ButtonSubmit": "Bekr\u00e4fta",
+ "LabelSelectPlaylist": "Spellista:",
+ "OptionNewPlaylist": "Ny spellista...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "Visa serieinspelning",
+ "ValueOriginalAirDate": "Ursprungligt s\u00e4ndningsdatum: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Filmer",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Avsnitt",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "S\u00e4songsnummer:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Avsnittsnummer:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Filmer",
+ "TabSeries": "Serie",
+ "TabEpisodes": "Avsnitt",
+ "TabTrailers": "Trailers",
+ "TabGames": "Spel",
+ "TabAlbums": "Album",
+ "TabSongs": "L\u00e5tar",
+ "TabMusicVideos": "Musikvideor",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json
new file mode 100644
index 000000000..9232c2fdd
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json
@@ -0,0 +1,433 @@
+{
+ "SettingsSaved": "Ayarlar Kaydedildi",
+ "AddUser": "Kullan\u0131c\u0131 Ekle",
+ "Users": "Kullan\u0131c\u0131lar",
+ "Delete": "Sil",
+ "Administrator": "Y\u00f6netici",
+ "Password": "Sifre",
+ "DeleteImage": "Resmi Sil",
+ "DeleteImageConfirmation": "Bu G\u00f6r\u00fcnt\u00fcy\u00fc Silmek \u0130stedi\u011finizden Eminmisiniz?",
+ "FileReadCancelled": "Dosya Okuma \u0130ptal Edildi",
+ "FileNotFound": "Dosya Bulunamad\u0131",
+ "FileReadError": "Dosya Okunurken Bir Hata Olu\u015ftu",
+ "DeleteUser": "Kullan\u0131c\u0131 Sil",
+ "DeleteUserConfirmation": "Silmek \u0130stedi\u011finizden Eminmisiniz {0} ?",
+ "PasswordResetHeader": "Sifre S\u0131f\u0131rland\u0131",
+ "PasswordResetComplete": "Parolan\u0131z S\u0131f\u0131rlanm\u0131st\u0131r.",
+ "PasswordResetConfirmation": "Sifrenizi S\u0131f\u0131rlamak \u0130stediginizden Eminmisiniz?",
+ "PasswordSaved": "Sifre Kaydedildi",
+ "PasswordMatchError": "Parola ve Sifre Eslesmelidir.",
+ "OptionRelease": "Resmi Yay\u0131n",
+ "OptionBeta": "Deneme",
+ "OptionDev": "Gelistirici",
+ "UninstallPluginHeader": "Eklenti Kald\u0131r",
+ "UninstallPluginConfirmation": "Kald\u0131rmak \u0130stediginizden Eminmisiniz {0} ?",
+ "NoPluginConfigurationMessage": "Eklenti \u0130cin Ayar Yok",
+ "NoPluginsInstalledMessage": "Eklentiler Y\u00fckl\u00fc De\u011fil",
+ "BrowsePluginCatalogMessage": "Mevcut Eklentileri G\u00f6rebilmek \u0130\u00e7in Eklenti Katologuna G\u00f6z At\u0131n.",
+ "MessageKeyEmailedTo": "Key emailed to {0}.",
+ "MessageKeysLinked": "Keys linked.",
+ "HeaderConfirmation": "Confirmation",
+ "MessageKeyUpdated": "Thank you. Your supporter key has been updated.",
+ "MessageKeyRemoved": "Thank you. Your supporter key has been removed.",
+ "ErrorLaunchingChromecast": "There was an error launching chromecast. Please ensure your device is connected to your wireless network.",
+ "HeaderSearch": "Search",
+ "LabelArtist": "Artist",
+ "LabelMovie": "Movie",
+ "LabelMusicVideo": "Music Video",
+ "LabelEpisode": "Episode",
+ "LabelSeries": "Series",
+ "LabelStopping": "Stopping",
+ "LabelCancelled": "(cancelled)",
+ "LabelFailed": "(failed)",
+ "LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
+ "LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
+ "HeaderDeleteTaskTrigger": "Delete Task Trigger",
+ "HeaderTaskTriggers": "Task Triggers",
+ "MessageDeleteTaskTrigger": "Are you sure you wish to delete this task trigger?",
+ "MessageNoPluginsInstalled": "You have no plugins installed.",
+ "LabelVersionInstalled": "{0} installed",
+ "LabelNumberReviews": "{0} Reviews",
+ "LabelFree": "Free",
+ "HeaderSelectAudio": "Select Audio",
+ "HeaderSelectSubtitles": "Select Subtitles",
+ "LabelDefaultStream": "(Default)",
+ "LabelForcedStream": "(Forced)",
+ "LabelDefaultForcedStream": "(Default\/Forced)",
+ "LabelUnknownLanguage": "Unknown language",
+ "ButtonMute": "Sessiz",
+ "ButtonUnmute": "Unmute",
+ "ButtonStop": "Durdur",
+ "ButtonNextTrack": "Sonraki Par\u00e7a",
+ "ButtonPause": "Duraklat",
+ "ButtonPlay": "\u00c7al",
+ "ButtonEdit": "D\u00fczenle",
+ "ButtonQueue": "Queue",
+ "ButtonPlayTrailer": "Play trailer",
+ "ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "\u00d6nceki Par\u00e7a",
+ "LabelEnabled": "Enabled",
+ "LabelDisabled": "Disabled",
+ "ButtonMoreInformation": "More Information",
+ "LabelNoUnreadNotifications": "No unread notifications.",
+ "ButtonViewNotifications": "View notifications",
+ "ButtonMarkTheseRead": "Mark these read",
+ "ButtonClose": "Close",
+ "LabelAllPlaysSentToPlayer": "All plays will be sent to the selected player.",
+ "MessageInvalidUser": "Invalid user or password.",
+ "HeaderAllRecordings": "T\u00fcm Kay\u0131tlar",
+ "RecommendationBecauseYouLike": "Because you like {0}",
+ "RecommendationBecauseYouWatched": "Because you watched {0}",
+ "RecommendationDirectedBy": "Directed by {0}",
+ "RecommendationStarring": "Starring {0}",
+ "HeaderConfirmRecordingCancellation": "Confirm Recording Cancellation",
+ "MessageConfirmRecordingCancellation": "Are you sure you wish to cancel this recording?",
+ "MessageRecordingCancelled": "Recording cancelled.",
+ "HeaderConfirmSeriesCancellation": "Confirm Series Cancellation",
+ "MessageConfirmSeriesCancellation": "Are you sure you wish to cancel this series?",
+ "MessageSeriesCancelled": "Series cancelled.",
+ "HeaderConfirmRecordingDeletion": "Confirm Recording Deletion",
+ "MessageConfirmRecordingDeletion": "Are you sure you wish to delete this recording?",
+ "MessageRecordingDeleted": "Recording deleted.",
+ "ButonCancelRecording": "Cancel Recording",
+ "MessageRecordingSaved": "Recording saved.",
+ "OptionSunday": "Pazar",
+ "OptionMonday": "Pazartesi",
+ "OptionTuesday": "Sal\u0131",
+ "OptionWednesday": "\u00c7ar\u015famba",
+ "OptionThursday": "Per\u015fembe",
+ "OptionFriday": "Cuma",
+ "OptionSaturday": "Cumartesi",
+ "HeaderConfirmDeletion": "Confirm Deletion",
+ "MessageConfirmPathSubstitutionDeletion": "Are you sure you wish to delete this path substitution?",
+ "LiveTvUpdateAvailable": "(Update available)",
+ "LabelVersionUpToDate": "Up to date!",
+ "ButtonResetTuner": "Reset tuner",
+ "HeaderResetTuner": "Reset Tuner",
+ "MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
+ "ButtonCancelSeries": "Cancel Series",
+ "HeaderSeriesRecordings": "Series Recordings",
+ "LabelAnytime": "Any time",
+ "StatusRecording": "Recording",
+ "StatusWatching": "Watching",
+ "StatusRecordingProgram": "Recording {0}",
+ "StatusWatchingProgram": "Watching {0}",
+ "HeaderSplitMedia": "Split Media Apart",
+ "MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
+ "HeaderError": "Error",
+ "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": "Media Browser clients will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?",
+ "HeaderResume": "Devam",
+ "HeaderMyViews": "My Views",
+ "HeaderLibraryFolders": "Media Klas\u00f6rleri",
+ "HeaderLatestMedia": "En Son G\u00f6r\u00fcnt\u00fclemeler",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
+ "HeaderFavoriteMovies": "Favori Filmler",
+ "HeaderFavoriteShows": "Favori Showlar",
+ "HeaderFavoriteEpisodes": "Favori B\u00f6l\u00fcmler",
+ "HeaderFavoriteGames": "Favori Oyunlar",
+ "HeaderRatingsDownloads": "Rating \/ Downloads",
+ "HeaderConfirmProfileDeletion": "Confirm Profile Deletion",
+ "MessageConfirmProfileDeletion": "Are you sure you wish to delete this profile?",
+ "HeaderSelectServerCachePath": "Select Server Cache Path",
+ "HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
+ "HeaderSelectImagesByNamePath": "Select Images By Name Path",
+ "HeaderSelectMetadataPath": "Select Metadata Path",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
+ "HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
+ "HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
+ "HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
+ "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": "Ekle",
+ "ButtonRemove": "Sil",
+ "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.",
+ "HeaderFavoriteAlbums": "Favori Albumler",
+ "HeaderLatestChannelMedia": "Latest Channel Items",
+ "ButtonOrganizeFile": "Organize File",
+ "ButtonDeleteFile": "Delete File",
+ "HeaderOrganizeFile": "Organize File",
+ "HeaderDeleteFile": "Delete File",
+ "StatusSkipped": "Skipped",
+ "StatusFailed": "Failed",
+ "StatusSuccess": "Success",
+ "MessageFileWillBeDeleted": "The following file will be deleted:",
+ "MessageSureYouWishToProceed": "Are you sure you wish to proceed?",
+ "MessageDuplicatesWillBeDeleted": "In addition the following dupliates will be deleted:",
+ "MessageFollowingFileWillBeMovedFrom": "The following file will be moved from:",
+ "MessageDestinationTo": "to:",
+ "HeaderSelectWatchFolder": "Select Watch Folder",
+ "HeaderSelectWatchFolderHelp": "Browse or enter the path to your watch folder. The folder must be writeable.",
+ "OrganizePatternResult": "Result: {0}",
+ "HeaderRestart": "Restart",
+ "HeaderShutdown": "Shutdown",
+ "MessageConfirmRestart": "Are you sure you wish to restart Media Browser Server?",
+ "MessageConfirmShutdown": "Are you sure you wish to shutdown Media Browser Server?",
+ "ButtonUpdateNow": "Update Now",
+ "NewVersionOfSomethingAvailable": "A new version of {0} is available!",
+ "VersionXIsAvailableForDownload": "Version {0} is now available for download.",
+ "LabelVersionNumber": "Version {0}",
+ "LabelPlayMethodTranscoding": "Transcoding",
+ "LabelPlayMethodDirectStream": "Direct Streaming",
+ "LabelPlayMethodDirectPlay": "Direct Playing",
+ "LabelAudioCodec": "Audio: {0}",
+ "LabelVideoCodec": "Video: {0}",
+ "LabelRemoteAccessUrl": "Remote access: {0}",
+ "LabelRunningOnPort": "Running on port {0}.",
+ "HeaderLatestFromChannel": "Latest from {0}",
+ "ButtonDownload": "Download",
+ "LabelUnknownLanaguage": "Unknown language",
+ "HeaderCurrentSubtitles": "Current Subtitles",
+ "MessageDownloadQueued": "The download has been queued.",
+ "MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
+ "ButtonRemoteControl": "Remote Control",
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "Tamam",
+ "ButtonCancel": "\u0130ptal",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "Diziler",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Anasayfa",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "Name",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Kanallar",
+ "HeaderMediaFolders": "Media Klas\u00f6rleri",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "Bitmi\u015f",
+ "OptionContinuing": "Topluluk",
+ "OptionOff": "Off",
+ "OptionOn": "On",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Etiketler",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPeople": "People",
+ "OptionRuntime": "\u00c7al\u0131\u015fma s\u00fcresi",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "Sunucu",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Geli\u015fmi\u015f",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Altyaz\u0131lar",
+ "ButtonScenes": "Sahneler",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "Se\u00e7im",
+ "ButtonNew": "Yeni",
+ "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": "\u0130sim",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Filmler",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episodes",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Season number:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "Filmler",
+ "TabSeries": "Seriler",
+ "TabEpisodes": "B\u00f6l\u00fcmler",
+ "TabTrailers": "Fragmanlar",
+ "TabGames": "Oyunlar",
+ "TabAlbums": "Alb\u00fcm",
+ "TabSongs": "\u015eark\u0131lar",
+ "TabMusicVideos": "Klipler",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
+} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json
index 8963853af..b62b24367 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "Create Password",
- "OptionOff": "Off",
- "OptionOn": "On",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "My Library",
"SettingsSaved": "L\u01b0u c\u00e1c c\u00e0i \u0111\u1eb7t.",
"AddUser": "Th\u00eam ng\u01b0\u1eddi d\u00f9ng",
"Users": "Ng\u01b0\u1eddi d\u00f9ng",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episode",
"LabelSeries": "Series",
"LabelStopping": "Stopping",
- "ButtonStop": "Stop",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Unknown language",
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
"ButtonPause": "Pause",
"ButtonPlay": "Play",
"ButtonEdit": "Edit",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
+ "ButtonPlayTrailer": "Play trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Previous Track",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
"ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
"HeaderSeriesRecordings": "Series Recordings",
"LabelAnytime": "Any time",
"StatusRecording": "Recording",
@@ -130,7 +123,8 @@
"HeaderMyViews": "My Views",
"HeaderLibraryFolders": "Media Folders",
"HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
"HeaderFavoriteMovies": "Favorite Movies",
"HeaderFavoriteShows": "Favorite Shows",
"HeaderFavoriteEpisodes": "Favorite Episodes",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
"HeaderSelectImagesByNamePath": "Select Images By Name Path",
"HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
"HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Remote access: {0}",
"LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
"HeaderLatestFromChannel": "Latest from {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Unknown language",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Tho\u00e1t",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "Scenes",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "T\u00ean",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "Channels",
+ "HeaderMediaFolders": "Media Folders",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "Ended",
+ "OptionContinuing": "Continuing",
+ "OptionOff": "Off",
+ "OptionOn": "On",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPeople": "People",
+ "OptionRuntime": "Th\u1eddi gian ph\u00e1t",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "M\u00e1y ch\u1ee7",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "Metadata",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "Advanced",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonScenes": "Scenes",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "L\u1ef1a ch\u1ecdn",
+ "ButtonNew": "M\u1edbi",
+ "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": "T\u00ean:",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Movies",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episodes",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Season number:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "C\u00e1c phim",
+ "TabSeries": "Series",
+ "TabEpisodes": "C\u00e1c t\u1eadp phim",
+ "TabTrailers": "Trailers",
+ "TabGames": "Games",
+ "TabAlbums": "C\u00e1c Album",
+ "TabSongs": "C\u00e1c ca kh\u00fac",
+ "TabMusicVideos": "C\u00e1c video \u00e2m nh\u1ea1c",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json
index 85ccd54eb..dc4e7eb84 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json
@@ -1,12 +1,4 @@
{
- "CreatePassword": "\u5275\u5efa\u5bc6\u78bc",
- "OptionOff": "\u95dc\u9589",
- "OptionOn": "\u958b\u555f",
- "LabelAborted": "(Aborted by server shutdown)",
- "MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
- "ButtonNextTrack": "Next Track",
- "ButtonPreviousTrack": "Previous Track",
- "HeaderMyLibrary": "My Library",
"SettingsSaved": "\u8a2d\u7f6e\u5df2\u4fdd\u5b58\u3002",
"AddUser": "\u6dfb\u52a0\u7528\u6236",
"Users": "\u7528\u6236",
@@ -46,7 +38,6 @@
"LabelEpisode": "Episode",
"LabelSeries": "Series",
"LabelStopping": "Stopping",
- "ButtonStop": "Stop",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
@@ -66,12 +57,15 @@
"LabelUnknownLanguage": "Unknown language",
"ButtonMute": "Mute",
"ButtonUnmute": "Unmute",
+ "ButtonStop": "Stop",
+ "ButtonNextTrack": "Next Track",
"ButtonPause": "Pause",
"ButtonPlay": "\u64ad\u653e",
"ButtonEdit": "\u7de8\u8f2f",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "PlayTrailer",
+ "ButtonPlayTrailer": "Play trailer",
"ButtonPlaylist": "Playlist",
+ "ButtonPreviousTrack": "Previous Track",
"LabelEnabled": "Enabled",
"LabelDisabled": "Disabled",
"ButtonMoreInformation": "More Information",
@@ -112,7 +106,6 @@
"HeaderResetTuner": "Reset Tuner",
"MessageConfirmResetTuner": "Are you sure you wish to reset this tuner? Any active players or recordings will be abruptly stopped.",
"ButtonCancelSeries": "Cancel Series",
- "LabelAllChannels": "All channels",
"HeaderSeriesRecordings": "Series Recordings",
"LabelAnytime": "Any time",
"StatusRecording": "Recording",
@@ -130,7 +123,8 @@
"HeaderMyViews": "My Views",
"HeaderLibraryFolders": "Media Folders",
"HeaderLatestMedia": "Latest Media",
- "ButtonMore": "More...",
+ "ButtonMoreItems": "More...",
+ "ButtonMore": "More",
"HeaderFavoriteMovies": "Favorite Movies",
"HeaderFavoriteShows": "Favorite Shows",
"HeaderFavoriteEpisodes": "Favorite Episodes",
@@ -142,7 +136,7 @@
"HeaderSelectTranscodingPath": "Select Transcoding Temporary Path",
"HeaderSelectImagesByNamePath": "Select Images By Name Path",
"HeaderSelectMetadataPath": "Select Metadata Path",
- "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable. The location of this folder will directly impact server performance and should ideally be placed on a solid state drive.",
+ "HeaderSelectServerCachePathHelp": "Browse or enter the path to use for server cache files. The folder must be writeable.",
"HeaderSelectTranscodingPathHelp": "Browse or enter the path to use for transcoding temporary files. The folder must be writeable.",
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
@@ -185,7 +179,6 @@
"LabelVideoCodec": "Video: {0}",
"LabelRemoteAccessUrl": "Remote access: {0}",
"LabelRunningOnPort": "Running on port {0}.",
- "LabelRunningOnPorts": "Running on ports {0} and {1}.",
"HeaderLatestFromChannel": "Latest from {0}",
"ButtonDownload": "Download",
"LabelUnknownLanaguage": "Unknown language",
@@ -193,5 +186,248 @@
"MessageDownloadQueued": "The download has been queued.",
"MessageAreYouSureDeleteSubtitles": "Are you sure you wish to delete this subtitle file?",
"ButtonRemoteControl": "Remote Control",
- "HeaderLatestTvRecordings": "Latest Recordings"
+ "HeaderLatestTvRecordings": "Latest Recordings",
+ "ButtonOk": "OK",
+ "ButtonCancel": "\u53d6\u6d88",
+ "ButtonRefresh": "Refresh",
+ "LabelCurrentPath": "Current path:",
+ "HeaderSelectMediaPath": "Select Media Path",
+ "ButtonNetwork": "Network",
+ "MessageDirectoryPickerInstruction": "Network paths can be entered manually in the event the Network button fails to locate your devices. For example, {0} or {1}.",
+ "HeaderMenu": "Menu",
+ "ButtonOpen": "Open",
+ "ButtonOpenInNewTab": "Open in new tab",
+ "ButtonShuffle": "Shuffle",
+ "ButtonInstantMix": "Instant mix",
+ "ButtonResume": "Resume",
+ "HeaderScenes": "\u5834\u666f",
+ "HeaderAudioTracks": "Audio Tracks",
+ "HeaderSubtitles": "Subtitles",
+ "HeaderVideoQuality": "Video Quality",
+ "MessageErrorPlayingVideo": "There was an error playing the video.",
+ "MessageEnsureOpenTuner": "Please ensure there is an open tuner availalble.",
+ "ButtonHome": "Home",
+ "ButtonDashboard": "Dashboard",
+ "ButtonReports": "Reports",
+ "ButtonMetadataManager": "Metadata Manager",
+ "HeaderTime": "Time",
+ "HeaderName": "Name",
+ "HeaderAlbum": "Album",
+ "HeaderAlbumArtist": "Album Artist",
+ "HeaderArtist": "Artist",
+ "LabelAddedOnDate": "Added {0}",
+ "ButtonStart": "Start",
+ "HeaderChannels": "\u983b\u5ea6",
+ "HeaderMediaFolders": "\u5a92\u9ad4\u6587\u4ef6\u593e",
+ "HeaderBlockItemsWithNoRating": "Block items with no rating information:",
+ "OptionBlockOthers": "Others",
+ "OptionBlockTvShows": "TV Shows",
+ "OptionBlockTrailers": "Trailers",
+ "OptionBlockMusic": "Music",
+ "OptionBlockMovies": "Movies",
+ "OptionBlockBooks": "Books",
+ "OptionBlockGames": "Games",
+ "OptionBlockLiveTvPrograms": "Live TV Programs",
+ "OptionBlockLiveTvChannels": "Live TV Channels",
+ "OptionBlockChannelContent": "Internet Channel Content",
+ "ButtonRevoke": "Revoke",
+ "MessageConfirmRevokeApiKey": "Are you sure you wish to revoke this api key? The application's connection to Media Browser will be abruptly terminated.",
+ "HeaderConfirmRevokeApiKey": "Revoke Api Key",
+ "ValueContainer": "Container: {0}",
+ "ValueAudioCodec": "Audio Codec: {0}",
+ "ValueVideoCodec": "Video Codec: {0}",
+ "ValueCodec": "Codec: {0}",
+ "ValueConditions": "Conditions: {0}",
+ "LabelAll": "All",
+ "HeaderDeleteImage": "Delete Image",
+ "MessageFileNotFound": "File not found.",
+ "MessageFileReadError": "An error occurred reading this file.",
+ "ButtonNextPage": "Next Page",
+ "ButtonPreviousPage": "Previous Page",
+ "ButtonMoveLeft": "Move left",
+ "ButtonMoveRight": "Move right",
+ "ButtonBrowseOnlineImages": "Browse online images",
+ "HeaderDeleteItem": "Delete Item",
+ "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
+ "MessageValueNotCorrect": "The value entered is not correct. Please try again.",
+ "MessageItemSaved": "Item saved.",
+ "OptionEnded": "\u5b8c\u7d50",
+ "OptionContinuing": "\u6301\u7e8c",
+ "OptionOff": "\u95dc\u9589",
+ "OptionOn": "\u958b\u555f",
+ "HeaderFields": "Fields",
+ "HeaderFieldsHelp": "Slide a field to 'off' to lock it and prevent it's data from being changed.",
+ "HeaderLiveTV": "Live TV",
+ "MissingLocalTrailer": "Missing local trailer.",
+ "MissingPrimaryImage": "Missing primary image.",
+ "MissingBackdropImage": "Missing backdrop image.",
+ "MissingLogoImage": "Missing logo image.",
+ "MissingEpisode": "Missing episode.",
+ "OptionScreenshots": "Screenshots",
+ "OptionBackdrops": "Backdrops",
+ "OptionImages": "Images",
+ "OptionKeywords": "Keywords",
+ "OptionTags": "Tags",
+ "OptionStudios": "Studios",
+ "OptionName": "Name",
+ "OptionOverview": "Overview",
+ "OptionGenres": "Genres",
+ "OptionParentalRating": "\u5bb6\u9577\u8a55\u7d1a",
+ "OptionPeople": "People",
+ "OptionRuntime": "\u64ad\u653e\u9577\u5ea6",
+ "OptionProductionLocations": "Production Locations",
+ "OptionBirthLocation": "Birth Location",
+ "LabelAllChannels": "All channels",
+ "LabelLiveProgram": "LIVE",
+ "LabelNewProgram": "NEW",
+ "LabelPremiereProgram": "PREMIERE",
+ "LabelHDProgram": "HD",
+ "HeaderChangeFolderType": "Change Folder Type",
+ "HeaderChangeFolderTypeHelp": "To change the folder type, please remove and rebuild the collection with the new type.",
+ "HeaderAlert": "Alert",
+ "MessagePleaseRestart": "Please restart to finish updating.",
+ "ButtonRestart": "Restart",
+ "MessagePleaseRefreshPage": "Please refresh this page to receive new updates from the server.",
+ "ButtonHide": "Hide",
+ "MessageSettingsSaved": "Settings saved.",
+ "ButtonSignOut": "Sign Out",
+ "ButtonMyProfile": "My Profile",
+ "ButtonMyPreferences": "My Preferences",
+ "MessageBrowserDoesNotSupportWebSockets": "This browser does not support web sockets. For a better experience, try a newer browser such as Chrome, Firefox, IE10+, Safari (iOS) or Opera.",
+ "LabelInstallingPackage": "Installing {0}",
+ "LabelPackageInstallCompleted": "{0} installation completed.",
+ "LabelPackageInstallFailed": "{0} installation failed.",
+ "LabelPackageInstallCancelled": "{0} installation cancelled.",
+ "TabServer": "\u4f3a\u670d\u5668",
+ "TabUsers": "Users",
+ "TabLibrary": "Library",
+ "TabMetadata": "\u5a92\u9ad4\u8cc7\u6599",
+ "TabDLNA": "DLNA",
+ "TabLiveTV": "Live TV",
+ "TabAutoOrganize": "Auto-Organize",
+ "TabPlugins": "Plugins",
+ "TabAdvanced": "\u9032\u968e",
+ "TabHelp": "Help",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "ButtonFullscreen": "Fullscreen",
+ "ButtonAudioTracks": "Audio Tracks",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonScenes": "Scenes",
+ "ButtonQuality": "Quality",
+ "HeaderNotifications": "Notifications",
+ "HeaderSelectPlayer": "Select Player:",
+ "ButtonSelect": "\u9078\u64c7",
+ "ButtonNew": "\u5275\u5efa",
+ "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": "\u540d\u5b57\uff1a",
+ "ButtonSubmit": "Submit",
+ "LabelSelectPlaylist": "Playlist:",
+ "OptionNewPlaylist": "New playlist...",
+ "MessageAddedToPlaylistSuccess": "Ok",
+ "ButtonViewSeriesRecording": "View series recording",
+ "ValueOriginalAirDate": "Original air date: {0}",
+ "ButtonRemoveFromPlaylist": "Remove from playlist",
+ "HeaderSpecials": "Specials",
+ "HeaderTrailers": "Trailers",
+ "HeaderAudio": "Audio",
+ "HeaderResolution": "Resolution",
+ "HeaderVideo": "Video",
+ "HeaderRuntime": "Runtime",
+ "HeaderCommunityRating": "Community rating",
+ "HeaderParentalRating": "Parental rating",
+ "HeaderReleaseDate": "Release date",
+ "HeaderDateAdded": "Date added",
+ "HeaderSeries": "Series",
+ "HeaderSeason": "Season",
+ "HeaderSeasonNumber": "Season number",
+ "HeaderNetwork": "Network",
+ "HeaderYear": "Year",
+ "HeaderGameSystem": "Game system",
+ "HeaderPlayers": "Players",
+ "HeaderEmbeddedImage": "Embedded image",
+ "HeaderTrack": "Track",
+ "HeaderDisc": "Disc",
+ "OptionMovies": "Movies",
+ "OptionCollections": "Collections",
+ "OptionSeries": "Series",
+ "OptionSeasons": "Seasons",
+ "OptionEpisodes": "Episodes",
+ "OptionGames": "Games",
+ "OptionGameSystems": "Game systems",
+ "OptionMusicArtists": "Music artists",
+ "OptionMusicAlbums": "Music albums",
+ "OptionMusicVideos": "Music videos",
+ "OptionSongs": "Songs",
+ "OptionHomeVideos": "Home videos",
+ "OptionBooks": "Books",
+ "OptionAdultVideos": "Adult videos",
+ "ButtonUp": "Up",
+ "ButtonDown": "Down",
+ "LabelMetadataReaders": "Metadata readers:",
+ "LabelMetadataReadersHelp": "Rank your preferred local metadata sources in order of priority. The first file found will be read.",
+ "LabelMetadataDownloaders": "Metadata downloaders:",
+ "LabelMetadataDownloadersHelp": "Enable and rank your preferred metadata downloaders in order of priority. Lower priority downloaders will only be used to fill in missing information.",
+ "LabelMetadataSavers": "Metadata savers:",
+ "LabelMetadataSaversHelp": "Choose the file formats to save your metadata to.",
+ "LabelImageFetchers": "Image fetchers:",
+ "LabelImageFetchersHelp": "Enable and rank your preferred image fetchers in order of priority.",
+ "ButtonQueueAllFromHere": "Queue all from here",
+ "ButtonPlayAllFromHere": "Play all from here",
+ "LabelDynamicExternalId": "{0} Id:",
+ "HeaderIdentify": "Identify Item",
+ "PersonTypePerson": "Person",
+ "LabelTitleDisplayOrder": "Title display order:",
+ "OptionSortName": "Sort name",
+ "OptionReleaseDate": "Release date",
+ "LabelSeasonNumber": "Season number:",
+ "LabelDiscNumber": "Disc number",
+ "LabelParentNumber": "Parent number",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelTrackNumber": "Track number:",
+ "LabelNumber": "Number:",
+ "LabelReleaseDate": "Release date:",
+ "LabelEndDate": "End date:",
+ "LabelYear": "Year:",
+ "LabelDateOfBirth": "Date of birth:",
+ "LabelBirthYear": "Birth year:",
+ "LabelDeathDate": "Death date:",
+ "HeaderRemoveMediaLocation": "Remove Media Location",
+ "MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
+ "HeaderRenameMediaFolder": "Rename Media Folder",
+ "LabelNewName": "New name:",
+ "HeaderAddMediaFolder": "Add Media Folder",
+ "HeaderAddMediaFolderHelp": "Name (Movies, Music, TV, etc):",
+ "HeaderRemoveMediaFolder": "Remove Media Folder",
+ "MessageTheFollowingLocationWillBeRemovedFromLibrary": "The following media locations will be removed from your library:",
+ "MessageAreYouSureYouWishToRemoveMediaFolder": "Are you sure you wish to remove this media folder?",
+ "ButtonRename": "Rename",
+ "ButtonChangeType": "Change type",
+ "HeaderMediaLocations": "Media Locations",
+ "LabelFolderTypeValue": "Folder type: {0}",
+ "LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
+ "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV shows",
+ "TabMovies": "\u96fb\u5f71",
+ "TabSeries": "\u96fb\u8996\u5287",
+ "TabEpisodes": "\u55ae\u5143",
+ "TabTrailers": "\u9810\u544a",
+ "TabGames": "\u904a\u6232",
+ "TabAlbums": "\u5c08\u8f2f",
+ "TabSongs": "\u6b4c\u66f2",
+ "TabMusicVideos": "Music Videos",
+ "BirthPlaceValue": "Birth place: {0}",
+ "DeathDateValue": "Died: {0}",
+ "BirthDateValue": "Born: {0}"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
index e1f5bcfdc..38a3730e8 100644
--- a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
+++ b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
@@ -235,7 +235,9 @@ namespace MediaBrowser.Server.Implementations.Localization
.Where(i => i != null)
.ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase);
- var countryCode = Path.GetFileNameWithoutExtension(file).Split('-').Last();
+ var countryCode = _fileSystem.GetFileNameWithoutExtension(file)
+ .Split('-')
+ .Last();
_allParentalRatings.TryAdd(countryCode, dict);
}
@@ -371,12 +373,14 @@ namespace MediaBrowser.Server.Implementations.Localization
new LocalizatonOption{ Name="Italian", Value="it"},
new LocalizatonOption{ Name="Kazakh", Value="kk"},
new LocalizatonOption{ Name="Norwegian Bokmål", Value="nb"},
+ new LocalizatonOption{ Name="Polish", Value="pl"},
new LocalizatonOption{ Name="Portuguese (Brazil)", Value="pt-BR"},
new LocalizatonOption{ Name="Portuguese (Portugal)", Value="pt-PT"},
new LocalizatonOption{ Name="Russian", Value="ru"},
- new LocalizatonOption{ Name="Spanish", Value="es"},
+ new LocalizatonOption{ Name="Spanish", Value="es-ES"},
new LocalizatonOption{ Name="Spanish (Mexico)", Value="es-MX"},
new LocalizatonOption{ Name="Swedish", Value="sv"},
+ new LocalizatonOption{ Name="Turkish", Value="tr"},
new LocalizatonOption{ Name="Vietnamese", Value="vi"}
}.OrderBy(i => i.Name);
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ar.json b/MediaBrowser.Server.Implementations/Localization/Server/ar.json
index ef58f37f9..bb05037f9 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ar.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ar.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Updates",
- "HeaderUpdateLevel": "Update Level",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "\u0639\u0631\u0636 \u0641\u0642\u0637 \u0627\u0644\u062a\u0631\u062c\u0645\u0627\u062a \u0627\u0644\u0642\u0633\u0631\u064a\u0629",
- "HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Failed",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "HeaderMyLibrary": "My Library",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "\u062e\u0631\u0648\u062c",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "\u0632\u064a\u0627\u0631\u0629 \u0627\u0644\u0645\u062c\u062a\u0645\u0639",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "\u0642\u064a\u0627\u0633\u0649",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "\u0645\u0634\u0627\u0647\u062f\u0629 \u0645\u0631\u0627\u062c\u0639 \u0627\u0644\u0640 Api",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "\u062a\u0635\u0641\u062d \u0627\u0644\u0645\u0643\u062a\u0628\u0629",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "\u0627\u0639\u062f\u0627\u062f\u0627\u062a \u0645\u064a\u062f\u064a\u0627 \u0628\u0631\u0627\u0648\u0632\u0631",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "\u0641\u062a\u062d \u0645\u062a\u0635\u062d\u0641 \u0627\u0644\u0645\u0643\u062a\u0628\u0629",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "\u0627\u0639\u0627\u062f\u0629 \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u062e\u0627\u062f\u0645",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "\u0639\u0631\u0636 \u0646\u0627\u0641\u0630\u0629 \u0627\u0644\u0633\u062c\u0644",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "\u0627\u0644\u0633\u0627\u0628\u0642",
+ "HeaderPassword": "Password",
"LabelFinish": "\u0627\u0646\u062a\u0647\u0627\u0621",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "\u0627\u0644\u062a\u0627\u0644\u0649",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "\u062a\u0645 \u0627\u0644\u0627\u0646\u062a\u0647\u0627\u0621!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "\u0645\u0631\u062d\u0628\u0627 \u0628\u0643 \u0644\u0644\u0645\u062f\u064a\u0627 \u0628\u0631\u0627\u0648\u0632\u0631!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "\u0645\u064a\u062f\u064a\u0627 \u0628\u0631\u0627\u0648\u0632\u0631",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "\u0645\u0631\u0634\u062f \u0627\u0644\u0627\u0639\u062f\u0627\u062f\u0627\u062a \u0633\u064a\u0633\u0627\u0639\u062f\u0643 \u062e\u0644\u0627\u0644 \u062e\u0637\u0648\u0627\u062a \u0639\u0645\u0644\u064a\u0629 \u0627\u0644\u0627\u0639\u062f\u0627\u062f\u0627\u062a.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "\u0627\u062e\u0628\u0631\u0646\u0627 \u0639\u0646 \u0646\u0641\u0633\u0643",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "\u0627\u0633\u0645\u0643 \u0627\u0644\u0627\u0648\u0644:",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "\u0627\u0644\u0645\u0632\u064a\u062f \u0645\u0646 \u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645\u064a\u0646 \u064a\u0645\u0643\u0646 \u0627\u0636\u0627\u0641\u062a\u0647\u0645 \u0644\u0627\u062d\u0642\u0627 \u0645\u0646 \u0644\u0648\u062d\u0629 \u0627\u0644\u0627\u0639\u062f\u0627\u062f\u0627\u062a.",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "\u0645\u064a\u062f\u064a\u0627 \u0628\u0631\u0627\u0648\u0632\u0631 \u0645\u062f\u0645\u062c \u0628\u0647 \u062f\u0639\u0645 \u0644\u0645\u0644\u0641\u0627\u062a \u062a\u0639\u0631\u064a\u0641 \u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645\u064a\u0646, \u0648\u062a\u0645\u0643\u064a\u0646 \u0643\u0644 \u0645\u0633\u062a\u062e\u062f\u0645 \u0645\u0646 \u062d\u0635\u0648\u0644\u0647 \u0639\u0644\u0649 \u0627\u0639\u062f\u0627\u062f\u0627\u062a \u0627\u0644\u0639\u0631\u0636 \u0627\u0644\u062e\u0627\u0635\u0647 \u0628\u0647\u0645, \u0648\u0627\u0644\u0640 playstate \u0648\u0627\u0644\u0631\u0642\u0627\u0628\u0629 \u0627\u0644\u0627\u0628\u0648\u064a\u0629.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "\u062e\u062f\u0645\u0629 \u0627\u0644\u0648\u0646\u062f\u0648\u0632",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "\u062a\u0645 \u062a\u062b\u0628\u064a\u062a \u062e\u062f\u0645\u0629 \u0627\u0644\u0648\u0646\u062f\u0648\u0632",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "\u0645\u064a\u062f\u064a\u0627 \u0628\u0631\u0627\u0648\u0632\u0631 \u0639\u0627\u062f\u0629 \u064a\u0639\u0645\u0644 \u0643\u0628\u0631\u0646\u0627\u0645\u062c \u0639\u0644\u0649 \u0633\u0637\u062d \u0627\u0644\u0645\u0643\u062a\u0628 \u0645\u0639 \u0627\u064a\u0642\u0648\u0646\u0629 \u0644\u0648\u062d\u0629 \u0627\u0644\u0646\u0638\u0627\u0645, \u0648\u0644\u0643\u0646 \u0627\u0630\u0627 \u0627\u062d\u0628\u0628\u062a \u0645\u0645\u0643\u0646 \u062a\u0634\u063a\u064a\u0644\u0647 \u0643\u062e\u062f\u0645\u0629 \u062e\u0644\u0641\u064a\u0629, \u064a\u0645\u0643\u0646 \u0627\u0646 \u064a\u0628\u062f\u0623 \u0645\u0646 \u062e\u062f\u0645\u0627\u062a \u0627\u0644\u0648\u0646\u062f\u0648\u0632 \u0645\u0646 \u0644\u0648\u062d\u0629 \u0627\u0644\u062a\u062d\u0643\u0645 \u0628\u062f\u0644\u0627 \u0645\u0646 \u0630\u0644\u0643.",
+ "HeaderIdentifyItem": "Identify Item",
"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.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Dashboard<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
"LabelConfigureSettings": "\u0636\u0628\u0637 \u0627\u0644\u0627\u0639\u062f\u0627\u062f\u0627\u062a",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "\u062a\u0641\u0639\u064a\u0644 \u0627\u0633\u062a\u062e\u0631\u0627\u062c \u0635\u0648\u0631 \u0627\u0644\u0641\u064a\u062f\u064a\u0648",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"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.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "\u0645\u0648\u0627\u0641\u0642",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "\u0627\u0644\u063a\u0627\u0621",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "New",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "\u0627\u0639\u062f\u0627\u062f \u0645\u0643\u062a\u0628\u0629 \u0627\u0644\u0648\u0633\u0627\u0626\u0637",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "\u0627\u0636\u0627\u0641\u0629 \u0645\u062c\u0644\u062f \u0644\u0644\u0648\u0633\u0627\u0626\u0637",
+ "LabelWebsite": "Website:",
"LabelFolderType": "\u0646\u0648\u0639 \u0627\u0644\u0645\u062c\u0644\u062f:",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "\u0627\u0644\u0631\u062c\u0648\u0639 \u0627\u0644\u0649 wiki \u0644\u0645\u0643\u062a\u0628\u0629 \u0627\u0644\u0648\u0633\u0627\u0626\u0637",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "\u0627\u0644\u0628\u0644\u062f:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "\u0627\u0644\u0644\u063a\u0629:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "\u0627\u0644\u0644\u063a\u0629 \u0627\u0644\u0645\u0641\u0636\u0644\u0629 \u0644\u0648\u0627\u0635\u0641\u0627\u062a \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a:",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "\u062d\u0641\u0638 \u0627\u0644\u0627\u0639\u0645\u0627\u0644 \u0627\u0644\u0641\u0646\u064a\u0629 \u0648\u0648\u0627\u0635\u0641\u0627\u062a \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0641\u0649 \u0645\u062c\u0644\u062f\u0627\u062a \u0627\u0644\u0648\u0633\u0627\u0626\u0637",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "\u0628\u062d\u0642\u0638 \u0627\u0644\u0627\u0639\u0645\u0627\u0644 \u0627\u0644\u0641\u0646\u064a\u0629 \u0648\u0648\u0627\u0635\u0641\u0627\u062a \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0645\u0628\u0627\u0634\u0631\u0629 \u0641\u0649 \u0645\u062c\u0644\u062f\u0627\u062a \u0627\u0644\u0648\u0633\u0627\u0626\u0637 \u0633\u064a\u0633\u0647\u0644 \u0639\u0644\u064a\u0643 \u0627\u0644\u0648\u0635\u0648\u0644 \u0648\u0639\u0645\u0644 \u0627\u0644\u062a\u0639\u062f\u064a\u0644\u0627\u0627\u062a \u0639\u0644\u064a\u0647\u0627.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "\u062a\u062d\u0645\u064a\u0644 \u0627\u0644\u0627\u0639\u0645\u0627\u0644 \u0627\u0644\u0641\u0646\u064a\u0629 \u0648\u0648\u0627\u0635\u0641\u0627\u062a \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0645\u0646 \u0627\u0644\u0627\u0646\u062a\u0631\u0646\u062a",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "\u064a\u0645\u0643\u0646 \u0644\u0644\u0645\u064a\u062f\u064a\u0627 \u0628\u0631\u0627\u0648\u0632\u0631 \u062a\u062d\u0645\u064a\u0644 \u0627\u0644\u0645\u0639\u0644\u0648\u0645\u0627\u062a \u0639\u0646 \u0648\u0633\u0627\u0626\u0637\u0643 \u0644\u062a\u0641\u0639\u064a\u0644 \u0627\u0644\u0639\u0631\u0648\u0636 \u0627\u0644\u063a\u0646\u064a\u0629.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "\u062a\u0641\u0636\u064a\u0644\u0627\u062a",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "\u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "\u0627\u0644\u062f\u062e\u0648\u0644 \u0627\u0644\u0649 \u0627\u0644\u0645\u0643\u062a\u0628\u0629",
+ "LabelBudget": "Budget",
"TabImage": "\u0635\u0648\u0631\u0629",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "\u0633\u062c\u0644",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "Images",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "Titles",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "\u0627\u0639\u062f\u0627\u062f\u0627\u062a \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u0641\u064a\u062f\u064a\u0648",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "\u0627\u0644\u0644\u063a\u0629 \u0627\u0644\u0645\u0641\u0636\u0644\u0629 \u0644\u0644\u0635\u0648\u062a:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "\u0627\u0644\u0644\u063a\u0629 \u0627\u0644\u0645\u0641\u0636\u0644\u0629 \u0644\u0644\u062a\u0631\u062c\u0645\u0629:",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
"TabProfiles": "\u0633\u062c\u0644 (\u0646\u0628\u0630\u0629)",
+ "HeaderTags": "Tags",
"TabSecurity": "\u062d\u0645\u0627\u064a\u0629",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "\u0627\u0636\u0627\u0641\u0629 \u0645\u0633\u062a\u062e\u062f\u0645",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "\u062a\u062e\u0632\u064a\u0646",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "\u0645\u0633\u062d \u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "\u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631 \u062c\u062f\u064a\u062f\u0629:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "\u062a\u0627\u0643\u064a\u062f \u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631 \u0627\u0644\u062c\u062f\u064a\u062f\u0629:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "\u0627\u0646\u0634\u0627\u0621 \u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "\u0643\u0644\u0645\u0629 \u0627\u0644\u0633\u0631 \u0627\u0644\u062d\u0627\u0644\u064a\u0629",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "\u0627\u0644\u062d\u062f \u0627\u0644\u0627\u0642\u0635\u0649 \u0644\u0644\u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0645\u0633\u0645\u0648\u062d \u0628\u0647 \u0644\u0644\u0631\u0642\u0627\u0628\u0629 \u0627\u0644\u0627\u0628\u0648\u064a\u0629:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "\u0627\u0632\u0627\u0644\u0629 \u0635\u0648\u0631\u0629",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "Select users:",
+ "OptionActor": "Actor",
"ButtonUpload": "\u062a\u062d\u0645\u064a\u0644",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "\u062a\u062d\u0645\u064a\u0644 \u0635\u0648\u0631\u0629 \u062c\u062f\u064a\u062f\u0629",
+ "OptionDirector": "Director",
"LabelDropImageHere": "\u0627\u0633\u0642\u0627\u0637 \u0627\u0644\u0635\u0648\u0631\u0629 \u0647\u0646\u0627",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "\u0644\u0627 \u0634\u0649\u0621 \u0647\u0646\u0627.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "\u0645\u0642\u062a\u0631\u062d",
+ "LabelAirTime": "Air time:",
"TabLatest": "\u0627\u0644\u0627\u062e\u064a\u0631",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "\u0627\u0644\u0642\u0627\u062f\u0645",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "\u0627\u0644\u0645\u0633\u0644\u0633\u0644\u0627\u062a",
"TabEpisodes": "\u0627\u0644\u062d\u0644\u0642\u0627\u062a",
"TabGenres": "\u0627\u0646\u0648\u0627\u0639",
@@ -163,7 +225,7 @@
"OptionAscending": "\u062a\u0635\u0627\u0639\u062f\u0649",
"OptionDescending": "\u062a\u0646\u0627\u0632\u0644\u0649",
"OptionRuntime": "\u0632\u0645\u0646 \u0627\u0644\u062a\u0634\u063a\u064a\u0644",
- "OptionReleaseDate": "\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0627\u0635\u062f\u0627\u0631",
+ "OptionReleaseDate": "Release Date",
"OptionPlayCount": "\u0639\u062f\u062f \u0627\u0644\u062a\u0634\u063a\u064a\u0644",
"OptionDatePlayed": "\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u062a\u0634\u063a\u064a\u0644",
"OptionDateAdded": "\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0627\u0636\u0627\u0641\u0629",
@@ -213,6 +275,8 @@
"TabMovies": "Movies",
"TabStudios": "Studios",
"TabTrailers": "Trailers",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "Latest Movies",
"HeaderLatestTrailers": "Latest Trailers",
"OptionHasSpecialFeatures": "Special Features",
@@ -224,7 +288,7 @@
"HeaderStatus": "Status",
"OptionContinuing": "Continuing",
"OptionEnded": "Ended",
- "HeaderAirDays": "Air Days:",
+ "HeaderAirDays": "Air Days",
"OptionSunday": "Sunday",
"OptionMonday": "Monday",
"OptionTuesday": "Tuesday",
@@ -232,7 +296,8 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
- "HeaderManagement": "Management:",
+ "HeaderManagement": "Management",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "Missing IMDb Id",
"OptionMissingTvdbId": "Missing TheTVDB Id",
"OptionMissingOverview": "Missing Overview",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "Select",
- "ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
@@ -290,13 +354,13 @@
"ButtonSelectDirectory": "Select Directory",
"LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.",
"LabelCachePath": "Cache path:",
- "LabelCachePathHelp": "This folder contains server cache files, such as images.",
+ "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.",
"LabelImagesByNamePath": "Images by name path:",
- "LabelImagesByNamePathHelp": "This folder contains actor, artist, genre and studio images.",
+ "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.",
"LabelMetadataPath": "Metadata path:",
- "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.",
+ "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.",
+ "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",
@@ -313,12 +377,12 @@
"LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.",
"LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
"LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
- "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "ExtractChapterImagesHelp": "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 when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
"LabelMetadataDownloadLanguage": "Preferred download language:",
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
- "OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
@@ -347,6 +411,8 @@
"TabStatus": "Status",
"TabSettings": "Settings",
"ButtonRefreshGuideData": "Refresh Guide Data",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
"OptionRecordOnAllChannels": "Record program on all channels",
"OptionRecordAnytime": "Record program at any time",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Cast & Crew",
"HeaderAdditionalParts": "Additional Parts",
"ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Missing",
"LabelOffline": "Offline",
"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.",
@@ -512,11 +579,13 @@
"HeaderProgram": "Program",
"HeaderClients": "Clients",
"LabelCompleted": "Completed",
+ "LabelFailed": "Failed",
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeasonNumber": "Season number",
- "LabelEpisodeNumber": "Episode number",
- "LabelEndingEpisodeNumber": "Ending episode number",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Enable this notification",
"LabelMonitorUsers": "Monitor activity from:",
"LabelSendNotificationToUsers": "Send the notification to:",
- "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.",
"LabelUseNotificationServices": "Use the following services:",
"CategoryUser": "User",
"CategorySystem": "System",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
"ButtonHome": "Home",
+ "ButtonSearch": "Search",
"ButtonSettings": "Settings",
"ButtonTakeScreenshot": "Capture Screenshot",
"ButtonLetterUp": "Letter Up",
@@ -661,6 +730,8 @@
"ButtonScenes": "Scenes",
"ButtonSubtitles": "Subtitles",
"ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Group movies into collections",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
"LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "Friendly name",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text",
"HeaderSearchForSubtitles": "Search for Subtitles",
@@ -796,13 +879,13 @@
"OptionAuto": "Auto",
"OptionYes": "Yes",
"OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferences",
"MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Mark Read",
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
"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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
"ButtonDismiss": "Dismiss",
"MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Display adult content",
"OptionLibraryFolders": "Media folders",
"TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 05f519056..36d831887 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ca.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ca.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Updates",
- "HeaderUpdateLevel": "Update Level",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
- "HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Failed",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "HeaderMyLibrary": "My Library",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "Sortir",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "Visitar la comunitat",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "Est\u00e0ndard",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "Veure la documentaci\u00f3 de l'API",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "Examinar la biblioteca",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "Configurar Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "Obrir el visor de la biblioteca",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "Reiniciar el servidor",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "Veure la finestra del registre",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "Anterior",
+ "HeaderPassword": "Password",
"LabelFinish": "Finalitzar",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "Seg\u00fcent",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "Ja est\u00e0!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "Benvingut a Meida Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "Aquest assistent us guiar\u00e0 a trav\u00e9s del proc\u00e9s de configuraci\u00f3.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "Expliqui'ns sobre vost\u00e8",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "El seu nom:",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "M\u00e9s usuaris es poden afegir m\u00e9s tard en el tauler d'instruments.",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser inclou suport integrat per als perfils d'usuari, la qual cosa permet que cada usuari tingui la seva pr\u00f2pia configuraci\u00f3 de pantalla, estat de reproducci\u00f3 i controls dels pares.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Servei de Windows",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "El servei de Windows s'ha instal \u00b7 lat.",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser Server s'executa normalment com una aplicaci\u00f3 d'escriptori amb una icona de la safata, per\u00f2 si ho prefereix, per executar com un servei en segon pla, es pot iniciar des del panell de control de serveis de Windows.",
+ "HeaderIdentifyItem": "Identify Item",
"WindowsServiceIntro2": "Si s'utilitza el servei de Windows, tingui en compte que no es pot executar a la vegada que la icona de la safata, de manera que haur\u00e0 de sortir de la safata per tal d'executar el servei. Tamb\u00e9 haur\u00e0 de ser configurat amb privilegis administratius a trav\u00e9s del panell de control del servei. Tingueu en compte que en aquest moment el servei no \u00e9s capa\u00e7 d'auto-actualitzaci\u00f3, de manera que les noves versions requereixen la interacci\u00f3 manual.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Dashboard<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
"LabelConfigureSettings": "Configure settings",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Enable video image extraction",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"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.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Cancel",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "New",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Setup your media library",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "Add media folder",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Folder type:",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Refer to the media library wiki.",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "Country:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "Language:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "Preferred metadata language:",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "Save artwork and metadata into media folders",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "Download artwork and metadata from the internet",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "Preferences",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "Password",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "Library Access",
+ "LabelBudget": "Budget",
"TabImage": "Image",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "Profile",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "Images",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "Titles",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "Video Playback Settings",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "Audio language preference:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "Subtitle language preference:",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Profiles",
+ "HeaderTags": "Tags",
"TabSecurity": "Security",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "Add User",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "Save",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "Reset Password",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "New password:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "New password confirm:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "Create Password",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Current password:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "Maximum allowed parental rating:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "Delete Image",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "Select users:",
+ "OptionActor": "Actor",
"ButtonUpload": "Upload",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Upload New Image",
- "LabelDropImageHere": "Drop Image Here",
+ "OptionDirector": "Director",
+ "LabelDropImageHere": "Drop image here",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Nothing here.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Suggested",
+ "LabelAirTime": "Air time:",
"TabLatest": "Latest",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "Upcoming",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Shows",
"TabEpisodes": "Episodes",
"TabGenres": "Genres",
@@ -213,6 +275,8 @@
"TabMovies": "Movies",
"TabStudios": "Studios",
"TabTrailers": "Trailers",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "Latest Movies",
"HeaderLatestTrailers": "Latest Trailers",
"OptionHasSpecialFeatures": "Special Features",
@@ -224,7 +288,7 @@
"HeaderStatus": "Status",
"OptionContinuing": "Continuing",
"OptionEnded": "Ended",
- "HeaderAirDays": "Air Days:",
+ "HeaderAirDays": "Air Days",
"OptionSunday": "Sunday",
"OptionMonday": "Monday",
"OptionTuesday": "Tuesday",
@@ -232,7 +296,8 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
- "HeaderManagement": "Management:",
+ "HeaderManagement": "Management",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "Missing IMDb Id",
"OptionMissingTvdbId": "Missing TheTVDB Id",
"OptionMissingOverview": "Missing Overview",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "Select",
- "ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
@@ -290,13 +354,13 @@
"ButtonSelectDirectory": "Select Directory",
"LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.",
"LabelCachePath": "Cache path:",
- "LabelCachePathHelp": "This folder contains server cache files, such as images.",
+ "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.",
"LabelImagesByNamePath": "Images by name path:",
- "LabelImagesByNamePathHelp": "This folder contains actor, artist, genre and studio images.",
+ "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.",
"LabelMetadataPath": "Metadata path:",
- "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.",
+ "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.",
+ "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",
@@ -313,12 +377,12 @@
"LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.",
"LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
"LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
- "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "ExtractChapterImagesHelp": "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 when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
"LabelMetadataDownloadLanguage": "Preferred download language:",
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
- "OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
@@ -347,6 +411,8 @@
"TabStatus": "Status",
"TabSettings": "Settings",
"ButtonRefreshGuideData": "Refresh Guide Data",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
"OptionRecordOnAllChannels": "Record program on all channels",
"OptionRecordAnytime": "Record program at any time",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Cast & Crew",
"HeaderAdditionalParts": "Additional Parts",
"ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Missing",
"LabelOffline": "Offline",
"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.",
@@ -512,11 +579,13 @@
"HeaderProgram": "Program",
"HeaderClients": "Clients",
"LabelCompleted": "Completed",
+ "LabelFailed": "Failed",
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeasonNumber": "Season number",
- "LabelEpisodeNumber": "Episode number",
- "LabelEndingEpisodeNumber": "Ending episode number",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Enable this notification",
"LabelMonitorUsers": "Monitor activity from:",
"LabelSendNotificationToUsers": "Send the notification to:",
- "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.",
"LabelUseNotificationServices": "Use the following services:",
"CategoryUser": "User",
"CategorySystem": "System",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
"ButtonHome": "Home",
+ "ButtonSearch": "Search",
"ButtonSettings": "Settings",
"ButtonTakeScreenshot": "Capture Screenshot",
"ButtonLetterUp": "Letter Up",
@@ -661,6 +730,8 @@
"ButtonScenes": "Scenes",
"ButtonSubtitles": "Subtitles",
"ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Group movies into collections",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
"LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "Friendly name",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text",
"HeaderSearchForSubtitles": "Search for Subtitles",
@@ -796,13 +879,13 @@
"OptionAuto": "Auto",
"OptionYes": "Yes",
"OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferences",
"MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Mark Read",
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
"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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
"ButtonDismiss": "Dismiss",
"MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Display adult content",
"OptionLibraryFolders": "Media folders",
"TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 167e21db8..d3acad939 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/cs.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/cs.json
@@ -1,135 +1,197 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Aktualizace",
- "HeaderUpdateLevel": "Level aktualizace",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "Zobrazit pouze vynucen\u00e9 titulky",
- "HeaderCustomizeOptionsPerMediaType": "Upravit nastaven\u00ed podle typu m\u00e9dia",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Chyba",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "HeaderMyLibrary": "My Library",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "Zav\u0159\u00edt",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "Nav\u0161t\u00edvit komunitu",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "Standardn\u00ed",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "Zobrazit dokumentaci API",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "Proch\u00e1zet knihovnu",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "Konfigurovat Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "Otev\u0159\u00edt knihovnu",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "Restartovat server",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "Zobrazit okno z\u00e1znam\u016f",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "P\u0159edchoz\u00ed",
+ "HeaderPassword": "Password",
"LabelFinish": "Dokon\u010dit",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "Dal\u0161\u00ed",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "Hotovo!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "V\u00edtejte v programu Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "Tento pr\u016fvodce V\u00e1m pom\u016f\u017ee proj\u00edt procesem nastaven\u00ed. Pro za\u010d\u00e1tek vyberte jazyk.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "\u0158ekn\u011bte n\u00e1m n\u011bco o sob\u011b",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "Va\u0161e k\u0159estn\u00ed jm\u00e9no:",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "Dal\u0161\u00ed u\u017eivatele m\u016f\u017eete p\u0159idat pozd\u011bji na n\u00e1st\u011bnce.",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser obsahuje zabudovanou podporu u\u017eivatelsk\u00fdch profil\u016f dovoluj\u00edc\u00ed ka\u017ed\u00e9mu u\u017eivateli konfigurovat nastaven\u00ed zobrazen\u00ed, p\u0159ehr\u00e1v\u00e1n\u00ed a rodi\u010dovskou kontrolu.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Slu\u017eba Windows",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "Slu\u017eba Windows byla nainstalov\u00e1na.",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser b\u011b\u017e\u00ed standardn\u011b jako desktopov\u00e1 aplikace s ikonou v oznamovac\u00ed oblasti, pokud ov\u0161em preferujete nastaven\u00ed jako slu\u017eby na pozad\u00ed, m\u016f\u017eete tak u\u010dinit v ovl\u00e1dac\u00edch panelech Va\u0161eho syst\u00e9mu pod polo\u017ekou Slu\u017eby Windows.",
+ "HeaderIdentifyItem": "Identify Item",
"WindowsServiceIntro2": "Pokud pou\u017e\u00edv\u00e1te Slu\u017ebu Windows berte na v\u011bdom\u00ed, \u017ee nem\u016f\u017ee b\u00fdt spu\u0161t\u011bna z\u00e1rove\u0148 s programem v oznamovac\u00ed oblasti. Bude nutn\u00e9 b\u011b\u017e\u00edc\u00ed aplikaci v oznamovac\u00ed oblasti ukon\u010dit. Slu\u017eba Windows mus\u00ed b\u00fdt z\u00e1rove\u0148 nakonfigurov\u00e1na s pr\u00e1vy administr\u00e1tora v ovl\u00e1dac\u00edch panelech. V tuto chv\u00edli slu\u017eba neumo\u017e\u0148uje automatickou aktualizaci, bude proto nutn\u00e9 novou verzi nainstalovat ru\u010dn\u011b.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "To je v\u0161e co prozat\u00edm pot\u0159ebujeme. Media Browser za\u010dne shroma\u017e\u010fovat informace o m\u00e9di\u00edch ve Va\u0161\u00ed knihovn\u011b. Pod\u00edvejte se na n\u011bkter\u00e9 z na\u0161ich aplikac\u00ed, a potom klepn\u011bte na tla\u010d\u00edtko <b>Dokon\u010dit<\/b> pro zobrazen\u00ed <b>Hlavn\u00edho panelu<\/b>",
+ "HeaderConfirmDeletion": "Potvrdit smaz\u00e1n\u00ed",
"LabelConfigureSettings": "Konfigurovat nastaven\u00ed",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Povolit extrahov\u00e1n\u00ed obr\u00e1zku ze souboru",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"VideoImageExtractionHelp": "Pro videa, kter\u00e9 je\u0161t\u011b nemaj\u00ed obr\u00e1zky obalu, a zat\u00edm nejsme schopni je dohledat. Tato operace vy\u017eaduje n\u011bjak\u00fd ten \u010das nav\u00edc, ve v\u00fdsledku ale p\u0159isp\u011bje k hez\u010d\u00edmu zobrazen\u00ed knihovny.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Extrahov\u00e1n\u00ed obr\u00e1zk\u016f sc\u00e9n pro Filmy",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "Extrahov\u00e1n\u00ed obr\u00e1zk\u016f sc\u00e9n pro Filmy dovol\u00ed klientovi graficky zobrazit v\u00fdb\u011br sc\u00e9n v menu. Proces m\u016f\u017ee b\u00fdt pomal\u00fd a n\u00e1ro\u010dn\u00fd na v\u00fdkon procesoru, z\u00e1rove\u0148 m\u016f\u017ee vy\u017eadovat n\u011bkolik gigabyt\u016f prostoru. Tento proces b\u011b\u017e\u00ed pl\u00e1novan\u011b ve 4 hodiny r\u00e1no (mo\u017en\u00e9 nastavit). Nen\u00ed doporu\u010deno nastavovat v dob\u011b vyu\u017e\u00edv\u00e1n\u00ed knihovny.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Povolit automatick\u00e9 mapov\u00e1n\u00ed port\u016f",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP umo\u017e\u0148uje automatick\u00e9 nastaven\u00ed routeru pro vzd\u00e1len\u00fd p\u0159\u00edstup. Nemus\u00ed fungovat s n\u011bkter\u00fdmi typy router\u016f.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Zru\u0161it",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "Nov\u00e9",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Nastaven\u00ed Va\u0161i knihovny m\u00e9di\u00ed",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "P\u0159idat slo\u017eku m\u00e9di\u00ed",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Typ slo\u017eky:",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Vy\u017eaduje pou\u017eit\u00ed pluginu, nap\u0159. GameBrowser nebo MB Bookshelf",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Pod\u00edvejte se na wiki knihovny m\u00e9di\u00ed.",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "Zem\u011b:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "Jazyk:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "Preferovan\u00fd jazyk metadat:",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "Ulo\u017eit p\u0159ebaly a metadata do slo\u017eky s m\u00e9dii",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "Povol\u00edte-li ulo\u017een\u00ed p\u0159ebal\u016f a metadat do slo\u017eky s m\u00e9dii bude mo\u017en\u00e9 je jednodu\u0161e upravovat.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "St\u00e1hnout p\u0159ebal a metadata z internetu",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser m\u016f\u017ee st\u00e1hnout informace o Va\u0161ich m\u00e9di\u00edch z internetu pro bohat\u0161\u00ed prezentaci.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "P\u0159edvolby",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "Heslo",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "P\u0159\u00edstup ke knihovn\u011b",
+ "LabelBudget": "Budget",
"TabImage": "Obr\u00e1zek",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "Profil",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "Obr\u00e1zky",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "N\u00e1zvy",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Zobrazit chyb\u011bj\u00edc\u00ed epizody",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Zobrazit neprov\u011btran\u00e9 epizody v r\u00e1mci sez\u00f3n",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "Nastaven\u00ed p\u0159ehr\u00e1v\u00e1n\u00ed videa",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "Up\u0159ednost\u0148ovan\u00fd jazyk videa:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "Up\u0159ednost\u0148ovan\u00fd jazyk titulk\u016f:",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Default",
- "OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
+ "OptionOnlyForcedSubtitles": "Pouze vynucen\u00e9 titulky",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Profily",
+ "HeaderTags": "Tags",
"TabSecurity": "Zabezpe\u010den\u00ed",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "P\u0159idat u\u017eivatele",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "Ulo\u017eit",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "Obnovit heslo",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "Nov\u00e9 heslo:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "Potvrzen\u00ed nov\u00e9ho heslo:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "Vytvo\u0159it heslo",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Aktu\u00e1ln\u00ed heslo:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "Maxim\u00e1ln\u00ed povolen\u00e9 rodi\u010dovsk\u00e9 hodnocen\u00ed:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "Obsah s vy\u0161\u0161\u00edm hodnocen\u00edm bude tomuto u\u017eivateli blokov\u00e1n.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "Vyberte slo\u017eky m\u00e9di\u00ed pro sd\u00edlen\u00ed s t\u00edmto u\u017eivatelem. Administr\u00e1to\u0159i budou moci editovat v\u0161echny slo\u017eky pomoc\u00ed metadata mana\u017eeru.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "Odstranit obr\u00e1zek",
- "LabelSelectUsers": "Select users:",
+ "LabelOneTimeDonationAmount": "Donation amount:",
+ "LabelSelectUsers": "Vyberte u\u017eivatele:",
+ "OptionActor": "Actor",
"ButtonUpload": "Nahr\u00e1t",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Nahr\u00e1t nov\u00fd obr\u00e1zek",
+ "OptionDirector": "Director",
"LabelDropImageHere": "P\u0159esu\u0148te obr\u00e1zek zde",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "Doporu\u010den pom\u011br 1:1. Pouze JPG\/PNG.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Tady nic nen\u00ed.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "Pros\u00edm zkontrolujte, zda m\u00e1te povoleno stahov\u00e1n\u00ed metadat z internetu.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Doporu\u010den\u00e9",
+ "LabelAirTime": "Air time:",
"TabLatest": "Posledn\u00ed",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "Nadch\u00e1zej\u00edc\u00ed",
- "TabShows": "Shows",
+ "HeaderPhotoInfo": "Photo Info",
+ "TabShows": "Seri\u00e1ly",
"TabEpisodes": "Epizody",
"TabGenres": "\u017d\u00e1nry",
"TabPeople": "Lid\u00e9",
@@ -163,7 +225,7 @@
"OptionAscending": "Vzestupn\u011b",
"OptionDescending": "Sestupn\u011b",
"OptionRuntime": "D\u00e9lka",
- "OptionReleaseDate": "Datum vyd\u00e1n\u00ed",
+ "OptionReleaseDate": "Release Date",
"OptionPlayCount": "Po\u010det p\u0159ehr\u00e1n\u00ed",
"OptionDatePlayed": "Datum p\u0159ehr\u00e1n\u00ed",
"OptionDateAdded": "Datum p\u0159id\u00e1n\u00ed",
@@ -203,8 +265,8 @@
"Option3D": "3D",
"LabelFeatures": "Vlastnosti:",
"LabelService": "Service:",
- "LabelStatus": "Status:",
- "LabelVersion": "Version:",
+ "LabelStatus": "Stav:",
+ "LabelVersion": "Verze:",
"LabelLastResult": "Last result:",
"OptionHasSubtitles": "Titulky",
"OptionHasTrailer": "Uk\u00e1zka\/trailer",
@@ -213,6 +275,8 @@
"TabMovies": "Filmy",
"TabStudios": "Studia",
"TabTrailers": "Uk\u00e1zky\/trailery",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "Posledn\u00ed filmy",
"HeaderLatestTrailers": "Posledn\u00ed uk\u00e1zky\/trailery",
"OptionHasSpecialFeatures": "Speci\u00e1ln\u00ed funkce",
@@ -233,14 +297,15 @@
"OptionFriday": "P\u00e1tek",
"OptionSaturday": "Sobota",
"HeaderManagement": "Management:",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "Chyb\u011bj\u00edc\u00ed IMDb Id",
"OptionMissingTvdbId": "Chyb\u011bj\u00edc\u00ed TheTVDB Id",
"OptionMissingOverview": "Chyb\u011bj\u00edc\u00ed p\u0159ehled",
"OptionFileMetadataYearMismatch": "Neodpov\u00edd\u00e1 rok v metadatech a v souboru.",
"TabGeneral": "Obecn\u00e9",
"TitleSupport": "Podpora",
- "TabLog": "Log",
- "TabAbout": "About",
+ "TabLog": "Z\u00e1znam",
+ "TabAbout": "O programu",
"TabSupporterKey": "Kl\u00ed\u010d sponzora",
"TabBecomeSupporter": "Sta\u0148te se sponzorem",
"MediaBrowserHasCommunity": "Media Browser m\u00e1 prosp\u00edvaj\u00edc\u00ed komunitu u\u017eivatel\u016f a p\u0159isp\u011bvatel\u016f.",
@@ -264,9 +329,8 @@
"OptionMissingTmdbId": "Chyb\u011bj\u00edc\u00ed Tmdb Id",
"OptionIsHD": "HD",
"OptionIsSD": "SD",
- "OptionMetascore": "Metascore",
+ "OptionMetascore": "Metask\u00f3re",
"ButtonSelect": "Vybrat",
- "ButtonSearch": "Hled\u00e1n\u00ed",
"ButtonGroupVersions": "Skupinov\u00e9 verze",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "Vyu\u017e\u00edv\u00e1me spr\u00e1vce soubor\u016f \"Pismo\" skrze dotovanou licenci.",
@@ -296,7 +360,7 @@
"LabelMetadataPath": "Adres\u00e1\u0159 pro metadata:",
"LabelMetadataPathHelp": "Tato slo\u017eka obsahuje metadata a obaly film\u016f. Pokud nen\u00ed nastaveno ukl\u00e1d\u00e1n\u00ed do slo\u017eky s m\u00e9dii.",
"LabelTranscodingTempPath": "Adres\u00e1\u0159 p\u0159ek\u00f3dov\u00e1n\u00ed:",
- "LabelTranscodingTempPathHelp": "Tato slo\u017eka obsahuje soubory pot\u0159ebn\u00e9 pro p\u0159ek\u00f3dov\u00e1n\u00ed vide\u00ed.",
+ "LabelTranscodingTempPathHelp": "Tato slo\u017eka obsahuje soubory pot\u0159ebn\u00e9 pro p\u0159ek\u00f3dov\u00e1n\u00ed vide\u00ed. Zadejte vlastn\u00ed cestu, nebo ponechte pr\u00e1zdn\u00e9 pro pou\u017eit\u00ed v\u00fdchoz\u00ed datov\u00e9 slo\u017eky serveru.",
"TabBasics": "Z\u00e1klady",
"TabTV": "Tv",
"TabGames": "Hry",
@@ -318,8 +382,8 @@
"ButtonAutoScroll": "Automatick\u00e9 posouv\u00e1n\u00ed",
"LabelImageSavingConvention": "Konvence ukl\u00e1d\u00e1n\u00ed obr\u00e1zk\u016f:",
"LabelImageSavingConventionHelp": "Media Browser rozpozn\u00e1 obr\u00e1zky z v\u011bt\u0161iny velk\u00fdch medi\u00e1ln\u00edch aplikac\u00ed. Nastavte v p\u0159\u00edpad\u011b, \u017ee vyu\u017e\u00edv\u00e1te jin produkt.",
- "OptionImageSavingCompatible": "Kompatibiln\u00ed - MB3\/Plex\/XBMC",
- "OptionImageSavingStandard": "Standardn\u00ed - MB3\/MB2",
+ "OptionImageSavingCompatible": "Kompatibiln\u00ed - Media Browser\/XBMC\/Plex",
+ "OptionImageSavingStandard": "Standardn\u00ed - MB2",
"ButtonSignIn": "P\u0159ihl\u00e1sit se",
"TitleSignIn": "P\u0159ihl\u00e1sit se",
"HeaderPleaseSignIn": "Pros\u00edme, p\u0159ihlaste se",
@@ -329,7 +393,7 @@
"PasswordLocalhostMessage": "Heslo nen\u00ed nutn\u00e9, pokud se p\u0159ihla\u0161ujete z m\u00edstn\u00edho PC-",
"TabGuide": "Pr\u016fvodce",
"TabChannels": "Kan\u00e1ly",
- "TabCollections": "Collections",
+ "TabCollections": "Kolekce",
"HeaderChannels": "Kan\u00e1ly",
"TabRecordings": "Nahran\u00e9",
"TabScheduled": "Napl\u00e1nov\u00e1no",
@@ -347,6 +411,8 @@
"TabStatus": "Stav",
"TabSettings": "Nastaven\u00ed",
"ButtonRefreshGuideData": "Obnovit data pr\u016fvodce",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priorita",
"OptionRecordOnAllChannels": "Nahr\u00e1vat program na v\u0161ech kan\u00e1lech",
"OptionRecordAnytime": "Nahr\u00e1vat program v jak\u00fdkoliv \u010das",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Herci a obsazen\u00ed",
"HeaderAdditionalParts": "Dal\u0161\u00ed sou\u010d\u00e1sti",
"ButtonSplitVersionsApart": "Rozd\u011blit verze od sebe",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Chyb\u00ed",
"LabelOffline": "Offline",
"PathSubstitutionHelp": "Nahrazen\u00ed cest se pou\u017e\u00edv\u00e1 pro namapov\u00e1n\u00ed cest k serveru, kter\u00e9 je p\u0159\u00edstupn\u00e9 u\u017eivateli. Povolen\u00edm p\u0159\u00edm\u00e9ho p\u0159\u00edstupu m\u016f\u017ee umo\u017enit u\u017eivateli jeho p\u0159ehr\u00e1n\u00ed bez u\u017eit\u00ed streamov\u00e1n\u00ed a p\u0159ek\u00f3dov\u00e1n\u00ed servru.",
@@ -503,8 +570,8 @@
"LabelMinResumePercentageHelp": "Tituly budou ozna\u010deny jako \"nep\u0159ehr\u00e1no\", pokud budou zastaveny p\u0159ed t\u00edmto \u010dasem.",
"LabelMaxResumePercentageHelp": "Tituly budou ozna\u010deny jako \"p\u0159ehr\u00e1no\", pokud budou zastaveny po tomto \u010dase",
"LabelMinResumeDurationHelp": "Tituly krat\u0161\u00ed, ne\u017e tento \u010das nebudou pozastaviteln\u00e9.",
- "TitleAutoOrganize": "Auto-Organize",
- "TabActivityLog": "Activity Log",
+ "TitleAutoOrganize": "Automatick\u00e9 uspo\u0159\u00e1dan\u00ed",
+ "TabActivityLog": "Z\u00e1znam \u010dinnosti",
"HeaderName": "N\u00e1zev",
"HeaderDate": "Datum",
"HeaderSource": "Zdroj",
@@ -512,70 +579,72 @@
"HeaderProgram": "Program",
"HeaderClients": "Klienti",
"LabelCompleted": "Hotovo",
- "LabelSkipped": "Skipped",
- "HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeasonNumber": "Season number",
- "LabelEpisodeNumber": "Episode number",
- "LabelEndingEpisodeNumber": "Ending episode number",
- "LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
- "HeaderSupportTheTeam": "Support the Media Browser Team",
- "LabelSupportAmount": "Amount (USD)",
- "HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.",
- "ButtonEnterSupporterKey": "Enter supporter key",
+ "LabelFailed": "Failed",
+ "LabelSkipped": "P\u0159esko\u010deno",
+ "HeaderEpisodeOrganization": "Organizace epizod",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "\u010c\u00edslo s\u00e9rie",
+ "LabelEpisodeNumber": "\u010c\u00edslo epizody",
+ "LabelEndingEpisodeNumber": "\u010c\u00edslo posledn\u00ed epizody",
+ "LabelEndingEpisodeNumberHelp": "Vy\u017eadovan\u00e9 jenom pro s\u00fabory s v\u00edce epizodami",
+ "HeaderSupportTheTeam": "Podpo\u0159te t\u00edm Media Browser",
+ "LabelSupportAmount": "Suma (USD)",
+ "HeaderSupportTheTeamHelp": "Pomozte zajistit pokra\u010dov\u00e1n\u00ed v\u00fdvoje tohoto projektu t\u00edm, \u017ee daruje. \u010c\u00e1st v\u0161ech dar\u016f bude pou\u017eita na dal\u0161\u00ed bezplatn\u00e9 n\u00e1stroje na kter\u00fdch jsme z\u00e1visl\u00ed.",
+ "ButtonEnterSupporterKey": "Vlo\u017ete kl\u00ed\u010d sponzora",
"DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.",
"AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.",
"AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.",
- "OptionEnableEpisodeOrganization": "Enable new episode organization",
- "LabelWatchFolder": "Watch folder:",
+ "OptionEnableEpisodeOrganization": "Povolit organizaci nov\u00fdch epizod",
+ "LabelWatchFolder": "Pozrie\u0165 slo\u017eku:",
"LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.",
- "ButtonViewScheduledTasks": "View scheduled tasks",
- "LabelMinFileSizeForOrganize": "Minimum file size (MB):",
- "LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.",
+ "ButtonViewScheduledTasks": "Zobrazit napl\u00e1novan\u00e9 \u00falohy",
+ "LabelMinFileSizeForOrganize": "Minim\u00e1ln\u00ed velikost souboru (MB):",
+ "LabelMinFileSizeForOrganizeHelp": "Men\u0161\u00ed soubory budou ignorov\u00e1ny.",
"LabelSeasonFolderPattern": "Season folder pattern:",
"LabelSeasonZeroFolderName": "Season zero folder name:",
"HeaderEpisodeFilePattern": "Episode file pattern",
"LabelEpisodePattern": "Episode pattern:",
"LabelMultiEpisodePattern": "Multi-Episode pattern:",
- "HeaderSupportedPatterns": "Supported Patterns",
+ "HeaderSupportedPatterns": "Podporovan\u00e9 vzory",
"HeaderTerm": "Term",
- "HeaderPattern": "Pattern",
- "HeaderResult": "Result",
- "LabelDeleteEmptyFolders": "Delete empty folders after organizing",
- "LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.",
- "LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:",
- "LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt",
- "OptionOverwriteExistingEpisodes": "Overwrite existing episodes",
- "LabelTransferMethod": "Transfer method",
- "OptionCopy": "Copy",
- "OptionMove": "Move",
+ "HeaderPattern": "Vzor",
+ "HeaderResult": "V\u00fdsledek",
+ "LabelDeleteEmptyFolders": "Odstranit pr\u00e1zdn\u00e9 slo\u017eky po zorganizov\u00e1n\u00ed",
+ "LabelDeleteEmptyFoldersHelp": "Povolit tohle, aby byl adres\u00e1\u0159 pro stahov\u00e1n\u00ed \u010dist\u00fd.",
+ "LabelDeleteLeftOverFiles": "Smazat zbyl\u00e9 soubory s n\u00e1sleduj\u00edc\u00edmi p\u0159\u00edponami:",
+ "LabelDeleteLeftOverFilesHelp": "Odd\u011blte ;. Nap\u0159.: .nfo;.txt",
+ "OptionOverwriteExistingEpisodes": "P\u0159epsat existuj\u00edc\u00ed epizody",
+ "LabelTransferMethod": "Metoda p\u0159enosu",
+ "OptionCopy": "Kop\u00edrovat",
+ "OptionMove": "P\u0159esunout",
"LabelTransferMethodHelp": "Copy or move files from the watch folder",
- "HeaderLatestNews": "Latest News",
- "HeaderHelpImproveMediaBrowser": "Help Improve Media Browser",
- "HeaderRunningTasks": "Running Tasks",
- "HeaderActiveDevices": "Active Devices",
- "HeaderPendingInstallations": "Pending Installations",
- "HeaerServerInformation": "Server Information",
- "ButtonRestartNow": "Restart Now",
+ "HeaderLatestNews": "Posledn\u00ed novinky",
+ "HeaderHelpImproveMediaBrowser": "Pomozte vylep\u0161it Media Browser",
+ "HeaderRunningTasks": "B\u011b\u017e\u00edc\u00ed \u00falohy",
+ "HeaderActiveDevices": "Akt\u00edvn\u00ed za\u0159\u00edzen\u00ed",
+ "HeaderPendingInstallations": "\u010cekaj\u00edc\u00ed instalace",
+ "HeaerServerInformation": "Informace o serveru",
+ "ButtonRestartNow": "Restartovat nyn\u00ed",
"ButtonRestart": "Restart",
- "ButtonShutdown": "Shutdown",
- "ButtonUpdateNow": "Update Now",
- "PleaseUpdateManually": "Please shutdown the server and update manually.",
- "NewServerVersionAvailable": "A new version of Media Browser Server is available!",
- "ServerUpToDate": "Media Browser Server is up to date",
+ "ButtonShutdown": "Vypnout",
+ "ButtonUpdateNow": "Aktualizujte te\u010f",
+ "PleaseUpdateManually": "Pros\u00edm, vypn\u011bte server a aktualizujte ru\u010dne.",
+ "NewServerVersionAvailable": "Je dostupn\u00e1 nov\u00e1 verze programu Media Browser!",
+ "ServerUpToDate": "Media Browser server je aktu\u00e1ln\u00ed.",
"ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.",
"LabelComponentsUpdated": "The following components have been installed or updated:",
"MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.",
"LabelDownMixAudioScale": "Audio boost when downmixing:",
"LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.",
"ButtonLinkKeys": "Link Keys",
- "LabelOldSupporterKey": "Old supporter key",
- "LabelNewSupporterKey": "New supporter key",
+ "LabelOldSupporterKey": "Star\u00fd kl\u00ed\u010d sponzora",
+ "LabelNewSupporterKey": "Nov\u00fd kl\u00ed\u010d sponzora",
"HeaderMultipleKeyLinking": "Multiple Key Linking",
"MultipleKeyLinkingHelp": "If you have more than one supporter key, use this form to link the old key's registrations with your new one.",
- "LabelCurrentEmailAddress": "Current email address",
+ "LabelCurrentEmailAddress": "Aktu\u00e1ln\u00ed e-mailov\u00e1 adresa",
"LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.",
"HeaderForgotKey": "Forgot Key",
- "LabelEmailAddress": "Email address",
+ "LabelEmailAddress": "E-mailov\u00e1 adresa",
"LabelSupporterEmailAddress": "The email address that was used to purchase the key.",
"ButtonRetrieveKey": "Retrieve Key",
"LabelSupporterKey": "Supporter Key (paste from email)",
@@ -583,18 +652,18 @@
"MessageInvalidKey": "Supporter key is missing or invalid.",
"ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
"HeaderDisplaySettings": "Display Settings",
- "TabPlayTo": "Play To",
+ "TabPlayTo": "P\u0159ehr\u00e1vat do",
"LabelEnableDlnaServer": "Enable Dlna server",
"LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Media Browser content.",
"LabelEnableBlastAliveMessages": "Blast alive messages",
"LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.",
"LabelBlastMessageInterval": "Alive message interval (seconds)",
"LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.",
- "LabelDefaultUser": "Default user:",
+ "LabelDefaultUser": "V\u00fdchoz\u00ed u\u017eivatel",
"LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.",
"TitleDlna": "DLNA",
"TitleChannels": "Channels",
- "HeaderServerSettings": "Server Settings",
+ "HeaderServerSettings": "Nastaven\u00ed serveru",
"LabelWeatherDisplayLocation": "Weather display location:",
"LabelWeatherDisplayLocationHelp": "US zip code \/ City, State, Country \/ City, Country",
"LabelWeatherDisplayUnit": "Weather display unit:",
@@ -621,46 +690,48 @@
"NotificationOptionNewLibraryContent": "New content added",
"NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
"SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.",
- "NotificationOptionServerRestartRequired": "Server restart required",
+ "NotificationOptionServerRestartRequired": "Je vy\u017eadov\u00e1n restart serveru",
"LabelNotificationEnabled": "Enable this notification",
"LabelMonitorUsers": "Monitor activity from:",
"LabelSendNotificationToUsers": "Send the notification to:",
- "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.",
"LabelUseNotificationServices": "Use the following services:",
- "CategoryUser": "User",
+ "CategoryUser": "U\u017eivatel:",
"CategorySystem": "System",
"CategoryApplication": "Application",
"CategoryPlugin": "Plugin",
"LabelMessageTitle": "Message title:",
"LabelAvailableTokens": "Available tokens:",
"AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.",
- "OptionAllUsers": "All users",
- "OptionAdminUsers": "Administrators",
+ "OptionAllUsers": "V\u0161ichni u\u017eivatel\u00e9",
+ "OptionAdminUsers": "Administr\u00e1to\u0159i",
"OptionCustomUsers": "Custom",
- "ButtonArrowUp": "Up",
- "ButtonArrowDown": "Down",
- "ButtonArrowLeft": "Left",
- "ButtonArrowRight": "Right",
- "ButtonBack": "Back",
+ "ButtonArrowUp": "Nahoru",
+ "ButtonArrowDown": "Dol\u016f",
+ "ButtonArrowLeft": "Vlevo",
+ "ButtonArrowRight": "Vpravo",
+ "ButtonBack": "Zp\u011bt",
"ButtonInfo": "Info",
"ButtonOsd": "On screen display",
"ButtonPageUp": "Page Up",
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
- "ButtonHome": "Home",
- "ButtonSettings": "Settings",
- "ButtonTakeScreenshot": "Capture Screenshot",
+ "ButtonHome": "Dom\u016f",
+ "ButtonSearch": "Hled\u00e1n\u00ed",
+ "ButtonSettings": "Nastaven\u00ed",
+ "ButtonTakeScreenshot": "Zachytit obrazovku",
"ButtonLetterUp": "Letter Up",
"ButtonLetterDown": "Letter Down",
"PageButtonAbbreviation": "PG",
"LetterButtonAbbreviation": "A",
"TabNowPlaying": "Now Playing",
- "TabNavigation": "Navigation",
+ "TabNavigation": "Navigace",
"TabControls": "Controls",
"ButtonFullscreen": "Toggle fullscreen",
- "ButtonScenes": "Scenes",
- "ButtonSubtitles": "Subtitles",
+ "ButtonScenes": "Sc\u00e9ny",
+ "ButtonSubtitles": "Titulky",
"ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Group movies into collections",
@@ -671,15 +742,17 @@
"ButtonMute": "Mute",
"HeaderLatestMedia": "Latest Media",
"OptionSpecialFeatures": "Special Features",
- "HeaderCollections": "Collections",
+ "HeaderCollections": "Kolekce",
"LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
- "LabelType": "Type:",
+ "LabelType": "Typ:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Container:",
- "LabelProfileVideoCodecs": "Video codecs:",
- "LabelProfileAudioCodecs": "Audio codecs:",
- "LabelProfileCodecs": "Codecs:",
+ "LabelProfileVideoCodecs": "Video kodeky:",
+ "LabelProfileAudioCodecs": "Audio kodeky:",
+ "LabelProfileCodecs": "Kodeky:",
"HeaderDirectPlayProfile": "Direct Play Profile",
"HeaderTranscodingProfile": "Transcoding Profile",
"HeaderCodecProfile": "Codec Profile",
@@ -689,7 +762,7 @@
"OptionProfileVideo": "Video",
"OptionProfileAudio": "Audio",
"OptionProfileVideoAudio": "Video Audio",
- "OptionProfilePhoto": "Photo",
+ "OptionProfilePhoto": "Fotografie",
"LabelUserLibrary": "User library:",
"LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.",
"OptionPlainStorageFolders": "Display all folders as plain storage folders",
@@ -697,7 +770,7 @@
"OptionPlainVideoItems": "Display all videos as plain video items",
"OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".",
"LabelSupportedMediaTypes": "Supported Media Types:",
- "TabIdentification": "Identification",
+ "TabIdentification": "Identifikace",
"TabDirectPlay": "Direct Play",
"TabContainers": "Containers",
"TabCodecs": "Codecs",
@@ -719,11 +792,19 @@
"HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "Friendly name",
- "LabelManufacturer": "Manufacturer",
- "LabelManufacturerUrl": "Manufacturer url",
+ "LabelManufacturer": "V\u00fdrobce",
+ "LabelManufacturerUrl": "Web v\u00fdrobce",
"LabelModelName": "Model name",
"LabelModelNumber": "Model number",
"LabelModelDescription": "Model description",
@@ -741,9 +822,9 @@
"LabelSonyAggregationFlags": "Sony aggregation flags:",
"LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.",
"LabelTranscodingContainer": "Container:",
- "LabelTranscodingVideoCodec": "Video codec:",
- "LabelTranscodingVideoProfile": "Video profile:",
- "LabelTranscodingAudioCodec": "Audio codec:",
+ "LabelTranscodingVideoCodec": "Video kodek:",
+ "LabelTranscodingVideoProfile": "Video profil:",
+ "LabelTranscodingAudioCodec": "Audio kodek:",
"OptionEnableM2tsMode": "Enable M2ts mode",
"OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.",
"OptionEstimateContentLength": "Estimate content length when transcoding",
@@ -752,10 +833,10 @@
"HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
"HeaderDownloadSubtitlesFor": "Download subtitles for:",
"MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.",
- "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresent": "P\u0159esko\u010dit, pokud video ji\u017e obsahuje grafick\u00e9 titulky",
"LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "TabSubtitles": "Subtitles",
- "TabChapters": "Chapters",
+ "TabSubtitles": "Titulky",
+ "TabChapters": "Kapitoly",
"HeaderDownloadChaptersFor": "Download chapter names for:",
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
@@ -763,7 +844,7 @@
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Download languages:",
- "ButtonRegister": "Register",
+ "ButtonRegister": "Registrovat",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
"LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
"HeaderSendMessage": "Send Message",
@@ -773,54 +854,59 @@
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
- "HeaderTypeText": "Enter Text",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
+ "HeaderTypeText": "Vlo\u017ete text",
"LabelTypeText": "Text",
- "HeaderSearchForSubtitles": "Search for Subtitles",
+ "HeaderSearchForSubtitles": "Vyhledat titulky",
"MessageNoSubtitleSearchResultsFound": "No search results founds.",
"TabDisplay": "Display",
- "TabLanguages": "Languages",
- "TabWebClient": "Web Client",
+ "TabLanguages": "Jazyky",
+ "TabWebClient": "Web klient",
"LabelEnableThemeSongs": "Enable theme songs",
- "LabelEnableBackdrops": "Enable backdrops",
+ "LabelEnableBackdrops": "Povolit kulisy",
"LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.",
"LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.",
- "HeaderHomePage": "Home Page",
+ "HeaderHomePage": "Hlavn\u00ed str\u00e1nka",
"HeaderSettingsForThisDevice": "Settings for This Device",
"OptionAuto": "Auto",
- "OptionYes": "Yes",
- "OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
- "OptionResumablemedia": "Resume",
+ "OptionYes": "Ano",
+ "OptionNo": "Ne",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
+ "OptionResumablemedia": "Pokra\u010dovat",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
"HeaderLatestChannelItems": "Latest Channel Items",
"OptionNone": "None",
"HeaderLiveTv": "Live TV",
- "HeaderReports": "Reports",
- "HeaderMetadataManager": "Metadata Manager",
+ "HeaderReports": "Hl\u00e1\u0161en\u00ed",
+ "HeaderMetadataManager": "Spr\u00e1vce metadat",
"HeaderPreferences": "Preferences",
"MessageLoadingChannels": "Loading channel content...",
- "ButtonMarkRead": "Mark Read",
+ "MessageLoadingContent": "Loading content...",
+ "ButtonMarkRead": "Ozna\u010dit jako p\u0159e\u010dten\u00e9",
"OptionDefaultSort": "Default",
- "OptionCommunityMostWatchedSort": "Most Watched",
+ "OptionCommunityMostWatchedSort": "Nejsledovan\u011bj\u0161\u00ed",
"TabNextUp": "Next Up",
"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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
- "ButtonDismiss": "Dismiss",
+ "ButtonDismiss": "Zam\u00edtnout",
"MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
"ButtonEditOtherUserPreferences": "Edit this user's personal preferences.",
"LabelChannelStreamQuality": "Preferred internet stream quality:",
@@ -834,19 +920,179 @@
"LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.",
"ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.",
"LabelSelectCollection": "Select collection:",
- "ViewTypeMovies": "Movies",
- "ViewTypeTvShows": "TV",
- "ViewTypeGames": "Games",
- "ViewTypeMusic": "Music",
- "ViewTypeBoxSets": "Collections",
- "ViewTypeChannels": "Channels",
- "ViewTypeLiveTV": "Live TV",
+ "ViewTypeMovies": "Filmy",
+ "ViewTypeTvShows": "Televize",
+ "ViewTypeGames": "Hry",
+ "ViewTypeMusic": "Hudba",
+ "ViewTypeBoxSets": "Kolekce",
+ "ViewTypeChannels": "Kan\u00e1ly",
+ "ViewTypeLiveTV": "\u017div\u00e1 TV",
"HeaderOtherDisplaySettings": "Display Settings",
"HeaderMyViews": "My Views",
"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": "Slo\u017eky m\u00e9di\u00ed",
"TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "XBMC",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Slu\u017eby",
+ "TabLogs": "Z\u00e1znamy",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "Seznam",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Z\u00e1znamy:",
+ "LabelMetadata": "Metadata",
+ "LabelImagesByName": "Obr\u00e1zky dle n\u00e1zvu:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "U\u017eivatel",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Zav\u0159\u00edt",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "V\u00edce...",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 e6ea74d50..6d3e9bc04 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/da.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/da.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Updates",
- "HeaderUpdateLevel": "Update Level",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
- "HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Failed",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "HeaderMyLibrary": "Mit bibliotek",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "Afslut",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "Bes\u00f8g F\u00e6lleskab",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "Standard",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "Se Api dokumentation",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "Gennemse biblitek",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "Konfigurere Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "\u00c5ben Biblioteks Fremviser",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "Genstart Server",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "Vis Log",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "Tidligere",
+ "HeaderPassword": "Password",
"LabelFinish": "Slut",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "N\u00e6ste",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "Du er f\u00e6rdig!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "Velkommen til Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "Denne guide vil hj\u00e6lpe dig igennem ops\u00e6tningen. For at begynde, venligst v\u00e6lg dit fortrukne sprog.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "Fort\u00e6l os lidt om dig selv",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "Dit fornavn",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "Flere brugere kan tilf\u00f8jes senere i Betjeningspanelet.",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser inkludere indbygget underst\u00f8ttelse af bruger profiler, der giver den enkelte bruger mulighed for individuelle visningsindstillinger, Afspilningsstatus og for\u00e6ldre kontrol.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Windows Service",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "Der er blevet installeret en Windows Service.",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser Server k\u00f8rer normalt som et skrivebords program med et tray ikon, men hvis du foretr\u00e6kker at k\u00f8re det som en service i baggrunden, kan den startes fra kontrolpanelet Windows services i stedet for.",
+ "HeaderIdentifyItem": "Identify Item",
"WindowsServiceIntro2": "Hvis windows servicen bruges skal du v\u00e6re opm\u00e6rksom p\u00e5, at servicen ikke kan k\u00f8re p\u00e5 samme tid som tray ikonet. Det er derfor n\u00f8dvendigt at afslutte tray ikonet f\u00f8r servicen startes. Det er n\u00f8dvendigt at konfigurere servicen til at k\u00f8re med administrative privileger, som kan g\u00f8res via Windows Service kontrol panelet. V\u00e6r opm\u00e6rksom p\u00e5 at servicen p\u00e5 nuv\u00e6rende tidspunkt ikke er i stand til at auto opdatere, s\u00e5 opdatering vil kr\u00e6ve manuel handling.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "Det var alt vi havde brug for lige nu. Media Browser er i gang med at indsamle information om dit medie bibliotek. Se nogle af vores programmer, og klik <b>F\u00e6rdig<\/b> for at se <b>Betjeningspanelet<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
"LabelConfigureSettings": "Konfigurer indstillinger",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Aktiver udtr\u00e6kning af video billede",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"VideoImageExtractionHelp": "For videoer der ikke allerede har billeder, og som vi ikke kan finde internet billeder til. Dette vil g\u00f8re den indledende biblioteks skanning l\u00e6ngere, men vil resulterer i en p\u00e6nere pr\u00e6sentation.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Aktiver udtr\u00e6kning af kapitel billeder for Film",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Aktiver automatisk port kortl\u00e6gning",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP tillader automatisk router konfiguration for nem fjern adgang. Dette virker muligvis ikke med alle routere.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Annuller",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "Ny",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Konfigurer dit medie bibliotek",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "Tilf\u00f8j medie mappe",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Mappe type:",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Kr\u00e6ver brug af en tilf\u00f8jelse, fx GameBrowser eller MB Bookshelf.",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Der henvises til medie bibliotekets wiki.",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "Land:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "Sprog:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "Foretrukket metadata sprog:",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "Gem illustrationer og metadata i medie mapper",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "Lagring af illustrationer og metadata i medie mapper, vil placerer dem et sted hvor de nemt kan redigeres.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "Hent illustrationer og metadata fra internettet",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser kan hente information omkring dine medier som vil g\u00f8re pr\u00e6sentationen mere omfattende.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "Indstillinger",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "Kode",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "Bibliotek adgang",
+ "LabelBudget": "Budget",
"TabImage": "Billede",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "Profil",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "Billeder",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "Titler",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Vis manglende episoder i s\u00e6soner",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Vis endnu ikke sendte episoder i s\u00e6soner",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "Video afspilnings indstillinger",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "Foretrukket lyd sprog:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "Foretrukket undertekst sprog:",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "Ingen undertekster",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Profiler",
+ "HeaderTags": "Tags",
"TabSecurity": "Sikkerhed",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "Tilf\u00f8j bruger",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "Gem",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "Nulstil kode",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "Ny kode:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "Bekr\u00e6ft ny kode:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "Opret kode",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Nuv\u00e6rende kode:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "Maximum allowed parental rating:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "V\u00e6lg hvilke medie mapper der skal deles med denne bruger. Administratorer vil kunne redigere alle mapper ved hj\u00e6lp af metadata administratoren.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "Slet Billede",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "Select users:",
+ "OptionActor": "Actor",
"ButtonUpload": "Upload",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Upload Nyt Billede",
+ "OptionDirector": "Director",
"LabelDropImageHere": "Slip Billede Her",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "1:1 formatforhold anbefalet. Kun JPG\/PNG.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Her er ingenting.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "V\u00e6r venligst sikker p\u00e5 at hentning af internet metadata er aktiveret.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Foresl\u00e5et",
+ "LabelAirTime": "Air time:",
"TabLatest": "Seneste",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "Kommende",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Shows",
"TabEpisodes": "Episoder",
"TabGenres": "Genre",
@@ -163,7 +225,7 @@
"OptionAscending": "Stigende",
"OptionDescending": "Faldende",
"OptionRuntime": "Varighed",
- "OptionReleaseDate": "Udgivelsesdato",
+ "OptionReleaseDate": "Release Date",
"OptionPlayCount": "Gange Afspillet",
"OptionDatePlayed": "Dato Afspillet",
"OptionDateAdded": "Dato Tilf\u00f8jet",
@@ -213,6 +275,8 @@
"TabMovies": "Film",
"TabStudios": "Studier",
"TabTrailers": "Trailere",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "Seneste Film",
"HeaderLatestTrailers": "Seneste Trailere",
"OptionHasSpecialFeatures": "Specielle Egenskaber",
@@ -233,6 +297,7 @@
"OptionFriday": "Fredag",
"OptionSaturday": "L\u00f8rdag",
"HeaderManagement": "Ledelse:",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "Manglende IMDB Id",
"OptionMissingTvdbId": "Manglende TheTVDB Id",
"OptionMissingOverview": "Manglende Overblik",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "V\u00e6lg",
- "ButtonSearch": "S\u00f8g",
"ButtonGroupVersions": "Grupp\u00e9r Versioner",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
@@ -296,7 +360,7 @@
"LabelMetadataPath": "Metadata sti:",
"LabelMetadataPathHelp": "Denne placering indeholder hentede illustrationer og metadata, der ikke er konfigureret til at blive gemt i medie mapperne.",
"LabelTranscodingTempPath": "Transcoding temporary path:",
- "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder.",
+ "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": "Basale",
"TabTV": "TV",
"TabGames": "Spil",
@@ -318,7 +382,7 @@
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
- "OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Log Ind",
"TitleSignIn": "Log Ind",
@@ -347,6 +411,8 @@
"TabStatus": "Status",
"TabSettings": "Indstillinger",
"ButtonRefreshGuideData": "Opdater Guide Data",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Prioritet",
"OptionRecordOnAllChannels": "Optag program p\u00e5 alle kanaler",
"OptionRecordAnytime": "Optag program uanset tidpunkt",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Cast & Crew",
"HeaderAdditionalParts": "Additional Parts",
"ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Missing",
"LabelOffline": "Offline",
"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.",
@@ -512,11 +579,13 @@
"HeaderProgram": "Program",
"HeaderClients": "Clients",
"LabelCompleted": "Completed",
+ "LabelFailed": "Failed",
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeasonNumber": "Season number",
- "LabelEpisodeNumber": "Episode number",
- "LabelEndingEpisodeNumber": "Ending episode number",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Enable this notification",
"LabelMonitorUsers": "Monitor activity from:",
"LabelSendNotificationToUsers": "Send the notification to:",
- "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.",
"LabelUseNotificationServices": "Use the following services:",
"CategoryUser": "User",
"CategorySystem": "System",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Side ned",
"PageAbbreviation": "PG",
"ButtonHome": "Hjem",
+ "ButtonSearch": "S\u00f8g",
"ButtonSettings": "Indstillinger",
"ButtonTakeScreenshot": "Capture Screenshot",
"ButtonLetterUp": "Bogstav op",
@@ -657,10 +726,12 @@
"TabNowPlaying": "Spiler nu",
"TabNavigation": "Navigation",
"TabControls": "Controls",
- "ButtonFullscreen": "Skift til fuldsk\u00e6rm",
+ "ButtonFullscreen": "Toggle fullscreen",
"ButtonScenes": "Scener",
"ButtonSubtitles": "Undertekster",
- "ButtonAudioTracks": "Lyd filer",
+ "ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Group movies into collections",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
"LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "System venligt navn",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text",
"HeaderSearchForSubtitles": "Search for Subtitles",
@@ -796,13 +879,13 @@
"OptionAuto": "Auto",
"OptionYes": "Yes",
"OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferences",
"MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Mark Read",
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
"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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
"ButtonDismiss": "Dismiss",
"MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Display adult content",
"OptionLibraryFolders": "Media folders",
"TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 c0e2415c2..907c466d0 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/de.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/de.json
@@ -1,138 +1,200 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Updates",
- "HeaderUpdateLevel": "Update Level",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "Zeige nur erzwungene Untertitel",
- "HeaderCustomizeOptionsPerMediaType": "Passe die Optionen per Medientyp an",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Gescheitert",
- "LabelSeries": "Serien:",
- "ButtonPreviousTrack": "Vorheriger Track",
- "ButtonNextTrack": "N\u00e4chster Track",
- "HeaderMyLibrary": "Meine Bibliothek",
- "HeaderLibraryViews": "Library Views",
- "LabelExit": "Ende",
+ "HeaderPeople": "Personen",
+ "LabelExit": "Beenden",
+ "HeaderDownloadPeopleMetadataFor": "Lade Biografien und Bilder herunter f\u00fcr:",
"LabelVisitCommunity": "Besuche die Community",
+ "OptionComposers": "Komponisten",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Andere",
"LabelSwagger": "Swagger",
"LabelStandard": "Standard",
+ "HeaderDownloadPeopleMetadataForHelp": "Die Aktivierung von zus\u00e4tzlichen Optionen wird mehr Informationen zur Verf\u00fcgung stellen, aber das scannen der Bibliothek verlangsamen.",
"LabelViewApiDocumentation": "Zeige API Dokumentation",
+ "ViewTypeFolders": "Verzeichnisse",
"LabelBrowseLibrary": "Durchsuche Bibliothek",
+ "LabelDisplayFoldersView": "Nutze die Verzeichnissansicht f\u00fcr die Darstellung der reinen Medienordner",
"LabelConfigureMediaBrowser": "Konfiguriere Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Aufnahmen",
"LabelOpenLibraryViewer": "\u00d6ffne Bibliothekenansicht",
+ "ViewTypeLiveTvChannels": "Kan\u00e4le",
"LabelRestartServer": "Server neustarten",
+ "LabelAllowLocalAccessWithoutPassword": "Erlaube lokalen Zugriff ohne Passwort",
"LabelShowLogWindow": "Zeige Log Fenster",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "Fall aktiviert, wird kein Passwort f\u00fcr einen Zugriff innerhalb deines Heimnetzwerks ben\u00f6tigt.",
"LabelPrevious": "Vorheriges",
+ "HeaderPassword": "Passwort",
"LabelFinish": "Ende",
+ "HeaderLocalAccess": "Lokaler Zugriff",
"LabelNext": "N\u00e4chstes",
+ "HeaderViewOrder": "Reihenfolge f\u00fcr Ansichten",
"LabelYoureDone": "Du bist fertig!",
+ "LabelSelectUserViewOrder": "W\u00e4hle die Reihenfolge in der die Ansichten innerhalb von Media Browser Apps angezeigt werden.",
"WelcomeToMediaBrowser": "Willkommen zu Media Browser!",
+ "LabelMetadataRefreshMode": "Metadaten Aktualisierungsmethode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Aktualisierungsmethode f\u00fcr Bilder:",
"ThisWizardWillGuideYou": "Dieser Assistent wird Sie durch den Einrichtungsprozess f\u00fchren. Um zu beginnen, w\u00e4hlen Sie bitte ihre bevorzugte Sprache.",
+ "OptionDownloadMissingImages": "Lade fehlende Bilder herunter",
"TellUsAboutYourself": "Sagen Sie uns etwas \u00fcber sich selbst",
+ "OptionReplaceExistingImages": "Ersetze vorhandene Bilder",
"LabelYourFirstName": "Ihr Vorname:",
- "MoreUsersCanBeAddedLater": "Weitere Benutzer k\u00f6nnen Sie sp\u00e4ter im Dashboard hinzuf\u00fcgen.",
+ "OptionRefreshAllData": "Aktualisiere alle Daten",
+ "MoreUsersCanBeAddedLater": "Weitere Benutzer k\u00f6nnen Sie sp\u00e4ter \u00fcber die Optionsleiste hinzuf\u00fcgen.",
+ "OptionAddMissingDataOnly": "F\u00fcge nur fehlende Daten hinzu",
"UserProfilesIntro": "Media Browser verf\u00fcgt \u00fcber integrierte Benutzer Profile. Verwenden Sie diese Profile um Anzeigeeinstellungen, Abspielstatus und Kinder- und Jugendschutzverwaltung pro Benutzer zu speichern und zu verwalten.",
+ "OptionLocalRefreshOnly": "Nur lokale Aktualisierung",
"LabelWindowsService": "Windows Service",
+ "HeaderRefreshMetadata": "Aktualisiere Metadaten",
"AWindowsServiceHasBeenInstalled": "Ein Windows Dienst wurde installiert.",
+ "HeaderPersonInfo": "Informationen zur Person",
"WindowsServiceIntro1": "Media Browser Server l\u00e4uft normalerweise als Desktop Applikation mit einem Symbol im System Tray. Sie k\u00f6nnen den Server aber auch als Hintergrunddienst starten. Verwenden Sie die dazu das Windows Service Control Panel..",
+ "HeaderIdentifyItem": "Identifiziere Element",
"WindowsServiceIntro2": "Das Service kann nicht zu gleichen Zeit wie die Desktop Applikation laufen. Schliessen Sie daher die Desktop Applikation, bevor Sie das Service starten. Das Service ben\u00f6tigt administrative Privilegien, die Sie \u00fcber die Systemsteuerung einstellen m\u00fcssen. Beachten Sie bitte auch, dass das Service zur Zeit nicht automatisch aktualisiert wird. Neue Versionen m\u00fcssen daher manuell installiert werden.",
- "WizardCompleted": "Das war's f\u00fcrs Erste. Media Browser hat gerade mit dem Sammeln von Informationen \u00fcber Ihre Medien Bibliothek begonnen. Probieren Sie auch unsere anderen Programme aus. Klicken Sie danach auf <b>Abschliessen<\/b> um das <b>Dashboard<\/b> anzuzeigen.",
+ "HeaderIdentifyItemHelp": "Gib ein oder mehrere Suchkriterien ein. Entferne Kriterien um die Suchergebnisse zu erweitern.",
+ "WizardCompleted": "Das war's f\u00fcrs Erste. Media Browser hat gerade mit dem Sammeln von Informationen \u00fcber Ihre Medien Bibliothek begonnen. Probieren Sie auch unsere anderen Programme aus. Klicken Sie danach auf <b>Abschliessen<\/b> um die <b>Optionsleiste<\/b> anzuzeigen.",
+ "HeaderConfirmDeletion": "Best\u00e4tige L\u00f6schung",
"LabelConfigureSettings": "Konfiguriere Einstellungen",
+ "LabelFollowingFileWillBeDeleted": "Die folgende Datei wird gel\u00f6scht werden:",
"LabelEnableVideoImageExtraction": "Aktiviere Videobild-Extrahierung",
+ "LabelIfYouWishToContinueWithDeletion": "Falls du fortfahren m\u00f6chtest, gibt bitte das Ergebnis aus folgender Rechnung an:",
"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.",
+ "ButtonIdentify": "Identifizieren",
"LabelEnableChapterImageExtractionForMovies": "Extrahiere Kapitelbilder f\u00fcr Filme",
+ "LabelAlbumArtist": "Album-Interpret:",
"LabelChapterImageExtractionForMoviesHelp": "Das Auslesen von Kapitelbildern erlaubt es den Clients grafische Szenenauswahlmen\u00fcs anzuzeigen. Der Prozess kann langsam, prozessorintensiv sein und mehrere Gigabyte an Speicherplatz erfordern. Er wird nachts um 4:00 Uhr als geplante Aufgabe ausgef\u00fchrt, dies l\u00e4sst sich im \"Geplante Aufgaben\" Bereich konfigurieren. Es ist nicht ratsam, diese Aufgabe in der Hauptbelastungszeit auszuf\u00fchren.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Aktiviere automatische Portweiterleitung",
+ "LabelCommunityRating": "Community Bewertung:",
"LabelEnableAutomaticPortMappingHelp": "UPnP erm\u00f6glicht die automatische Routerkonfiguration f\u00fcr den einfachen Remote-Zugriff. Diese Option ist nicht f\u00fcr jeden Router verf\u00fcgbar.",
+ "LabelVoteCount": "Stimmen:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Abbrechen",
+ "LabelCriticRating": "Kritiker Bewertung:",
"ButtonNew": "Neu",
+ "LabelCriticRatingSummary": "Kritiker Bewertungszusammenfassung:",
"HeaderSetupLibrary": "Medienbibliothek einrichten",
- "ButtonAddMediaFolder": "Medienordner hinzuf\u00fcgen",
- "LabelFolderType": "Ordnertyp:",
+ "LabelAwardSummary": "Auszeichnungszusammenfassung:",
+ "ButtonAddMediaFolder": "Medienverzeichnis hinzuf\u00fcgen",
+ "LabelWebsite": "Website:",
+ "LabelFolderType": "Verzeichnistyp:",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Ben\u00f6tigt ein Plugin, wie GameBrowser oder MB Bookshelf.",
+ "LabelOverview": "\u00dcbersicht:",
"ReferToMediaLibraryWiki": "Siehe die Medienbibliothek Wiki",
+ "LabelShortOverview": "Kurz\u00fcbersicht:",
"LabelCountry": "Land:",
+ "LabelReleaseDate": "Ver\u00f6ffentlichungsdatum:",
"LabelLanguage": "Sprache:",
+ "LabelYear": "Jahr:",
"HeaderPreferredMetadataLanguage": "Bevorzugte Metadata Sprache:",
- "LabelSaveLocalMetadata": "Speichere Bildmaterial und Metadaten in den Medienordnern",
- "LabelSaveLocalMetadataHelp": "Durch die Speicherung von Bildmaterial und Metadaten direkt in den Medienordnern, befinden sie sich an einem Ort, wo sie sehr leicht bearbeitet werden k\u00f6nnen.",
+ "LabelPlaceOfBirth": "Geburtsort:",
+ "LabelSaveLocalMetadata": "Speichere Bildmaterial und Metadaten in den Medienverzeichnissen",
+ "LabelEndDate": "Endzeit:",
+ "LabelSaveLocalMetadataHelp": "Durch die Speicherung von Bildmaterial und Metadaten direkt in den Medienverzeichnissen, befinden sie sich an einem Ort, wo sie sehr leicht bearbeitet werden k\u00f6nnen.",
+ "LabelAirDate": "Ausstrahlungstage:",
"LabelDownloadInternetMetadata": "Lade Bildmaterial und Metadaten aus dem Internet",
+ "LabelAirTime:": "Ausstrahlungszeit:",
"LabelDownloadInternetMetadataHelp": "Media Browser kann Informationen \u00fcber ihre Medien aus dem Internet abrufen um eine optisch ansprechende Darstellung zu erm\u00f6glichen.",
+ "LabelRuntimeMinutes": "Laufzeit (Minuten):",
"TabPreferences": "Einstellungen",
+ "LabelParentalRating": "Altersfreigabe:",
"TabPassword": "Passwort",
+ "LabelCustomRating": "Eigene Bewertung:",
"TabLibraryAccess": "Bibliothekenzugriff",
+ "LabelBudget": "Budget",
"TabImage": "Bild",
+ "LabelRevenue": "Einnahmen ($):",
"TabProfile": "Profil",
+ "LabelOriginalAspectRatio": "Originales Seitenverh\u00e4ltnis:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Schauspieler:",
"TabImages": "Bilder",
+ "Label3DFormat": "3D Format:",
"TabNotifications": "Benachrichtigungen",
+ "HeaderAlternateEpisodeNumbers": "Alternative Episodennummern",
"TabCollectionTitles": "Titel",
+ "HeaderSpecialEpisodeInfo": "Spezialepisoden Information",
"LabelDisplayMissingEpisodesWithinSeasons": "Zeige fehlende Episoden innerhalb von Staffeln",
+ "HeaderExternalIds": "Externe Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Zeige noch nicht ausgestahlte Episoden innerhalb von Staffeln",
+ "LabelDvdSeasonNumber": "DVD Staffelnummer:",
"HeaderVideoPlaybackSettings": "Videowiedergabe Einstellungen",
+ "LabelDvdEpisodeNumber": "DVD Episodennummer:",
"HeaderPlaybackSettings": "Wiedergabe Einstellungen",
+ "LabelAbsoluteEpisodeNumber": "Absolute Episodennummer:",
"LabelAudioLanguagePreference": "Audiosprache Einstellungen:",
+ "LabelAirsBeforeSeason": "Ausstrahlungen vor Staffel:",
"LabelSubtitleLanguagePreference": "Untertitelsprache Einstellungen:",
- "OptionDefaultSubtitles": "Default",
- "OptionOnlyForcedSubtitles": "Only forced subtitles",
- "OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelAirsAfterSeason": "Ausstrahlungen nach Staffel:",
+ "OptionDefaultSubtitles": "Standard",
+ "LabelAirsBeforeEpisode": "Ausstrahlungen vor Episode:",
+ "OptionOnlyForcedSubtitles": "Nur erzwungene Untertitel",
+ "LabelTreatImageAs": "Bild behandeln, wie:",
+ "OptionAlwaysPlaySubtitles": "Untertitel immer anzeigen",
+ "LabelDisplayOrder": "Anzeigereihenfolge:",
"OptionNoSubtitles": "Keine Untertitel",
- "OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
- "OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
- "OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
- "OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "LabelDisplaySpecialsWithinSeasons": "Zeige Sonderinhalt innerhalb der Staffel in der er ausgestrahlt wurde",
+ "OptionDefaultSubtitlesHelp": "Untertitel die den Spracheinstellungen entsprechen werden nur bei einer Tonspur in fremder Sprache heruntergeladen.",
+ "HeaderCountries": "L\u00e4nder",
+ "OptionOnlyForcedSubtitlesHelp": "Nur Untertitel, die als erzwungener Download markiert wurden, werden heruntergeladen.",
+ "HeaderGenres": "Genres",
+ "OptionAlwaysPlaySubtitlesHelp": "Untertitel die den Spracheinstellungen entsprechen werden unabh\u00e4ngig von der Tonspur Sprache heruntergeladen.",
+ "HeaderPlotKeywords": "Handlungsstichworte",
+ "OptionNoSubtitlesHelp": "Untertitel wird standardm\u00e4\u00dfig nicht geladen.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Profile",
+ "HeaderTags": "Tags",
"TabSecurity": "Sicherheit",
+ "HeaderMetadataSettings": "Metadaten Einstellungen",
"ButtonAddUser": "User hinzuf\u00fcgen",
+ "LabelLockItemToPreventChanges": "Sperre diesen Eintrag um zuk\u00fcnftige \u00c4nderungen zu verhindern",
"ButtonSave": "Speichern",
+ "MessageLeaveEmptyToInherit": "Freilassen f\u00fcr die Vererbung von Berechtigungen oder dem systemweiten Standardwert.",
"ButtonResetPassword": "Passwort zur\u00fccksetzten",
+ "TabSupporterClub": "Unterst\u00fctzer Club",
"LabelNewPassword": "Neues Passwort:",
+ "HeaderDonationType": "Spendentyp:",
"LabelNewPasswordConfirm": "Neues Passwort wiederhohlen:",
+ "OptionMakeOneTimeDonation": "Mache eine einmalige Spende",
"HeaderCreatePassword": "Erstelle Passwort",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Aktuelles Passwort:",
+ "OptionLifeTimeSupporterClubMembership": "Lebensl\u00e4ngliche Unterst\u00fctzer Club Mitgliedschaft",
"LabelMaxParentalRating": "H\u00f6chste erlaubte elterlich Bewertung:",
+ "HeaderSupporterBenefit": "Eine Mitgliedschaft im Unterst\u00fctzer Club erm\u00f6glicht den Zugang zu Premium Plugins, Internet Kanalinhalten und mehr.",
"MaxParentalRatingHelp": "Inhalt mit einer h\u00f6heren Bewertung wird dem User nicht angezeigt.",
- "LibraryAccessHelp": "W\u00e4hlen Sie die Medienordner die Sie mit diesem Benutzer teilen m\u00f6chten. Administratoren k\u00f6nnen den Metadata-Manager verwenden um alle Ordner zu bearbeiten.",
+ "OptionNoTrailer": "Kein Trailer",
+ "LibraryAccessHelp": "W\u00e4hlen Sie die Medienverzeichnisse die Sie mit diesem Benutzer teilen m\u00f6chten. Administratoren k\u00f6nnen den Metadata-Manager verwenden um alle Ordner zu bearbeiten.",
+ "OptionNoThemeSong": "Kein Theme Song",
"ChannelAccessHelp": "W\u00e4hlen Sie die Kan\u00e4le, die mit diesem Benutzer geteilt werden sollen. Administratoren sind in der Lage alle K\u00e4nale \u00fcber den Metadata Manager zu bearbeiten.",
+ "OptionNoThemeVideo": "Kein Theme Video",
"ButtonDeleteImage": "L\u00f6sche Bild",
+ "LabelOneTimeDonationAmount": "Spendenbetrag:",
"LabelSelectUsers": "W\u00e4hle Benutzer:",
+ "OptionActor": "Schauspieler",
"ButtonUpload": "Hochladen",
+ "OptionComposer": "Komponist",
"HeaderUploadNewImage": "Neues Bild hochladen",
- "LabelDropImageHere": "Bild hierher ziehen",
+ "OptionDirector": "Regisseur",
+ "LabelDropImageHere": "Fotos hierher ziehen",
+ "OptionGuestStar": "Gaststar",
"ImageUploadAspectRatioHelp": "1:1 Seitenverh\u00e4ltnis empfohlen. Nur JPG\/PNG.",
+ "OptionProducer": "Produzent",
"MessageNothingHere": "Nichts hier.",
+ "OptionWriter": "Drehbuchautor",
"MessagePleaseEnsureInternetMetadata": "Bitte sicherstellen, dass das Herunterladen von Internet Metadaten aktiviert ist.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Vorgeschlagen",
+ "LabelAirTime": "Air time:",
"TabLatest": "Neueste",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "Bevorstehend",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Shows",
"TabEpisodes": "Episoden",
"TabGenres": "Genres",
- "TabPeople": "Menschen",
+ "TabPeople": "Personen",
"TabNetworks": "Sendergruppen",
"HeaderUsers": "Benutzer",
"HeaderFilters": "Filter:",
@@ -153,7 +215,7 @@
"TabSongs": "Songs",
"TabAlbums": "Alben",
"TabArtists": "Interpreten",
- "TabAlbumArtists": "Album Interpreten",
+ "TabAlbumArtists": "Album-Interpreten",
"TabMusicVideos": "Musikvideos",
"ButtonSort": "Sortieren",
"HeaderSortBy": "Sortiert nach",
@@ -163,17 +225,17 @@
"OptionAscending": "Aufsteigend",
"OptionDescending": "Absteigend",
"OptionRuntime": "Dauer",
- "OptionReleaseDate": "Erscheinungstermin",
+ "OptionReleaseDate": "Ver\u00f6ffentlichungsdatum",
"OptionPlayCount": "Z\u00e4hler",
"OptionDatePlayed": "Abgespielt am",
"OptionDateAdded": "Hinzugef\u00fcgt am",
- "OptionAlbumArtist": "Album Interpret",
+ "OptionAlbumArtist": "Album-Interpret",
"OptionArtist": "Interpret",
"OptionAlbum": "Album",
"OptionTrackName": "Track Name",
"OptionCommunityRating": "Community Bewertung",
"OptionNameSort": "Name",
- "OptionFolderSort": "Ordner",
+ "OptionFolderSort": "Verzeichnisse",
"OptionBudget": "Budget",
"OptionRevenue": "Einnahme",
"OptionPoster": "Poster",
@@ -205,7 +267,7 @@
"LabelService": "Service:",
"LabelStatus": "Status:",
"LabelVersion": "Version:",
- "LabelLastResult": "Last result:",
+ "LabelLastResult": "Letztes Ergebnis:",
"OptionHasSubtitles": "Untertitel",
"OptionHasTrailer": "Trailer",
"OptionHasThemeSong": "Titellied",
@@ -213,6 +275,8 @@
"TabMovies": "Filme",
"TabStudios": "Studios",
"TabTrailers": "Trailer",
+ "LabelArtists": "Interpreten:",
+ "LabelArtistsHelp": "Trenne mehrere Eintr\u00e4ge durch ;",
"HeaderLatestMovies": "Neueste Filme",
"HeaderLatestTrailers": "Neueste Trailer",
"OptionHasSpecialFeatures": "Besonderes Merkmal",
@@ -224,7 +288,7 @@
"HeaderStatus": "Status",
"OptionContinuing": "Fortdauernd",
"OptionEnded": "Beendent",
- "HeaderAirDays": "Ausstrahlungstage:",
+ "HeaderAirDays": "Ausstrahlungstage",
"OptionSunday": "Sonntag",
"OptionMonday": "Montag",
"OptionTuesday": "Dienstag",
@@ -232,7 +296,8 @@
"OptionThursday": "Donnerstag",
"OptionFriday": "Freitag",
"OptionSaturday": "Samstag",
- "HeaderManagement": "Verwaltung:",
+ "HeaderManagement": "Verwaltung",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "Fehlende IMDb Id",
"OptionMissingTvdbId": "Fehlende TheTVDB Id",
"OptionMissingOverview": "Fehlende \u00dcbersicht",
@@ -249,7 +314,7 @@
"VisitTheCommunity": "Besuche die Community",
"VisitMediaBrowserWebsite": "Besuche die Media Browser Website",
"VisitMediaBrowserWebsiteLong": "Besuche die Media Browser Website um die aktuellsten Neuigkeiten zu erfahren und halte dich auf dem Laufenden mit dem Entwicklerblog.",
- "OptionHideUser": "Verberge diesen Benutzer in den Anmelde-Bildschirmen",
+ "OptionHideUser": "Verberge diesen Benutzer in den Anmeldebildschirmen",
"OptionDisableUser": "Sperre diesen Benutzer",
"OptionDisableUserHelp": "Wenn deaktiviert,wird der Server keine Verbindung von diesem Benutzer erlauben. Bestehenden Verbindungen werden sofort beendet.",
"HeaderAdvancedControl": "Erweiterte Kontrolle",
@@ -257,21 +322,20 @@
"OptionAllowUserToManageServer": "Dieser Benutzer kann den Server managen",
"HeaderFeatureAccess": "Funktionszugriff",
"OptionAllowMediaPlayback": "Erlaube das Abspielen von Medien",
- "OptionAllowBrowsingLiveTv": "Erlaube das durchsuchen von Live TV",
+ "OptionAllowBrowsingLiveTv": "Erlaube das durchsuchen von Live-TV",
"OptionAllowDeleteLibraryContent": "Erlaube diesem Benutzer das L\u00f6schen von Bibliothelkeninhalten",
- "OptionAllowManageLiveTv": "Erlaube die Verwaltung von Live TV Aufnahmen",
+ "OptionAllowManageLiveTv": "Erlaube die Verwaltung von Live-TV Aufnahmen",
"OptionAllowRemoteControlOthers": "Erlaube diesem Benutzer, andere Benutzer fernzusteuern",
"OptionMissingTmdbId": "Fehlende Tmdb Id",
"OptionIsHD": "HD",
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "Ausw\u00e4hlen",
- "ButtonSearch": "Suche",
"ButtonGroupVersions": "Gruppiere Versionen",
- "ButtonAddToCollection": "Add to Collection",
+ "ButtonAddToCollection": "Zur Sammlung hinzuf\u00fcgen",
"PismoMessage": "Verwendet Pismo File Mount durch eine gespendete Lizenz.",
- "TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
- "HeaderCredits": "Credits",
+ "TangibleSoftwareMessage": "Verwendung konkreter L\u00f6sungen von Java\/C# Konvertern durch eine gespendete Lizenz.",
+ "HeaderCredits": "Herausgeber",
"PleaseSupportOtherProduces": "Bitte unterst\u00fctzen Sie andere freie Produkte die wir benutzen:",
"VersionNumber": "Version {0}",
"TabPaths": "Pfade",
@@ -286,17 +350,17 @@
"LabelAllowServerAutoRestartHelp": "Der Server startet nur in benutzerfreien Leerlaufzeiten neu.",
"LabelEnableDebugLogging": "Aktiviere Debug Logging",
"LabelRunServerAtStartup": "Starte Server beim hochfahren.",
- "LabelRunServerAtStartupHelp": "Dies wird die Anwendung als Symbol in der Taskleiste starten, w\u00e1hrend Windows-Anmeldung. Um den Windows-Dienst zu starten, deaktivieren Sie es und starten Sie den Service \u00fcber die Windows-Systemsteuerung. Bitte beachten Sie, dass Sie den Service und die Anwendung nicht zur gleichen Zeit ausf\u00fchren k\u00f6nnen. Bevor Sie den Service starten, m\u00fcssen Sie zuerst die Anwendung schlie\u00dfen.",
+ "LabelRunServerAtStartupHelp": "Dies wird Media Browser als Anwendung w\u00e4hrend der Windows Anmeldung starten und ihn in der Taskleiste anzeigen. Um Media Browser als Systemdienst zu nutzen, deaktivieren Sie diese Einstellung und starten anschlie\u00dfend den Dienst \u00fcber die Windows Systemsteuerung. Bitte beachten Sie, dass Sie Media Browser nicht zur gleichen Zeit als Systemdienst und als Anwendung nutzen k\u00f6nnen. Bevor Sie den Service starten, m\u00fcssen Sie zuerst die Anwendung schlie\u00dfen.",
"ButtonSelectDirectory": "W\u00e4hle Verzeichnis",
"LabelCustomPaths": "Definiere eigene Pfade. Felder leer lassen um die Standardwerte zu nutzen.",
"LabelCachePath": "Cache Pfad:",
- "LabelCachePathHelp": "Dieser Ordner beinhaltet Server Cache Dateien, wie z.B. Bilddateien.",
+ "LabelCachePathHelp": "W\u00e4hle eine Verzeichnis f\u00fcr Server Cache Dateien, wie z.B. Bilddateien.",
"LabelImagesByNamePath": "Images by name Pfad:",
- "LabelImagesByNamePathHelp": "Dieser Ordner beinhaltet Schauspieler, K\u00fcnstler, Genre und Studio Bilder.",
+ "LabelImagesByNamePathHelp": "W\u00e4hle eine Verzeichnis f\u00fcr Schauspieler, Interpreten, Genre und Studio Bilder.",
"LabelMetadataPath": "Metadata Pfad:",
- "LabelMetadataPathHelp": "Dieser Ort beinhaltet das heruntergeladene Bildmaterial und die Metadaten, falls sie nicht innerhalb der Medienordner gespeichert werden sollen.",
+ "LabelMetadataPathHelp": "W\u00e4hle eine Verzeichnis f\u00fcr heruntergeladenes Bildmaterial und Metadaten, falls diese nicht innerhalb der Medienverzeichnisse gespeichert werden sollen.",
"LabelTranscodingTempPath": "Tempor\u00e4rer Transcoding Pfad:",
- "LabelTranscodingTempPathHelp": "Dieser Ordner beinhaltet Dateien die f\u00fcr den Betrieb des Transcoders benutzt werden.",
+ "LabelTranscodingTempPathHelp": "Dieses Verzeichnis beinhaltet Dateien die f\u00fcr den Betrieb des Transcoders benutzt werden. W\u00e4hle einen eigenen Pfad oder lasse das Feld frei, um den Standardspeicherort im Server Datenverzeichnis zu nutzen.",
"TabBasics": "Grundlagen",
"TabTV": "TV",
"TabGames": "Spiele",
@@ -313,42 +377,44 @@
"LabelAutomaticUpdatesFanartHelp": "Falls aktviert, werden Bilder die unter fanart.tv neu hinzugef\u00fcgt wurden, automatisch geladen. Vorhandene Bilder werden nicht ersetzt.",
"LabelAutomaticUpdatesTmdbHelp": "Falls aktviert, werden Bilder die unter TheMovieDB.org neu hinzugef\u00fcgt wurden, automatisch geladen. Vorhandene Bilder werden nicht ersetzt.",
"LabelAutomaticUpdatesTvdbHelp": "Falls aktviert, werden Bilder die unter TheTVDB.com neu hinzugef\u00fcgt wurden, automatisch geladen. Vorhandene Bilder werden nicht ersetzt.",
- "ExtractChapterImagesHelp": "Das Auslesen von Kapitelbildern erlaubt es den Clients grafische Szenenauswahlmen\u00fcs anzuzeigen. Der Prozess kann langsam, prozessorintensiv sein und mehrere Gigabyte an Speicherplatz erfordern. Er wird nachts um 4:00 Uhr als geplante Aufgabe ausgef\u00fchrt, dies l\u00e4sst sich im \"Geplante Aufgaben\" Bereich konfigurieren. Es ist nicht ratsam, diese Aufgabe in der Hauptbelastungszeit auszuf\u00fchren.",
+ "ExtractChapterImagesHelp": "Das Auslesen von Kapitelbildern erlaubt es den Clients grafische Szenenauswahlmen\u00fcs anzuzeigen. Der Prozess kann langsam sowie prozessorintensiv sein und kann mehrere Gigabyte an Speicherplatz erfordern. Er wird nachts um 4:00 Uhr als geplante Aufgabe ausgef\u00fchrt, dies l\u00e4sst sich im \"Geplante Aufgaben\" Bereich konfigurieren. Es ist nicht ratsam, diese Aufgabe in der Hauptbelastungszeit auszuf\u00fchren.",
"LabelMetadataDownloadLanguage": "Bevorzugte Sprache f\u00fcr Downloads:",
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Speicherconvention der Bilddatein:",
"LabelImageSavingConventionHelp": "Media Browser erkennt Bilddateien von den meisten gro\u00dfen Medienanwendungen. Die Auswahl ihrer Downloadconvention ist n\u00fctzlich, wenn Sie auch andere Produkte benutzen.",
- "OptionImageSavingCompatible": "Kompatibel - Media Browser\/Plex\/Xbmc",
+ "OptionImageSavingCompatible": "Kompatibilit\u00e4t - Media Browser\/XBMC\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Einloggen",
"TitleSignIn": "Einloggen",
"HeaderPleaseSignIn": "Bitte einloggen",
"LabelUser": "Benutzer:",
"LabelPassword": "Passwort:",
- "ButtonManualLogin": "Manueller Login",
+ "ButtonManualLogin": "Manuelle Anmeldung",
"PasswordLocalhostMessage": "Passw\u00f6rter werden nich gebraucht, wenn Sie sich vom Localhost aus einloggen.",
"TabGuide": "Programm",
"TabChannels": "Kan\u00e4le",
- "TabCollections": "Collections",
+ "TabCollections": "Sammlungen",
"HeaderChannels": "Kan\u00e4le",
"TabRecordings": "Aufnahmen",
"TabScheduled": "Geplant",
"TabSeries": "Serie",
- "TabFavorites": "Favorites",
- "TabMyLibrary": "My Library",
+ "TabFavorites": "Favoriten",
+ "TabMyLibrary": "Meine Bibliothek",
"ButtonCancelRecording": "Aufnahme abbrechen",
"HeaderPrePostPadding": "Pufferzeit vor\/nach der Aufnahme",
"LabelPrePaddingMinutes": "Minuten vor der Aufnahme",
"OptionPrePaddingRequired": "Die Pufferzeit vor der Aufnahme ist notwendig um aufzunehmen",
"LabelPostPaddingMinutes": "Pufferminuten nach der Aufnahme",
"OptionPostPaddingRequired": "Die Pufferzeit nach der Aufnahme ist notwendig um aufzunehmen",
- "HeaderWhatsOnTV": "Was gibt",
+ "HeaderWhatsOnTV": "Was gibts",
"HeaderUpcomingTV": "Bevorstehend",
"TabStatus": "Status",
"TabSettings": "Einstellungen",
"ButtonRefreshGuideData": "Aktualisiere TV-Guide Daten",
+ "ButtonRefresh": "Aktualisieren",
+ "ButtonAdvancedRefresh": "Erweiterte Aktualiserung",
"OptionPriority": "Priorit\u00e4t",
- "OptionRecordOnAllChannels": "Neme Programm auf allen Kan\u00e4len auf",
+ "OptionRecordOnAllChannels": "Nehme Programm auf allen Kan\u00e4len auf",
"OptionRecordAnytime": "Neme Programm zu jeder Zeit auf",
"OptionRecordOnlyNewEpisodes": "Nehme nur neue Episoden auf",
"HeaderDays": "Tage",
@@ -362,15 +428,15 @@
"ButtonRemove": "Entfernen",
"OptionRecordSeries": "Nehme Serie auf",
"HeaderDetails": "Details",
- "TitleLiveTV": "Live TV",
+ "TitleLiveTV": "Live-TV",
"LabelNumberOfGuideDays": "Anzahl von Tagen f\u00fcr die Programminformationen geladen werden sollen:",
- "LabelNumberOfGuideDaysHelp": "Laden Sie weitere Tage von F\u00fchrungs Daten bietet die M\u00f6glichkeit, weiter in die Zukunft zu planen und einen besseren \u00dcberblick, aber es wird l\u00e4nger dauern alles herunter zu laden. Auto w\u00e4hlt auf der Grundlage der Anzahl der Kan\u00e4le.",
+ "LabelNumberOfGuideDaysHelp": "Das laden von zus\u00e4tzlichen Programmdaten bietet einen besseren \u00dcberblick und die M\u00f6glichkeit weiter in die Zukunft zu planen. Aber es wird l\u00e4nger dauern alles herunterzuladen. Auto w\u00e4hlt auf der Grundlage der Anzahl der Kan\u00e4le.",
"LabelActiveService": "Aktiver Service:",
"LabelActiveServiceHelp": "Mehrere TV Plugins k\u00f6nnen installiert sein, aber nur eines kann aktiv sein.",
"OptionAutomatic": "Auto",
- "LiveTvPluginRequired": "Ein Live TV Serviceproviderplugin ist notwendig um fortzufahren.",
+ "LiveTvPluginRequired": "Ein Live-TV Serviceproviderplugin ist notwendig um fortzufahren.",
"LiveTvPluginRequiredHelp": "Bitte installieren Sie eines der verf\u00fcgbaren Plugins, wie z.B. Next Pvr oder ServerWmc.",
- "LabelCustomizeOptionsPerMediaType": "Customize for media type:",
+ "LabelCustomizeOptionsPerMediaType": "Anpassungen f\u00fcr Medientyp:",
"OptionDownloadThumbImage": "Thumb",
"OptionDownloadMenuImage": "Men\u00fc",
"OptionDownloadLogoImage": "Logo",
@@ -382,10 +448,10 @@
"OptionDownloadPrimaryImage": "Prim\u00e4r",
"HeaderFetchImages": "Bilder abrufen:",
"HeaderImageSettings": "Bild Einstellungen",
- "TabOther": "Other",
- "LabelMaxBackdropsPerItem": "Maximale Anzahl von Backdrops pro Element:",
+ "TabOther": "Andere",
+ "LabelMaxBackdropsPerItem": "Maximale Anzahl von Hintergr\u00fcnden pro Element:",
"LabelMaxScreenshotsPerItem": "Maximale Anzahl von Screenshots pro Element:",
- "LabelMinBackdropDownloadWidth": "Minimale Breite f\u00fcr zu herunterladende Backdrops:",
+ "LabelMinBackdropDownloadWidth": "Minimale Breite f\u00fcr zu herunterladende Hintergr\u00fcnde:",
"LabelMinScreenshotDownloadWidth": "Minimale Breite f\u00fcr zu herunterladende Screenshot:",
"ButtonAddScheduledTaskTrigger": "F\u00fcge Task Ausl\u00f6ser hinzu",
"HeaderAddScheduledTaskTrigger": "F\u00fcge Task Ausl\u00f6ser hinzu",
@@ -407,7 +473,7 @@
"HeaderRecentlyPlayedGames": "Zuletzt gespielte Spiele",
"TabGameSystems": "Spielsysteme",
"TitleMediaLibrary": "Medienbibliothek",
- "TabFolders": "Ordner",
+ "TabFolders": "Verzeichnisse",
"TabPathSubstitution": "Pfadersetzung",
"LabelSeasonZeroDisplayName": "Anzeigename f\u00fcr Season 0:",
"LabelEnableRealtimeMonitor": "Erlaube Echtzeit\u00fcberwachung:",
@@ -419,7 +485,7 @@
"Option2Player": "2+",
"Option3Player": "3+",
"Option4Player": "4+",
- "HeaderMediaFolders": "Medien Ordner",
+ "HeaderMediaFolders": "Medienverzeichnisse",
"HeaderThemeVideos": "Titelvideos",
"HeaderThemeSongs": "Titelsongs",
"HeaderScenes": "Szenen",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Besetzung & Crew",
"HeaderAdditionalParts": "Zus\u00e4tzliche Teile",
"ButtonSplitVersionsApart": "Spalte Versionen ab",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Fehlend",
"LabelOffline": "Offline",
"PathSubstitutionHelp": "Pfad Substitutionen werden zum Abbilden eines Pfad auf dem Server zu einem Pfad der Clients direkt zugreifen k\u00f6nnen, verwendet. Weil Clients direkten Zugang zu den Medien auf dem Server haben, sind sie in der Lage die Medien direkt \u00fcber das Netzwerk zu spielen und dabei vermeiden sie die nutzung von Server-Ressourcen f\u00fcr streaming transkodieren.",
@@ -458,7 +525,7 @@
"OptionEnableDebugTranscodingLoggingHelp": "Dies wird sehr lange Logdateien erzeugen und ist nur zur Fehlerbehebung empfehlenswert.",
"OptionUpscaling": "Erlaube den Clients ein hochskaliertes Video anzufordern",
"OptionUpscalingHelp": "In manchen F\u00e4llen wird dadurch die Videoqualit\u00e4t verbesserert, aber es erh\u00f6ht auch die CPU Last.",
- "EditCollectionItemsHelp": "Hinzuf\u00fcgen oder entfernen Sie alle Filme, Serien, Alben, B\u00fccher oder Spiele, die Sie in dieser Sammlung gruppieren wollen.",
+ "EditCollectionItemsHelp": "Entferne oder f\u00fcge alle Filme, Serien, Alben, B\u00fccher oder Spiele, die du in dieser Sammlung gruppieren willst hinzu.",
"HeaderAddTitles": "Titel hinzuf\u00fcgen",
"LabelEnableDlnaPlayTo": "Aktiviere DLNA Play To",
"LabelEnableDlnaPlayToHelp": "Media Browser kann Ger\u00e4te in ihrem Netzwerk erkennen und die M\u00f6glichekeit der Fernsteuerung anbieten.",
@@ -470,7 +537,7 @@
"HeaderSystemDlnaProfiles": "Systemprofile",
"CustomDlnaProfilesHelp": "Erstellen Sie ein benutzerdefiniertes Profil, um eine neue Zielger\u00e4t oder ein Systemprofil zu \u00fcberschreiben.",
"SystemDlnaProfilesHelp": "Systemprofile sind schreibgesch\u00fctzt. \u00c4nderungen an einem Systemprofil werden als neues benutzerdefiniertes Profil gespeichert.",
- "TitleDashboard": "Dashboard",
+ "TitleDashboard": "Optionsleiste",
"TabHome": "Home",
"TabInfo": "Info",
"HeaderLinks": "Links",
@@ -484,8 +551,8 @@
"LabelPreferredDisplayLanguageHelp": "Die \u00dcbersetzung von Media Browser ist ein andauerndes Projekt und noch nicht abgeschlossen.",
"LabelReadHowYouCanContribute": "Lesen Sie wie Sie dazu beitragen k\u00f6nnen.",
"HeaderNewCollection": "Neue Collection",
- "HeaderAddToCollection": "Add to Collection",
- "ButtonSubmit": "Submit",
+ "HeaderAddToCollection": "Zur Sammlung hinzuf\u00fcgen",
+ "ButtonSubmit": "Best\u00e4tigen",
"NewCollectionNameExample": "Beispiel: Star Wars Collection",
"OptionSearchForInternetMetadata": "Suche im Internet nach Bildmaterial und Metadaten",
"ButtonCreate": "Kreieren",
@@ -503,7 +570,7 @@
"LabelMinResumePercentageHelp": "Titel werden als nicht abgespielt angenommen, wenn sie vor dieser Zeit gestoppt werden",
"LabelMaxResumePercentageHelp": "Titel werden als komplett abgespielt angenommen, wenn sie nach dieser Zeit gestoppt werden",
"LabelMinResumeDurationHelp": "Titel k\u00fcrzer als dies werden nicht fortsetzbar sein",
- "TitleAutoOrganize": "Auto-Organize",
+ "TitleAutoOrganize": "automatische Sortierung",
"TabActivityLog": "Aktivit\u00e4tsverlauf",
"HeaderName": "Name",
"HeaderDate": "Datum",
@@ -512,43 +579,45 @@
"HeaderProgram": "Programm",
"HeaderClients": "Clients",
"LabelCompleted": "Fertiggestellt",
+ "LabelFailed": "Fehlgeschlagen",
"LabelSkipped": "\u00dcbersprungen",
- "HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeasonNumber": "Staffelnummer",
- "LabelEpisodeNumber": "Episodennummer",
- "LabelEndingEpisodeNumber": "Ending episode number",
+ "HeaderEpisodeOrganization": "Episodensortierung",
+ "LabelSeries": "Serien:",
+ "LabelSeasonNumber": "Staffelnummer:",
+ "LabelEpisodeNumber": "Episodennummer:",
+ "LabelEndingEpisodeNumber": "Nummer der letzten Episode:",
"LabelEndingEpisodeNumberHelp": "Nur erforderlich f\u00fcr Mehrfachepisoden",
"HeaderSupportTheTeam": "Unterst\u00fcze das Media Browser Team",
"LabelSupportAmount": "Betrag (USD)",
- "HeaderSupportTheTeamHelp": "Helfen sie der Weiterentwicklung dieses Projekts in dem Sie spenden. Ein Teil der Spenden wird weitergespendet an freie Anwendungen auf die wir angewiesen sind.",
+ "HeaderSupportTheTeamHelp": "Helfen sie der Weiterentwicklung dieses Projekts indem Sie spenden. Ein Teil der Spenden wird an freie Anwendungen auf die wir angewiesen sind weitergespendet.",
"ButtonEnterSupporterKey": "Supporter Key eintragen",
"DonationNextStep": "Sobald abgeschlossen, kehren Sie bitte hierher zur\u00fcck und tragen Sie den Unterst\u00fctzerschl\u00fcssel ein, den Sie per E-Mail erhalten haben.",
- "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.",
+ "AutoOrganizeHelp": "Die \"Auto-Organisation\" \u00fcberpr\u00fcft die Download-Verzeichnisse auf neue Dateien und verschiebt diese in die Medienverzeichnisse.",
"AutoOrganizeTvHelp": "TV Dateien Organisation wird nur Episoden zu bereits vorhandenen Serien hinzuf\u00fcgen. Es werden keine neuen Serien angelegt.",
- "OptionEnableEpisodeOrganization": "Enable new episode organization",
- "LabelWatchFolder": "\u00dcberwachungsordner:",
- "LabelWatchFolderHelp": "Der Server wird diesen Ordner, w\u00e4hrend des geplanten Tasks \"Organisiere neue Mediendateien\", abfragen.",
+ "OptionEnableEpisodeOrganization": "Aktiviere die Sortierung neuer Episoden",
+ "LabelWatchFolder": "\u00dcberwache Verzeichnis:",
+ "LabelWatchFolderHelp": "Der Server wird dieses Verzeichnis, w\u00e4hrend der geplanten Aufgabe \"Organisiere neue Mediendateien\", abfragen.",
"ButtonViewScheduledTasks": "Zeige Geplante Aufgaben",
"LabelMinFileSizeForOrganize": "Minimale Dateigr\u00f6\u00dfe (MB):",
"LabelMinFileSizeForOrganizeHelp": "Dateien unter dieser Gr\u00f6\u00dfe werden ignoriert.",
"LabelSeasonFolderPattern": "Staffelordnervorlage:",
- "LabelSeasonZeroFolderName": "Ordnername f\u00fcr Staffel 0:",
+ "LabelSeasonZeroFolderName": "Verzeichnisname f\u00fcr Staffel 0:",
"HeaderEpisodeFilePattern": "Episodendateivorlage:",
"LabelEpisodePattern": "Episodenvorlage:",
"LabelMultiEpisodePattern": "Multi-Episodenvorlage:",
"HeaderSupportedPatterns": "Unterst\u00fctzte Vorlagen:",
- "HeaderTerm": "Term",
+ "HeaderTerm": "Begriff",
"HeaderPattern": "Vorlagen",
"HeaderResult": "Ergebnis",
- "LabelDeleteEmptyFolders": "L\u00f6sche leere Ordner nach dem Organisieren.",
- "LabelDeleteEmptyFoldersHelp": "Aktiviere dies um den Downloadordner sauber zu halten.",
+ "LabelDeleteEmptyFolders": "L\u00f6sche leere Verzeichnisse nach dem Organisieren.",
+ "LabelDeleteEmptyFoldersHelp": "Aktiviere dies um den Downloadverzeichnisse sauber zu halten.",
"LabelDeleteLeftOverFiles": "L\u00f6sche \u00fcbriggebliebene Dateien mit den folgenden Dateiendungen:",
"LabelDeleteLeftOverFilesHelp": "Unterteile mit ;. Zum Beispiel: .nfo;.txt",
"OptionOverwriteExistingEpisodes": "\u00dcberschreibe vorhandene Episoden",
"LabelTransferMethod": "\u00dcbertragungsmethode",
"OptionCopy": "Kopieren",
"OptionMove": "Verschieben",
- "LabelTransferMethodHelp": "Kopiere oder verschiebe Dateien aus dem \u00dcberwachungsordner",
+ "LabelTransferMethodHelp": "Kopiere oder verschiebe Dateien aus dem \u00dcberwachungsverzeichnis",
"HeaderLatestNews": "Neueste Nachrichten",
"HeaderHelpImproveMediaBrowser": "Hilf Media Browser zu verbessern",
"HeaderRunningTasks": "Laufende Aufgaben",
@@ -565,7 +634,7 @@
"ErrorConnectingToMediaBrowserRepository": "Es trat ein Fehler bei der Verbindung zum Media Browser Repository auf.",
"LabelComponentsUpdated": "Die folgenden Komponenten wurden installiert oder aktualisiert:",
"MessagePleaseRestartServerToFinishUpdating": "Bitte den Server neustarten, um die Aktualisierungen abzuschlie\u00dfen.",
- "LabelDownMixAudioScale": "Audio boost when downmixing:",
+ "LabelDownMixAudioScale": "Audio Verst\u00e4rkung bei Downmixing:",
"LabelDownMixAudioScaleHelp": "Erh\u00f6he die Audiolautst\u00e4rke beim Heruntermischen. Setzte auf 1 um die original Lautst\u00e4rke zu erhalten.",
"ButtonLinkKeys": "Schl\u00fcssel zusammenf\u00fchren",
"LabelOldSupporterKey": "Alter Unterst\u00fctzerschl\u00fcssel",
@@ -593,18 +662,18 @@
"LabelDefaultUser": "Standardbenutzer",
"LabelDefaultUserHelp": "Legt fest, welche Benutzerbibliothek auf verbundenen Ger\u00e4ten angezeigt werden soll. Dies kann f\u00fcr jedes Ger\u00e4t durch Profile \u00fcberschrieben werden.",
"TitleDlna": "DLNA",
- "TitleChannels": "Channel",
+ "TitleChannels": "Kanal",
"HeaderServerSettings": "Server Einstellungen",
"LabelWeatherDisplayLocation": "Wetteranzeige Ort:",
"LabelWeatherDisplayLocationHelp": "US Postleitzahl \/ Stadt, Staat, Land \/ Stadt, Land",
"LabelWeatherDisplayUnit": "Wetteranzeige Einheit:",
"OptionCelsius": "Celsius",
"OptionFahrenheit": "Fahrenheit",
- "HeaderRequireManualLogin": "Manuelle Eingabe des Usernamen bei:",
- "HeaderRequireManualLoginHelp": "Wenn deaktiviert k\u00f6nnen Clients einen Loginbildschirm mit einer visuellen Auswahl der User anzeigen.",
+ "HeaderRequireManualLogin": "Manuelle Eingabe des Benutzernamens bei:",
+ "HeaderRequireManualLoginHelp": "Wenn deaktiviert k\u00f6nnen Clients einen Anmeldebildschirm mit einer visuellen Auswahl der User anzeigen.",
"OptionOtherApps": "Andere Apps",
"OptionMobileApps": "Mobile Apps",
- "HeaderNotificationList": "Click on a notification to configure it's sending options.",
+ "HeaderNotificationList": "Klicke auf eine Benachrichtigung um die Benachrichtigungseinstellungen zu bearbeiten",
"NotificationOptionApplicationUpdateAvailable": "Anwendungsaktualisierung verf\u00fcgbar",
"NotificationOptionApplicationUpdateInstalled": "Anwendungsaktualisierung installiert",
"NotificationOptionPluginUpdateInstalled": "Pluginaktualisierung installiert",
@@ -613,27 +682,26 @@
"NotificationOptionVideoPlayback": "Videowiedergabe gestartet",
"NotificationOptionAudioPlayback": "Audiowiedergabe gestartet",
"NotificationOptionGamePlayback": "Spielwiedergabe gestartet",
- "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
- "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
- "NotificationOptionGamePlaybackStopped": "Game playback stopped",
- "NotificationOptionTaskFailed": "Scheduled task failure",
+ "NotificationOptionVideoPlaybackStopped": "Videowiedergabe gestoppt",
+ "NotificationOptionAudioPlaybackStopped": "Audiowiedergabe gestoppt",
+ "NotificationOptionGamePlaybackStopped": "Spielwiedergabe gestoppt",
+ "NotificationOptionTaskFailed": "Fehler bei geplanter Aufgabe",
"NotificationOptionInstallationFailed": "Installationsfehler",
"NotificationOptionNewLibraryContent": "Neuer Inhalt hinzugef\u00fcgt",
- "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
- "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.",
+ "NotificationOptionNewLibraryContentMultiple": "Neuen Inhalte hinzugef\u00fcgt (mehrere)",
+ "SendNotificationHelp": "Standardm\u00e4\u00dfig werden Benachrichtigungen in der Optionsleiste angezeigt. Durchsuche den Plugin Katalog f\u00fcr die Installation von weiteren Benachrichtigungsm\u00f6glichkeiten.",
"NotificationOptionServerRestartRequired": "Serverneustart notwendig",
"LabelNotificationEnabled": "Aktiviere diese Benachrichtigung",
"LabelMonitorUsers": "\u00dcberwache Aktivit\u00e4t von:",
"LabelSendNotificationToUsers": "Sende die Benachrichtigung an:",
- "UsersNotNotifiedAboutSelfActivity": "Benutzer werden nicht \u00fcber ihre eigenen Aktivit\u00e4ten benachrichtigt.",
- "LabelUseNotificationServices": "Nutze folgende Services:",
+ "LabelUseNotificationServices": "Nutze folgende Dienste:",
"CategoryUser": "Benutzer",
"CategorySystem": "System",
"CategoryApplication": "Anwendung",
"CategoryPlugin": "Plugin",
"LabelMessageTitle": "Benachrichtigungstitel:",
"LabelAvailableTokens": "Verf\u00fcgbare Tokens:",
- "AdditionalNotificationServices": "Durchsuchen Sie den Plugin Katalog, um weitere Benachrichtigungsservices zu installieren.",
+ "AdditionalNotificationServices": "Durchsuche den Plugin Katalog, um weitere Benachrichtigungsdienste zu installieren.",
"OptionAllUsers": "Alle Benutzer",
"OptionAdminUsers": "Administratoren",
"OptionCustomUsers": "Benutzer",
@@ -643,11 +711,12 @@
"ButtonArrowRight": "Rechts",
"ButtonBack": "Zur\u00fcck",
"ButtonInfo": "Info",
- "ButtonOsd": "On screen display",
+ "ButtonOsd": "On Screen Display",
"ButtonPageUp": "Bild auf",
"ButtonPageDown": "Bild ab",
"PageAbbreviation": "PG",
"ButtonHome": "Home",
+ "ButtonSearch": "Suche",
"ButtonSettings": "Einstellungen",
"ButtonTakeScreenshot": "Bildschirmfoto aufnehmen",
"ButtonLetterUp": "Buchstabe hoch",
@@ -657,10 +726,12 @@
"TabNowPlaying": "Aktuelle Wiedergabe",
"TabNavigation": "Navigation",
"TabControls": "Controls",
- "ButtonFullscreen": "Schalte Vollbild um",
+ "ButtonFullscreen": "Vollbild umschalten",
"ButtonScenes": "Szenen",
"ButtonSubtitles": "Untertitel",
"ButtonAudioTracks": "Audiospuren",
+ "ButtonPreviousTrack": "Vorheriges St\u00fcck",
+ "ButtonNextTrack": "N\u00e4chstes St\u00fcck",
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Gruppiere Filme in Collections",
@@ -669,13 +740,15 @@
"ButtonVolumeUp": "Lauter",
"ButtonVolumeDown": "Leiser",
"ButtonMute": "Stumm",
- "HeaderLatestMedia": "Letzte Medien",
+ "HeaderLatestMedia": "Neueste Medien",
"OptionSpecialFeatures": "Special Features",
"HeaderCollections": "Collections",
"LabelProfileCodecsHelp": "Getrennt durch Komma. Leerlassen, um auf alle Codecs anzuwenden.",
"LabelProfileContainersHelp": "Getrennt durch Komma. Leerlassen, um auf alle Container anzuwenden.",
"HeaderResponseProfile": "Antwort Profil",
"LabelType": "Typ:",
+ "LabelPersonRole": "Rolle:",
+ "LabelPersonRoleHelp": "Rollen sind generell nur f\u00fcr Schauspieler verf\u00fcgbar.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video Codecs:",
"LabelProfileAudioCodecs": "Audio Codecs:",
@@ -691,11 +764,11 @@
"OptionProfileVideoAudio": "Video Audio",
"OptionProfilePhoto": "Photo",
"LabelUserLibrary": "Benutzer Bibliothek:",
- "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.",
- "OptionPlainStorageFolders": "Display all folders as plain storage folders",
- "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".",
- "OptionPlainVideoItems": "Display all videos as plain video items",
- "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".",
+ "LabelUserLibraryHelp": "W\u00e4hle aus, welche Medienbibliothek auf den Endger\u00e4ten angezeigt werden soll. Ohne Eintrag wird die Standardeinstellung beibehalten.",
+ "OptionPlainStorageFolders": "Zeige alle Verzeichnisse als reine Speicherorte an",
+ "OptionPlainStorageFoldersHelp": "Falls aktiviert, werden alle Verzeichnisse in DIDL als \"object.container.storageFolder\" angezeigt, anstatt eines spezifischen Typs wie beispielsweise \"object.container.person.musicArtist\".",
+ "OptionPlainVideoItems": "Zeige alle Videos als reine Videodateien an",
+ "OptionPlainVideoItemsHelp": "Falls aktiviert, werden alle Videos in DIDL als \"object.item.videoItem\" angezeigt, anstatt eines spezifischen Typs wie beispielsweise \"object.item.videoItem.movie\".",
"LabelSupportedMediaTypes": "Unterst\u00fczte Medientypen:",
"TabIdentification": "Identifikation",
"TabDirectPlay": "Direktwiedergabe",
@@ -703,24 +776,32 @@
"TabCodecs": "Codecs",
"TabResponses": "Antworten",
"HeaderProfileInformation": "Profil Infomationen",
- "LabelEmbedAlbumArtDidl": "Embed album art in Didl",
- "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.",
- "LabelAlbumArtPN": "Album art PN:",
- "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.",
- "LabelAlbumArtMaxWidth": "Album art max width:",
- "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
- "LabelAlbumArtMaxHeight": "Album art max height:",
- "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
+ "LabelEmbedAlbumArtDidl": "Integrierte Alben-Cover in Didl",
+ "LabelEmbedAlbumArtDidlHelp": "Einige Ger\u00e4te bevorzugen diese Methode um Album Art darstellen zu k\u00f6nnen. Andere wiederum k\u00f6nnen evtl. nichts abspielen, wenn diese Funktion aktiviert ist.",
+ "LabelAlbumArtPN": "Alben-Cover PN:",
+ "LabelAlbumArtHelp": "Die genutzte PN f\u00fcr Alben-Cover innerhalb der dlna:profileID Eigenschaften auf upnp:albumArtURL. Manche Abspielger\u00e4te ben\u00f6tigen einen bestimmten Wert, unabh\u00e4ngig von der Bildgr\u00f6\u00dfe.",
+ "LabelAlbumArtMaxWidth": "Maximale Breite f\u00fcr Album Art:",
+ "LabelAlbumArtMaxWidthHelp": "Maximale Aufl\u00f6sung f\u00fcr durch UPnP \u00fcbermittelte Album Art:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "Maximale H\u00f6he f\u00fcr Album Art:",
+ "LabelAlbumArtMaxHeightHelp": "Maximale Aufl\u00f6sung f\u00fcr durch UPnP \u00fcbermittelte Album Art:albumArtURI.",
"LabelIconMaxWidth": "Maximale Iconbreite:",
- "LabelIconMaxWidthHelp": "Max resolution of icons exposed via upnp:icon.",
+ "LabelIconMaxWidthHelp": "Maximale Aufl\u00f6sung f\u00fcr durch UPnP \u00fcbermittelte Icons:icon.",
"LabelIconMaxHeight": "Maximale Iconh\u00f6he:",
- "LabelIconMaxHeightHelp": "Max resolution of icons exposed via upnp:icon.",
- "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.",
- "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
+ "LabelIconMaxHeightHelp": "Maximale Aufl\u00f6sung f\u00fcr durch UPnP \u00fcbermittelte Icons:icon.",
+ "LabelIdentificationFieldHelp": "Ein Teilstring oder Regex Ausdruck, der keine Gro\u00df- und Kleinschreibung ber\u00fccksichtigt.",
+ "HeaderProfileServerSettingsHelp": "Diese Einstellungen legen fest, wie sich MediaBrowser gegen\u00fcber den Endger\u00e4ten verh\u00e4lt.",
"LabelMaxBitrate": "Maximale Bitrate:",
- "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
- "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
- "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
+ "LabelMaxBitrateHelp": "Lege eine maximale Bitrate, f\u00fcr Anwendungsgebiete mit begrenzter Bandbreite oder bei durch die Endger\u00e4te auferlegten Banbdbreitenbegrenzungen, fest",
+ "LabelMaxStreamingBitrate": "Maximale Streamingbitrate",
+ "LabelMaxStreamingBitrateHelp": "W\u00e4hle die maximale Bitrate w\u00e4hrend des streamens.",
+ "LabelMaxStaticBitrate": "Maximale Synchronisierungsbitrate ",
+ "LabelMaxStaticBitrateHelp": "W\u00e4hle die maximale Bitrate f\u00fcr das synchronisieren von Inhalten mit hoher Qualit\u00e4t.",
+ "LabelMusicStaticBitrate": "Musik Synchronisierungsbitrate:",
+ "LabelMusicStaticBitrateHelp": "W\u00e4hle die maximale Bitrate f\u00fcr das synchronisieren von Musik",
+ "LabelMusicStreamingTranscodingBitrate": "Musik Transkodier Bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "W\u00e4hle die maximale Bitrate f\u00fcr das streamen von Musik",
+ "OptionIgnoreTranscodeByteRangeRequests": "Ignoriere Anfragen f\u00fcr Transkodierbytebereiche",
+ "OptionIgnoreTranscodeByteRangeRequestsHelp": "Falls aktiviert, werden diese Anfragen ber\u00fccksichtigt aber Byte-Range-Header ignoriert werden.",
"LabelFriendlyName": "Freundlicher Name",
"LabelManufacturer": "Hersteller",
"LabelManufacturerUrl": "Hersteller URL",
@@ -731,122 +812,287 @@
"LabelSerialNumber": "Seriennummer",
"LabelDeviceDescription": "Ger\u00e4tebeschreibung",
"HeaderIdentificationCriteriaHelp": "Geben sie mindestens ein Identificationskriterium an.",
- "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.",
- "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.",
- "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.",
- "LabelXDlnaCap": "X-Dlna cap:",
- "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.",
- "LabelXDlnaDoc": "X-Dlna doc:",
- "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.",
- "LabelSonyAggregationFlags": "Sony aggregation flags:",
- "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.",
+ "HeaderDirectPlayProfileHelp": "F\u00fcge Direct-Play Profile hinzu um die nativen Abspielm\u00f6glichkeiten von Ger\u00e4ten festzulegen.",
+ "HeaderTranscodingProfileHelp": "F\u00fcge Transkodierprofile hinzu, um festzulegen welche Formate genutzt werden sollen, falls transkodiert werden muss.",
+ "HeaderResponseProfileHelp": "Antwortprofile bieten eine M\u00f6glichkeit die Informationen, die w\u00e4hrend dem abspielen diverser Medientypen an die Abspielger\u00e4te gesendet werden, zu personalisieren.",
+ "LabelXDlnaCap": "X-DLNA Grenze:",
+ "LabelXDlnaCapHelp": "Legt den Inhalt des X_DLNACAP Elements in der urn:schemas-dlna-org:device-1-0 namespace fest.",
+ "LabelXDlnaDoc": "X-DLNA Dokument:",
+ "LabelXDlnaDocHelp": "Legt den Inhalt des X_DLNADOC Elements in der urn:schemas-dlna-org:device-1-0 namespace fest.",
+ "LabelSonyAggregationFlags": "Sony Aggregation Flags:",
+ "LabelSonyAggregationFlagsHelp": "Legt den Inhalt des aggregationFlags Elements in der rn:schemas-sonycom:av namespace fest.",
"LabelTranscodingContainer": "Container:",
"LabelTranscodingVideoCodec": "Video Codec:",
"LabelTranscodingVideoProfile": "Video Profil:",
"LabelTranscodingAudioCodec": "Audio Codec:",
"OptionEnableM2tsMode": "Aktiviere M2TS Modus",
"OptionEnableM2tsModeHelp": "Aktiviere M2TS Modus beim Encodieren nach MPEGTS.",
- "OptionEstimateContentLength": "Estimate content length when transcoding",
- "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding",
- "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.",
- "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
- "HeaderDownloadSubtitlesFor": "Download subtitles for:",
- "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.",
- "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
- "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "TabSubtitles": "Subtitles",
- "TabChapters": "Chapters",
- "HeaderDownloadChaptersFor": "Download chapter names for:",
- "LabelOpenSubtitlesUsername": "Open Subtitles username:",
- "LabelOpenSubtitlesPassword": "Open Subtitles password:",
- "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.",
- "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
- "LabelSubtitlePlaybackMode": "Subtitle mode:",
- "LabelDownloadLanguages": "Download languages:",
- "ButtonRegister": "Register",
- "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
- "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
- "HeaderSendMessage": "Send Message",
- "ButtonSend": "Send",
- "LabelMessageText": "Message text:",
- "MessageNoAvailablePlugins": "No available plugins.",
- "LabelDisplayPluginsFor": "Display plugins for:",
+ "OptionEstimateContentLength": "Voraussichtliche Inhaltsl\u00e4nge beim Transkodieren",
+ "OptionReportByteRangeSeekingWhenTranscoding": "Teilt die Unterst\u00fctzung der Bytesuche w\u00e4hrend des transkodierens auf dem Server mit.",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "Dies wird f\u00fcr manche Abspielger\u00e4te ben\u00f6tigt, auf denen die Zeitsuche nicht gut funktioniert.",
+ "HeaderSubtitleDownloadingHelp": "Wenn Media Browser deine Videodateien scannt kann er nach fehlenden Untertiteln suchen und diese mit Hilfe eines Untertitelanbieters, wie beispielsweise OpenSubtitles.org, herunterladen.",
+ "HeaderDownloadSubtitlesFor": "Lade Untertitel runter f\u00fcr",
+ "MessageNoChapterProviders": "Installiere ein Plugin f\u00fcr Kapitelinhalte, wie beispielsweise ChapterDb, um weitere Optionen f\u00fcr Kapitel zu erhalten.",
+ "LabelSkipIfGraphicalSubsPresent": "\u00dcberspringen, falls das Video bereits grafische Untertitel enth\u00e4lt",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Die Beibehaltung von Textversionen der Untertitel ist effizienter f\u00fcr die \u00dcbermittlung an mobile Endger\u00e4te.",
+ "TabSubtitles": "Untertitel",
+ "TabChapters": "Kapitel",
+ "HeaderDownloadChaptersFor": "Lade Kapitelnamen herunter f\u00fcr:",
+ "LabelOpenSubtitlesUsername": "\"Open Subtitles\" Benutzername:",
+ "LabelOpenSubtitlesPassword": "\"Open Subtitles\" Passwort:",
+ "HeaderChapterDownloadingHelp": "Wenn Media Browser deine Videodateien scannt kann er nach passenden Kapitelnamen suchen und diese mit Hilfe eines Kapitel Plugins, wie beispielsweise ChapterDb, herunterladen.",
+ "LabelPlayDefaultAudioTrack": "Spiele unabh\u00e4ngig von der Sprache die Standardtonspur",
+ "LabelSubtitlePlaybackMode": "Untertitel Modus:",
+ "LabelDownloadLanguages": "Herunterzuladende Sprachen:",
+ "ButtonRegister": "Registrierung",
+ "LabelSkipIfAudioTrackPresent": "\u00dcberspringen, falls der Ton bereits der herunterladbaren Sprache entspricht",
+ "LabelSkipIfAudioTrackPresentHelp": "Entferne den Haken, um sicherzustellen das alle Videos Untertitel haben, unabh\u00e4ngig von der Audiosprache",
+ "HeaderSendMessage": "sende Nachricht",
+ "ButtonSend": "senden",
+ "LabelMessageText": "Inhalt der Nachricht",
+ "MessageNoAvailablePlugins": "Keine verf\u00fcgbaren Erweiterungen.",
+ "LabelDisplayPluginsFor": "Zeige Plugins f\u00fcr:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
- "ValueSeriesNamePeriod": "Series.name",
- "ValueSeriesNameUnderscore": "Series_name",
- "ValueEpisodeNamePeriod": "Episode.name",
- "ValueEpisodeNameUnderscore": "Episode_name",
- "HeaderTypeText": "Enter Text",
+ "LabelEpisodeNamePlain": "Episodenname",
+ "LabelSeriesNamePlain": "Serienname",
+ "ValueSeriesNamePeriod": "Serien.Name",
+ "ValueSeriesNameUnderscore": "Serien_Name",
+ "ValueEpisodeNamePeriod": "Episodentitel",
+ "ValueEpisodeNameUnderscore": "Episoden_Name",
+ "LabelSeasonNumberPlain": "Staffelnummer",
+ "LabelEpisodeNumberPlain": "Episodennummer",
+ "LabelEndingEpisodeNumberPlain": "Nummer der letzten Episode",
+ "HeaderTypeText": "Texteingabe",
"LabelTypeText": "Text",
- "HeaderSearchForSubtitles": "Search for Subtitles",
- "MessageNoSubtitleSearchResultsFound": "No search results founds.",
- "TabDisplay": "Display",
- "TabLanguages": "Languages",
- "TabWebClient": "Web Client",
- "LabelEnableThemeSongs": "Enable theme songs",
- "LabelEnableBackdrops": "Aktiviere Backdrops",
- "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.",
- "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.",
- "HeaderHomePage": "Home Page",
+ "HeaderSearchForSubtitles": "Suche nach Untertiteln",
+ "MessageNoSubtitleSearchResultsFound": "Keine Suchergebnisse gefunden",
+ "TabDisplay": "Anzeige",
+ "TabLanguages": "Sprachen",
+ "TabWebClient": "Webclient",
+ "LabelEnableThemeSongs": "Aktiviere Titelmelodie",
+ "LabelEnableBackdrops": "Aktiviere Hintergr\u00fcnde",
+ "LabelEnableThemeSongsHelp": "Wenn aktiviert, wird die Titelmusik w\u00e4hrend dem Durchsuchen durch die Bibliothek im Hintergrund abgespielt",
+ "LabelEnableBackdropsHelp": "Falls aktiviert, werden beim durchsuchen der Bibliothek auf einigen Seiten passende Hintergr\u00fcnde angezeigt.",
+ "HeaderHomePage": "Startseite",
"HeaderSettingsForThisDevice": "Einstellungen f\u00fcr dieses Ger\u00e4t",
"OptionAuto": "Auto",
"OptionYes": "Ja",
"OptionNo": "Nein",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
- "OptionResumablemedia": "Resume",
- "OptionLatestMedia": "Latest media",
- "OptionLatestChannelMedia": "Latest channel items",
- "HeaderLatestChannelItems": "Latest Channel Items",
- "OptionNone": "None",
- "HeaderLiveTv": "Live TV",
+ "LabelHomePageSection1": "Startseite Bereich 1:",
+ "LabelHomePageSection2": "Startseite Bereich 2:",
+ "LabelHomePageSection3": "Startseite Bereich 3:",
+ "LabelHomePageSection4": "Startseite Bereich 4:",
+ "OptionMyViewsButtons": "Meine Ansichten (Tasten)",
+ "OptionMyViews": "Meine Ansichten",
+ "OptionMyViewsSmall": "Meine Ansichten (Klein)",
+ "OptionResumablemedia": "Wiederhole",
+ "OptionLatestMedia": "Neuste Medien",
+ "OptionLatestChannelMedia": "Neueste Channel Inhalte:",
+ "HeaderLatestChannelItems": "Neueste Channel Inhalte:",
+ "OptionNone": "Keines",
+ "HeaderLiveTv": "Live-TV",
"HeaderReports": "Meldungen",
- "HeaderMetadataManager": "Metadata Manager",
+ "HeaderMetadataManager": "Metadaten-Manager",
"HeaderPreferences": "Einstellungen",
- "MessageLoadingChannels": "Lade Channel Inhalt...",
+ "MessageLoadingChannels": "Lade Kanalinhalt...",
+ "MessageLoadingContent": "Lade Inhalt...",
"ButtonMarkRead": "Als gelesen markieren",
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Meistgesehen",
"TabNextUp": "Als N\u00e4chstes",
- "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 New button to start creating Collections.",
+ "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 es dir eine personalisierte Zusammenstellung von Filmen, Serien, Alben, B\u00fcchern und Spielen zu genie\u00dfen. Klicke auf den \"Neu\" Button um mit der Erstellung von Sammlungen zu beginnen.",
+ "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.",
+ "MessageNoPlaylistItemsAvailable": "Diese Wiedergabeliste ist momentan leer.",
"HeaderWelcomeToMediaBrowserWebClient": "Willkommen zum Media Browser Web Client",
"ButtonDismiss": "Verwerfen",
- "MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
+ "MessageLearnHowToCustomize": "Lerne wie du diese Seite deinen pers\u00f6nlichen Vorlieben anpassen kannst. Klicke auf dein Benutzerbild in der oberen rechten Ecke des Bildschirms f\u00fcr die Anzeige und \u00c4nderung von Einstellungen.",
"ButtonEditOtherUserPreferences": "Bearbeite die pers\u00f6nlichen Einstellungen dieses Benutzers",
"LabelChannelStreamQuality": "Bevorzugte Qualit\u00e4t des Internetstreams",
- "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.",
- "OptionBestAvailableStreamQuality": "Best available",
- "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:",
- "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.",
- "LabelChannelDownloadPath": "Channel content download path:",
- "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.",
+ "LabelChannelStreamQualityHelp": "In einer Umgebung mit langsamer Bandbreite kann die Beschr\u00e4nkung der Wiedergabequalit\u00e4t eine fl\u00fcssige Darstellung sichern.",
+ "OptionBestAvailableStreamQuality": "Die besten verf\u00fcgbaren",
+ "LabelEnableChannelContentDownloadingFor": "Aktiviere das herunterladen von Channel Inhalten f\u00fcr:",
+ "LabelEnableChannelContentDownloadingForHelp": "Manche Kan\u00e4le unterst\u00fctzen das herunterladen von Inhalten vor dem eigentlichen ansehen. Aktiviere diese Funktion in Umgebungen mit langsamer Bandbreite um Inhalte herunterzuladen w\u00e4hrend keine aktive Nutzung stattfindet. Die Inhalte werden dabei im Zuge der automatisierten Channel Download Aufgabe heruntergeladen.",
+ "LabelChannelDownloadPath": "Channel Inhalt Downloadverzeichnis:",
+ "LabelChannelDownloadPathHelp": "Lege, falls gew\u00fcnscht, einen eigenen Pfad f\u00fcr Downloads fest. Lasse das Feld frei, wenn in den internen Programmdatenordner heruntergeladen werden soll.",
"LabelChannelDownloadAge": "L\u00f6sche Inhalt nach: (Tagen)",
- "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.",
- "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.",
- "LabelSelectCollection": "Select collection:",
- "ViewTypeMovies": "Movies",
+ "LabelChannelDownloadAgeHelp": "Heruntergeladene Inhalte die \u00e4lter als dieser Wert sind werden gel\u00f6scht. Sie werden aber weiterhin \u00fcber das Internetstreaming verf\u00fcgbar sein.",
+ "ChannelSettingsFormHelp": "Installiere Kan\u00e4le wie beispielsweise \"Trailers\" oder \"Vimeo\" aus dem Plugin Katalog.",
+ "LabelSelectCollection": "W\u00e4hle Zusammenstellung:",
+ "ViewTypeMovies": "Filme",
"ViewTypeTvShows": "TV",
- "ViewTypeGames": "Games",
- "ViewTypeMusic": "Music",
- "ViewTypeBoxSets": "Collections",
- "ViewTypeChannels": "Channels",
- "ViewTypeLiveTV": "Live TV",
- "HeaderOtherDisplaySettings": "Display Settings",
- "HeaderMyViews": "My Views",
- "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",
- "TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "ViewTypeGames": "Spiele",
+ "ViewTypeMusic": "Musik",
+ "ViewTypeBoxSets": "Sammlungen",
+ "ViewTypeChannels": "Kan\u00e4le",
+ "ViewTypeLiveTV": "Live-TV",
+ "HeaderOtherDisplaySettings": "Anzeige Einstellungen",
+ "HeaderMyViews": "Meine Ansichten",
+ "LabelSelectFolderGroups": "Gruppiere Inhalte von folgenden Verzeichnissen automatisch zu Ansichten wie beispielsweise Filme, Musik und TV:",
+ "LabelSelectFolderGroupsHelp": "Verzeichnisse die nicht markiert sind werden alleine, mit ihren eigenen Ansichten, angezeigt.",
+ "OptionDisplayAdultContent": "Zeige Inhalt f\u00fcr Erwachsene an",
+ "OptionLibraryFolders": "Medienverzeichnisse",
+ "TitleRemoteControl": "Fernsteuerung",
+ "OptionLatestTvRecordings": "Neueste Aufnahmen",
+ "LabelProtocolInfo": "Protokoll Information:",
+ "LabelProtocolInfoHelp": "Der Wert, der f\u00fcr die Beantwortung von GetProtocolInfo Anfragen durch die Endger\u00e4te benutzt wird.",
+ "TabXbmcMetadata": "XBMC",
+ "HeaderXbmcMetadataHelp": "Media Browser beinhaltet die native Unterst\u00fctzung von XBMC .nfo Metadaten und Bildern. Benutze den \"Erweitert\" Reiter um Optionen f\u00fcr deine Medientypen zu konfigurieren und XBMC Metadaten zu aktivieren oder zu deaktivieren.",
+ "LabelXbmcMetadataUser": "F\u00fcge \"Bereits gesehen\" Daten in .nfo Dateien f\u00fcr folgende Benutzer hinzu:",
+ "LabelXbmcMetadataUserHelp": "Aktiviere diese Funktion um den \"Gesehen\" Status zwischen Media Browser und XBMC synchron zu halten.",
+ "LabelXbmcMetadataDateFormat": "Ver\u00f6ffentlichungsdatum Format:",
+ "LabelXbmcMetadataDateFormatHelp": "Alle Zeiten innerhalb von nfo Dateien werden ausgelesen und auf das angegeben Format angepasst.",
+ "LabelXbmcMetadataSaveImagePaths": "Speichere Bildpfade innerhalb von nfo Dateien",
+ "LabelXbmcMetadataSaveImagePathsHelp": "Diese Funktion ist n\u00fctzlich, falls du Bildnamen nutzt, die nicht mit den XBMC Vorgaben kompatibel sind.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Aktiviere Pfadersetzung",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Aktiviert die Pfadersetzung f\u00fcr Bildpfade mit Hilfe der Server Pfadersetzungseinstellungen.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "Siehe Pfadersetzung.",
+ "LabelGroupChannelsIntoViews": "Zeige die folgenden Kan\u00e4le direkt innerhalb meiner Ansichten:",
+ "LabelGroupChannelsIntoViewsHelp": "Falls aktiviert, werden diese Kan\u00e4le direkt neben den anderen Ansichten angezeigt. Falls deaktiviert, werden sie innerhalb einer separaten Kanalansicht angezeigt.",
+ "LabelDisplayCollectionsView": "Zeigt eine Ansicht f\u00fcr Sammlungen, um Filmsammlungen darzustellen",
+ "LabelXbmcMetadataEnableExtraThumbs": "Kopiere extrafanart in extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "Wenn Bilder heruntergeladen werden, k\u00f6nnen sie sowohl in extrafanart als auch in extrathumbs gespeichert werden, um die maximale Kompatibilit\u00e4t mit XBMC Skins zu gew\u00e4hrleisten.",
+ "TabServices": "Dienste",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server Logdateien",
+ "TabBranding": "Markierung",
+ "HeaderBrandingHelp": "Personalisiere die Darstellung von Media Browser um sie den Bed\u00fcrfnissen deiner Gemeinschaft oder Organisation anzupassen.",
+ "LabelLoginDisclaimer": "Anmeldung Haftungsausschluss:",
+ "LabelLoginDisclaimerHelp": "Dies wird am Boden des Anmeldebildschirms angezeigt.",
+ "LabelAutomaticallyDonate": "Spende diesen Geldbetrag jeden Monat automatisch",
+ "LabelAutomaticallyDonateHelp": "Du kannst die Zahlungen jederzeit \u00fcber deinen PayPal Account deaktivieren.",
+ "OptionList": "List",
+ "TabDashboard": "Optionsleiste",
+ "TitleServer": "Server:",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadaten:",
+ "LabelImagesByName": "Bilder nach Namen:",
+ "LabelTranscodingTemporaryFiles": "Transkodiere tempor\u00e4re Dateien:",
+ "HeaderLatestMusic": "Neueste Musik",
+ "HeaderBranding": "Markierung",
+ "HeaderApiKeys": "API Schl\u00fcssel",
+ "HeaderApiKeysHelp": "Externe Anwendungen ben\u00f6tigen API Schl\u00fcssel um mit Media Browser kommunizieren zu k\u00f6nnen. Schl\u00fcssel k\u00f6nnen automatisch, durch das einloggen \u00fcber einen Media Browser Benutzeraccount, oder \u00fcber das manuelle Eintragen des Schl\u00fcssels innerhalb der jeweiligen Anwendung vergeben werden.",
+ "HeaderApiKey": "API Schl\u00fcssel",
+ "HeaderApp": "App",
+ "HeaderDevice": "Endger\u00e4t",
+ "HeaderUser": "Benutzer",
+ "HeaderDateIssued": "Datum gesetzt",
+ "LabelChapterName": "Kapitel {0}",
+ "HeaderNewApiKey": "Neuer API Schl\u00fcssel",
+ "LabelAppName": "App Name",
+ "LabelAppNameExample": "Beispiel: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Erteile einer Anwendung Berechtigungen um mit Media Browser kommunizieren zu k\u00f6nnen.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identfikations Header",
+ "LabelValue": "Wert:",
+ "LabelMatchType": "\u00dcbereinstimmungstyp:",
+ "OptionEquals": "Gleiche",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "Ansicht",
+ "TabSort": "Sortieren",
+ "TabFilter": "Filter",
+ "ButtonView": "Ansicht",
+ "LabelPageSize": "Elementenbegrenzung:",
+ "LabelPath": "Pfad:",
+ "LabelView": "Ansicht:",
+ "TabUsers": "Benutzer",
+ "LabelSortName": "Sortiername:",
+ "LabelDateAdded": "Hinzugef\u00fcgt am:",
+ "HeaderFeatures": "Funktionen",
+ "HeaderAdvanced": "Erweitert",
+ "ButtonSync": "Synchronisieren",
+ "TabScheduledTasks": "Geplante Aufgaben",
+ "HeaderChapters": "Kapitel",
+ "HeaderResumeSettings": "Einstellungen zur\u00fccksetzen",
+ "TabSync": "Synchronisieren",
+ "TitleUsers": "Benutzer",
+ "LabelProtocol": "Protokoll: ",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Kontext:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Synchronisieren",
+ "ButtonAddToPlaylist": "Hinzuf\u00fcgen zur Wiedergabeliste",
+ "TabPlaylists": "Wiedergabelisten",
+ "ButtonClose": "Schlie\u00dfen",
+ "LabelAllLanguages": "Alle Sprachen",
+ "HeaderBrowseOnlineImages": "Durchsuche Onlinebilder",
+ "LabelSource": "Quelle:",
+ "OptionAll": "Alle",
+ "LabelImage": "Bild:",
+ "ButtonBrowseImages": "Durchsuche Bilder",
+ "HeaderImages": "Bilder",
+ "HeaderBackdrops": "Hintergr\u00fcnde",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Hinzuf\u00fcgen\/Aktualisieren von Bild",
+ "LabelJpgPngOnly": "Nur JPG\/PNG",
+ "LabelImageType": "Bildtyp:",
+ "OptionPrimary": "Prim\u00e4r",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box R\u00fcckseite",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Men\u00fc",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Gesperrt",
+ "OptionUnidentified": "Undefiniert",
+ "OptionMissingParentalRating": "Fehlende Altersfreigabe",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Eoisoden:",
+ "OptionSeason0": "Staffel 0",
+ "LabelReport": "Bericht:",
+ "OptionReportSongs": "Lieder",
+ "OptionReportSeries": "Serien",
+ "OptionReportSeasons": "Staffeln",
+ "OptionReportTrailers": "Trailer",
+ "OptionReportMusicVideos": "Musikvideos",
+ "OptionReportMovies": "Filme",
+ "OptionReportHomeVideos": "Heimvideos",
+ "OptionReportGames": "Spiele",
+ "OptionReportEpisodes": "Episoden",
+ "OptionReportCollections": "Sammlungen",
+ "OptionReportBooks": "B\u00fccher",
+ "OptionReportArtists": "Interpreten",
+ "OptionReportAlbums": "Alben",
+ "OptionReportAdultVideos": "Videos f\u00fcr Erwachsene",
+ "ButtonMore": "Mehr",
+ "HeaderActivity": "Aktivit\u00e4ten",
+ "ScheduledTaskStartedWithName": "{0} gestartet",
+ "ScheduledTaskCancelledWithName": "{0} wurde abgebrochen",
+ "ScheduledTaskCompletedWithName": "{0} abgeschlossen",
+ "ScheduledTaskFailed": "Geplante Aufgabe abgeschlossen",
+ "PluginInstalledWithName": "{0} wurde installiert",
+ "PluginUpdatedWithName": "{0} wurde aktualisiert",
+ "PluginUninstalledWithName": "{0} wurde deinstalliert",
+ "ScheduledTaskFailedWithName": "{0} fehlgeschlagen",
+ "ItemAddedWithName": "{0} wurde der Bibliothek hinzugef\u00fcgt",
+ "ItemRemovedWithName": "{0} wurde aus der Bibliothek entfernt",
+ "DeviceOnlineWithName": "{0} ist verbunden",
+ "UserOnlineFromDevice": "{0} ist online von {1}",
+ "DeviceOfflineWithName": "{0} wurde getrennt",
+ "UserOfflineFromDevice": "{0} wurde getrennt von {1}",
+ "SubtitlesDownloadedForItem": "Untertitel heruntergeladen f\u00fcr {0}",
+ "SubtitleDownloadFailureForItem": "Download der Untertitel fehlgeschlagen f\u00fcr {0}",
+ "LabelRunningTimeValue": "Laufzeit: {0}",
+ "LabelIpAddressValue": "IP Adresse: {0}",
+ "UserConfigurationUpdatedWithName": "Benutzereinstellungen wurden aktualisiert f\u00fcr {0}",
+ "UserCreatedWithName": "Benutzer {0} wurde erstellt",
+ "UserPasswordChangedWithName": "Das Passwort f\u00fcr Benutzer {0} wurde ge\u00e4ndert",
+ "UserDeletedWithName": "Benutzer {0} wurde gel\u00f6scht",
+ "MessageServerConfigurationUpdated": "Server Einstellungen wurden aktualisiert",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Der Server Einstellungsbereich {0} wurde aktualisiert",
+ "MessageApplicationUpdated": "Media Browser Server wurde aktualisiert",
+ "AuthenticationSucceededWithUserName": "{0} erfolgreich authentifiziert",
+ "FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}",
+ "UserStartedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} beendet",
+ "UserStoppedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} beendet",
+ "AppDeviceValues": "App: {0}, Ger\u00e4t: {1}",
+ "ProviderValue": "Anbieter: {0}",
+ "LabelChannelDownloadSizeLimit": "Download Gr\u00f6\u00dfenlimit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Beschr\u00e4nkt die Gr\u00f6\u00dfe der Channel Downloadverzeichnisse",
+ "HeaderRecentActivity": "K\u00fcrzliche Aktivit\u00e4ten"
} \ 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 1caf760b1..2923d3a9f 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/el.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/el.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Updates",
- "HeaderUpdateLevel": "Update Level",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
- "HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Failed",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "HeaderMyLibrary": "My Library",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "\u03ad\u03be\u03bf\u03b4\u03bf\u03c2",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "\u0395\u03c0\u03af\u03c3\u03ba\u03b5\u03c8\u03b7 \u039a\u03bf\u03b9\u03bd\u03cc\u03c4\u03b7\u03c4\u03b1",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "\u03c0\u03c1\u03cc\u03c4\u03c5\u03c0\u03bf",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "\u03a0\u03c1\u03bf\u03b2\u03bf\u03bb\u03ae Api \u03a4\u03b5\u03ba\u03bc\u03b7\u03c1\u03af\u03c9\u03c3\u03b7",
+ "ViewTypeFolders": "Folders",
"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",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "\u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03c4\u03b5 \u03c4\u03bf Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"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",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "\u03b5\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03b4\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"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",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "\u03c0\u03c1\u03bf\u03b7\u03b3\u03bf\u03cd\u03bc\u03b5\u03bd\u03bf\u03c2",
+ "HeaderPassword": "Password",
"LabelFinish": "\u03c4\u03ad\u03bb\u03bf\u03c2",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "\u03b5\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf\u03c2 ",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "\u03a4\u03b5\u03bb\u03b5\u03b9\u03ce\u03c3\u03b1\u03c4\u03b5",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "\u039a\u03b1\u03bb\u03ce\u03c2 \u03ae\u03c1\u03b8\u03b1\u03c4\u03b5 \u03c3\u03c4\u03bf Media Browser",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"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.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "\u03a0\u03b5\u03af\u03c4\u03b5 \u03bc\u03b1\u03c2 \u03b3\u03b9\u03b1 \u03b5\u03c3\u03ac\u03c2",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "\u03a4\u03bf \u03cc\u03bd\u03bf\u03bc\u03ac \u03c3\u03b1\u03c2",
+ "OptionRefreshAllData": "Refresh all data",
"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",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser \u03c0\u03b5\u03c1\u03b9\u03bb\u03b1\u03bc\u03b2\u03ac\u03bd\u03b5\u03b9 \u03b5\u03bd\u03c3\u03c9\u03bc\u03b1\u03c4\u03c9\u03bc\u03ad\u03bd\u03b7 \u03c5\u03c0\u03bf\u03c3\u03c4\u03ae\u03c1\u03b9\u03be\u03b7 \u03b3\u03b9\u03b1 \u03c0\u03c1\u03bf\u03c6\u03af\u03bb \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7, \u03c0\u03bf\u03c5 \u03b5\u03c0\u03b9\u03c4\u03c1\u03ad\u03c0\u03bf\u03c5\u03bd \u03c3\u03b5 \u03ba\u03ac\u03b8\u03b5 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7 \u03bd\u03b1 \u03ad\u03c7\u03b5\u03b9 \u03c4\u03b9\u03c2 \u03b4\u03b9\u03ba\u03ad\u03c2 \u03c4\u03bf\u03c5\u03c2 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u03bf\u03b8\u03cc\u03bd\u03b7\u03c2, playstate \u03ba\u03b1\u03b9 \u03b3\u03bf\u03bd\u03b9\u03ba\u03bf\u03cd \u03b5\u03bb\u03ad\u03b3\u03c7\u03bf\u03c5.\n",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Windows \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 ",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"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",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser Server \u03b5\u03ba\u03c4\u03b5\u03bb\u03b5\u03af \u03c3\u03c5\u03bd\u03ae\u03b8\u03c9\u03c2 \u03c9\u03c2 \u03ad\u03bd\u03b1 desktop \u03b5\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae \u03bc\u03b5 \u03ad\u03bd\u03b1 \u03b5\u03b9\u03ba\u03bf\u03bd\u03af\u03b4\u03b9\u03bf \u03c4\u03bf\u03c5 \u03b4\u03af\u03c3\u03ba\u03bf\u03c5, \u03b1\u03bb\u03bb\u03ac \u03b1\u03bd \u03c0\u03c1\u03bf\u03c4\u03b9\u03bc\u03ac\u03c4\u03b5 \u03bd\u03b1 \u03c4\u03c1\u03ad\u03be\u03b5\u03b9 \u03c9\u03c2 \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03af\u03b1 \u03c5\u03c0\u03cc\u03b2\u03b1\u03b8\u03c1\u03bf, \u03bc\u03c0\u03bf\u03c1\u03b5\u03af \u03bd\u03b1 \u03be\u03b5\u03ba\u03b9\u03bd\u03ae\u03c3\u03b5\u03b9 \u03b1\u03c0\u03cc \u03c4\u03bf\u03bd \u03c0\u03af\u03bd\u03b1\u03ba\u03b1 \u03b5\u03bb\u03ad\u03b3\u03c7\u03bf\u03c5 \u03c4\u03c9\u03bd Windows \u03c5\u03c0\u03b7\u03c1\u03b5\u03c3\u03b9\u03ce\u03bd \u03b1\u03bd\u03c4 '\u03b1\u03c5\u03c4\u03bf\u03cd. ",
+ "HeaderIdentifyItem": "Identify Item",
"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.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Dashboard<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
"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",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Enable video image extraction",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"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.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelAlbum": "Album:",
"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",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "\u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7 ",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "New",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Setup your media library",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "\u03a0\u03c1\u03bf\u03c3\u03b8\u03ad\u03c3\u03c4\u03b5 \u03c4\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03c4\u03bf\u03c5 Media",
+ "LabelWebsite": "Website:",
"LabelFolderType": "\u03a4\u03cd\u03c0\u03bf \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5 ",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "\u0391\u03c0\u03b1\u03b9\u03c4\u03b5\u03af \u03c4\u03b7 \u03c7\u03c1\u03ae\u03c3\u03b7 \u03b5\u03bd\u03cc\u03c2 plugin.\u03c0.\u03c7. Gamebrowser \u03ae MB Bookshelf.",
+ "LabelOverview": "Overview:",
"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",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "T\u03b7 \u03c7\u03ce\u03c1\u03b1",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "\u03a4\u03b7 \u03b3\u03bb\u03ce\u03c3\u03c3\u03b1",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "\u03a0\u03c1\u03bf\u03c4\u03b9\u03bc\u03ce\u03bc\u03b5\u03bd\u03b7 \u03b3\u03bb\u03ce\u03c3\u03c3\u03b1 \u03bc\u03b5\u03c4\u03b1",
+ "LabelPlaceOfBirth": "Place of birth:",
"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",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 artwork \u03ba\u03b1\u03b9 \u03bc\u03b5\u03c4\u03b1-\u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1 \u03b1\u03c0\u03b5\u03c5\u03b8\u03b5\u03af\u03b1\u03c2 \u03c3\u03b5 \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5\u03c2 \u03bc\u03ad\u03c3\u03c9\u03bd \u03b8\u03b1 \u03c4\u03bf\u03c5\u03c2 \u03b8\u03ad\u03c3\u03b5\u03b9 \u03c3\u03b5 \u03ad\u03bd\u03b1 \u03c4\u03cc\u03c0\u03bf \u03cc\u03c0\u03bf\u03c5 \u03bc\u03c0\u03bf\u03c1\u03bf\u03cd\u03bd \u03b5\u03cd\u03ba\u03bf\u03bb\u03b1 \u03bd\u03b1 \u03b5\u03c0\u03b5\u03be\u03b5\u03c1\u03b3\u03b1\u03c3\u03c4\u03b5\u03af\u03c4\u03b5.",
+ "LabelAirDate": "Air days:",
"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 ",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser \u03bc\u03c0\u03bf\u03c1\u03b5\u03af \u03bd\u03b1 \u03ba\u03b1\u03c4\u03b5\u03b2\u03ac\u03c3\u03b5\u03b9 \u03c0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 \u03c3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ac \u03bc\u03b5 \u03c4\u03b1 \u03bc\u03ad\u03c3\u03b1 \u03c3\u03b1\u03c2 \u03b3\u03b9\u03b1 \u03bd\u03b1 \u03b5\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03b9\u03ae\u03c3\u03b5\u03c4\u03b5 \u03c4\u03b7\u03bd \u03c0\u03bb\u03bf\u03cd\u03c3\u03b9\u03b1 \u03c0\u03b1\u03c1\u03bf\u03c5\u03c3\u03b9\u03ac\u03c3\u03b5\u03b9\u03c2.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "\u03a0\u03c1\u03bf\u03c4\u03b9\u03bc\u03ae\u03c3\u03b5\u03b9\u03c2 ",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "\u03c4\u03bf\u03bd \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "\u03a0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03c3\u03c4\u03b7 \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7",
+ "LabelBudget": "Budget",
"TabImage": "\u03b5\u03b9\u03ba\u03cc\u03bd\u03b1",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "\u03c0\u03c1\u03bf\u03c6\u03af\u03bb ",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "Images",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "Titles",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"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",
+ "HeaderExternalIds": "External Id's:",
"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",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"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.",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"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",
+ "LabelAirsBeforeSeason": "Airs before season:",
"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",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
"TabProfiles": "\u03c4\u03b1 \u03c0\u03c1\u03bf\u03c6\u03af\u03bb",
+ "HeaderTags": "Tags",
"TabSecurity": "A\u03c3\u03c6\u03ac\u03bb\u03b5\u03b9\u03b1 ",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "\u03a0\u03c1\u03bf\u03c3\u03b8\u03ae\u03ba\u03b7 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "\u0391\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c3\u03c4\u03b5",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"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",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "\u039d\u03ad\u03bf \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2 ",
+ "HeaderDonationType": "Donation type:",
"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 ",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"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 ",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "\u03a4\u03c1\u03ad\u03c7\u03bf\u03bd\u03c4\u03b1 \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"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:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"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",
+ "OptionNoTrailer": "No Trailer",
"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.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae \u03b5\u03b9\u03ba\u03cc\u03bd\u03b1\u03c2",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "Select users:",
+ "OptionActor": "Actor",
"ButtonUpload": "\u0391\u03bd\u03b5\u03b2\u03ac\u03c3\u03c4\u03b5 ",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "\u0391\u03bd\u03b5\u03b2\u03ac\u03c3\u03c4\u03b5 \u03bd\u03ad\u03b1 \u03b5\u03b9\u03ba\u03cc\u03bd\u03b1",
+ "OptionDirector": "Director",
"LabelDropImageHere": "\u03c1\u03af\u03c7\u03bd\u03b5\u03c4\u03b5 \u03c4\u03b7\u03bd \u03b5\u03b9\u03ba\u03cc\u03bd\u03b1 \u03b5\u03b4\u03ce",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only",
+ "OptionProducer": "Producer",
"MessageNothingHere": "\u03a4\u03af\u03c0\u03bf\u03c4\u03b1 \u03b5\u03b4\u03ce ",
+ "OptionWriter": "Writer",
"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",
+ "LabelAirDays": "Air days:",
"TabSuggested": "\u03a0\u03c1\u03bf\u03c4\u03b5\u03b9\u03bd\u03cc\u03bc\u03b5\u03bd\u03b7",
+ "LabelAirTime": "Air time:",
"TabLatest": "\u03c4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03bf\u03c2",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "\u0395\u03c0\u03b5\u03c1\u03c7\u03cc\u03bc\u03b5\u03bd\u03b7",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "\u0395\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1",
"TabEpisodes": "\u0395\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1",
"TabGenres": "\u0395\u03af\u03b4\u03b7",
@@ -163,7 +225,7 @@
"OptionAscending": "\u03b1\u03cd\u03be\u03bf\u03c5\u03c3\u03b1",
"OptionDescending": "\u03c6\u03b8\u03af\u03bd\u03bf\u03c5\u03c3\u03b1 ",
"OptionRuntime": "Runtime",
- "OptionReleaseDate": "\u03b7\u03bc\u03b5\u03c1\u03bf\u03bc\u03b7\u03bd\u03af\u03b1 \u03ba\u03c5\u03ba\u03bb\u03bf\u03c6\u03bf\u03c1\u03af\u03b1\u03c2",
+ "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",
@@ -213,6 +275,8 @@
"TabMovies": "Movies",
"TabStudios": "Studios",
"TabTrailers": "Trailers",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "Latest Movies",
"HeaderLatestTrailers": "Latest Trailers",
"OptionHasSpecialFeatures": "Special Features",
@@ -224,7 +288,7 @@
"HeaderStatus": "Status",
"OptionContinuing": "Continuing",
"OptionEnded": "Ended",
- "HeaderAirDays": "Air Days:",
+ "HeaderAirDays": "Air Days",
"OptionSunday": "Sunday",
"OptionMonday": "Monday",
"OptionTuesday": "Tuesday",
@@ -232,7 +296,8 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
- "HeaderManagement": "Management:",
+ "HeaderManagement": "Management",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "Missing IMDb Id",
"OptionMissingTvdbId": "Missing TheTVDB Id",
"OptionMissingOverview": "Missing Overview",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "Select",
- "ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
@@ -290,13 +354,13 @@
"ButtonSelectDirectory": "Select Directory",
"LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.",
"LabelCachePath": "Cache path:",
- "LabelCachePathHelp": "This folder contains server cache files, such as images.",
+ "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.",
"LabelImagesByNamePath": "Images by name path:",
- "LabelImagesByNamePathHelp": "This folder contains actor, artist, genre and studio images.",
+ "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.",
"LabelMetadataPath": "Metadata path:",
- "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.",
+ "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.",
+ "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",
@@ -313,12 +377,12 @@
"LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.",
"LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
"LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
- "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "ExtractChapterImagesHelp": "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 when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
"LabelMetadataDownloadLanguage": "Preferred download language:",
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
- "OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
@@ -347,6 +411,8 @@
"TabStatus": "Status",
"TabSettings": "Settings",
"ButtonRefreshGuideData": "Refresh Guide Data",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
"OptionRecordOnAllChannels": "Record program on all channels",
"OptionRecordAnytime": "Record program at any time",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Cast & Crew",
"HeaderAdditionalParts": "Additional Parts",
"ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Missing",
"LabelOffline": "Offline",
"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.",
@@ -512,11 +579,13 @@
"HeaderProgram": "Program",
"HeaderClients": "Clients",
"LabelCompleted": "Completed",
+ "LabelFailed": "Failed",
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeasonNumber": "Season number",
- "LabelEpisodeNumber": "Episode number",
- "LabelEndingEpisodeNumber": "Ending episode number",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Enable this notification",
"LabelMonitorUsers": "Monitor activity from:",
"LabelSendNotificationToUsers": "Send the notification to:",
- "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.",
"LabelUseNotificationServices": "Use the following services:",
"CategoryUser": "User",
"CategorySystem": "System",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
"ButtonHome": "Home",
+ "ButtonSearch": "Search",
"ButtonSettings": "Settings",
"ButtonTakeScreenshot": "Capture Screenshot",
"ButtonLetterUp": "Letter Up",
@@ -661,6 +730,8 @@
"ButtonScenes": "Scenes",
"ButtonSubtitles": "Subtitles",
"ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Group movies into collections",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
"LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "Friendly name",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text",
"HeaderSearchForSubtitles": "Search for Subtitles",
@@ -796,13 +879,13 @@
"OptionAuto": "Auto",
"OptionYes": "Yes",
"OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferences",
"MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Mark Read",
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
"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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
"ButtonDismiss": "Dismiss",
"MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Display adult content",
"OptionLibraryFolders": "Media folders",
"TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 751d1e468..7d328c042 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Updates",
- "HeaderUpdateLevel": "Update Level",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
- "HeaderCustomizeOptionsPerMediaType": "Customise options per media type",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Failed",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "HeaderMyLibrary": "My Library",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "Exit",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "Visit Community",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "Standard",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "View Api Documentation",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "Browse Library",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "Configure Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "Open Library Viewer",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "Restart Server",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "Show Log Window",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "Previous",
+ "HeaderPassword": "Password",
"LabelFinish": "Finish",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "Next",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "You're Done!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "Welcome to Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "Tell us about yourself",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "Your first name:",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Windows Service",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.",
+ "HeaderIdentifyItem": "Identify Item",
"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.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Dashboard<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
"LabelConfigureSettings": "Configure settings",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Enable video image extraction",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"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.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Cancel",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "New",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Setup your media library",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "Add media folder",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Folder type:",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Refer to the media library wiki.",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "Country:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "Language:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "Preferred metadata language:",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "Save artwork and metadata into media folders",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "Download artwork and metadata from the internet",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "Preferences",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "Password",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "Library Access",
+ "LabelBudget": "Budget",
"TabImage": "Image",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "Profile",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "Images",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "Titles",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "Video Playback Settings",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "Audio language preference:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "Subtitle language preference:",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Profiles",
+ "HeaderTags": "Tags",
"TabSecurity": "Security",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "Add User",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "Save",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "Reset Password",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "New password:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "New password confirm:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "Create Password",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Current password:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "Maximum allowed parental rating:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "Delete Image",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "Select users:",
+ "OptionActor": "Actor",
"ButtonUpload": "Upload",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Upload New Image",
- "LabelDropImageHere": "Drop Image Here",
+ "OptionDirector": "Director",
+ "LabelDropImageHere": "Drop image here",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Nothing here.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Suggested",
+ "LabelAirTime": "Air time:",
"TabLatest": "Latest",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "Upcoming",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Shows",
"TabEpisodes": "Episodes",
"TabGenres": "Genres",
@@ -213,6 +275,8 @@
"TabMovies": "Movies",
"TabStudios": "Studios",
"TabTrailers": "Trailers",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "Latest Movies",
"HeaderLatestTrailers": "Latest Trailers",
"OptionHasSpecialFeatures": "Special Features",
@@ -224,7 +288,7 @@
"HeaderStatus": "Status",
"OptionContinuing": "Continuing",
"OptionEnded": "Ended",
- "HeaderAirDays": "Air Days:",
+ "HeaderAirDays": "Air Days",
"OptionSunday": "Sunday",
"OptionMonday": "Monday",
"OptionTuesday": "Tuesday",
@@ -232,7 +296,8 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
- "HeaderManagement": "Management:",
+ "HeaderManagement": "Management",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "Missing IMDb Id",
"OptionMissingTvdbId": "Missing TheTVDB Id",
"OptionMissingOverview": "Missing Overview",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "Select",
- "ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
@@ -290,13 +354,13 @@
"ButtonSelectDirectory": "Select Directory",
"LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.",
"LabelCachePath": "Cache path:",
- "LabelCachePathHelp": "This folder contains server cache files, such as images.",
+ "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.",
"LabelImagesByNamePath": "Images by name path:",
- "LabelImagesByNamePathHelp": "This folder contains actor, artist, genre and studio images.",
+ "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.",
"LabelMetadataPath": "Metadata path:",
- "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.",
+ "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.",
+ "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",
@@ -313,12 +377,12 @@
"LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.",
"LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
"LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
- "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "ExtractChapterImagesHelp": "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 when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
"LabelMetadataDownloadLanguage": "Preferred download language:",
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognises images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
- "OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
@@ -334,7 +398,7 @@
"TabRecordings": "Recordings",
"TabScheduled": "Scheduled",
"TabSeries": "Series",
- "TabFavorites": "Favorites",
+ "TabFavorites": "Favourites",
"TabMyLibrary": "My Library",
"ButtonCancelRecording": "Cancel Recording",
"HeaderPrePostPadding": "Pre\/Post Padding",
@@ -347,6 +411,8 @@
"TabStatus": "Status",
"TabSettings": "Settings",
"ButtonRefreshGuideData": "Refresh Guide Data",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
"OptionRecordOnAllChannels": "Record programme on all channels",
"OptionRecordAnytime": "Record programme at any time",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Cast & Crew",
"HeaderAdditionalParts": "Additional Parts",
"ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Missing",
"LabelOffline": "Offline",
"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.",
@@ -512,11 +579,13 @@
"HeaderProgram": "Program",
"HeaderClients": "Clients",
"LabelCompleted": "Completed",
+ "LabelFailed": "Failed",
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeasonNumber": "Season number",
- "LabelEpisodeNumber": "Episode number",
- "LabelEndingEpisodeNumber": "Ending episode number",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Enable this notification",
"LabelMonitorUsers": "Monitor activity from:",
"LabelSendNotificationToUsers": "Send the notification to:",
- "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.",
"LabelUseNotificationServices": "Use the following services:",
"CategoryUser": "User",
"CategorySystem": "System",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
"ButtonHome": "Home",
+ "ButtonSearch": "Search",
"ButtonSettings": "Settings",
"ButtonTakeScreenshot": "Capture Screenshot",
"ButtonLetterUp": "Letter Up",
@@ -661,6 +730,8 @@
"ButtonScenes": "Scenes",
"ButtonSubtitles": "Subtitles",
"ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Group movies into collections",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
"LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "Friendly name",
@@ -733,7 +814,7 @@
"HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.",
"HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.",
"HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.",
- "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.",
+ "HeaderResponseProfileHelp": "Response profiles provide a way to customise information sent to the device when playing certain kinds of media.",
"LabelXDlnaCap": "X-Dlna cap:",
"LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.",
"LabelXDlnaDoc": "X-Dlna doc:",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text",
"HeaderSearchForSubtitles": "Search for Subtitles",
@@ -796,13 +879,13 @@
"OptionAuto": "Auto",
"OptionYes": "Yes",
"OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -813,15 +896,18 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferences",
"MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Mark Read",
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
"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 New button to start creating Collections.",
+ "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalised groupings of Movies, Series, Albums, Books and Games. Click the New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
"ButtonDismiss": "Dismiss",
- "MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
+ "MessageLearnHowToCustomize": "Learn how to customise this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
"ButtonEditOtherUserPreferences": "Edit this user's personal preferences.",
"LabelChannelStreamQuality": "Preferred internet stream quality:",
"LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Display adult content",
"OptionLibraryFolders": "Media folders",
"TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customise the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 503e8e8d6..79f5001b8 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Updates",
- "HeaderUpdateLevel": "Update Level",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
- "HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Failed",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "HeaderMyLibrary": "My Library",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "Exit",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "Visit Community",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "Standard",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "View Api Documentation",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "Browse Library",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "Configure Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "Open Library Viewer",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "Restart Server",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "Show Log Window",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "Previous",
+ "HeaderPassword": "Password",
"LabelFinish": "Finish",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "Next",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "You're Done!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "Welcome to Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "Tell us about yourself",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "Your first name:",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Windows Service",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.",
+ "HeaderIdentifyItem": "Identify Item",
"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.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Dashboard<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
"LabelConfigureSettings": "Configure settings",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Enable video image extraction",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"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.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Cancel",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "New",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Setup your media library",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "Add media folder",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Folder type:",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Refer to the media library wiki.",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "Country:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "Language:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "Preferred metadata language:",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "Save artwork and metadata into media folders",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "Download artwork and metadata from the internet",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "Preferences",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "Password",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "Library Access",
+ "LabelBudget": "Budget",
"TabImage": "Image",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "Profile",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "Images",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "Titles",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "Video Playback Settings",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "Audio language preference:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "Subtitle language preference:",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Profiles",
+ "HeaderTags": "Tags",
"TabSecurity": "Security",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "Add User",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "Save",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "Reset Password",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "New password:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "New password confirm:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "Create Password",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Current password:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "Maximum allowed parental rating:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "Delete Image",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "Select users:",
+ "OptionActor": "Actor",
"ButtonUpload": "Upload",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Upload New Image",
- "LabelDropImageHere": "Drop Image Here",
+ "OptionDirector": "Director",
+ "LabelDropImageHere": "Drop image here",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Nothing here.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Suggested",
+ "LabelAirTime": "Air time:",
"TabLatest": "Latest",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "Upcoming",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Shows",
"TabEpisodes": "Episodes",
"TabGenres": "Genres",
@@ -213,6 +275,8 @@
"TabMovies": "Movies",
"TabStudios": "Studios",
"TabTrailers": "Trailers",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "Latest Movies",
"HeaderLatestTrailers": "Latest Trailers",
"OptionHasSpecialFeatures": "Special Features",
@@ -224,7 +288,7 @@
"HeaderStatus": "Status",
"OptionContinuing": "Continuing",
"OptionEnded": "Ended",
- "HeaderAirDays": "Air Days:",
+ "HeaderAirDays": "Air Days",
"OptionSunday": "Sunday",
"OptionMonday": "Monday",
"OptionTuesday": "Tuesday",
@@ -232,7 +296,8 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
- "HeaderManagement": "Management:",
+ "HeaderManagement": "Management",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "Missing IMDb Id",
"OptionMissingTvdbId": "Missing TheTVDB Id",
"OptionMissingOverview": "Missing Overview",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "Select",
- "ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
@@ -290,13 +354,13 @@
"ButtonSelectDirectory": "Select Directory",
"LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.",
"LabelCachePath": "Cache path:",
- "LabelCachePathHelp": "This folder contains server cache files, such as images.",
+ "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.",
"LabelImagesByNamePath": "Images by name path:",
- "LabelImagesByNamePathHelp": "This folder contains actor, artist, genre and studio images.",
+ "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.",
"LabelMetadataPath": "Metadata path:",
- "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.",
+ "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.",
+ "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",
@@ -313,12 +377,12 @@
"LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.",
"LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
"LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
- "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "ExtractChapterImagesHelp": "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 when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
"LabelMetadataDownloadLanguage": "Preferred download language:",
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
- "OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
@@ -347,6 +411,8 @@
"TabStatus": "Status",
"TabSettings": "Settings",
"ButtonRefreshGuideData": "Refresh Guide Data",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
"OptionRecordOnAllChannels": "Record program on all channels",
"OptionRecordAnytime": "Record program at any time",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Cast & Crew",
"HeaderAdditionalParts": "Additional Parts",
"ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Missing",
"LabelOffline": "Offline",
"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.",
@@ -512,11 +579,13 @@
"HeaderProgram": "Program",
"HeaderClients": "Clients",
"LabelCompleted": "Completed",
+ "LabelFailed": "Failed",
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeasonNumber": "Season number",
- "LabelEpisodeNumber": "Episode number",
- "LabelEndingEpisodeNumber": "Ending episode number",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Enable this notification",
"LabelMonitorUsers": "Monitor activity from:",
"LabelSendNotificationToUsers": "Send the notification to:",
- "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.",
"LabelUseNotificationServices": "Use the following services:",
"CategoryUser": "User",
"CategorySystem": "System",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
"ButtonHome": "Home",
+ "ButtonSearch": "Search",
"ButtonSettings": "Settings",
"ButtonTakeScreenshot": "Capture Screenshot",
"ButtonLetterUp": "Letter Up",
@@ -661,6 +730,8 @@
"ButtonScenes": "Scenes",
"ButtonSubtitles": "Subtitles",
"ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Group movies into collections",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
"LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "Friendly name",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text",
"HeaderSearchForSubtitles": "Search for Subtitles",
@@ -796,13 +879,13 @@
"OptionAuto": "Auto",
"OptionYes": "Yes",
"OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferences",
"MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Mark Read",
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
"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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
"ButtonDismiss": "Dismiss",
"MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Display adult content",
"OptionLibraryFolders": "Media folders",
"TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 5819ab339..4b8bb6cc6 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/es.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/es.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Actualizaciones",
- "HeaderUpdateLevel": "Nivel de actualizaci\u00f3n",
- "LabelRequireTextSubtitles": "Descarga incluso si el v\u00eddeo ya contiene subt\u00edtulos gr\u00e1ficos",
- "LabelRequireTextSubtitlesHelp": "Mantener versiones de texto de los subt\u00edtulos se traducir\u00e1 en una prestaci\u00f3n m\u00e1s eficiente para los clientes m\u00f3viles.",
- "HeaderSubtitleDownloadingMoreHelp": "Los subt\u00edtulos se consideran faltantes cuando la pista de audio est\u00e1 en un idioma extranjero, y no hay subt\u00edtulos disponibles en el idioma preferido.",
- "LabelDisplayForcedSubtitlesOnly": "Mostrar \u00fanicamente subtitulos forzados",
- "HeaderCustomizeOptionsPerMediaType": "Personalizar las opciones por tipo de medio",
- "LabelAudioLanguagePreferenceHelp": "Si est\u00e1 vac\u00edo, se seleccionar\u00e1 la pista de audio por defecto, sin importar el idioma.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "Todos los dispositivos",
- "HeaderThisDevice": "Este dispositivo",
- "OptionLibraryButtons": "Botones de biblioteca",
- "OptionLibraryTiles": "T\u00edtulos de biblioteca",
- "OptionSmallLibraryTiles": "T\u00edtulos de librer\u00eda (peque\u00f1o)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Err\u00f3neo",
- "LabelSeries": "Serie:",
- "ButtonPreviousTrack": "Pista anterior",
- "ButtonNextTrack": "Pista siguiente",
- "HeaderMyLibrary": "Mi librer\u00eda",
- "HeaderLibraryViews": "Vistas de librer\u00eda",
+ "HeaderPeople": "People",
"LabelExit": "Salir",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "Visitar la comunidad",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Wiki de Github",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "Est\u00e1ndar",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "Ver documentacion de Api",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "Navegar biblioteca",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "Configurar Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "Abrir el visor de la biblioteca",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "Reiniciar el servidor",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "Mostrar la ventana del log",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "Anterior",
+ "HeaderPassword": "Password",
"LabelFinish": "Terminar",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "Siguiente",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "Ha Terminado!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "\u00a1Bienvenido a Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "Este asistente lo guiar\u00e1 por el proceso de instalaci\u00f3n. Para comenzar seleccione su idioma preferido.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "D\u00edganos acerca de usted",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "Su nombre:",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "M\u00e1s usuarios pueden agregarse m\u00e1s tarde en el panel de control.",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser incluye soporte integrado para los perfiles de usuario, lo que permite que cada usuario tenga su propia configuraci\u00f3n de la pantalla, estado de reproducci\u00f3n y control parental.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Servicio de Windows",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "Un servicio de Windows se ha instalado",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser Server se ejecuta normalmente como una aplicaci\u00f3n de escritorio con un icono de la bandeja, pero si prefiere ejecutarlo como un servicio en segundo plano, se puede iniciar desde el panel de control de servicios de Windows en su lugar.",
+ "HeaderIdentifyItem": "Identify Item",
"WindowsServiceIntro2": "Si se utiliza el servicio de Windows, tenga en cuenta que no se puede ejecutar al mismo tiempo que el icono de la bandeja, por lo que tendr\u00e1 que salir de la bandeja con el fin de ejecutar el servicio. Tambi\u00e9n tendr\u00e1 que ser configurado con privilegios administrativos a trav\u00e9s del panel de control del servicio. Tenga en cuenta que en este momento el servicio no es capaz de auto-actualizaci\u00f3n, por lo que las nuevas versiones requieren la interacci\u00f3n manual.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "Eso es todo lo que necesitamos por ahora. Media Browser ha comenzado a reunir informaci\u00f3n sobre su biblioteca de medios. Echa un vistazo a algunas de nuestras aplicaciones, y luego haga clic en <b>Finalizar<\/b> para ver el <b>Panel de control<\/b>.",
+ "HeaderConfirmDeletion": "Confirmar borrado",
"LabelConfigureSettings": "Configuraci\u00f3n de opciones",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Habilitar extracci\u00f3n de im\u00e1genes de video",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"VideoImageExtractionHelp": "Para los v\u00eddeos que no dispongan de im\u00e1genes y que no podemos encontrar en Internet. Esto agregar\u00e1 un tiempo adicional para la exploraci\u00f3n inicial de bibliotecas, pero resultar\u00e1 en una presentaci\u00f3n m\u00e1s agradable.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Extraer im\u00e1genes de cap\u00edtulos para pel\u00edculas",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "Extraer im\u00e1genes de cap\u00edtulo permitir\u00e1 a los clientes mostrar men\u00fas gr\u00e1ficos de selecci\u00f3n de escenas. El proceso puede ser lento, intensivo en utilizaci\u00f3n del CPU y puede requerir varios gigabytes de espacio. Se ejecuta como una tarea nocturna, a las 4 de la ma\u00f1ana, aunque esto se puede configurar en el \u00e1rea de tareas programadas. No se recomienda ejecutar esta tarea durante las horas pico de uso.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Habilitar asignaci\u00f3n de puertos autom\u00e1tico",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP permite la configuraci\u00f3n del router para acceso externo de forma f\u00e1cil y autom\u00e1tica. Esto puede no funcionar en algunos modelos de routers.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "OK",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Cancelar",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "Nuevo",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Configurar biblioteca de medios",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "Agregar una carpeta de medios",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Tipo de carpeta:",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Requiere el uso de un plugin, por ejemplo GameBrowser o MB Bookshelf",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Consultar el wiki de la biblioteca de medios",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "Pa\u00eds:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "Idioma:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "Idioma preferido para metadata",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "Guardar im\u00e1genes y metadata en las carpetas de medios",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "Guardar im\u00e1genes y metadata directamente en las carpetas de medios, permitir\u00e1 colocarlas en un lugar donde se pueden editar f\u00e1cilmente.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "Descargar imagenes y metadata de internet",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser permite descargar informaci\u00f3n acerca de su media para enriquecer la presentaci\u00f3n.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "Preferencias",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "Contrase\u00f1a",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "Acceso a biblioteca",
+ "LabelBudget": "Budget",
"TabImage": "imagen",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "Perfil",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "Im\u00e1genes",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notificaciones",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "T\u00edtulos",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Mostar episodios no disponibles en temporadas",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Mostrar episodios a\u00fan no emitidos en temporadas",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "Ajustes de Reproducci\u00f3n de Video",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Ajustes de reproducci\u00f3n",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "Preferencia de idioma de audio",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "Preferencia de idioma de subtitulos",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Por defecto",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "S\u00f3lo subt\u00edtulos forzados",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Mostrar siempre subt\u00edtulos",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "Sin subt\u00edtulos",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Los subt\u00edtulos que concuerden con la preferencia de idioma se cargar\u00e1n cuando el audio est\u00e9 en un idioma extranjero.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "S\u00f3lo se cargar\u00e1n los subt\u00edtulos marcados como forzados.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Los subt\u00edtulos que concuerden con la preferencia de idioma se cargar\u00e1n independientemente del idioma de audio.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Los subt\u00edtulos no se cargar\u00e1n de forma predeterminada.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Perfiles",
+ "HeaderTags": "Tags",
"TabSecurity": "Seguridad",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "Agregar Usuario",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "Grabar",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "Reiniciar Contrase\u00f1a",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "Nueva Contrase\u00f1a:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "Confirmaci\u00f3n de contrase\u00f1a nueva:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "Crear Contrase\u00f1a",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Contrase\u00f1a actual",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "M\u00e1xima clasificaci\u00f3n permitida",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "El contenido con clasificaci\u00f3n parental superior se ocultar\u00e1 para este usuario.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "Seleccione las carpetas de medios para compartir con este usuario. Los administradores podr\u00e1n editar todas las carpetas usando el gestor de metadata.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Seleccione los canales para compartir con este usuario. Los administradores podr\u00e1n editar todos los canales mediante el gestor de metadatos.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "Borrar imagen",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "Seleccionar usuarios:",
+ "OptionActor": "Actor",
"ButtonUpload": "Subir",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Subir nueva imagen",
+ "OptionDirector": "Director",
"LabelDropImageHere": "Depositar Imagen Aqu\u00ed",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "Se Recomienda una Proporci\u00f3n de Aspecto 1:1. Solo JPG\/PNG",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Nada aqu\u00ed.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "Por favor aseg\u00farese que la descarga de metadata de internet esta habilitada",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Sugerencia",
- "TabLatest": "\u00daltima",
- "TabUpcoming": "Siguiente",
+ "LabelAirTime": "Air time:",
+ "TabLatest": "Novedades",
+ "HeaderMediaInfo": "Media Info",
+ "TabUpcoming": "Pr\u00f3ximos",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Programas",
"TabEpisodes": "Episodios",
"TabGenres": "G\u00e9neros",
@@ -163,7 +225,7 @@
"OptionAscending": "Ascendente",
"OptionDescending": "Descendente",
"OptionRuntime": "Tiempo",
- "OptionReleaseDate": "Fecha de estreno",
+ "OptionReleaseDate": "Release Date",
"OptionPlayCount": "N\u00famero de reproducc.",
"OptionDatePlayed": "Fecha de reproducci\u00f3n",
"OptionDateAdded": "A\u00f1adido el",
@@ -213,6 +275,8 @@
"TabMovies": "Pel\u00edculas",
"TabStudios": "Estudios",
"TabTrailers": "Trailers",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "\u00daltimas pel\u00edculas",
"HeaderLatestTrailers": "\u00daltimos trailers",
"OptionHasSpecialFeatures": "Caracter\u00edsticas especiales",
@@ -233,6 +297,7 @@
"OptionFriday": "Viernes",
"OptionSaturday": "S\u00e1bado",
"HeaderManagement": "Administraci\u00f3n",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "Falta IMDb Id",
"OptionMissingTvdbId": "Falta TheTVDB Id",
"OptionMissingOverview": "Falta argumento",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metavalor",
"ButtonSelect": "Seleccionar",
- "ButtonSearch": "Buscar",
"ButtonGroupVersions": "Versiones de Grupo",
"ButtonAddToCollection": "A\u00f1adir a la colecci\u00f3n",
"PismoMessage": "Usando Pismo File Mount a trav\u00e9s de una licencia donada.",
@@ -347,6 +411,8 @@
"TabStatus": "Estado",
"TabSettings": "Opciones",
"ButtonRefreshGuideData": "Actualizar datos de la gu\u00eda",
+ "ButtonRefresh": "Refrescar",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Prioridad",
"OptionRecordOnAllChannels": "Grabar programa en cualquier canal",
"OptionRecordAnytime": "Grabar programa a cualquier hora",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Reparto y equipo t\u00e9cnico",
"HeaderAdditionalParts": "Partes adicionales",
"ButtonSplitVersionsApart": "Dividir versiones aparte",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Falta",
"LabelOffline": "Apagado",
"PathSubstitutionHelp": "Las rutas alternativas se utilizan para mapear una ruta en el servidor a la que los clientes puedan acceder. El permitir que los clientes se conecten directamente a trav\u00e9s de la red y puedan reproducir los medios directamente, evita utilizar recursos del servidor para la transcodificaci\u00f3n y el stream,",
@@ -512,8 +579,10 @@
"HeaderProgram": "Programa",
"HeaderClients": "Clientes",
"LabelCompleted": "Completado",
+ "LabelFailed": "Error",
"LabelSkipped": "Omitido",
"HeaderEpisodeOrganization": "Organizaci\u00f3n de episodios",
+ "LabelSeries": "Series:",
"LabelSeasonNumber": "Temporada n\u00famero:",
"LabelEpisodeNumber": "Episodio n\u00famero:",
"LabelEndingEpisodeNumber": "N\u00famero episodio final:",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Activar esta notificaci\u00f3n",
"LabelMonitorUsers": "Supervisar la actividad de:",
"LabelSendNotificationToUsers": "Enviar la notificaci\u00f3n a:",
- "UsersNotNotifiedAboutSelfActivity": "Los usuarios no ser\u00e1n notificados acerca de sus propias actividades.",
"LabelUseNotificationServices": "Usar los siguientes servicios:",
"CategoryUser": "Usuario",
"CategorySystem": "Sistema",
@@ -648,6 +716,7 @@
"ButtonPageDown": "P\u00e1gina abajo",
"PageAbbreviation": "PG",
"ButtonHome": "Inicio",
+ "ButtonSearch": "Buscar",
"ButtonSettings": "Opciones",
"ButtonTakeScreenshot": "Captura de pantalla",
"ButtonLetterUp": "Letter arriba",
@@ -657,10 +726,12 @@
"TabNowPlaying": "Reproduciendo ahora",
"TabNavigation": "Navegaci\u00f3n",
"TabControls": "Controles",
- "ButtonFullscreen": "Pantalla completa",
+ "ButtonFullscreen": "Toggle fullscreen",
"ButtonScenes": "Escenas",
"ButtonSubtitles": "Subt\u00edtulos",
- "ButtonAudioTracks": "Pistas de audio",
+ "ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Pista anterior",
+ "ButtonNextTrack": "Pista siguiente",
"ButtonStop": "Detener",
"ButtonPause": "Pausa",
"LabelGroupMoviesIntoCollections": "Agrupar pel\u00edculas en colecciones",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separados por comas. Esto se puede dejar vac\u00edo para aplicar a todos los contenedores.",
"HeaderResponseProfile": "Perfil de respuesta",
"LabelType": "Tipo:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Contenedor:",
"LabelProfileVideoCodecs": "Codecs de video:",
"LabelProfileAudioCodecs": "Codecs de audio:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "Estos valores controlan el modo en que Media Browser se presentar\u00e1 en el dispositivo.",
"LabelMaxBitrate": "Bitrate m\u00e1ximo:",
"LabelMaxBitrateHelp": "Especificar una tasa de bits m\u00e1xima en entornos de ancho de banda limitado, o si el dispositivo impone su propio l\u00edmite.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignorar las solicitudes de intervalo de bytes de transcodificaci\u00f3n",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "Si est\u00e1 activado, estas solicitudes ser\u00e1n atendidas pero ignorar\u00e1n el encabezado de intervalo de bytes.",
"LabelFriendlyName": "Nombre amigable",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Mostrar plugins para:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Otros",
- "LabelEpisodeName": "Nombre episodio",
- "LabelSeriesName": "Nombre de la serie",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Entrar texto",
"LabelTypeText": "Texto",
"HeaderSearchForSubtitles": "B\u00fasqueda de Subt\u00edtulos",
@@ -799,26 +882,29 @@
"LabelHomePageSection1": "Secci\u00f3n uno de la p\u00e1gina de inicio:",
"LabelHomePageSection2": "Secci\u00f3n dos de la p\u00e1gina de inicio:",
"LabelHomePageSection3": "Secci\u00f3n tres de la p\u00e1gina de inicio:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "Mi librer\u00eda (botones)",
- "OptionMyLibrary": "Mi librer\u00eda",
- "OptionMyLibrarySmall": "Mi librer\u00eda (peque\u00f1o)",
+ "LabelHomePageSection4": "Secci\u00f3n cuarta de la p\u00e1gina de inicio",
+ "OptionMyViewsButtons": "Mis vistas (botones)",
+ "OptionMyViews": "Mis vistas",
+ "OptionMyViewsSmall": "Mis vistas (peque\u00f1o)",
"OptionResumablemedia": "Continuar",
"OptionLatestMedia": "\u00daltimos medios",
- "OptionLatestChannelMedia": "Latest channel items",
- "HeaderLatestChannelItems": "Latest Channel Items",
+ "OptionLatestChannelMedia": "Ultimos elementos de canales",
+ "HeaderLatestChannelItems": "Ultimos elementos de canales",
"OptionNone": "Nada",
"HeaderLiveTv": "TV en vivo",
"HeaderReports": "Informes",
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferencias",
"MessageLoadingChannels": "Cargando contenidos del canal...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Marcar como le\u00eddo",
"OptionDefaultSort": "Por defecto",
"OptionCommunityMostWatchedSort": "M\u00e1s visto",
"TabNextUp": "Siguiendo",
"MessageNoMovieSuggestionsAvailable": "No hay sugerencias de pel\u00edculas disponibles. Comience ver y calificar sus pel\u00edculas y vuelva para ver las recomendaciones.",
"MessageNoCollectionsAvailable": "Colecciones le permitir\u00e1 disfrutar de grupos personalizados de Pel\u00edculas, Series, Discos, Libros y Juegos. Haga click en el bot\u00f3n nuevo para empezar a crear Colecciones.",
+ "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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Vienvenido al Cliente Web de Media Browser",
"ButtonDismiss": "Descartar",
"MessageLearnHowToCustomize": "Aprenda c\u00f3mo personalizar esta p\u00e1gina a sus propios gustos personales. Haga clic en su icono de usuario en la esquina superior derecha de la pantalla para ver y actualizar sus preferencias.",
@@ -842,11 +928,171 @@
"ViewTypeChannels": "Canales",
"ViewTypeLiveTV": "Tv en vivo",
"HeaderOtherDisplaySettings": "Configuraci\u00f3n de pantalla",
- "HeaderMyViews": "My Views",
+ "HeaderMyViews": "Mis vistas",
"LabelSelectFolderGroups": "Agrupar autom\u00e1ticamente las siguientes carpetas en vistas tales como pel\u00edculas, m\u00fasica y televisi\u00f3n",
"LabelSelectFolderGroupsHelp": "Las carpetas que no est\u00e9n marcadas se mostrar\u00e1n por s\u00ed mismas en su propia secci\u00f3n.",
"OptionDisplayAdultContent": "Mostrar contenido para adultos",
"OptionLibraryFolders": "Vista de carpeta",
- "TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "TitleRemoteControl": "Control remoto",
+ "OptionLatestTvRecordings": "\u00daltimas grabaciones",
+ "LabelProtocolInfo": "Informaci\u00f3n de protocolo:",
+ "LabelProtocolInfoHelp": "El valor que se utilizar\u00e1 cuando se responde a una solicitud GetProtocolInfo desde el dispositivo.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser incluye soporte nativo para XBMC, Nfo, metadatos e im\u00e1genes. Para activar o desactivar los metadatos XBMC, utilice la ficha Avanzadas para configurar opciones para sus tipos de medios.",
+ "LabelXbmcMetadataUser": "A\u00f1adir datos de reproducciones de usuario a los nfo\u00b4s para:",
+ "LabelXbmcMetadataUserHelp": "Activar esto para mantener sincronizados los datos de reproducci\u00f3n entre Media Browser y Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Formato de fecha de estreno:",
+ "LabelXbmcMetadataDateFormatHelp": "Todas las fechas dentro de los nfo se leer\u00e1n y se escribir\u00e1n usando este formato.",
+ "LabelXbmcMetadataSaveImagePaths": "Grabar las rutas de las im\u00e1genes en los archivos nfo",
+ "LabelXbmcMetadataSaveImagePathsHelp": "\nEsto se recomienda si usted tiene los nombres de archivo de imagen que no se ajusten a las directrices de XBMC.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Habilitar rutas de sustituci\u00f3n",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Permite la sustituci\u00f3n de las rutas de im\u00e1genes utilizando la configuraci\u00f3n de rutas de sustituci\u00f3n en las opciones del servidor.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "Ver rutas de sustituci\u00f3n.",
+ "LabelGroupChannelsIntoViews": "Visualice los siguientes canales dentro de mis vistas:",
+ "LabelGroupChannelsIntoViewsHelp": "Si est\u00e1 activado, estos canales se mostrar\u00e1n directamente junto a Mis Vistas. Si est\u00e1 desactivada, ser\u00e1n mostrados separadamente en la vista de Canales.",
+ "LabelDisplayCollectionsView": "Mostrar una vista Colecciones para mostrar colecciones de pel\u00edculas",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copiar extrafanart en extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "Cuando se descargan im\u00e1genes se pueden guardar tanto en extrafanart como en extrathumbs para una m\u00e1xima compatibilidad con el skin de XBMC.",
+ "TabServices": "Servicios",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Archivos de log del servidor:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Personalizar la apariencia de Explorador de medios para satisfacer las necesidades de su grupo u organizaci\u00f3n.",
+ "LabelLoginDisclaimer": "Login renuncia:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Donar autom\u00e1ticamente esta cantidad cada mes",
+ "LabelAutomaticallyDonateHelp": "Usted puede cancelar en cualquier momento desde su cuenta de PayPal.",
+ "OptionList": "Lista",
+ "TabDashboard": "Panel de control",
+ "TitleServer": "Servidor",
+ "LabelCache": "Cach\u00e9:",
+ "LabelLogs": "Registros:",
+ "LabelMetadata": "Metadatos:",
+ "LabelImagesByName": "Im\u00e1genes por nombre:",
+ "LabelTranscodingTemporaryFiles": "Archivos temporales de transcodificaci\u00f3n:",
+ "HeaderLatestMusic": "\u00daltima m\u00fasica",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Keys de Api",
+ "HeaderApiKeysHelp": "Se requieren aplicaciones externas para tener una clave de API con el fin de comunicarse con Media Browser. Las claves son emitidas al iniciar una sesi\u00f3n con una cuenta de Media Browser, o mediante la introducci\u00f3n manualmente de una clave en la aplicaci\u00f3n.",
+ "HeaderApiKey": "Clave Api",
+ "HeaderApp": "App",
+ "HeaderDevice": "Dispositivo",
+ "HeaderUser": "Usuario",
+ "HeaderDateIssued": "Fecha de emisi\u00f3n",
+ "LabelChapterName": "Cap\u00edtulo {0}",
+ "HeaderNewApiKey": "Nueva Clave Api",
+ "LabelAppName": "Nombre de la app",
+ "LabelAppNameExample": "Ejemplo: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Otorgar un permiso a la aplicaci\u00f3n para comunicarse con Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Cerrar",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "M\u00e1s...",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/es_ES.json b/MediaBrowser.Server.Implementations/Localization/Server/es_ES.json
new file mode 100644
index 000000000..02412b97f
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Localization/Server/es_ES.json
@@ -0,0 +1,872 @@
+{
+ "LabelExit": "Salir",
+ "LabelVisitCommunity": "Visitar la comunidad",
+ "LabelGithubWiki": "Wiki de Github",
+ "LabelSwagger": "Swagger",
+ "LabelStandard": "Est\u00e1ndar",
+ "LabelViewApiDocumentation": "Ver documentacion de Api",
+ "LabelBrowseLibrary": "Navegar biblioteca",
+ "LabelConfigureMediaBrowser": "Configurar Media Browser",
+ "LabelOpenLibraryViewer": "Abrir el visor de la biblioteca",
+ "LabelRestartServer": "Reiniciar el servidor",
+ "LabelShowLogWindow": "Mostrar la ventana del log",
+ "LabelPrevious": "Anterior",
+ "LabelFinish": "Terminar",
+ "LabelNext": "Siguiente",
+ "LabelYoureDone": "Ha Terminado!",
+ "WelcomeToMediaBrowser": "\u00a1Bienvenido a Media Browser!",
+ "TitleMediaBrowser": "Media Browser",
+ "ThisWizardWillGuideYou": "Este asistente lo guiar\u00e1 por el proceso de instalaci\u00f3n. Para comenzar seleccione su idioma preferido.",
+ "TellUsAboutYourself": "D\u00edganos acerca de usted",
+ "LabelYourFirstName": "Su nombre:",
+ "MoreUsersCanBeAddedLater": "M\u00e1s usuarios pueden agregarse m\u00e1s tarde en el panel de control.",
+ "UserProfilesIntro": "Media Browser incluye soporte integrado para los perfiles de usuario, lo que permite que cada usuario tenga su propia configuraci\u00f3n de la pantalla, estado de reproducci\u00f3n y control parental.",
+ "LabelWindowsService": "Servicio de Windows",
+ "AWindowsServiceHasBeenInstalled": "Un servicio de Windows se ha instalado",
+ "WindowsServiceIntro1": "Media Browser Server se ejecuta normalmente como una aplicaci\u00f3n de escritorio con un icono de la bandeja, pero si prefiere ejecutarlo como un servicio en segundo plano, se puede iniciar desde el panel de control de servicios de Windows en su lugar.",
+ "WindowsServiceIntro2": "Si se utiliza el servicio de Windows, tenga en cuenta que no se puede ejecutar al mismo tiempo que el icono de la bandeja, por lo que tendr\u00e1 que salir de la bandeja con el fin de ejecutar el servicio. Tambi\u00e9n tendr\u00e1 que ser configurado con privilegios administrativos a trav\u00e9s del panel de control del servicio. Tenga en cuenta que en este momento el servicio no es capaz de auto-actualizaci\u00f3n, por lo que las nuevas versiones requieren la interacci\u00f3n manual.",
+ "WizardCompleted": "Eso es todo lo que necesitamos por ahora. Media Browser ha comenzado a reunir informaci\u00f3n sobre su biblioteca de medios. Echa un vistazo a algunas de nuestras aplicaciones, y luego haga clic en <b>Finalizar<\/b> para ver el <b>Panel de control<\/b>.",
+ "LabelConfigureSettings": "Configuraci\u00f3n de opciones",
+ "LabelEnableVideoImageExtraction": "Habilitar extracci\u00f3n de im\u00e1genes de video",
+ "VideoImageExtractionHelp": "Para los v\u00eddeos que no dispongan de im\u00e1genes y que no podemos encontrar en Internet. Esto agregar\u00e1 un tiempo adicional para la exploraci\u00f3n inicial de bibliotecas, pero resultar\u00e1 en una presentaci\u00f3n m\u00e1s agradable.",
+ "LabelEnableChapterImageExtractionForMovies": "Extraer im\u00e1genes de cap\u00edtulos para pel\u00edculas",
+ "LabelChapterImageExtractionForMoviesHelp": "Extraer im\u00e1genes de cap\u00edtulo permitir\u00e1 a los clientes mostrar men\u00fas gr\u00e1ficos de selecci\u00f3n de escenas. El proceso puede ser lento, intensivo en utilizaci\u00f3n del CPU y puede requerir varios gigabytes de espacio. Se ejecuta como una tarea nocturna, a las 4 de la ma\u00f1ana, aunque esto se puede configurar en el \u00e1rea de tareas programadas. No se recomienda ejecutar esta tarea durante las horas pico de uso.",
+ "LabelEnableAutomaticPortMapping": "Habilitar asignaci\u00f3n de puertos autom\u00e1tico",
+ "LabelEnableAutomaticPortMappingHelp": "UPnP permite la configuraci\u00f3n del router para acceso externo de forma f\u00e1cil y autom\u00e1tica. Esto puede no funcionar en algunos modelos de routers.",
+ "ButtonOk": "OK",
+ "ButtonCancel": "Cancelar",
+ "ButtonNew": "Nuevo",
+ "HeaderSetupLibrary": "Configurar biblioteca de medios",
+ "ButtonAddMediaFolder": "Agregar una carpeta de medios",
+ "LabelFolderType": "Tipo de carpeta:",
+ "MediaFolderHelpPluginRequired": "* Requiere el uso de un plugin, por ejemplo GameBrowser o MB Bookshelf",
+ "ReferToMediaLibraryWiki": "Consultar el wiki de la biblioteca de medios",
+ "LabelCountry": "Pa\u00eds:",
+ "LabelLanguage": "Idioma:",
+ "HeaderPreferredMetadataLanguage": "Idioma preferido para metadata",
+ "LabelSaveLocalMetadata": "Guardar im\u00e1genes y metadata en las carpetas de medios",
+ "LabelSaveLocalMetadataHelp": "Guardar im\u00e1genes y metadata directamente en las carpetas de medios, permitir\u00e1 colocarlas en un lugar donde se pueden editar f\u00e1cilmente.",
+ "LabelDownloadInternetMetadata": "Descargar imagenes y metadata de internet",
+ "LabelDownloadInternetMetadataHelp": "Media Browser permite descargar informaci\u00f3n acerca de su media para enriquecer la presentaci\u00f3n.",
+ "TabPreferences": "Preferencias",
+ "TabPassword": "Contrase\u00f1a",
+ "TabLibraryAccess": "Acceso a biblioteca",
+ "TabImage": "imagen",
+ "TabProfile": "Perfil",
+ "TabMetadata": "Metadata",
+ "TabImages": "Im\u00e1genes",
+ "TabNotifications": "Notificaciones",
+ "TabCollectionTitles": "T\u00edtulos",
+ "LabelDisplayMissingEpisodesWithinSeasons": "Mostar episodios no disponibles en temporadas",
+ "LabelUnairedMissingEpisodesWithinSeasons": "Mostrar episodios a\u00fan no emitidos en temporadas",
+ "HeaderVideoPlaybackSettings": "Ajustes de Reproducci\u00f3n de Video",
+ "HeaderPlaybackSettings": "Ajustes de reproducci\u00f3n",
+ "LabelAudioLanguagePreference": "Preferencia de idioma de audio",
+ "LabelSubtitleLanguagePreference": "Preferencia de idioma de subtitulos",
+ "OptionDefaultSubtitles": "Por defecto",
+ "OptionOnlyForcedSubtitles": "S\u00f3lo subt\u00edtulos forzados",
+ "OptionAlwaysPlaySubtitles": "Mostrar siempre subt\u00edtulos",
+ "OptionNoSubtitles": "Sin subt\u00edtulos",
+ "OptionDefaultSubtitlesHelp": "Los subt\u00edtulos que concuerden con la preferencia de idioma se cargar\u00e1n cuando el audio est\u00e9 en un idioma extranjero.",
+ "OptionOnlyForcedSubtitlesHelp": "S\u00f3lo se cargar\u00e1n los subt\u00edtulos marcados como forzados.",
+ "OptionAlwaysPlaySubtitlesHelp": "Los subt\u00edtulos que concuerden con la preferencia de idioma se cargar\u00e1n independientemente del idioma de audio.",
+ "OptionNoSubtitlesHelp": "Los subt\u00edtulos no se cargar\u00e1n de forma predeterminada.",
+ "TabProfiles": "Perfiles",
+ "TabSecurity": "Seguridad",
+ "ButtonAddUser": "Agregar Usuario",
+ "ButtonSave": "Grabar",
+ "ButtonResetPassword": "Reiniciar Contrase\u00f1a",
+ "LabelNewPassword": "Nueva Contrase\u00f1a:",
+ "LabelNewPasswordConfirm": "Confirmaci\u00f3n de contrase\u00f1a nueva:",
+ "HeaderCreatePassword": "Crear Contrase\u00f1a",
+ "LabelCurrentPassword": "Contrase\u00f1a actual",
+ "LabelMaxParentalRating": "M\u00e1xima clasificaci\u00f3n permitida",
+ "MaxParentalRatingHelp": "El contenido con clasificaci\u00f3n parental superior se ocultar\u00e1 para este usuario.",
+ "LibraryAccessHelp": "Seleccione las carpetas de medios para compartir con este usuario. Los administradores podr\u00e1n editar todas las carpetas usando el gestor de metadata.",
+ "ChannelAccessHelp": "Seleccione los canales para compartir con este usuario. Los administradores podr\u00e1n editar todos los canales mediante el gestor de metadatos.",
+ "ButtonDeleteImage": "Borrar imagen",
+ "LabelSelectUsers": "Seleccionar usuarios:",
+ "ButtonUpload": "Subir",
+ "HeaderUploadNewImage": "Subir nueva imagen",
+ "LabelDropImageHere": "Depositar Imagen Aqu\u00ed",
+ "ImageUploadAspectRatioHelp": "Se Recomienda una Proporci\u00f3n de Aspecto 1:1. Solo JPG\/PNG",
+ "MessageNothingHere": "Nada aqu\u00ed.",
+ "MessagePleaseEnsureInternetMetadata": "Por favor aseg\u00farese que la descarga de metadata de internet esta habilitada",
+ "TabSuggested": "Sugerencia",
+ "TabLatest": "Novedades",
+ "TabUpcoming": "Pr\u00f3ximos",
+ "TabShows": "Programas",
+ "TabEpisodes": "Episodios",
+ "TabGenres": "G\u00e9neros",
+ "TabPeople": "Gente",
+ "TabNetworks": "redes",
+ "HeaderUsers": "Usuarios",
+ "HeaderFilters": "Filtros:",
+ "ButtonFilter": "Filtro",
+ "OptionFavorite": "Favoritos",
+ "OptionLikes": "Me gusta",
+ "OptionDislikes": "No me gusta",
+ "OptionActors": "Actores",
+ "OptionGuestStars": "Estrellas invitadas",
+ "OptionDirectors": "Directores",
+ "OptionWriters": "Guionistas",
+ "OptionProducers": "Productores",
+ "HeaderResume": "Continuar",
+ "HeaderNextUp": "Siguiendo",
+ "NoNextUpItemsMessage": "Nada encontrado. \u00a1Comienza a ver tus programas!",
+ "HeaderLatestEpisodes": "Ultimos episodios",
+ "HeaderPersonTypes": "Tipos de personas:",
+ "TabSongs": "Canciones",
+ "TabAlbums": "Albums",
+ "TabArtists": "Artistas",
+ "TabAlbumArtists": "Album Artistas",
+ "TabMusicVideos": "Videos Musicales",
+ "ButtonSort": "Ordenar",
+ "HeaderSortBy": "Ordenar por:",
+ "HeaderSortOrder": "Ordenado por:",
+ "OptionPlayed": "Reproducido",
+ "OptionUnplayed": "No reproducido",
+ "OptionAscending": "Ascendente",
+ "OptionDescending": "Descendente",
+ "OptionRuntime": "Tiempo",
+ "OptionReleaseDate": "Fecha de estreno",
+ "OptionPlayCount": "N\u00famero de reproducc.",
+ "OptionDatePlayed": "Fecha de reproducci\u00f3n",
+ "OptionDateAdded": "A\u00f1adido el",
+ "OptionAlbumArtist": "Album Artista",
+ "OptionArtist": "Artista",
+ "OptionAlbum": "Album",
+ "OptionTrackName": "Nombre de pista",
+ "OptionCommunityRating": "Valoraci\u00f3n comunidad",
+ "OptionNameSort": "Nombre",
+ "OptionFolderSort": "Carpetas",
+ "OptionBudget": "Presupuesto",
+ "OptionRevenue": "Recaudaci\u00f3n",
+ "OptionPoster": "Poster",
+ "OptionBackdrop": "Imagen de fondo",
+ "OptionTimeline": "L\u00ednea de tiempo",
+ "OptionThumb": "Miniatura",
+ "OptionBanner": "Banner",
+ "OptionCriticRating": "Valoraci\u00f3n cr\u00edtica",
+ "OptionVideoBitrate": "Video Bitrate",
+ "OptionResumable": "Se puede continuar",
+ "ScheduledTasksHelp": "Click en una tarea para ajustar su programaci\u00f3n",
+ "ScheduledTasksTitle": "Tareas programadas",
+ "TabMyPlugins": "Mis Plugins",
+ "TabCatalog": "Cat\u00e1logo",
+ "PluginsTitle": "Plugins",
+ "HeaderAutomaticUpdates": "Actualizaciones autom\u00e1ticas",
+ "HeaderNowPlaying": "Reproduciendo ahora",
+ "HeaderLatestAlbums": "\u00dcltimos Albums",
+ "HeaderLatestSongs": "\u00daltimas canciones",
+ "HeaderRecentlyPlayed": "Reproducido recientemente",
+ "HeaderFrequentlyPlayed": "Reproducido frequentemente",
+ "DevBuildWarning": "Las actualizaciones en desarrollo no est\u00e1n convenientemente probadas. La aplicaci\u00f3n se puede bloquear y caracter\u00edsticas completas pueden no funcionar del todo.",
+ "LabelVideoType": "Tipo de video",
+ "OptionBluray": "Bluray",
+ "OptionDvd": "Dvd",
+ "OptionIso": "Iso",
+ "Option3D": "3D",
+ "LabelFeatures": "Caracter\u00edsticas",
+ "LabelService": "Servicio:",
+ "LabelStatus": "Estado:",
+ "LabelVersion": "Versi\u00f3n:",
+ "LabelLastResult": "\u00daltimo resultado:",
+ "OptionHasSubtitles": "Subt\u00edtulos",
+ "OptionHasTrailer": "Trailer",
+ "OptionHasThemeSong": "Banda sonora",
+ "OptionHasThemeVideo": "Viideotema",
+ "TabMovies": "Pel\u00edculas",
+ "TabStudios": "Estudios",
+ "TabTrailers": "Trailers",
+ "HeaderLatestMovies": "\u00daltimas pel\u00edculas",
+ "HeaderLatestTrailers": "\u00daltimos trailers",
+ "OptionHasSpecialFeatures": "Caracter\u00edsticas especiales",
+ "OptionImdbRating": "Valoraci\u00f3n IMDb",
+ "OptionParentalRating": "Clasificaci\u00f3n parental",
+ "OptionPremiereDate": "Fecha de estreno",
+ "TabBasic": "B\u00e1sico",
+ "TabAdvanced": "Avanzado",
+ "HeaderStatus": "Estado",
+ "OptionContinuing": "Continuando",
+ "OptionEnded": "Finalizado",
+ "HeaderAirDays": "D\u00eda emisi\u00f3n",
+ "OptionSunday": "Domingo",
+ "OptionMonday": "Lunes",
+ "OptionTuesday": "Martes",
+ "OptionWednesday": "Mi\u00e9rcoles",
+ "OptionThursday": "Jueves",
+ "OptionFriday": "Viernes",
+ "OptionSaturday": "S\u00e1bado",
+ "HeaderManagement": "Administraci\u00f3n",
+ "OptionMissingImdbId": "Falta IMDb Id",
+ "OptionMissingTvdbId": "Falta TheTVDB Id",
+ "OptionMissingOverview": "Falta argumento",
+ "OptionFileMetadataYearMismatch": "Archivo\/Metadata a\u00f1os no coinciden",
+ "TabGeneral": "General",
+ "TitleSupport": "Soporte",
+ "TabLog": "Log",
+ "TabAbout": "Acerca de",
+ "TabSupporterKey": "Clave de Seguidor",
+ "TabBecomeSupporter": "Hazte Seguidor",
+ "MediaBrowserHasCommunity": "Media Browser cuenta con una pr\u00f3spera comunidad de usuarios y colaboradores.",
+ "CheckoutKnowledgeBase": "Echa un vistazo a nuestra base de conocimiento para ayudarte a sacar el m\u00e1ximo provecho de Media Browser.",
+ "SearchKnowledgeBase": "Buscar en la base de conocimiento",
+ "VisitTheCommunity": "Visitar la comunidad",
+ "VisitMediaBrowserWebsite": "Visitar la web de Media Browser",
+ "VisitMediaBrowserWebsiteLong": "Visita la web de Media Browser para estar informado de las \u00faltimas not\u00edcias y mantenerte al d\u00eda con el blog de desarrolladores.",
+ "OptionHideUser": "Ocultar este usuario en las pantallas de inicio de sesi\u00f3n",
+ "OptionDisableUser": "Deshabilitar este usuario",
+ "OptionDisableUserHelp": "Si est\u00e1 deshabilitado, el servidor no aceptar\u00e1 conexiones de este usuario. Si existen conexiones de este usuario, finalizar\u00e1n inmediatamente.",
+ "HeaderAdvancedControl": "Control avanzado",
+ "LabelName": "Nombre:",
+ "OptionAllowUserToManageServer": "Permite a este usuario administrar el servidor",
+ "HeaderFeatureAccess": "Permisos de acceso",
+ "OptionAllowMediaPlayback": "Permitir reproducci\u00f3n de medios",
+ "OptionAllowBrowsingLiveTv": "Acceso a TV en vivo",
+ "OptionAllowDeleteLibraryContent": "Permitir a este usuario eliminar contenido de la biblioteca",
+ "OptionAllowManageLiveTv": "Permitir la gesti\u00f3n de las grabaciones de TV en vivo",
+ "OptionAllowRemoteControlOthers": "Permitir a este usuario controlar rem\u00f3tamente a otros usuarios",
+ "OptionMissingTmdbId": "Falta Tmdb Id",
+ "OptionIsHD": "HD",
+ "OptionIsSD": "SD",
+ "OptionMetascore": "Metavalor",
+ "ButtonSelect": "Seleccionar",
+ "ButtonSearch": "Buscar",
+ "ButtonGroupVersions": "Versiones de Grupo",
+ "ButtonAddToCollection": "A\u00f1adir a la colecci\u00f3n",
+ "PismoMessage": "Usando Pismo File Mount a trav\u00e9s de una licencia donada.",
+ "TangibleSoftwareMessage": "Utilizamos convertidores Java\/C# de Tangible Solutions a trav\u00e9s de una licencia donada.",
+ "HeaderCredits": "Cr\u00e9ditos",
+ "PleaseSupportOtherProduces": "Por favor apoye otros productos gratuitos que utilizamos:",
+ "VersionNumber": "Versi\u00f3n {0}",
+ "TabPaths": "Ruta",
+ "TabServer": "Servidor",
+ "TabTranscoding": "Transcodificaci\u00f3n",
+ "TitleAdvanced": "Avanzado",
+ "LabelAutomaticUpdateLevel": "Actualizaci\u00f3n de nivel autom\u00e1tica",
+ "OptionRelease": "Release Oficial",
+ "OptionBeta": "Beta",
+ "OptionDev": "Desarrollo",
+ "LabelAllowServerAutoRestart": "Permitir al servidor reiniciarse autom\u00e1ticamente para aplicar las actualizaciones",
+ "LabelAllowServerAutoRestartHelp": "El servidor s\u00f3lo se reiniciar\u00e1 durante periodos de reposo, cuando no hayan usuarios activos.",
+ "LabelEnableDebugLogging": "Habilitar entrada de debug",
+ "LabelRunServerAtStartup": "Arrancar servidor al iniciar",
+ "LabelRunServerAtStartupHelp": "Esto iniciar\u00e1 como aplicaci\u00f3n en el inicio. Para iniciar en modo servicio de windows, desmarque esto e inicie el servicio desde el panel de control de windows. Tenga en cuenta que no es posible inciar de las dos formas a la vez, usted debe salir de la aplicaci\u00f3n para iniciar el servicio.",
+ "ButtonSelectDirectory": "Seleccionar directorio",
+ "LabelCustomPaths": "Especificar las rutas personalizadas que desee. D\u00e9jelo en blanco para usar las rutas por defecto.",
+ "LabelCachePath": "Ruta del cach\u00e9:",
+ "LabelCachePathHelp": "Esta carpeta contienes archivos de cach\u00e9 del servidor, tales como im\u00e1genes.",
+ "LabelImagesByNamePath": "Ruta de im\u00e1genes:",
+ "LabelImagesByNamePathHelp": "Esta carpeta contiene im\u00e1genes de actores, artistas, g\u00e9neros y estudios.",
+ "LabelMetadataPath": "Ruta de Metadata:",
+ "LabelMetadataPathHelp": "Esta localizaci\u00f3n contiene im\u00e1genes y metadata descargados que no est\u00e1n configurados para ser guardados en carpetas de medios.",
+ "LabelTranscodingTempPath": "Ruta temporal de transcodificaci\u00f3n:",
+ "LabelTranscodingTempPathHelp": "Esta carpeta contiene archivos de trabajo usados por el transcodificador.",
+ "TabBasics": "Basicos",
+ "TabTV": "TV",
+ "TabGames": "Juegos",
+ "TabMusic": "M\u00fasica",
+ "TabOthers": "Otros",
+ "HeaderExtractChapterImagesFor": "Extraer im\u00e1genes de cap\u00edtulos para:",
+ "OptionMovies": "Pel\u00edculas",
+ "OptionEpisodes": "Episodios",
+ "OptionOtherVideos": "Otros v\u00eddeos",
+ "TitleMetadata": "Metadata",
+ "LabelAutomaticUpdatesFanart": "Activar actualizaciones autom\u00e1ticas desde FanArt.tv",
+ "LabelAutomaticUpdatesTmdb": "Activar actualizaciones autom\u00e1ticas desde TheMovieDB.org",
+ "LabelAutomaticUpdatesTvdb": "Activar actualizaciones autom\u00e1ticas desde TheTVDB.com",
+ "LabelAutomaticUpdatesFanartHelp": "Si est\u00e1 activado, las nuevas im\u00e1genes se descargan autom\u00e1ticamente a medida que se a\u00f1aden a fanart.tv. Im\u00e1genes existentes no ser\u00e1n reemplazadas.",
+ "LabelAutomaticUpdatesTmdbHelp": "Si est\u00e1 activado, las nuevas im\u00e1genes se descargan autom\u00e1ticamente a medida que se a\u00f1aden a TheMovieDB.org. Im\u00e1genes existentes no ser\u00e1n reemplazados.",
+ "LabelAutomaticUpdatesTvdbHelp": "Si est\u00e1 activado, las nuevas im\u00e1genes se descargan autom\u00e1ticamente a medida que se a\u00f1aden a TheTVDB.com. Im\u00e1genes existentes no ser\u00e1n reemplazados.",
+ "ExtractChapterImagesHelp": "Extraer im\u00e1genes de cap\u00edtulo permitir\u00e1 a los clientes mostrar men\u00fas gr\u00e1ficos de selecci\u00f3n de escenas. El proceso puede ser lento, uso de CPU intensivo y puede requerir varios gigabytes de espacio. Se ejecuta como una tarea nocturna, a las 4 de la ma\u00f1ana, aunque esto se puede configurar en el \u00e1rea de tareas programadas. No se recomienda ejecutar esta tarea durante las horas pico.",
+ "LabelMetadataDownloadLanguage": "Idioma preferido:",
+ "ButtonAutoScroll": "Auto-desplazamiento",
+ "LabelImageSavingConvention": "Sistema de guardado de im\u00e1genes:",
+ "LabelImageSavingConventionHelp": "Media Browser reconoce im\u00e1genes de la mayor\u00eda de aplicaciones de medios. La elecci\u00f3n de su sistema de descarga es \u00fatil si tambi\u00e9n usa otros productos.",
+ "OptionImageSavingCompatible": "Compatible - MB3\/Plex\/Xbmc",
+ "OptionImageSavingStandard": "Est\u00e1ndard - MB3\/MB2",
+ "ButtonSignIn": "Registrarse",
+ "TitleSignIn": "Registrarse",
+ "HeaderPleaseSignIn": "Por favor reg\u00edstrese",
+ "LabelUser": "Usuario:",
+ "LabelPassword": "Contrase\u00f1a:",
+ "ButtonManualLogin": "Registro manual:",
+ "PasswordLocalhostMessage": "No se necesitan contrase\u00f1as al iniciar sesi\u00f3n desde localhost.",
+ "TabGuide": "Gu\u00eda",
+ "TabChannels": "Canales",
+ "TabCollections": "Colecciones",
+ "HeaderChannels": "Canales",
+ "TabRecordings": "Grabaciones",
+ "TabScheduled": "Programado",
+ "TabSeries": "Series",
+ "TabFavorites": "Favoritos",
+ "TabMyLibrary": "Mi biblioteca",
+ "ButtonCancelRecording": "Cancelar grabaci\u00f3n",
+ "HeaderPrePostPadding": "Pre\/post grabaci\u00f3n extra",
+ "LabelPrePaddingMinutes": "Minutos previos extras:",
+ "OptionPrePaddingRequired": "Minutos previos extras requeridos para grabar.",
+ "LabelPostPaddingMinutes": "Minutos extras post grabaci\u00f3n:",
+ "OptionPostPaddingRequired": "Minutos post grabaci\u00f3n extras requeridos para grabar.",
+ "HeaderWhatsOnTV": "Que hacen ahora",
+ "HeaderUpcomingTV": "Pr\u00f3ximos programas",
+ "TabStatus": "Estado",
+ "TabSettings": "Opciones",
+ "ButtonRefreshGuideData": "Actualizar datos de la gu\u00eda",
+ "OptionPriority": "Prioridad",
+ "OptionRecordOnAllChannels": "Grabar programa en cualquier canal",
+ "OptionRecordAnytime": "Grabar programa a cualquier hora",
+ "OptionRecordOnlyNewEpisodes": "Grabar s\u00f3lo nuevos episodios",
+ "HeaderDays": "D\u00edas",
+ "HeaderActiveRecordings": "Grabaciones activas",
+ "HeaderLatestRecordings": "\u00daltimas grabaciones",
+ "HeaderAllRecordings": "Todas la grabaciones",
+ "ButtonPlay": "Reproducir",
+ "ButtonEdit": "Editar",
+ "ButtonRecord": "Grabar",
+ "ButtonDelete": "Borrar",
+ "ButtonRemove": "Quitar",
+ "OptionRecordSeries": "Grabar serie",
+ "HeaderDetails": "Detalles",
+ "TitleLiveTV": "Tv en vivo",
+ "LabelNumberOfGuideDays": "N\u00famero de d\u00edas de descarga de la gu\u00eda.",
+ "LabelNumberOfGuideDaysHelp": "Descargar m\u00e1s d\u00edas de la gu\u00eda ofrece la posibilidad de programar grabaciones con mayor antelaci\u00f3n y ver m\u00e1s listas, pero tambi\u00e9n tarda m\u00e1s en descargarse. Auto elegir\u00e1 en funci\u00f3n del n\u00famero de canales.",
+ "LabelActiveService": "Activar servicio",
+ "LabelActiveServiceHelp": "Es posible instalar m\u00faltiples plugins de tv, pero s\u00f3lo puede estar activo uno a la vez.",
+ "OptionAutomatic": "Auto",
+ "LiveTvPluginRequired": "El servicio de TV en vivo es necesario para poder continuar.",
+ "LiveTvPluginRequiredHelp": "Instale uno de los plugins disponibles, como Next Pvr o ServerVmc.",
+ "LabelCustomizeOptionsPerMediaType": "Personalizar por tipo de medio:",
+ "OptionDownloadThumbImage": "Miniatura",
+ "OptionDownloadMenuImage": "Men\u00fa",
+ "OptionDownloadLogoImage": "Logo",
+ "OptionDownloadBoxImage": "Caja",
+ "OptionDownloadDiscImage": "Disco",
+ "OptionDownloadBannerImage": "Pancarta",
+ "OptionDownloadBackImage": "Atr\u00e1s",
+ "OptionDownloadArtImage": "Arte",
+ "OptionDownloadPrimaryImage": "Principal",
+ "HeaderFetchImages": "Buscar im\u00e1genes",
+ "HeaderImageSettings": "Opciones de im\u00e1gen",
+ "TabOther": "Otros",
+ "LabelMaxBackdropsPerItem": "M\u00e1ximo n\u00famero de im\u00e1genes de fondo por \u00edtem:",
+ "LabelMaxScreenshotsPerItem": "M\u00e1ximo n\u00famero de capturas de pantalla por \u00edtem:",
+ "LabelMinBackdropDownloadWidth": "Anchura m\u00ednima de descarga de im\u00e1genes de fondo:",
+ "LabelMinScreenshotDownloadWidth": "Anchura m\u00ednima de descarga de capturas de pantalla:",
+ "ButtonAddScheduledTaskTrigger": "A\u00f1adir eventos",
+ "HeaderAddScheduledTaskTrigger": "A\u00f1adir eventos de ejecuci\u00f3n",
+ "ButtonAdd": "A\u00f1adir",
+ "LabelTriggerType": "Tipo de evento:",
+ "OptionDaily": "Diario",
+ "OptionWeekly": "Semanal",
+ "OptionOnInterval": "En un intervalo",
+ "OptionOnAppStartup": "Al iniciar la aplicaci\u00f3n",
+ "OptionAfterSystemEvent": "Despu\u00e9s de un evento de sistema",
+ "LabelDay": "D\u00eda:",
+ "LabelTime": "Hora:",
+ "LabelEvent": "Evento:",
+ "OptionWakeFromSleep": "Despertar",
+ "LabelEveryXMinutes": "Cada:",
+ "HeaderTvTuners": "Sintonizadores",
+ "HeaderGallery": "Galer\u00eda",
+ "HeaderLatestGames": "\u00daltimos Juegos",
+ "HeaderRecentlyPlayedGames": "Juegos utilizados recientemente",
+ "TabGameSystems": "Sistema de Juego",
+ "TitleMediaLibrary": "Librer\u00eda de medios",
+ "TabFolders": "Carpetas",
+ "TabPathSubstitution": "Ruta alternativa",
+ "LabelSeasonZeroDisplayName": "Nombre de la Temporada 0:",
+ "LabelEnableRealtimeMonitor": "Activar monitoreo en tiempo real",
+ "LabelEnableRealtimeMonitorHelp": "Los cambios se procesar\u00e1n inmediatamente, en sistemas de archivo que lo soporten.",
+ "ButtonScanLibrary": "Escanear Librer\u00eda",
+ "HeaderNumberOfPlayers": "Jugadores:",
+ "OptionAnyNumberOfPlayers": "Cualquiera",
+ "Option1Player": "1+",
+ "Option2Player": "2+",
+ "Option3Player": "3+",
+ "Option4Player": "4+",
+ "HeaderMediaFolders": "Carpetas de medios",
+ "HeaderThemeVideos": "V\u00eddeos de tema",
+ "HeaderThemeSongs": "Canciones de tema",
+ "HeaderScenes": "Escenas",
+ "HeaderAwardsAndReviews": "Premios y reconocimientos",
+ "HeaderSoundtracks": "Pistas de audio",
+ "HeaderMusicVideos": "V\u00eddeos musicales",
+ "HeaderSpecialFeatures": "Caracter\u00edsticas especiales",
+ "HeaderCastCrew": "Reparto y equipo t\u00e9cnico",
+ "HeaderAdditionalParts": "Partes adicionales",
+ "ButtonSplitVersionsApart": "Dividir versiones aparte",
+ "ButtonPlayTrailer": "Trailer",
+ "LabelMissing": "Falta",
+ "LabelOffline": "Apagado",
+ "PathSubstitutionHelp": "Las rutas alternativas se utilizan para mapear una ruta en el servidor a la que los clientes puedan acceder. El permitir que los clientes se conecten directamente a trav\u00e9s de la red y puedan reproducir los medios directamente, evita utilizar recursos del servidor para la transcodificaci\u00f3n y el stream,",
+ "HeaderFrom": "Desde",
+ "HeaderTo": "Hasta",
+ "LabelFrom": "Desde:",
+ "LabelFromHelp": "Ejemplo: D:\\Pel\u00edculas (en el servidor)",
+ "LabelTo": "Hasta:",
+ "LabelToHelp": "Ejemplo: \\\\MiServidor\\Pel\u00edculas (ruta a la que puedan acceder los clientes)",
+ "ButtonAddPathSubstitution": "A\u00f1adir ruta alternativa",
+ "OptionSpecialEpisode": "Especiales",
+ "OptionMissingEpisode": "Episodios que faltan",
+ "OptionUnairedEpisode": "Episodios no emitidos",
+ "OptionEpisodeSortName": "Nombre corto del episodio",
+ "OptionSeriesSortName": "Nombre de la serie",
+ "OptionTvdbRating": "Valoraci\u00f3n tvdb",
+ "HeaderTranscodingQualityPreference": "Preferencia de calidad de transcodificaci\u00f3n:",
+ "OptionAutomaticTranscodingHelp": "El servidor decidir\u00e1 la calidad y la velocidad",
+ "OptionHighSpeedTranscodingHelp": "Calidad menor, pero codificaci\u00f3n r\u00e1pida",
+ "OptionHighQualityTranscodingHelp": "C\u00e1lidad mayor, pero codificaci\u00f3n lenta",
+ "OptionMaxQualityTranscodingHelp": "La mayor calidad posible con codificaci\u00f3n lenta y alto uso de CPU",
+ "OptionHighSpeedTranscoding": "Mayor velocidad",
+ "OptionHighQualityTranscoding": "Mayor calidad",
+ "OptionMaxQualityTranscoding": "M\u00e1xima calidad",
+ "OptionEnableDebugTranscodingLogging": "Activar el registro de depuraci\u00f3n del transcodificador",
+ "OptionEnableDebugTranscodingLoggingHelp": "Esto crear\u00e1 archivos de registro muy grandes y s\u00f3lo se recomienda cuando sea necesario para solucionar problemas.",
+ "OptionUpscaling": "Permitir que los clientes soliciten v\u00eddeo upscaled",
+ "OptionUpscalingHelp": "En algunos casos esto se traducir\u00e1 en una mejora de la calidad del v\u00eddeo, pero aumentar\u00e1 el uso de CPU.",
+ "EditCollectionItemsHelp": "Agregar o quitar pel\u00edculas, series, discos, libros o juegos que desee agrupar dentro de esta colecci\u00f3n.",
+ "HeaderAddTitles": "A\u00f1adir T\u00edtulos",
+ "LabelEnableDlnaPlayTo": "Actvar la reproducci\u00f3n en DLNAi",
+ "LabelEnableDlnaPlayToHelp": "Media Browser puede detectar dispositivos en su red y ofrecer la posibilidad de controlarlos remotamente.",
+ "LabelEnableDlnaDebugLogging": "Activar el registro de depuraci\u00f3n de DLNA",
+ "LabelEnableDlnaDebugLoggingHelp": "Esto crear\u00e1 archivos de registro de gran tama\u00f1o y s\u00f3lo debe ser utilizado cuando sea necesario para solucionar problemas.",
+ "LabelEnableDlnaClientDiscoveryInterval": "Intervalo de detecci\u00f3n de cliente (segundos)",
+ "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determina la duraci\u00f3n en segundos del intervalo entre las b\u00fasquedas SSDP realizadas por Media Browser.",
+ "HeaderCustomDlnaProfiles": "Perfiles personalizados",
+ "HeaderSystemDlnaProfiles": "Perfiles del sistema",
+ "CustomDlnaProfilesHelp": "Crear un perfil personalizado para un nuevo dispositivo o reemplazar un perfil del sistema.",
+ "SystemDlnaProfilesHelp": "Los perfiles del sistema son de s\u00f3lo lectura. Para anular un perfil del sistema, crear un perfil personalizado del mismo dispositivo.",
+ "TitleDashboard": "Panel de control",
+ "TabHome": "Inicio",
+ "TabInfo": "Info",
+ "HeaderLinks": "Enlaces",
+ "HeaderSystemPaths": "Rutas del sistema",
+ "LinkCommunity": "Comunidad",
+ "LinkGithub": "Github",
+ "LinkApiDocumentation": "Documentaci\u00f3n API",
+ "LabelFriendlyServerName": "Nombre informal del servidor:",
+ "LabelFriendlyServerNameHelp": "Este nombre se podr\u00e1 utilizar para identificar este servidor. Si se deja en blanco se usar\u00e1 el nombre del ordenador.",
+ "LabelPreferredDisplayLanguage": "Idioma de pantalla preferido",
+ "LabelPreferredDisplayLanguageHelp": "La traducci\u00f3n de Media Browser es un proyecto en curso y a\u00fan no est\u00e1 completado.",
+ "LabelReadHowYouCanContribute": "Lea acerca de c\u00f3mo usted puede contribuir.",
+ "HeaderNewCollection": "Nueva colecci\u00f3n",
+ "HeaderAddToCollection": "A\u00f1adir a la colecci\u00f3n",
+ "ButtonSubmit": "Enviar",
+ "NewCollectionNameExample": "Ejemplo: Star Wars Colecci\u00f3n",
+ "OptionSearchForInternetMetadata": "Buscar en internet ilustraciones y metadatos",
+ "ButtonCreate": "Crear",
+ "LabelHttpServerPortNumber": "Puerto Http del servidor:",
+ "LabelWebSocketPortNumber": "N\u00famero de puerto WebSocket:",
+ "LabelEnableAutomaticPortHelp": "UPnP permite automatizar la configuraci\u00f3n del router para el acceso remoto. Esto puede no funcionar en algunos modelos de router.",
+ "LabelExternalDDNS": "DDNS externa:",
+ "LabelExternalDDNSHelp": "Si dispone de DNS din\u00e1mica, escr\u00edbala aqu\u00ed. Media Brower la utilizar\u00e1 para las conexiones remotas.",
+ "TabResume": "Continuar",
+ "TabWeather": "El tiempo",
+ "TitleAppSettings": "Opciones de la App",
+ "LabelMinResumePercentage": "Porcentaje m\u00ednimo para reanudaci\u00f3n:",
+ "LabelMaxResumePercentage": "Porcentaje m\u00e1ximo para reanudaci\u00f3n::",
+ "LabelMinResumeDuration": "Duraci\u00f3n m\u00ednima de reanudaci\u00f3n (segundos):",
+ "LabelMinResumePercentageHelp": "Los t\u00edtulos se asumir\u00e1n como no reproducidos si se paran antes de este momento",
+ "LabelMaxResumePercentageHelp": "Los t\u00edtulos se asumir\u00e1n como reproducidos si se paran despu\u00e9s de este momento",
+ "LabelMinResumeDurationHelp": "Los t\u00edtulos m\u00e1s cortos de esto no ser\u00e1n reanudables",
+ "TitleAutoOrganize": "Organizaci\u00f3n autom\u00e1tica",
+ "TabActivityLog": "Log de actividad",
+ "HeaderName": "Nombre",
+ "HeaderDate": "Fecha",
+ "HeaderSource": "Origen",
+ "HeaderDestination": "Destino",
+ "HeaderProgram": "Programa",
+ "HeaderClients": "Clientes",
+ "LabelCompleted": "Completado",
+ "LabelFailed": "Error",
+ "LabelSkipped": "Omitido",
+ "HeaderEpisodeOrganization": "Organizaci\u00f3n de episodios",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Temporada n\u00famero:",
+ "LabelEpisodeNumber": "Episodio n\u00famero:",
+ "LabelEndingEpisodeNumber": "N\u00famero episodio final:",
+ "LabelEndingEpisodeNumberHelp": "S\u00f3lo requerido para archivos multi-episodio",
+ "HeaderSupportTheTeam": "Apoye al Equipo de Media Browser",
+ "LabelSupportAmount": "Importe (USD)",
+ "HeaderSupportTheTeamHelp": "Ayude a garantizar el desarrollo continuo de este proyecto mediante una donaci\u00f3n. Una parte de todas las donaciones ir\u00e1n a parar a otras herramientas gratuitas de las que dependemos.",
+ "ButtonEnterSupporterKey": "Entre la Key de Seguidor",
+ "DonationNextStep": "Cuando haya terminado, vuelva y entre su key de seguidor que recibir\u00e1 por email.",
+ "AutoOrganizeHelp": "Organizaci\u00f3n autom\u00e1tica monitoriza sus carpetas de descarga en busca de nuevos archivos y los mueve a sus directorios de medios.",
+ "AutoOrganizeTvHelp": "La organizaci\u00f3n de archivos de TV s\u00f3lo a\u00f1adir\u00e1 episodios a series existentes. No crear\u00e1 carpetas para series nuevas.",
+ "OptionEnableEpisodeOrganization": "Activar la organizaci\u00f3n de nuevos episodios",
+ "LabelWatchFolder": "Ver carpeta:",
+ "LabelWatchFolderHelp": "El servidor sondear\u00e1 esta carpeta durante la tarea programada \"Organizar nuevos archivos de medios\".",
+ "ButtonViewScheduledTasks": "Ver tareas programadas",
+ "LabelMinFileSizeForOrganize": "Tama\u00f1o m\u00ednimo de archivo (MB):",
+ "LabelMinFileSizeForOrganizeHelp": "Los archivos menores de este tama\u00f1po se ignorar\u00e1n.",
+ "LabelSeasonFolderPattern": "Patr\u00f3n de la carpeta para temporadas:",
+ "LabelSeasonZeroFolderName": "Nombre de la carpeta para la temporada cero:",
+ "HeaderEpisodeFilePattern": "Patr\u00f3n para archivos de episodio",
+ "LabelEpisodePattern": "Patr\u00f3n de episodio:",
+ "LabelMultiEpisodePattern": "Patr\u00f3n para multi-episodio:",
+ "HeaderSupportedPatterns": "Patrones soportados",
+ "HeaderTerm": "Plazo",
+ "HeaderPattern": "Patr\u00f3n",
+ "HeaderResult": "Resultado",
+ "LabelDeleteEmptyFolders": "Borrar carpetas vacias despu\u00e9s de la organizaci\u00f3n",
+ "LabelDeleteEmptyFoldersHelp": "Activar para mantener el directorio de descargas limpio.",
+ "LabelDeleteLeftOverFiles": "Eliminar los archivos sobrantes con las siguientes extensiones:",
+ "LabelDeleteLeftOverFilesHelp": "Separar con ;. Por ejemplo: .nfo;.txt",
+ "OptionOverwriteExistingEpisodes": "Sobreescribir episodios ya existentes",
+ "LabelTransferMethod": "M\u00e9todo de transferencia",
+ "OptionCopy": "Copiar",
+ "OptionMove": "Mover",
+ "LabelTransferMethodHelp": "Copiar o mover archivos desde la carpeta de inspecci\u00f3n",
+ "HeaderLatestNews": "Ultimas noticias",
+ "HeaderHelpImproveMediaBrowser": "Ayuda a mejorar Media Browser",
+ "HeaderRunningTasks": "Tareas en ejecuci\u00f3n",
+ "HeaderActiveDevices": "Dispositivos activos",
+ "HeaderPendingInstallations": "Instalaciones pendientes",
+ "HeaerServerInformation": "Informaci\u00f3n del servidor",
+ "ButtonRestartNow": "Reiniciar ahora",
+ "ButtonRestart": "Reiniciar",
+ "ButtonShutdown": "Apagar",
+ "ButtonUpdateNow": "Actualizar ahora",
+ "PleaseUpdateManually": "Por favor cierre el servidor y actualice manualmente.",
+ "NewServerVersionAvailable": "\u00a1Hay disponible una nueva versi\u00f3n de Media Browser Server!",
+ "ServerUpToDate": "Media Browser Server est\u00e1 actualizado",
+ "ErrorConnectingToMediaBrowserRepository": "Hubo un error al conectarse remotamente al repositorio de Media Browser,",
+ "LabelComponentsUpdated": "Los componentes siguientes se han instalado o actualizado:",
+ "MessagePleaseRestartServerToFinishUpdating": "Reinicie el servidor para acabar de aplicar las actualizaciones.",
+ "LabelDownMixAudioScale": "Escala de reducci\u00f3n de potencia de audio:",
+ "LabelDownMixAudioScaleHelp": "Potenciador de audio. Establecer a 1 para preservar el volumen original.",
+ "ButtonLinkKeys": "Enlazar claves",
+ "LabelOldSupporterKey": "Antigua clave de seguidor",
+ "LabelNewSupporterKey": "Nueva clave de seguidor",
+ "HeaderMultipleKeyLinking": "Vinculaci\u00f3n de m\u00faltiples claves",
+ "MultipleKeyLinkingHelp": "Si usted tiene m\u00e1s de una clave de seguidor, utilice este formulario para vincular los registros de la antigua clave con la nueva.",
+ "LabelCurrentEmailAddress": "Cuenta de correo actual",
+ "LabelCurrentEmailAddressHelp": "La direcci\u00f3n de correo electr\u00f3nico actual a la que se envi\u00f3 la nueva clave.",
+ "HeaderForgotKey": "Perd\u00ed mi clave",
+ "LabelEmailAddress": "Direcci\u00f3n de correo",
+ "LabelSupporterEmailAddress": "La direcci\u00f3n de correo que utliz\u00f3 para comprar la clave.",
+ "ButtonRetrieveKey": "Recuperar clave",
+ "LabelSupporterKey": "Clave de seguidor (pegar desde el correo)",
+ "LabelSupporterKeyHelp": "Entre su clave de seguidor para empezar a disfrutar de los beneficios adicionales que la comunidad ha creado para Media Browser.",
+ "MessageInvalidKey": "La clave MB3 falta o es inv\u00e1lida",
+ "ErrorMessageInvalidKey": "Para acceder al contenido premium debe registrarse, tambi\u00e9n debe ser un MB3 Seguidor. Por favor, done y apoye el desarrollo continuado del producto principal. Gracias.",
+ "HeaderDisplaySettings": "Opciones de pantalla",
+ "TabPlayTo": "Reproducir en",
+ "LabelEnableDlnaServer": "Habilitar servidor Dlna",
+ "LabelEnableDlnaServerHelp": "Permite que los dispositivos UPnp de su red puedan navegar y repoducir contenidos de Media Browser.",
+ "LabelEnableBlastAliveMessages": "Explotar mensajes en vivo",
+ "LabelEnableBlastAliveMessagesHelp": "Active aqu\u00ed si el servidor no es detectado correctamente por otros dispositivos UPnP en su red.",
+ "LabelBlastMessageInterval": "Intervalo para mensajes en vivo (segundos)",
+ "LabelBlastMessageIntervalHelp": "Determina la duraci\u00f3n en segundos entre los mensajes en vivo del servidor .",
+ "LabelDefaultUser": "Usuario por defecto:",
+ "LabelDefaultUserHelp": "Determina de q\u00fae usuario se utilizar\u00e1 su biblioteca de medios para mostrarla por defecto en los dipositivos conectados. Esto puede cambiarse para cada dispositivo mediante el uso de perfiles.",
+ "TitleDlna": "DLNA",
+ "TitleChannels": "Canales",
+ "HeaderServerSettings": "Ajustes del Servidor",
+ "LabelWeatherDisplayLocation": "Lugar del que mostar el tiempo:",
+ "LabelWeatherDisplayLocationHelp": "C\u00f3digo postal USA \/ Ciudad, Estado, Pa\u00eds \/ Ciudad, Pa\u00eds",
+ "LabelWeatherDisplayUnit": "Unidad de media para la temperatura:",
+ "OptionCelsius": "Celsius",
+ "OptionFahrenheit": "Fahrenheit",
+ "HeaderRequireManualLogin": "Requerir entrada de usuario manual para:",
+ "HeaderRequireManualLoginHelp": "Cuando est\u00e1 desactivado los clientes saldr\u00e1n en la pantalla de inicio para seleccionarlos visualmente.",
+ "OptionOtherApps": "Otras aplicaciones",
+ "OptionMobileApps": "Aplicaciones m\u00f3viles",
+ "HeaderNotificationList": "Haga click en una notificaci\u00f3n para configurar sus opciones de env\u00edo.",
+ "NotificationOptionApplicationUpdateAvailable": "Disponible actualizaci\u00f3n de la aplicaci\u00f3n",
+ "NotificationOptionApplicationUpdateInstalled": "Se ha instalado la actualizaci\u00f3n de la aplicaci\u00f3n",
+ "NotificationOptionPluginUpdateInstalled": "Se ha instalado la actualizaci\u00f3n del plugin",
+ "NotificationOptionPluginInstalled": "Plugin instalado",
+ "NotificationOptionPluginUninstalled": "Plugin desinstalado",
+ "NotificationOptionVideoPlayback": "Reproducci\u00f3n de video",
+ "NotificationOptionAudioPlayback": "Reproducci\u00f3n de audio",
+ "NotificationOptionGamePlayback": "Iniciar juegos",
+ "NotificationOptionVideoPlaybackStopped": "Reproducci\u00f3n de video detenida",
+ "NotificationOptionAudioPlaybackStopped": "Reproducci\u00f3n de audio detenida",
+ "NotificationOptionGamePlaybackStopped": "Reproducci\u00f3n de juego detenida",
+ "NotificationOptionTaskFailed": "La tarea programada ha fallado",
+ "NotificationOptionInstallationFailed": "Fallo en la instalaci\u00f3n",
+ "NotificationOptionNewLibraryContent": "Nuevo contenido a\u00f1adido",
+ "NotificationOptionNewLibraryContentMultiple": "Nuevo contenido a\u00f1adido (multiple)",
+ "SendNotificationHelp": "Por defecto, las notificaciones aparecer\u00e1n en el panel de control. Compruebe el cat\u00e1logo de plugins para instalar opciones adicionales para las notificaciones.",
+ "NotificationOptionServerRestartRequired": "Se requiere el reinicio del servidor",
+ "LabelNotificationEnabled": "Activar esta notificaci\u00f3n",
+ "LabelMonitorUsers": "Supervisar la actividad de:",
+ "LabelSendNotificationToUsers": "Enviar la notificaci\u00f3n a:",
+ "UsersNotNotifiedAboutSelfActivity": "Los usuarios no ser\u00e1n notificados acerca de sus propias actividades.",
+ "LabelUseNotificationServices": "Usar los siguientes servicios:",
+ "CategoryUser": "Usuario",
+ "CategorySystem": "Sistema",
+ "CategoryApplication": "Aplicaci\u00f3n",
+ "CategoryPlugin": "Plugin",
+ "LabelMessageTitle": "T\u00edtulo del mensaje:",
+ "LabelAvailableTokens": "Tokens disponibles:",
+ "AdditionalNotificationServices": "Visite el cat\u00e1logo de plugins para instalar servicios de notificaci\u00f3n adicionales.",
+ "OptionAllUsers": "Todos los usuarios",
+ "OptionAdminUsers": "Administradores",
+ "OptionCustomUsers": "A medida",
+ "ButtonArrowUp": "Arriba",
+ "ButtonArrowDown": "Abajo",
+ "ButtonArrowLeft": "Izquierda",
+ "ButtonArrowRight": "Derecha",
+ "ButtonBack": "Atr\u00e1s",
+ "ButtonInfo": "Info",
+ "ButtonOsd": "Visualizaci\u00f3n en pantalla",
+ "ButtonPageUp": "P\u00e1gina arriba",
+ "ButtonPageDown": "P\u00e1gina abajo",
+ "PageAbbreviation": "PG",
+ "ButtonHome": "Inicio",
+ "ButtonSettings": "Opciones",
+ "ButtonTakeScreenshot": "Captura de pantalla",
+ "ButtonLetterUp": "Letter arriba",
+ "ButtonLetterDown": "Letter abajo",
+ "PageButtonAbbreviation": "PG",
+ "LetterButtonAbbreviation": "A",
+ "TabNowPlaying": "Reproduciendo ahora",
+ "TabNavigation": "Navegaci\u00f3n",
+ "TabControls": "Controles",
+ "ButtonFullscreen": "Pantalla completa",
+ "ButtonScenes": "Escenas",
+ "ButtonSubtitles": "Subt\u00edtulos",
+ "ButtonAudioTracks": "Pistas de audio",
+ "ButtonPreviousTrack": "Pista anterior",
+ "ButtonNextTrack": "Pista siguiente",
+ "ButtonStop": "Detener",
+ "ButtonPause": "Pausa",
+ "LabelGroupMoviesIntoCollections": "Agrupar pel\u00edculas en colecciones",
+ "LabelGroupMoviesIntoCollectionsHelp": "Cuando se muestran las listas de pel\u00edculas, las pel\u00edculas pertenecientes a una colecci\u00f3n se mostrar\u00e1n como un elemento agrupado.",
+ "NotificationOptionPluginError": "Error en plugin",
+ "ButtonVolumeUp": "Subir volumen",
+ "ButtonVolumeDown": "Bajar volumen",
+ "ButtonMute": "Silencio",
+ "HeaderLatestMedia": "\u00daltimos medios",
+ "OptionSpecialFeatures": "Caracter\u00edsticas especiales",
+ "HeaderCollections": "Colecciones",
+ "LabelProfileCodecsHelp": "Separados por comas. Esto se puede dejar vac\u00edo para aplicar a todos los codecs.",
+ "LabelProfileContainersHelp": "Separados por comas. Esto se puede dejar vac\u00edo para aplicar a todos los contenedores.",
+ "HeaderResponseProfile": "Perfil de respuesta",
+ "LabelType": "Tipo:",
+ "LabelProfileContainer": "Contenedor:",
+ "LabelProfileVideoCodecs": "Codecs de video:",
+ "LabelProfileAudioCodecs": "Codecs de audio:",
+ "LabelProfileCodecs": "Codecs:",
+ "HeaderDirectPlayProfile": "Perfil de reproducci\u00f3n directa",
+ "HeaderTranscodingProfile": "Perfil de transcodificaci\u00f3n",
+ "HeaderCodecProfile": "Perfil de codec",
+ "HeaderCodecProfileHelp": "Perfiles de codec indican las limitaciones de un dispositivo cuando se reproducen codecs espec\u00edficos. Si se aplica una limitaci\u00f3n entonces el medio se transcodificar\u00e1, incluso si el codec est\u00e1 configurado para reproducci\u00f3n directa.",
+ "HeaderContainerProfile": "Perfil de contenedor",
+ "HeaderContainerProfileHelp": "Perfiles de codec indican las limitaciones de un dispositivo mientras reproduce formatos espec\u00edficos. If se aplica una limitaci\u00f3n entonces el medio se transcodificar\u00e1, incluso si el formato est\u00e1 configurado para reproducci\u00f3n directa.",
+ "OptionProfileVideo": "Video",
+ "OptionProfileAudio": "Audio",
+ "OptionProfileVideoAudio": "Video audio",
+ "OptionProfilePhoto": "Foto",
+ "LabelUserLibrary": "Librer\u00eda de usuario:",
+ "LabelUserLibraryHelp": "Seleccione de qu\u00e9 usuario se utilizar\u00e1 la librer\u00eda en el dispositivo. D\u00e9jelo vac\u00edo para utilizar la configuraci\u00f3n por defecto.",
+ "OptionPlainStorageFolders": "Ver todas las carpetas como carpetas de almacenamiento sin formato.",
+ "OptionPlainStorageFoldersHelp": "Si est\u00e1 activado, todas las carpetas se representan en DIDL como \"object.container.storageFolder\" en lugar de un tipo m\u00e1s espec\u00edfico, como por ejemplo \"object.container.person.musicArtist\".",
+ "OptionPlainVideoItems": "Mostrar todos los videos como elementos de video sin formato",
+ "OptionPlainVideoItemsHelp": "Si est\u00e1 habilitado, todos los v\u00eddeos est\u00e1n representados en DIDL como \"object.item.videoItem\" en lugar de un tipo m\u00e1s espec\u00edfico, como por ejemplo \"object.item.videoItem.movie\".",
+ "LabelSupportedMediaTypes": "Tipos de medio soportados:",
+ "TabIdentification": "Identificaci\u00f3n",
+ "TabDirectPlay": "Reproducci\u00f3n directa",
+ "TabContainers": "Contenedores",
+ "TabCodecs": "Codecs",
+ "TabResponses": "Respuestas",
+ "HeaderProfileInformation": "Informaci\u00f3n del perfil",
+ "LabelEmbedAlbumArtDidl": "Incorporar la car\u00e1tula del \u00e1lbum en didl",
+ "LabelEmbedAlbumArtDidlHelp": "Algunos dispositivos prefieren este m\u00e9todo para obtener la car\u00e1tula del \u00e1lbum. Otros pueden fallar al reproducir con esta opci\u00f3n habilitada.",
+ "LabelAlbumArtPN": "Car\u00e1tula del album PN:",
+ "LabelAlbumArtHelp": "PN utilizado para la car\u00e1tula del \u00e1lbum, dentro del atributo dlna:profileID en upnp:albumArtURI. Algunos clientes requieren un valor espec\u00edfico, independientemente del tama\u00f1o de la imagen.",
+ "LabelAlbumArtMaxWidth": "Anchura m\u00e1xima de la car\u00e1tula del album:",
+ "LabelAlbumArtMaxWidthHelp": "Resoluci\u00f3n m\u00e1xima de la car\u00e1tula del \u00e1lbum expuesta a trav\u00e9s de upnp:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "Altura m\u00e1xima de la car\u00e1tula del album:",
+ "LabelAlbumArtMaxHeightHelp": "Resoluci\u00f3n m\u00e1xima de la car\u00e1tula del \u00e1lbum expuesta a trav\u00e9s de upnp:albumArtURI.",
+ "LabelIconMaxWidth": "Anchura m\u00e1xima de icono:",
+ "LabelIconMaxWidthHelp": "Resoluci\u00f3n m\u00e1xima de los iconos expuestos via upnp:icon.",
+ "LabelIconMaxHeight": "Altura m\u00e1xima de icono:",
+ "LabelIconMaxHeightHelp": "Resoluci\u00f3n m\u00e1xima de los iconos expuestos via upnp:icon.",
+ "LabelIdentificationFieldHelp": "Una subcadena insensible a may\u00fasculas o min\u00fasculas o una expresi\u00f3n regex.",
+ "HeaderProfileServerSettingsHelp": "Estos valores controlan el modo en que Media Browser se presentar\u00e1 en el dispositivo.",
+ "LabelMaxBitrate": "Bitrate m\u00e1ximo:",
+ "LabelMaxBitrateHelp": "Especificar una tasa de bits m\u00e1xima en entornos de ancho de banda limitado, o si el dispositivo impone su propio l\u00edmite.",
+ "OptionIgnoreTranscodeByteRangeRequests": "Ignorar las solicitudes de intervalo de bytes de transcodificaci\u00f3n",
+ "OptionIgnoreTranscodeByteRangeRequestsHelp": "Si est\u00e1 activado, estas solicitudes ser\u00e1n atendidas pero ignorar\u00e1n el encabezado de intervalo de bytes.",
+ "LabelFriendlyName": "Nombre amigable",
+ "LabelManufacturer": "Fabricante",
+ "LabelManufacturerUrl": "Url del fabricante",
+ "LabelModelName": "Nombre de modelo",
+ "LabelModelNumber": "N\u00famero de modelo",
+ "LabelModelDescription": "Descripci\u00f3n de modelo",
+ "LabelModelUrl": "Url del modelo",
+ "LabelSerialNumber": "N\u00famero de serie",
+ "LabelDeviceDescription": "Descripci\u00f3n del dispositivo",
+ "HeaderIdentificationCriteriaHelp": "Entre al menos un criterio de identificaci\u00f3n.",
+ "HeaderDirectPlayProfileHelp": "A\u00f1adir perfiles de reproducci\u00f3n directa para indicar qu\u00e9 formatos puede utilizar el dispositivo de forma nativa.",
+ "HeaderTranscodingProfileHelp": "A\u00f1adir perfiles de transcodificaci\u00f3n para indicar qu\u00e9 formatos se deben utilizar cuando se requiera transcodificaci\u00f3n.",
+ "HeaderResponseProfileHelp": "Perfiles de respuesta proporcionan una forma de personalizar la informaci\u00f3n que se env\u00eda al dispositivo cuando se reproducen ciertos tipos de medios.",
+ "LabelXDlnaCap": "X-Dlna cap:",
+ "LabelXDlnaCapHelp": "Determina el contenido del elemento X_DLNACAP en el espacio de nombre urn:schemas-dlna-org:device-1-0.",
+ "LabelXDlnaDoc": "X-Dlna doc:",
+ "LabelXDlnaDocHelp": "Determina el contenido del elemento X_DLNADOC en el espacio de nombreurn:schemas-dlna-org:device-1-0.",
+ "LabelSonyAggregationFlags": "Agregaci\u00f3n de banderas Sony:",
+ "LabelSonyAggregationFlagsHelp": "Determina el contenido del elemento aggregationFlags en el espacio de nombre urn:schemas-sonycom:av.",
+ "LabelTranscodingContainer": "Contenedor:",
+ "LabelTranscodingVideoCodec": "Codec de video:",
+ "LabelTranscodingVideoProfile": "Perfil de video:",
+ "LabelTranscodingAudioCodec": "Codec de audio:",
+ "OptionEnableM2tsMode": "Activar modo M2ts",
+ "OptionEnableM2tsModeHelp": "Activar modo m2ts cuando se codifique a mpegts",
+ "OptionEstimateContentLength": "Estimar longitud del contenido al transcodificar",
+ "OptionReportByteRangeSeekingWhenTranscoding": "Indicar que el servidor soporta la b\u00fasqueda de byte al transcodificar",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "Esto es necesario para algunos dispositivos que no buscan el tiempo muy bien.",
+ "HeaderSubtitleDownloadingHelp": "Cuando Media Browser escanea los archivos de v\u00eddeo, puede buscar subt\u00edtulos faltantes y descargarlos usando un proveedor de subt\u00edtulos como OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "Descarga subt\u00edtulos para:",
+ "MessageNoChapterProviders": "Instalar un plugin proveedor de cap\u00edtulos como ChapterDb o tagChimp para permitir opciones de cap\u00edtulo adicionales.",
+ "LabelSkipIfGraphicalSubsPresent": "Omitir si el video ya contiene subt\u00edtulos gr\u00e1ficos",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Mantener versiones de texto de los subt\u00edtulos se traducir\u00e1 en una prestaci\u00f3n m\u00e1s eficiente para los clientes m\u00f3viles.",
+ "TabSubtitles": "Subt\u00edtulos",
+ "TabChapters": "Cap\u00edtulos",
+ "HeaderDownloadChaptersFor": "Descarga nombres de los cap\u00edtulos de:",
+ "LabelOpenSubtitlesUsername": "Usuario de Open Subtitles:",
+ "LabelOpenSubtitlesPassword": "Contrase\u00f1a de Open Subtitles:",
+ "HeaderChapterDownloadingHelp": "Cuando Media Browser escanea los archivos de v\u00eddeo, puede descargar nombres de los cap\u00edtulos desde la red utilizando plugins de cap\u00edtulos como ChapterDb y tagChimp.",
+ "LabelPlayDefaultAudioTrack": "\nReproducir pista de audio predeterminado, independientemente del idioma",
+ "LabelSubtitlePlaybackMode": "Modo de Subt\u00edtulo:",
+ "LabelDownloadLanguages": "Idiomas de descarga:",
+ "ButtonRegister": "Registrar",
+ "LabelSkipIfAudioTrackPresent": "Omitir si la pista de audio por defecto coincide con el idioma de descarga",
+ "LabelSkipIfAudioTrackPresentHelp": "Desactive esta opci\u00f3n para asegurar que todos los v\u00eddeos tienen subt\u00edtulos, sin importar el idioma de audio.",
+ "HeaderSendMessage": "Enviar mensaje",
+ "ButtonSend": "Enviar",
+ "LabelMessageText": "Mensaje de texto:",
+ "MessageNoAvailablePlugins": "No hay plugins disponibles.",
+ "LabelDisplayPluginsFor": "Mostrar plugins para:",
+ "PluginTabMediaBrowserClassic": "MB Classic",
+ "PluginTabMediaBrowserTheater": "MB Theater",
+ "TabOtherPlugins": "Otros",
+ "LabelEpisodeName": "Nombre episodio",
+ "LabelSeriesName": "Nombre de la serie",
+ "ValueSeriesNamePeriod": "Series.name",
+ "ValueSeriesNameUnderscore": "Series_name",
+ "ValueEpisodeNamePeriod": "Episode.name",
+ "ValueEpisodeNameUnderscore": "Episode_name",
+ "HeaderTypeText": "Entrar texto",
+ "LabelTypeText": "Texto",
+ "HeaderSearchForSubtitles": "B\u00fasqueda de Subt\u00edtulos",
+ "MessageNoSubtitleSearchResultsFound": "No se han encontrado resultados en la b\u00fasqueda.",
+ "TabDisplay": "Pantalla",
+ "TabLanguages": "Idiomas",
+ "TabWebClient": "Cliente web",
+ "LabelEnableThemeSongs": "Habilitar temas musicales",
+ "LabelEnableBackdrops": "Habilitar im\u00e1genes de fondo",
+ "LabelEnableThemeSongsHelp": "Si est\u00e1 habilitado, se reproducir\u00e1n temas musicales de fondo mientras navega por la biblioteca.",
+ "LabelEnableBackdropsHelp": "Si est\u00e1 habilitado, se mostrar\u00e1n im\u00e1genes de fondo en algunas p\u00e1ginas mientras navega por la biblioteca.",
+ "HeaderHomePage": "P\u00e1gina de inicio",
+ "HeaderSettingsForThisDevice": "Opciones para este dispositivo",
+ "OptionAuto": "Auto",
+ "OptionYes": "Si",
+ "OptionNo": "No",
+ "LabelHomePageSection1": "Secci\u00f3n uno de la p\u00e1gina de inicio:",
+ "LabelHomePageSection2": "Secci\u00f3n dos de la p\u00e1gina de inicio:",
+ "LabelHomePageSection3": "Secci\u00f3n tres de la p\u00e1gina de inicio:",
+ "LabelHomePageSection4": "Secci\u00f3n cuarta de la p\u00e1gina de inicio",
+ "OptionMyViewsButtons": "Mis vistas (botones)",
+ "OptionMyViews": "Mis vistas",
+ "OptionMyViewsSmall": "Mis vistas (peque\u00f1o)",
+ "OptionResumablemedia": "Continuar",
+ "OptionLatestMedia": "\u00daltimos medios",
+ "OptionLatestChannelMedia": "Ultimos elementos de canales",
+ "HeaderLatestChannelItems": "Ultimos elementos de canales",
+ "OptionNone": "Nada",
+ "HeaderLiveTv": "TV en vivo",
+ "HeaderReports": "Informes",
+ "HeaderMetadataManager": "Metadata Manager",
+ "HeaderPreferences": "Preferencias",
+ "MessageLoadingChannels": "Cargando contenidos del canal...",
+ "ButtonMarkRead": "Marcar como le\u00eddo",
+ "OptionDefaultSort": "Por defecto",
+ "OptionCommunityMostWatchedSort": "M\u00e1s visto",
+ "TabNextUp": "Siguiendo",
+ "MessageNoMovieSuggestionsAvailable": "No hay sugerencias de pel\u00edculas disponibles. Comience ver y calificar sus pel\u00edculas y vuelva para ver las recomendaciones.",
+ "MessageNoCollectionsAvailable": "Colecciones le permitir\u00e1 disfrutar de grupos personalizados de Pel\u00edculas, Series, Discos, Libros y Juegos. Haga click en el bot\u00f3n nuevo para empezar a crear Colecciones.",
+ "HeaderWelcomeToMediaBrowserWebClient": "Vienvenido al Cliente Web de Media Browser",
+ "ButtonDismiss": "Descartar",
+ "MessageLearnHowToCustomize": "Aprenda c\u00f3mo personalizar esta p\u00e1gina a sus propios gustos personales. Haga clic en su icono de usuario en la esquina superior derecha de la pantalla para ver y actualizar sus preferencias.",
+ "ButtonEditOtherUserPreferences": "Editar preferencias personales de este usuario.",
+ "LabelChannelStreamQuality": "Calidad preferida para la transmisi\u00f3n por Internet:",
+ "LabelChannelStreamQualityHelp": "En un entorno de bajo ancho de banda, limitar la calidad puede ayudar a asegurar una experiencia de streaming suave.",
+ "OptionBestAvailableStreamQuality": "Mejor disponible",
+ "LabelEnableChannelContentDownloadingFor": "Habilitar descargas de contenido para el canal:",
+ "LabelEnableChannelContentDownloadingForHelp": "Algunos canales soportan descargar contenido antes de ver. Habilite esta en ambientes de poco ancho de banda para descargar el contenido del canal durante las horas libres. El contenido se descarga como parte de la tarea programada de descargas de canal.",
+ "LabelChannelDownloadPath": "Ruta para descargas de contenidos de canales:",
+ "LabelChannelDownloadPathHelp": "Especifique una ruta personalizada si lo desea. D\u00e9jelo en blanco para utilizar un carpeta interna del programa.",
+ "LabelChannelDownloadAge": "Borrar contenido despues de: (d\u00edas)",
+ "LabelChannelDownloadAgeHelp": "Todo contenido descargado anterior se borrar\u00e1. Continuar\u00e1 estando disponible v\u00eda streaming de internet.",
+ "ChannelSettingsFormHelp": "Instale canales como Trailers y Vimeo desde el cat\u00e1logo de plugins.",
+ "LabelSelectCollection": "Seleccionar colecci\u00f3n:",
+ "ViewTypeMovies": "Pel\u00edculas",
+ "ViewTypeTvShows": "TV",
+ "ViewTypeGames": "Juegos",
+ "ViewTypeMusic": "M\u00fasica",
+ "ViewTypeBoxSets": "Colecciones",
+ "ViewTypeChannels": "Canales",
+ "ViewTypeLiveTV": "Tv en vivo",
+ "HeaderOtherDisplaySettings": "Configuraci\u00f3n de pantalla",
+ "HeaderMyViews": "Mis vistas",
+ "LabelSelectFolderGroups": "Agrupar autom\u00e1ticamente las siguientes carpetas en vistas tales como pel\u00edculas, m\u00fasica y televisi\u00f3n",
+ "LabelSelectFolderGroupsHelp": "Las carpetas que no est\u00e9n marcadas se mostrar\u00e1n por s\u00ed mismas en su propia secci\u00f3n.",
+ "OptionDisplayAdultContent": "Mostrar contenido para adultos",
+ "OptionLibraryFolders": "Vista de carpeta",
+ "TitleRemoteControl": "Control remoto",
+ "OptionLatestTvRecordings": "\u00daltimas grabaciones",
+ "LabelProtocolInfo": "Informaci\u00f3n de protocolo:",
+ "LabelProtocolInfoHelp": "El valor que se utilizar\u00e1 cuando se responde a una solicitud GetProtocolInfo desde el dispositivo.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser incluye soporte nativo para XBMC, Nfo, metadatos e im\u00e1genes. Para activar o desactivar los metadatos XBMC, utilice la ficha Avanzadas para configurar opciones para sus tipos de medios.",
+ "LabelXbmcMetadataUser": "A\u00f1adir datos de reproducciones de usuario a los nfo\u00b4s para:",
+ "LabelXbmcMetadataUserHelp": "Activar esto para mantener sincronizados los datos de reproducci\u00f3n entre Media Browser y Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Formato de fecha de estreno:",
+ "LabelXbmcMetadataDateFormatHelp": "Todas las fechas dentro de los nfo se leer\u00e1n y se escribir\u00e1n usando este formato.",
+ "LabelXbmcMetadataSaveImagePaths": "Grabar las rutas de las im\u00e1genes en los archivos nfo",
+ "LabelXbmcMetadataSaveImagePathsHelp": "\nEsto se recomienda si usted tiene los nombres de archivo de imagen que no se ajusten a las directrices de XBMC.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Habilitar rutas de sustituci\u00f3n",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Permite la sustituci\u00f3n de las rutas de im\u00e1genes utilizando la configuraci\u00f3n de rutas de sustituci\u00f3n en las opciones del servidor.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "Ver rutas de sustituci\u00f3n.",
+ "LabelGroupChannelsIntoViews": "Visualice los siguientes canales dentro de mis vistas:",
+ "LabelGroupChannelsIntoViewsHelp": "Si est\u00e1 activado, estos canales se mostrar\u00e1n directamente junto a Mis Vistas. Si est\u00e1 desactivada, ser\u00e1n mostrados separadamente en la vista de Canales.",
+ "LabelDisplayCollectionsView": "Mostrar una vista Colecciones para mostrar colecciones de pel\u00edculas",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copiar extrafanart en extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "Cuando se descargan im\u00e1genes se pueden guardar tanto en extrafanart como en extrathumbs para una m\u00e1xima compatibilidad con el skin de XBMC.",
+ "TabServices": "Servicios",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Archivos de log del servidor:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Personalizar la apariencia de Explorador de medios para satisfacer las necesidades de su grupo u organizaci\u00f3n.",
+ "LabelLoginDisclaimer": "Login renuncia:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Donar autom\u00e1ticamente esta cantidad cada mes",
+ "LabelAutomaticallyDonateHelp": "Usted puede cancelar en cualquier momento desde su cuenta de PayPal.",
+ "OptionList": "Lista",
+ "TabDashboard": "Panel de control",
+ "TitleServer": "Servidor",
+ "LabelCache": "Cach\u00e9:",
+ "LabelLogs": "Registros:",
+ "LabelMetadata": "Metadatos:",
+ "LabelImagesByName": "Im\u00e1genes por nombre:",
+ "LabelTranscodingTemporaryFiles": "Archivos temporales de transcodificaci\u00f3n:",
+ "HeaderLatestMusic": "\u00daltima m\u00fasica",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Keys de Api",
+ "HeaderApiKeysHelp": "Se requieren aplicaciones externas para tener una clave de API con el fin de comunicarse con Media Browser. Las claves son emitidas al iniciar una sesi\u00f3n con una cuenta de Media Browser, o mediante la introducci\u00f3n manualmente de una clave en la aplicaci\u00f3n.",
+ "HeaderApiKey": "Clave Api",
+ "HeaderApp": "App",
+ "HeaderDevice": "Dispositivo",
+ "HeaderUser": "Usuario",
+ "HeaderDateIssued": "Fecha de emisi\u00f3n",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser."
+} \ 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 741646596..d040bdc23 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "Cuando los usuarios reproduzcan contenidos",
- "HeaderEnableNotificationForEvents": "Enviar notificaciones para los siguientes eventos:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Cuando se encuentren disponibles actualizaciones",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Cuando las tareas programadas fallen",
- "OptionNotifyOnNewLibraryContent": "Cuando se a\u00f1adan nuevos contenidos a la biblioteca",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Actualizaciones",
- "HeaderUpdateLevel": "Nivel de Actualizaci\u00f3n",
- "LabelRequireTextSubtitles": "Descargar a\u00fan cuando el video ya contiene subt\u00edtulos gr\u00e1ficos",
- "LabelRequireTextSubtitlesHelp": "Mantener versiones de texto de los subt\u00edtulos resultar\u00e1 en una entrega m\u00e1s eficiente para clientes m\u00f3viles.",
- "HeaderSubtitleDownloadingMoreHelp": "Los subt\u00edtulos se consideran como faltantes cuando la pista de audio se encuentra en un lenguaje extranjero y no se cuenta con subt\u00edtulos disponibles en el lenguaje preferido.",
- "LabelDisplayForcedSubtitlesOnly": "Mostrar \u00fanicamente subtitulos forzados",
- "HeaderCustomizeOptionsPerMediaType": "Personalice opciones por tipo de medio",
- "LabelAudioLanguagePreferenceHelp": "Si se deja vac\u00edo, la pista de audio por defecto ser\u00e1 seleccionada, independientemente del lenguaje.",
- "TabCustomizations": "Personalizaciones",
- "HeaderAllDevices": "Todos los Dispositivos",
- "HeaderThisDevice": "Este Dispositivo",
- "OptionLibraryButtons": "Botones de la biblioteca",
- "OptionLibraryTiles": "Mosaicos de biblioteca (largo)",
- "OptionSmallLibraryTiles": "Mosaicos de biblioteca (peque\u00f1o)",
- "ButtonPlayTrailer": "Avance",
- "LabelFailed": "Fallido",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Pista Anterior",
- "ButtonNextTrack": "Pista Siguiente",
- "HeaderMyLibrary": "Mi Biblioteca",
- "HeaderLibraryViews": "Vistas de Biblioteca",
+ "HeaderPeople": "Personas",
"LabelExit": "Salir",
+ "HeaderDownloadPeopleMetadataFor": "Descargar biograf\u00eda e im\u00e1genes para:",
"LabelVisitCommunity": "Visitar la Comunidad",
+ "OptionComposers": "Compositores",
"LabelGithubWiki": "Wiki de Github",
+ "OptionOthers": "Otros",
"LabelSwagger": "Swagger",
"LabelStandard": "Est\u00e1ndar",
+ "HeaderDownloadPeopleMetadataForHelp": "Habilitar opciones adicionales proporcionar\u00e1 m\u00e1s informaci\u00f3n en pantalla pero resultar\u00e1 en barridos de la biblioteca m\u00e1s lentos",
"LabelViewApiDocumentation": "Ver documentaci\u00f3n del Api",
+ "ViewTypeFolders": "Carpetas",
"LabelBrowseLibrary": "Explorar Biblioteca",
+ "LabelDisplayFoldersView": "Mostrar una vista de carpetas para mostrar carpetas de medios simples",
"LabelConfigureMediaBrowser": "Configurar Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Grabaciones",
"LabelOpenLibraryViewer": "Abrir el Visor de la Biblioteca",
+ "ViewTypeLiveTvChannels": "Canales",
"LabelRestartServer": "Reiniciar el Servidor",
+ "LabelAllowLocalAccessWithoutPassword": "Permite acceso local sin una contrase\u00f1a",
"LabelShowLogWindow": "Mostrar Ventana de Bit\u00e1cora",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "Al habilitarse, no se requerir\u00e1 de una contrase\u00f1a cuando se inicie sesi\u00f3n desde su red local.",
"LabelPrevious": "Anterior",
+ "HeaderPassword": "Contrase\u00f1a",
"LabelFinish": "Terminar",
+ "HeaderLocalAccess": "Acceso Local",
"LabelNext": "Siguiente",
+ "HeaderViewOrder": "Orden de Despliegue",
"LabelYoureDone": "Ha Terminado!",
+ "LabelSelectUserViewOrder": "Seleccione el orden en que sus vistas ser\u00e1n desplegadas dentro de las apps de Media Browser",
"WelcomeToMediaBrowser": "\u00a1Bienvenido a Media Broswer!",
+ "LabelMetadataRefreshMode": "Modo de actualizaci\u00f3n de metadatos:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Modo de actualizaci\u00f3n de im\u00e1genes:",
"ThisWizardWillGuideYou": "Este asistente le guiar\u00e1 a trav\u00e9s del proceso de instalaci\u00f3n. Para comenzar, por favor seleccione su lenguaje preferido.",
+ "OptionDownloadMissingImages": "Descargar im\u00e1genes faltantes",
"TellUsAboutYourself": "D\u00edganos sobre usted",
+ "OptionReplaceExistingImages": "Reemplazar im\u00e1genes existentes",
"LabelYourFirstName": "Su nombre:",
+ "OptionRefreshAllData": "Actualizar todos los metadatos",
"MoreUsersCanBeAddedLater": "Se pueden agregar m\u00e1s usuarios posteriormente en el panel de control.",
+ "OptionAddMissingDataOnly": "S\u00f3lo agregar datos faltantes",
"UserProfilesIntro": "Media Browser incluye soporte integrado para perfiles de usuario, permiti\u00e9ndo a cada usuario tener su propia configuraci\u00f3n de pantalla, estado de reproducci\u00f3n y controles parentales.",
+ "OptionLocalRefreshOnly": "S\u00f3lo actualizaci\u00f3n local",
"LabelWindowsService": "Servicio de Windows",
+ "HeaderRefreshMetadata": "Actualizar Metadatos",
"AWindowsServiceHasBeenInstalled": "Se ha instalado un Servicio de Windows.",
+ "HeaderPersonInfo": "Info de la Persona",
"WindowsServiceIntro1": "Media Browser Server se ejecuta normalmente como una aplicaci\u00f3n de escritorio con un icono en el \u00e1rea de notificaci\u00f3n, pero si prefiere ejecutarlo como un servicio de segundo plano, puede ser iniciado desde el panel de control de servicios de windows.",
+ "HeaderIdentifyItem": "Identificar \u00cdtem",
"WindowsServiceIntro2": "Si utiliza el servicio de Windows, tenga en cuenta que no se puede ejecutar simult\u00e1neamiente con el icono en el \u00e1rea de notificaci\u00f3n, por lo que tendr\u00e1 que finalizar desde el icono para poder ejecutar el servicio. Adicionalmente, el servicio deber\u00e1 ser configurado con privilegios administrativos a trav\u00e9s del panel de control del servicio. Tenga en cuenta que en este momento el servicio no es capaz de actualizarse a s\u00ed mismo, por lo que las nuevas versiones requerir\u00e1n de interacci\u00f3n manual.",
+ "HeaderIdentifyItemHelp": "Ingrese uno o m\u00e1s criterios de b\u00fasqueda. Elimine criterios para expandir los resultados.",
"WizardCompleted": "Eso es todo lo que necesitamos por ahora. Media Browser ha comenzado a recolectar informaci\u00f3n sobre su biblioteca de medios. Eche un vistazo a algunas de nuestras aplicaciones, y luego haga clic en <b>Finalizar<\/b> para ver el <b>Panel de Control<\/b>.",
+ "HeaderConfirmDeletion": "Confirmar Eliminaci\u00f3n",
"LabelConfigureSettings": "Configuraci\u00f3n de opciones",
+ "LabelFollowingFileWillBeDeleted": "Lo siguiente ser\u00e1 eliminado:",
"LabelEnableVideoImageExtraction": "Habilitar extracci\u00f3n de im\u00e1genes de video",
+ "LabelIfYouWishToContinueWithDeletion": "Si desea continuar, por favor confirme ingresando el valor de:",
"VideoImageExtractionHelp": "Para videos que no cuenten con im\u00e1genes, y para los que no podemos encontrar im\u00e1genes en Internet. Esto incrementar\u00e1 un poco el tiempo de la exploraci\u00f3n inicial de las bibliotecas, pero resultar\u00e1 en una presentaci\u00f3n m\u00e1s agradable.",
+ "ButtonIdentify": "Identificar",
"LabelEnableChapterImageExtractionForMovies": "Extraer im\u00e1genes de cap\u00edtulos para Pel\u00edculas",
+ "LabelAlbumArtist": "Artista del \u00e1lbum:",
"LabelChapterImageExtractionForMoviesHelp": "Extraer im\u00e1genes de cap\u00edtulos permite a los clientes mostrar men\u00fas gr\u00e1ficos de selecci\u00f3n de escenas. El proceso puede ser lento, intensivo en utilizaci\u00f3n del CPU y puede requerir varios gigabytes de espacio. Se ejecuta como una tarea nocturna, programada a las 4 de la ma\u00f1ana, aunque esto se puede configurar en el \u00e1rea de tareas programadas. No se recomienda ejecutar esta tarea durante las horas pico de uso.",
+ "LabelAlbum": "\u00c1lbum",
"LabelEnableAutomaticPortMapping": "Habilitar mapeo autom\u00e1tico de puertos",
+ "LabelCommunityRating": "Calificaci\u00f3n de la comunidad:",
"LabelEnableAutomaticPortMappingHelp": "UPnP permite la configuraci\u00f3n de ruteador de manera autom\u00e1tica, para acceso remoto de manera f\u00e1cil. Eso puede no funcionar con algunos modelos de ruteadores.",
+ "LabelVoteCount": "Cantidad de votos:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metaescore:",
"ButtonCancel": "Cancelar",
+ "LabelCriticRating": "Calificaci\u00f3n de la cr\u00edtica:",
"ButtonNew": "Nuevo",
+ "LabelCriticRatingSummary": "Res\u00famen de la calificaci\u00f3n de la cr\u00edtica:",
"HeaderSetupLibrary": "Configurar su biblioteca de medios",
+ "LabelAwardSummary": "Res\u00famen de premios:",
"ButtonAddMediaFolder": "Agregar carpeta de medios",
+ "LabelWebsite": "Sitio web:",
"LabelFolderType": "Tipo de carpeta:",
+ "LabelTagline": "Eslogan",
"MediaFolderHelpPluginRequired": "* Requiere el uso de un complemento, p. ej. GameBrowser o MB Bookshelf.",
+ "LabelOverview": "Sinopsis:",
"ReferToMediaLibraryWiki": "Consultar la wiki de la biblioteca de medios.",
+ "LabelShortOverview": "Sinopsis corta:",
"LabelCountry": "Pa\u00eds:",
+ "LabelReleaseDate": "Fecha de estreno:",
"LabelLanguage": "Idioma:",
+ "LabelYear": "A\u00f1o:",
"HeaderPreferredMetadataLanguage": "Idioma preferido para metadatos:",
+ "LabelPlaceOfBirth": "Lugar de nacimiento:",
"LabelSaveLocalMetadata": "Guardar im\u00e1genes y metadatos en las carpetas de medios",
+ "LabelEndDate": "Fecha de Fin:",
"LabelSaveLocalMetadataHelp": "Guardar im\u00e1genes y metadatos directamente en las carpetas de medios los colocar\u00e1 en un lugar donde se pueden editar f\u00e1cilmente.",
- "LabelDownloadInternetMetadata": "Descargar imagenes y metadatos de internet",
+ "LabelAirDate": "D\u00edas al aire:",
+ "LabelDownloadInternetMetadata": "Descargar im\u00e1genes y metadatos de internet",
+ "LabelAirTime:": "Tiempo al \u00e1ire:",
"LabelDownloadInternetMetadataHelp": "Media Browser permite descargar informaci\u00f3n de sus medios para enriquecer la presentaci\u00f3n.",
+ "LabelRuntimeMinutes": "Duraci\u00f3n (minutos):",
"TabPreferences": "Preferencias",
+ "LabelParentalRating": "Calificaci\u00f3n parental:",
"TabPassword": "Contrase\u00f1a",
+ "LabelCustomRating": "Calificaci\u00f3n personalizada:",
"TabLibraryAccess": "Acceso a biblioteca",
+ "LabelBudget": "Presupuesto",
"TabImage": "Imagen",
+ "LabelRevenue": "Ingresos ($):",
"TabProfile": "Perf\u00edl",
+ "LabelOriginalAspectRatio": "Relaci\u00f3n de aspecto original:",
"TabMetadata": "Metadatos",
+ "LabelPlayers": "Jugadores:",
"TabImages": "Im\u00e1genes",
+ "Label3DFormat": "Formato 3D:",
"TabNotifications": "Notificaciones",
+ "HeaderAlternateEpisodeNumbers": "N\u00fameros de Episodio Alternativos:",
"TabCollectionTitles": "T\u00edtulos",
+ "HeaderSpecialEpisodeInfo": "Informaci\u00f3n del Episodio Especial",
"LabelDisplayMissingEpisodesWithinSeasons": "Mostar episodios no disponibles en las temporadas",
+ "HeaderExternalIds": "Id\u00b4s Externos:",
"LabelUnairedMissingEpisodesWithinSeasons": "Mostrar episodios a\u00fan no emitidos en las temporadas",
+ "LabelDvdSeasonNumber": "N\u00famero de temporada del DVD:",
"HeaderVideoPlaybackSettings": "Ajustes de Reproducci\u00f3n de Video",
+ "LabelDvdEpisodeNumber": "N\u00famero de episodio de DVD:",
"HeaderPlaybackSettings": "Configuraci\u00f3n de Reproducci\u00f3n",
+ "LabelAbsoluteEpisodeNumber": "N\u00famero de episodio absoluto:",
"LabelAudioLanguagePreference": "Preferencia de idioma de audio:",
+ "LabelAirsBeforeSeason": "Transmisi\u00f3n antes de la temporada:",
"LabelSubtitleLanguagePreference": "Preferencia de idioma de subt\u00edtulos:",
+ "LabelAirsAfterSeason": "Transmisi\u00f3n despu\u00e9s de la temporada:",
"OptionDefaultSubtitles": "Por Defecto",
+ "LabelAirsBeforeEpisode": "Transmisi\u00f3n antes del episodio:",
"OptionOnlyForcedSubtitles": "\u00danicamente subt\u00edtulos forzados",
+ "LabelTreatImageAs": "Tratar imagen como:",
"OptionAlwaysPlaySubtitles": "Siempre mostrar subt\u00edtulos",
+ "LabelDisplayOrder": "Ordenamiento de despliegue:",
"OptionNoSubtitles": "Sin Subtitulos",
+ "LabelDisplaySpecialsWithinSeasons": "Desplegar especiales dentro de las temporadas en que fueron transmitidos",
"OptionDefaultSubtitlesHelp": "Los subt\u00edtulos que coincidan con el lenguaje preferido ser\u00e1n cargados cuando el audio se encuentre en un lenguaje extranjero.",
+ "HeaderCountries": "Pa\u00edses",
"OptionOnlyForcedSubtitlesHelp": "Se cargar\u00e1n \u00fanicamente subt\u00edtulos marcados como forzados.",
+ "HeaderGenres": "G\u00e9neros",
"OptionAlwaysPlaySubtitlesHelp": "Los subt\u00edtulos que coincidan con el lenguaje preferido ser\u00e1n cargados independientemente del lenguaje del audio.",
+ "HeaderPlotKeywords": "Palabras clave de la Trama",
"OptionNoSubtitlesHelp": "Los subt\u00edtulos no ser\u00e1n cargados por defecto.",
+ "HeaderStudios": "Estudios",
"TabProfiles": "Perfiles",
+ "HeaderTags": "Etiquetas",
"TabSecurity": "Seguridad",
+ "HeaderMetadataSettings": "Configuraciones de los metadatos",
"ButtonAddUser": "Agregar Usuario",
+ "LabelLockItemToPreventChanges": "Bloquear este \u00edtem para evitar cambios futuros",
"ButtonSave": "Guardar",
+ "MessageLeaveEmptyToInherit": "Dejar vac\u00edo para heredar la configuraci\u00f3n del \u00edtem padre, o el valor global por omisi\u00f3n.",
"ButtonResetPassword": "Restablecer Contrase\u00f1a",
+ "TabSupporterClub": "Club de Aficionados",
"LabelNewPassword": "Nueva contrase\u00f1a:",
+ "HeaderDonationType": "Tipo de Donaci\u00f3n:",
"LabelNewPasswordConfirm": "Confirmaci\u00f3n de contrase\u00f1a nueva:",
+ "OptionMakeOneTimeDonation": "Hacer una donaci\u00f3n \u00fanica",
"HeaderCreatePassword": "Crear Contrase\u00f1a",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Contrase\u00f1a actual:",
+ "OptionLifeTimeSupporterClubMembership": "Membres\u00eda vitalicia del club de aficionados",
"LabelMaxParentalRating": "M\u00e1xima clasificaci\u00f3n parental permitida:",
+ "HeaderSupporterBenefit": "Convertirse en un miembro del club de aficionados proporciona beneficios adicionales tales como acceso a complementos premium, contenido de canales de internet y m\u00e1s.",
"MaxParentalRatingHelp": "El contenido con clasificaci\u00f3n parental superior se ocultar\u00e1 para este usuario.",
+ "OptionNoTrailer": "Sin Avance",
"LibraryAccessHelp": "Seleccione las carpetas de medios para compartir con este usuario. Los administradores podr\u00e1n editar todas las carpetas usando el administrador de metadatos.",
+ "OptionNoThemeSong": "Sin Canci\u00f3n del Tema",
"ChannelAccessHelp": "Seleccione los canales a compartir con este usuario. Los administradores podr\u00e1n editar todos los canales empleando el administrador de metadatos.",
+ "OptionNoThemeVideo": "Sin Video del Tema",
"ButtonDeleteImage": "Eliminar Imagen",
+ "LabelOneTimeDonationAmount": "Cantidad a donar:",
"LabelSelectUsers": "Seleccionar Usuarios:",
+ "OptionActor": "Actor",
"ButtonUpload": "Subir",
+ "OptionComposer": "Compositor",
"HeaderUploadNewImage": "Subir Nueva Imagen",
- "LabelDropImageHere": "Depositar Imagen Aqu\u00ed",
+ "OptionDirector": "Director",
+ "LabelDropImageHere": "Depositar imagen aqu\u00ed",
+ "OptionGuestStar": "Estrella invitada",
"ImageUploadAspectRatioHelp": "Se Recomienda una Proporci\u00f3n de Aspecto 1:1. Solo JPG\/PNG.",
+ "OptionProducer": "Productor",
"MessageNothingHere": "Nada aqu\u00ed.",
+ "OptionWriter": "Escritor",
"MessagePleaseEnsureInternetMetadata": "Por favor aseg\u00farese que la descarga de metadatos de internet esta habilitada.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Sugerencias",
+ "LabelAirTime": "Air time:",
"TabLatest": "Recientes",
- "TabUpcoming": "Pr\u00f3ximo Estreno",
+ "HeaderMediaInfo": "Media Info",
+ "TabUpcoming": "Por Estrenar",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Programas",
"TabEpisodes": "Episodios",
"TabGenres": "G\u00e9neros",
@@ -163,10 +225,10 @@
"OptionAscending": "Ascendente",
"OptionDescending": "Descendente",
"OptionRuntime": "Duraci\u00f3n",
- "OptionReleaseDate": "Fecha de Estreno",
+ "OptionReleaseDate": "Release Date",
"OptionPlayCount": "N\u00famero de Reproducc.",
"OptionDatePlayed": "Fecha de Reproducci\u00f3n",
- "OptionDateAdded": "A\u00f1adido el",
+ "OptionDateAdded": "Fecha de Adici\u00f3n",
"OptionAlbumArtist": "Artista del \u00c1lbum",
"OptionArtist": "Artista",
"OptionAlbum": "\u00c1lbum",
@@ -182,7 +244,7 @@
"OptionThumb": "Miniatura",
"OptionBanner": "T\u00edtulo",
"OptionCriticRating": "Calificaci\u00f3n de la Cr\u00edtica",
- "OptionVideoBitrate": "Tasa de Bits de Video",
+ "OptionVideoBitrate": "Tasa de bits de Video",
"OptionResumable": "Reanudable",
"ScheduledTasksHelp": "Da click en una tarea para ajustar su programaci\u00f3n.",
"ScheduledTasksTitle": "Tareas Programadas",
@@ -213,6 +275,8 @@
"TabMovies": "Pel\u00edculas",
"TabStudios": "Estudios",
"TabTrailers": "Avances",
+ "LabelArtists": "Artistas:",
+ "LabelArtistsHelp": "Separar m\u00faltiples empleando:",
"HeaderLatestMovies": "Pel\u00edculas Recientes",
"HeaderLatestTrailers": "Avances Recientes",
"OptionHasSpecialFeatures": "Caracter\u00edsticas Especiales",
@@ -224,7 +288,7 @@
"HeaderStatus": "Estado",
"OptionContinuing": "Continuando",
"OptionEnded": "Finalizado",
- "HeaderAirDays": "D\u00edas de Emisi\u00f3n:",
+ "HeaderAirDays": "D\u00edas de Emisi\u00f3n",
"OptionSunday": "Domingo",
"OptionMonday": "Lunes",
"OptionTuesday": "Martes",
@@ -232,7 +296,8 @@
"OptionThursday": "Jueves",
"OptionFriday": "Viernes",
"OptionSaturday": "S\u00e1bado",
- "HeaderManagement": "Administraci\u00f3n:",
+ "HeaderManagement": "Administraci\u00f3n",
+ "LabelManagement": "Administraci\u00f3n:",
"OptionMissingImdbId": "Falta Id de IMDb",
"OptionMissingTvdbId": "Falta Id de TheTVDB",
"OptionMissingOverview": "Falta Sinopsis",
@@ -266,9 +331,8 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "Seleccionar",
- "ButtonSearch": "B\u00fasqueda",
"ButtonGroupVersions": "Agrupar Versiones",
- "ButtonAddToCollection": "Agregar a Colecci\u00f3n.",
+ "ButtonAddToCollection": "Agregar a Colecci\u00f3n",
"PismoMessage": "Utilizando Pismo File Mount a trav\u00e9s de una licencia donada.",
"TangibleSoftwareMessage": "Utilizando convertidores Java\/C# de Tangible Solutions por medio de una licencia donada.",
"HeaderCredits": "Cr\u00e9ditos",
@@ -290,13 +354,13 @@
"ButtonSelectDirectory": "Seleccionar Carpeta",
"LabelCustomPaths": "Especificar rutas personalizadas cuando se desee. Deje los campos vac\u00edos para usar los valores predeterminados.",
"LabelCachePath": "Ruta para el Cach\u00e9:",
- "LabelCachePathHelp": "Esta carpeta contiene los archivos de cach\u00e9 del servidor, por ejemplo im\u00e1genes.",
+ "LabelCachePathHelp": "Especifique una ubicaci\u00f3n personalizada para los archivos de cach\u00e9 del servidor, tales como im\u00e1genes.",
"LabelImagesByNamePath": "Ruta para Im\u00e1genes por nombre:",
- "LabelImagesByNamePathHelp": "Esta carpeta contiene im\u00e1genes de actor, artista, g\u00e9nero y estudio.",
+ "LabelImagesByNamePathHelp": "Especifique una ubicaci\u00f3n personalizada para im\u00e1genes descargadas de actores, artistas, g\u00e9neros y estudios.",
"LabelMetadataPath": "Ruta para metadatos:",
- "LabelMetadataPathHelp": "Esta ubicaci\u00f3n contiene ilustraciones descargadas y metadatos cuando no han sido configurados para almacenarse en carpetas de medios.",
+ "LabelMetadataPathHelp": "Especifique una ubicaci\u00f3n personalizada para ilustraciones descargadas y metadatos cuando no han sido configurados para almacenarse en carpetas de medios.",
"LabelTranscodingTempPath": "Ruta para transcodificaci\u00f3n temporal:",
- "LabelTranscodingTempPathHelp": "Esta carpeta contiene archivos de trabajo usados por el transcodificador.",
+ "LabelTranscodingTempPathHelp": "Esta carpeta contiene archivos de trabajo usados por el transcodificador. Especifique una trayectoria personalizada, o d\u00e9jela vac\u00eda para utilizar su valor por omisi\u00f3n en la carpeta de datos del servidor.",
"TabBasics": "B\u00e1sicos",
"TabTV": "TV",
"TabGames": "Juegos",
@@ -313,12 +377,12 @@
"LabelAutomaticUpdatesFanartHelp": "Al habilitarlo, se descargar\u00e1n autom\u00e1ticamente nuevas im\u00e1genes conforme son a\u00f1adidas a fanart.tv. Las Im\u00e1genes existentes no ser\u00e1n reemplazadas.",
"LabelAutomaticUpdatesTmdbHelp": "Al habilitarlo, se descargar\u00e1n autom\u00e1ticamente nuevas im\u00e1genes conforme son a\u00f1adidas a TheMovieDB.org. Las im\u00e1genes existentes no ser\u00e1n reemplazadas.",
"LabelAutomaticUpdatesTvdbHelp": "Al habilitarlo, se descargar\u00e1n autom\u00e1ticamente nuevas im\u00e1genes conforme son a\u00f1adidas a TheTVDB.com. Las im\u00e1genes existentes no ser\u00e1n reemplazadas.",
- "ExtractChapterImagesHelp": "Extraer im\u00e1genes de cap\u00edtulos permite a los clientes mostrar men\u00fas gr\u00e1ficos de selecci\u00f3n de escenas. El proceso puede ser lento, intensivo en utilizaci\u00f3n del CPU y puede requerir varios gigabytes de espacio. Se ejecuta como una tarea nocturna, programada a las 4 de la ma\u00f1ana, aunque esto se puede configurar en el \u00e1rea de tareas programadas. No se recomienda ejecutar esta tarea durante las horas pico de uso.",
+ "ExtractChapterImagesHelp": "Extraer im\u00e1genes de cap\u00edtulos permite a los clientes mostrar men\u00fas gr\u00e1ficos de selecci\u00f3n de escenas. El proceso puede ser lento, intensivo en utilizaci\u00f3n del CPU y puede requerir varios gigabytes de espacio. Se ejecuta cuando se detectan nuevos videos, tambi\u00e9n como una tarea nocturna, programada a las 4:00 am. La programaci\u00f3n puede configurarse en el \u00e1rea de tareas programadas. No se recomienda ejecutar esta tarea durante horas pico de uso.",
"LabelMetadataDownloadLanguage": "Lenguaje preferido para descargas:",
"ButtonAutoScroll": "Auto-desplazamiento",
"LabelImageSavingConvention": "Convenci\u00f3n de almacenamiento de im\u00e1genes:",
"LabelImageSavingConventionHelp": "MediaBrowser reconoce im\u00e1genes de las aplicaciones de medios m\u00e1s importantes. Seleccionar la convenci\u00f3n de descarga es \u00fatil si utiliza otros productos.",
- "OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
"OptionImageSavingStandard": "Est\u00e1ndar - MB2",
"ButtonSignIn": "Iniciar Sesi\u00f3n",
"TitleSignIn": "Iniciar Sesi\u00f3n",
@@ -347,6 +411,8 @@
"TabStatus": "Estado",
"TabSettings": "Configuraci\u00f3n",
"ButtonRefreshGuideData": "Actualizar Datos de la Gu\u00eda",
+ "ButtonRefresh": "Actualizar",
+ "ButtonAdvancedRefresh": "Actualizaci\u00f3n Avanzada",
"OptionPriority": "Prioridad",
"OptionRecordOnAllChannels": "Grabar programa en todos los canales",
"OptionRecordAnytime": "Grabar programa en cualquier momento",
@@ -387,9 +453,9 @@
"LabelMaxScreenshotsPerItem": "N\u00famero m\u00e1ximo de capturas de pantalla por \u00edtem:",
"LabelMinBackdropDownloadWidth": "Anchura m\u00ednima de descarga de im\u00e1genes de fondo:",
"LabelMinScreenshotDownloadWidth": "Anchura m\u00ednima de descarga de capturas de pantalla:",
- "ButtonAddScheduledTaskTrigger": "A\u00f1adir Evento",
- "HeaderAddScheduledTaskTrigger": "A\u00f1adir Evento",
- "ButtonAdd": "A\u00f1adir",
+ "ButtonAddScheduledTaskTrigger": "Agregar Disparador de Tarea",
+ "HeaderAddScheduledTaskTrigger": "Agregar Disparador de Tarea",
+ "ButtonAdd": "Agregar",
"LabelTriggerType": "Tipo de Evento:",
"OptionDaily": "Diario",
"OptionWeekly": "Semanal",
@@ -405,7 +471,7 @@
"HeaderGallery": "Galer\u00eda",
"HeaderLatestGames": "Juegos Recientes",
"HeaderRecentlyPlayedGames": "Juegos Usados Recientemente",
- "TabGameSystems": "Sistemas de Juego",
+ "TabGameSystems": "Sistemas de Juegos",
"TitleMediaLibrary": "Biblioteca de Medios",
"TabFolders": "Carpetas",
"TabPathSubstitution": "Rutas Alternativas",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Reparto y Personal",
"HeaderAdditionalParts": "Partes Adicionales",
"ButtonSplitVersionsApart": "Separar Versiones",
+ "ButtonPlayTrailer": "Avance",
"LabelMissing": "Falta",
"LabelOffline": "Desconectado",
"PathSubstitutionHelp": "Las rutas alternativas se utilizan para mapear una ruta en el servidor a la que los clientes puedan acceder. Al permitir a los clientes acceder directamente a los medios en el servidor podr\u00e1n reproducirlos directamente a trav\u00e9s de la red evitando el uso de recursos del servidor para transmitirlos y transcodificarlos.",
@@ -439,7 +506,7 @@
"LabelFromHelp": "Ejemplo: D:\\Pel\u00edculas (en el servidor)",
"LabelTo": "Hasta:",
"LabelToHelp": "Ejemplo: \\\\MiServidor\\Pel\u00edculas (una ruta a la que los clientes pueden acceder)",
- "ButtonAddPathSubstitution": "A\u00f1adir Ruta Alternativa",
+ "ButtonAddPathSubstitution": "Agregar Ruta Alternativa",
"OptionSpecialEpisode": "Especiales",
"OptionMissingEpisode": "Episodios Faltantes",
"OptionUnairedEpisode": "Episodios no Emitidos",
@@ -458,7 +525,7 @@
"OptionEnableDebugTranscodingLoggingHelp": "Esto crear\u00e1 archivos de bit\u00e1cora muy grandes y solo se recomienda cuando se requiera solucionar problemas.",
"OptionUpscaling": "Permitir que los clientes solicitar v\u00eddeo de escala aumentada",
"OptionUpscalingHelp": "En algunos casos esto resultar\u00e1 en una mejora de la calidad del video pero incrementar\u00e1 el uso del CPU.",
- "EditCollectionItemsHelp": "A\u00f1adir o quitar pel\u00edculas, series, discos, libros o juegos que usted desee agrupar dentro de esta colecci\u00f3n.",
+ "EditCollectionItemsHelp": "Agregar o quitar pel\u00edculas, series, discos, libros o juegos que usted desee agrupar dentro de esta colecci\u00f3n.",
"HeaderAddTitles": "Agregar T\u00edtulos",
"LabelEnableDlnaPlayTo": "Habilitar \"Reproducir en\" por DLNA",
"LabelEnableDlnaPlayToHelp": "Media Browser puede detectar dispositivos en su red y ofrecer la posibilidad de controlarlos remotamente.",
@@ -494,15 +561,15 @@
"LabelEnableAutomaticPortHelp": "UPnP permite la configuraci\u00f3n autom\u00e1tica del router para acceso remoto. Esto puede no funcionar en algunos modelos de routers.",
"LabelExternalDDNS": "DDNS Externo:",
"LabelExternalDDNSHelp": "Si dispone de una DNS din\u00e1mica, introducirla aqu\u00ed. Media Brower la utilizar\u00e1 para las conexiones remotas.",
- "TabResume": "Reanudar",
+ "TabResume": "Continuar",
"TabWeather": "El tiempo",
"TitleAppSettings": "Configuraci\u00f3n de la App",
- "LabelMinResumePercentage": "Porcentaje m\u00ednimo para reanudaci\u00f3n:",
- "LabelMaxResumePercentage": "Porcentaje m\u00e1ximo para reanudaci\u00f3n:",
- "LabelMinResumeDuration": "Duraci\u00f3n m\u00ednima de reanudaci\u00f3n (segundos):",
+ "LabelMinResumePercentage": "Porcentaje m\u00ednimo para continuar:",
+ "LabelMaxResumePercentage": "Porcentaje m\u00e1ximo para continuar:",
+ "LabelMinResumeDuration": "Duraci\u00f3n m\u00ednima para continuar (segundos):",
"LabelMinResumePercentageHelp": "Se asumir\u00e1 que los t\u00edtulos no han sido reproducidos si se detienen antes de este momento",
"LabelMaxResumePercentageHelp": "Se asumir\u00e1 que los t\u00edtulos han sido reproducidos por completo si se detienen despu\u00e9s de este momento",
- "LabelMinResumeDurationHelp": "Los titulos con duraci\u00f3n menor a esto no podr\u00e1n ser reanudados",
+ "LabelMinResumeDurationHelp": "Los titulos con duraci\u00f3n menor a esto no podr\u00e1n ser continuados",
"TitleAutoOrganize": "Auto-Organizar",
"TabActivityLog": "Bit\u00e1cora de Actividades",
"HeaderName": "Nombre",
@@ -512,11 +579,13 @@
"HeaderProgram": "Programa",
"HeaderClients": "Clientes",
"LabelCompleted": "Completado",
+ "LabelFailed": "Fallido",
"LabelSkipped": "Omitido",
"HeaderEpisodeOrganization": "Organizaci\u00f3n de Episodios",
- "LabelSeasonNumber": "N\u00famero de temporada",
- "LabelEpisodeNumber": "N\u00famero de episodio",
- "LabelEndingEpisodeNumber": "N\u00famero episodio final",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "N\u00famero de temporada:",
+ "LabelEpisodeNumber": "N\u00famero de episodio:",
+ "LabelEndingEpisodeNumber": "N\u00famero episodio final:",
"LabelEndingEpisodeNumberHelp": "S\u00f3lo requerido para archivos multi-episodio",
"HeaderSupportTheTeam": "Apoye al Equipo de Media Browser",
"LabelSupportAmount": "Importe (USD)",
@@ -618,14 +687,13 @@
"NotificationOptionGamePlaybackStopped": "Ejecuci\u00f3n de juego detenida",
"NotificationOptionTaskFailed": "Falla de tarea programada",
"NotificationOptionInstallationFailed": "Falla de instalaci\u00f3n",
- "NotificationOptionNewLibraryContent": "Adici\u00f3n de nuevos contenidos",
- "NotificationOptionNewLibraryContentMultiple": "Nuevo contenido agregado (varios).",
+ "NotificationOptionNewLibraryContent": "Nuevo contenido agregado",
+ "NotificationOptionNewLibraryContentMultiple": "Nuevo contenido agregado (varios)",
"SendNotificationHelp": "Por defecto, las notificaciones son enviadas a la bandeja de entrada del panel de control. Navegue el cat\u00e1logo de complementos para instalar opciones de notificaci\u00f3n adicionales.",
"NotificationOptionServerRestartRequired": "Reinicio del servidor requerido",
"LabelNotificationEnabled": "Habilitar esta notificaci\u00f3n",
"LabelMonitorUsers": "Monitorear actividad desde:",
"LabelSendNotificationToUsers": "Enviar la notificaci\u00f3n a:",
- "UsersNotNotifiedAboutSelfActivity": "Los usuarios no ser\u00e1n notificados sobre sus propias actividades.",
"LabelUseNotificationServices": "Utilizar los siguientes servicios:",
"CategoryUser": "Usuario",
"CategorySystem": "Sistema",
@@ -648,6 +716,7 @@
"ButtonPageDown": "P\u00e1gina abajo",
"PageAbbreviation": "Pag.",
"ButtonHome": "Inicio",
+ "ButtonSearch": "B\u00fasqueda",
"ButtonSettings": "Configuraci\u00f3n",
"ButtonTakeScreenshot": "Capturar Pantalla",
"ButtonLetterUp": "Siguiente letra",
@@ -657,10 +726,12 @@
"TabNowPlaying": "Reproduci\u00e9ndo Ahora",
"TabNavigation": "Navegaci\u00f3n",
"TabControls": "Controles",
- "ButtonFullscreen": "Alternar pantalla completa",
+ "ButtonFullscreen": "Cambiar a pantalla completa",
"ButtonScenes": "Escenas",
"ButtonSubtitles": "Subt\u00edtulos",
"ButtonAudioTracks": "Pistas de audio",
+ "ButtonPreviousTrack": "Pista anterior",
+ "ButtonNextTrack": "Pista siguiente",
"ButtonStop": "Detener",
"ButtonPause": "Pausar",
"LabelGroupMoviesIntoCollections": "Agrupar pel\u00edculas en colecciones",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separados por comas. Puede dejarse vaci\u00f3 para aplicarlo a todos los contenedores.",
"HeaderResponseProfile": "Perfil de Respuesta:",
"LabelType": "Tipo:",
+ "LabelPersonRole": "Rol:",
+ "LabelPersonRoleHelp": "El Rol generalmente solo aplica a actores.",
"LabelProfileContainer": "Contenedor:",
"LabelProfileVideoCodecs": "Codecs de Video:",
"LabelProfileAudioCodecs": "Codecs de Audio:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "Estos valores controlan la manera en que Media Browser se presentar\u00e1 a s\u00ed mismo ante el dispositivo.",
"LabelMaxBitrate": "Tasa de bits m\u00e1xima:",
"LabelMaxBitrateHelp": "Especifique la tasa de bits m\u00e1xima para ambientes con un ancho de banda limitado, o si el dispositivo impone sus propios l\u00edmites.",
+ "LabelMaxStreamingBitrate": "Tasa de bits m\u00e1xima para transmisi\u00f3n:",
+ "LabelMaxStreamingBitrateHelp": "Especifique una tasa de bits m\u00e1xima al transferir en tiempo real.",
+ "LabelMaxStaticBitrate": "Tasa m\u00e1xima de bits de sinc",
+ "LabelMaxStaticBitrateHelp": "Especifique una tasa de bits cuando se sincronice contenido en alta calidad.",
+ "LabelMusicStaticBitrate": "Tasa de bits de sinc de m\u00fascia",
+ "LabelMusicStaticBitrateHelp": "Especifique la tasa de bits m\u00e1xima al sincronizar m\u00fasica",
+ "LabelMusicStreamingTranscodingBitrate": "Tasa de transcodificaci\u00f3n de m\u00fasica:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Especifique la tasa de bits m\u00e1xima al transferir musica en tiempo real",
"OptionIgnoreTranscodeByteRangeRequests": "Ignorar solicitudes de transcodificaci\u00f3n de rango de byte.",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "Si se habilita, estas solicitudes seran honradas pero se ignorar\u00e1 el encabezado de rango de byte.",
"LabelFriendlyName": "Nombre amistoso:",
@@ -731,8 +812,8 @@
"LabelSerialNumber": "N\u00famero de serie:",
"LabelDeviceDescription": "Descripci\u00f3n del dispositivo",
"HeaderIdentificationCriteriaHelp": "Capture, al menos, un criterio de identificaci\u00f3n.",
- "HeaderDirectPlayProfileHelp": "A\u00f1ada perfiles de reproducci\u00f3n directa para indicar que formatos puede manejar el dispositivo de manera nativa.",
- "HeaderTranscodingProfileHelp": "A\u00f1ada perfiles de transcodificaci\u00f3n para indicar que formatos deben ser usados cuando se requiera transcodificar.",
+ "HeaderDirectPlayProfileHelp": "Agregue perfiles de reproducci\u00f3n directa para indicar que formatos puede manejar el dispositivo de manera nativa.",
+ "HeaderTranscodingProfileHelp": "Agruegue perfiles de transcodificaci\u00f3n para indicar que formatos deben ser usados cuando se requiera transcodificar.",
"HeaderResponseProfileHelp": "Los perfiles de respuesta proporcionan un medio para personalizar la informaci\u00f3n enviada a un dispositivo cuando se reproducen ciertos tipos de medios.",
"LabelXDlnaCap": "X-DLNA cap:",
"LabelXDlnaCapHelp": "Determina el contenido del elemento X_DLNACAP en el namespace urn:schemas-dlna-org:device-1-0.",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Desplegar complementos para:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Otros",
- "LabelEpisodeName": "Nombre del episodio",
- "LabelSeriesName": "Nombre de la serie",
+ "LabelEpisodeNamePlain": "Nombre del episodio",
+ "LabelSeriesNamePlain": "Nombre de la serie",
"ValueSeriesNamePeriod": "Nombre.serie",
"ValueSeriesNameUnderscore": "Nombre_serie",
"ValueEpisodeNamePeriod": "Nombre del episodio",
"ValueEpisodeNameUnderscore": "Nombre_episodio",
+ "LabelSeasonNumberPlain": "N\u00famero de temporada",
+ "LabelEpisodeNumberPlain": "N\u00famero de episodio",
+ "LabelEndingEpisodeNumberPlain": "N\u00famero del episodio final",
"HeaderTypeText": "Capturar Texto",
"LabelTypeText": "Texto",
"HeaderSearchForSubtitles": "Buscar Subtitulos",
@@ -796,14 +879,14 @@
"OptionAuto": "Autom\u00e1tico",
"OptionYes": "Si",
"OptionNo": "No",
- "LabelHomePageSection1": "Pagina principal secci\u00f3n uno:",
- "LabelHomePageSection2": "Pagina principal secci\u00f3n dos:",
- "LabelHomePageSection3": "Pagina principal secci\u00f3n tres:",
- "LabelHomePageSection4": "Pagina principal secci\u00f3n cuatro:",
- "OptionMyLibraryButtons": "Mi Biblioteca (botones)",
- "OptionMyLibrary": "Mi Biblioteca",
- "OptionMyLibrarySmall": "Mi Biblioteca (peque\u00f1o)",
- "OptionResumablemedia": "Reanudar",
+ "LabelHomePageSection1": "Pagina de Inicio secci\u00f3n uno:",
+ "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)",
+ "OptionResumablemedia": "Continuar",
"OptionLatestMedia": "Agregados recientemente",
"OptionLatestChannelMedia": "Elementos recientes de canales",
"HeaderLatestChannelItems": "Elementos Recientes de Canales",
@@ -813,25 +896,28 @@
"HeaderMetadataManager": "Administrador de Metadatos",
"HeaderPreferences": "Preferencias",
"MessageLoadingChannels": "Cargando contenidos del canal...",
+ "MessageLoadingContent": "Cargando contenido...",
"ButtonMarkRead": "Marcar como Le\u00eddo",
"OptionDefaultSort": "Por defecto",
"OptionCommunityMostWatchedSort": "M\u00e1s Visto",
"TabNextUp": "A Continuaci\u00f3n",
"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 te permiten disfrutar de grupos personalizados de Pel\u00edculas, Series, \u00c1lbumes, Libros y Juegos. Da clic en el bot\u00f3n \"Nuevo\" para empezar a crear colecciones.",
+ "MessageNoPlaylistsAvailable": "Las listas de reproducci\u00f3n le permiten crear listas de contenidos a ser reproducidos de manera consecutiva. Para a\u00f1adir \u00edtems a una lista de reproducci\u00f3n, haga click derecho o seleccione y mantenga, despu\u00e9s seleccione A\u00f1adir a Lista de Reproducci\u00f3n.",
+ "MessageNoPlaylistItemsAvailable": "Esta lista de reproducci\u00f3n se encuentra vac\u00eda.",
"HeaderWelcomeToMediaBrowserWebClient": "Bienvenido al Cliente Web de Media Browser",
"ButtonDismiss": "Descartar",
"MessageLearnHowToCustomize": "Aprenda c\u00f3mo personalizar esta p\u00e1gina a sus gustos personales. Haga clic en su icono de usuario en la esquina superior derecha de la pantalla para ver y actualizar sus preferencias.",
"ButtonEditOtherUserPreferences": "Edita las preferencias personales de este usuario.",
"LabelChannelStreamQuality": "Calidad por defecto para transmisi\u00f3n por internet:",
- "LabelChannelStreamQualityHelp": "En un ambiente de ancho de banda limitados, limitar la calidad puede ayudar a asegurar una experiencia de transimisi\u00f3n fluida.",
+ "LabelChannelStreamQualityHelp": "En un ambiente de ancho de banda limitado, limitar la calidad puede ayudar a asegurar una experiencia de transimisi\u00f3n en tiempo real fluida.",
"OptionBestAvailableStreamQuality": "La mejor disponible",
"LabelEnableChannelContentDownloadingFor": "Habilitar descarga de contenidos del canal para:",
"LabelEnableChannelContentDownloadingForHelp": "Algunos canales soportan la descarga de contenido previo a su despliegue. Habilite esto en ambientes de ancho de banda limitados para descargar contenido del canal en horarios no pico. El contenido es descargado como parte de la tarea programada para descarga del canal.",
"LabelChannelDownloadPath": "Ruta de descarga de contenido del canal:",
"LabelChannelDownloadPathHelp": "Especifique una ruta personalizada para descargas si as\u00ed lo desea. D\u00e9jelo vac\u00edo para descargar a una carpeta de datos interna del programa.",
"LabelChannelDownloadAge": "Eliminar contenido despu\u00e9s de: (d\u00edas)",
- "LabelChannelDownloadAgeHelp": "El contenido descargado anterior a esto ser\u00e1 eliminado. Permanecer\u00e1 reproducible via transmisi\u00f3n por Internet.",
+ "LabelChannelDownloadAgeHelp": "El contenido descargado anterior a esto ser\u00e1 eliminado. Permanecer\u00e1 reproducible via transmisi\u00f3n en tiempo real por Internet.",
"ChannelSettingsFormHelp": "Instale canales tales como Avances y Vimeo desde el cat\u00e1logo de complementos.",
"LabelSelectCollection": "Elegir colecci\u00f3n:",
"ViewTypeMovies": "Pel\u00edculas",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Desplegar contenido para Adultos",
"OptionLibraryFolders": "Carpetas de medios",
"TitleRemoteControl": "Control Remoto",
- "OptionLatestTvRecordings": "\u00daltimas grabaciones"
+ "OptionLatestTvRecordings": "\u00daltimas grabaciones",
+ "LabelProtocolInfo": "Informaci\u00f3n del protocolo:",
+ "LabelProtocolInfoHelp": "El valor que ser\u00e1 utilizado cuando se responde a solicitudes GetProtocolInfo desde el dispositivo.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser incluye soporte nativo para metadatos Nfo e im\u00e1genes de Xbmc. Para habilitar o deshabilitar metadatos de Xbmc, utilice la pesta\u00f1a Avanzado para configurar opciones para sus tipos de medios.",
+ "LabelXbmcMetadataUser": "Agregar usuario de monitoreo de datos a los nfo\u00b4s para:",
+ "LabelXbmcMetadataUserHelp": "Habilitar esto para mantener el monitoreo de datos en sincron\u00eda entre Media Browser y Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Formato de fecha de esteno:",
+ "LabelXbmcMetadataDateFormatHelp": "Todas las fechas en los archivos nfo's ser\u00e1n le\u00eddas y escritas empleando este formato.",
+ "LabelXbmcMetadataSaveImagePaths": "Guardar rutas de las im\u00e1genes dentro de los archivos nfo.",
+ "LabelXbmcMetadataSaveImagePathsHelp": "Esto se recomienda si usted tiene nombres de im\u00e1genes que no se ajustan a los lineamientos de Xbmc.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Habilitar sustituci\u00f3n de rutas.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Habilita la sustituci\u00f3n de rutas de las rutas de im\u00e1genes usando la configuraci\u00f3n de sustituci\u00f3n de rutas del servidor.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "Ver sustituci\u00f3n de rutas.",
+ "LabelGroupChannelsIntoViews": "Desplegar los siguientes canales directamente en mis vistas:",
+ "LabelGroupChannelsIntoViewsHelp": "Al habilitarse, estos canales ser\u00e1n desplegados directamente junto con otras vistas. Si permanecen deshabilitados, ser\u00e1n desplegados dentro de una vista independiente de Canales.",
+ "LabelDisplayCollectionsView": "Desplegar una vista de colecciones para mostrar las colecciones de pel\u00edculas",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copiar extrafanart en extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "Cuando se descargan im\u00e1genes \u00e9stas pueden ser almacenadas en extrafanart y extrathumbs para una m\u00e1xima compatibilidad con los skins de Xbmc.",
+ "TabServices": "Servicios",
+ "TabLogs": "Bit\u00e1coras",
+ "HeaderServerLogFiles": "Archivos de registro del servidor:",
+ "TabBranding": "Establecer Marca",
+ "HeaderBrandingHelp": "Personaliza la apariencia de Media Browser para ajustarla a las necesidades de tu grupo u organizaci\u00f3n.",
+ "LabelLoginDisclaimer": "Aviso de Inicio de Sesi\u00f3n:",
+ "LabelLoginDisclaimerHelp": "Esto se mostrara al final de la pagina de inicio de sesi\u00f3n.",
+ "LabelAutomaticallyDonate": "Donar autom\u00e1ticamente este monto cada mes",
+ "LabelAutomaticallyDonateHelp": "Puedes cancelarlo en cualquier momento por medio de tu cuenta PayPal.",
+ "OptionList": "Lista",
+ "TabDashboard": "Panel de Control",
+ "TitleServer": "Servidor",
+ "LabelCache": "Cach\u00e9:",
+ "LabelLogs": "Bit\u00e1coras:",
+ "LabelMetadata": "Metadatos:",
+ "LabelImagesByName": "Im\u00e1genes por nombre:",
+ "LabelTranscodingTemporaryFiles": "Archivos temporales de transcodificaci\u00f3n:",
+ "HeaderLatestMusic": "M\u00fasica Reciente",
+ "HeaderBranding": "Establecer Marca",
+ "HeaderApiKeys": "Llaves de API",
+ "HeaderApiKeysHelp": "Las aplicaciones externas requieren de una llave de API para comunicarse con Media Browser. Las llaves son otorgadas al iniciar sesi\u00f3n con una cuenta de Media Browser; o bien, otorgando manualmente una llave a la aplicaci\u00f3n.",
+ "HeaderApiKey": "Llave de API",
+ "HeaderApp": "App",
+ "HeaderDevice": "Dispositivo",
+ "HeaderUser": "Usuario",
+ "HeaderDateIssued": "Fecha de Emisi\u00f3n",
+ "LabelChapterName": "Cap\u00edtulo {0}",
+ "HeaderNewApiKey": "Nueva llave de API",
+ "LabelAppName": "Nombre del App",
+ "LabelAppNameExample": "Ejemplo: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Otorgar a la aplicaci\u00f3n persmiso para comunicarse con Media Browser.",
+ "HeaderHttpHeaders": "Encabezados Http",
+ "HeaderIdentificationHeader": "Encabezado de Identificaci\u00f3n",
+ "LabelValue": "Valor:",
+ "LabelMatchType": "Tipo de Coincidencia:",
+ "OptionEquals": "Igual a",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Subcadena",
+ "TabView": "Vista",
+ "TabSort": "Ordenaci\u00f3n",
+ "TabFilter": "Filtro",
+ "ButtonView": "Vista",
+ "LabelPageSize": "Cantidad de \u00cdtems:",
+ "LabelPath": "Trayectoria:",
+ "LabelView": "Vista:",
+ "TabUsers": "Usuarios",
+ "LabelSortName": "Nombre para ordenar:",
+ "LabelDateAdded": "Fecha de adici\u00f3n:",
+ "HeaderFeatures": "Caracter\u00edsticas",
+ "HeaderAdvanced": "Avanzado",
+ "ButtonSync": "Sinc",
+ "TabScheduledTasks": "Tareas Programadas",
+ "HeaderChapters": "Cap\u00edtulos",
+ "HeaderResumeSettings": "Configuraci\u00f3n para Continuar",
+ "TabSync": "Sinc",
+ "TitleUsers": "Usuarios",
+ "LabelProtocol": "Protocolo:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Transmisi\u00f3n en vivo por Http",
+ "LabelContext": "Contexto:",
+ "OptionContextStreaming": "Transmisi\u00f3n",
+ "OptionContextStatic": "Sinc.",
+ "ButtonAddToPlaylist": "A\u00f1adir a lista de reproducci\u00f3n",
+ "TabPlaylists": "Listas de reproducci\u00f3n",
+ "ButtonClose": "Cerrar",
+ "LabelAllLanguages": "Todos los lenguajes",
+ "HeaderBrowseOnlineImages": "Buscar Im\u00e1genes en L\u00ednea",
+ "LabelSource": "Fuente:",
+ "OptionAll": "Todos",
+ "LabelImage": "Im\u00e1gen:",
+ "ButtonBrowseImages": "Buscar im\u00e1genes",
+ "HeaderImages": "Im\u00e1genes",
+ "HeaderBackdrops": "Im\u00e1genes de fondo",
+ "HeaderScreenshots": "Capturas de pantalla",
+ "HeaderAddUpdateImage": "Agregar\/Actualizar Im\u00e1gen",
+ "LabelJpgPngOnly": "JPG\/PNG solamente",
+ "LabelImageType": "Tipo de Im\u00e1gen:",
+ "OptionPrimary": "Principal",
+ "OptionArt": "Arte",
+ "OptionBox": "Caja",
+ "OptionBoxRear": "Reverso de caja",
+ "OptionDisc": "Disco",
+ "OptionLogo": "Logotipo",
+ "OptionMenu": "Men\u00fa",
+ "OptionScreenshot": "Captura de pantalla",
+ "OptionLocked": "Bloqueado",
+ "OptionUnidentified": "No Identificado",
+ "OptionMissingParentalRating": "Falta clasificaci\u00f3n parental",
+ "OptionStub": "Plantilla",
+ "HeaderEpisodes": "Episodios:",
+ "OptionSeason0": "Temporada 0",
+ "LabelReport": "Reporte:",
+ "OptionReportSongs": "Canciones",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Temporadas",
+ "OptionReportTrailers": "Avances",
+ "OptionReportMusicVideos": "Videos Musicales",
+ "OptionReportMovies": "Pel\u00edculas",
+ "OptionReportHomeVideos": "Videos caseros",
+ "OptionReportGames": "Juegos",
+ "OptionReportEpisodes": "Episodios",
+ "OptionReportCollections": "Colecciones",
+ "OptionReportBooks": "Libros",
+ "OptionReportArtists": "Artistas",
+ "OptionReportAlbums": "\u00c1lbums",
+ "OptionReportAdultVideos": "Videos para Adultos",
+ "ButtonMore": "M\u00e1s",
+ "HeaderActivity": "Actividad",
+ "ScheduledTaskStartedWithName": "{0} Iniciado",
+ "ScheduledTaskCancelledWithName": "{0} fue cancelado",
+ "ScheduledTaskCompletedWithName": "{0} completado",
+ "ScheduledTaskFailed": "Tarea programada completada",
+ "PluginInstalledWithName": "{0} fue instalado",
+ "PluginUpdatedWithName": "{0} fue actualizado",
+ "PluginUninstalledWithName": "{0} fue desinstalado",
+ "ScheduledTaskFailedWithName": "{0} fall\u00f3",
+ "ItemAddedWithName": "{0} fue agregado a la biblioteca",
+ "ItemRemovedWithName": "{0} fue removido de la biblioteca",
+ "DeviceOnlineWithName": "{0} est\u00e1 conectado",
+ "UserOnlineFromDevice": "{0} est\u00e1 en l\u00ednea desde {1}",
+ "DeviceOfflineWithName": "{0} se ha desconectado",
+ "UserOfflineFromDevice": "{0} se ha desconecatdo desde {1}",
+ "SubtitlesDownloadedForItem": "Subt\u00edtulos descargados para {0}",
+ "SubtitleDownloadFailureForItem": "Fall\u00f3 la descarga de subt\u00edtulos para {0}",
+ "LabelRunningTimeValue": "Duraci\u00f3n: {0}",
+ "LabelIpAddressValue": "Direcci\u00f3n IP: {0}",
+ "UserConfigurationUpdatedWithName": "Se ha actualizado la configuraci\u00f3n del usuario {0}",
+ "UserCreatedWithName": "Se ha creado el usuario {0}",
+ "UserPasswordChangedWithName": "Se ha cambiado la contrase\u00f1a para el usuario {0}",
+ "UserDeletedWithName": "Se ha eliminado al usuario {0}",
+ "MessageServerConfigurationUpdated": "Se ha actualizado la configuraci\u00f3n del servidor",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Se ha actualizado la secci\u00f3n {0} de la configuraci\u00f3n del servidor",
+ "MessageApplicationUpdated": "Se ha actualizado el Servidor de Media Browser",
+ "AuthenticationSucceededWithUserName": "{0} autenticado con \u00e9xito",
+ "FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesi\u00f3n de {0}",
+ "UserStartedPlayingItemWithValues": "{0} ha iniciado la reproducci\u00f3n de {1}",
+ "UserStoppedPlayingItemWithValues": "{0} ha detenido la reproducci\u00f3n de {1}",
+ "AppDeviceValues": "App: {0}, Dispositivo: {1}",
+ "ProviderValue": "Proveedor: {0}",
+ "LabelChannelDownloadSizeLimit": "L\u00edmite de tama\u00f1o de descarga (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limitar el tama\u00f1o de la carpeta de descargas del canal",
+ "HeaderRecentActivity": "Actividad Reciente"
} \ 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 3975d5b43..f0d030f4d 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/fr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/fr.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Mises \u00e0 jour",
- "HeaderUpdateLevel": "Niveau de mise \u00e0 jour",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Les sous-titres son consid\u00e9r\u00e9s manquants lorsque la piste audio est dans une langue \u00e9trang\u00e8re, et qu'aucun sous-titre n'est disponible dans la langue pr\u00e9f\u00e9r\u00e9e.",
- "LabelDisplayForcedSubtitlesOnly": "Afficher seulement les sous-titres forc\u00e9s",
- "HeaderCustomizeOptionsPerMediaType": "Personnaliser les param\u00e8tres par type de m\u00e9dias",
- "LabelAudioLanguagePreferenceHelp": "Si laiss\u00e9 vide, la piste audio par d\u00e9faut sera s\u00e9lectionn\u00e9e, peu importe la langue.",
- "TabCustomizations": "Personnalisations",
- "HeaderAllDevices": "Tous les appareils",
- "HeaderThisDevice": "Cet appareil",
- "OptionLibraryButtons": "Boutons de r\u00e9pertoires de m\u00e9dias",
- "OptionLibraryTiles": "Tuiles de r\u00e9pertoires de m\u00e9dias",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Bande-annonce",
- "LabelFailed": "\u00c9chec",
- "LabelSeries": "S\u00e9ries:",
- "ButtonPreviousTrack": "Piste pr\u00e9c\u00e9dante",
- "ButtonNextTrack": "Piste suivante",
- "HeaderMyLibrary": "Ma biblioth\u00e8que",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "Personnes",
"LabelExit": "Quitter",
+ "HeaderDownloadPeopleMetadataFor": "T\u00e9l\u00e9charger la biographie et les images pour:",
"LabelVisitCommunity": "Visiter la Communaut\u00e9",
+ "OptionComposers": "Compositeurs",
"LabelGithubWiki": "GitHub Wiki",
+ "OptionOthers": "Autres",
"LabelSwagger": "Swagger",
"LabelStandard": "Standard",
+ "HeaderDownloadPeopleMetadataForHelp": "Activer les options compl\u00e9mentaires fournira plus d'information \u00e0 l'\u00e9cran mais causera une lenteur des scans de librairie.",
"LabelViewApiDocumentation": "Consulter la documentation API",
+ "ViewTypeFolders": "R\u00e9pertoires",
"LabelBrowseLibrary": "Parcourir la biblioth\u00e8que",
+ "LabelDisplayFoldersView": "Afficher une vue mosa\u00efque pour montrer les dossiers media en int\u00e9gralit\u00e9.",
"LabelConfigureMediaBrowser": "Configurer Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Enregistrements",
"LabelOpenLibraryViewer": "Ouvrir le navigateur de biblioth\u00e8que",
+ "ViewTypeLiveTvChannels": "Cha\u00eenes",
"LabelRestartServer": "Red\u00e9marrer le Serveur",
+ "LabelAllowLocalAccessWithoutPassword": "Autoriser l'acc\u00e8s local sans un mot de passe",
"LabelShowLogWindow": "Afficher la fen\u00eatre du journal d'\u00e9v\u00e8nements",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "Si activ\u00e9, le mot de passe ne sera pas requis pour s'authentifier depuis le r\u00e9seau local.",
"LabelPrevious": "Pr\u00e9c\u00e9dent",
+ "HeaderPassword": "Mot de passe",
"LabelFinish": "Terminer",
+ "HeaderLocalAccess": "Acc\u00e8s local",
"LabelNext": "Suivant",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "Vous avez Termin\u00e9!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "Bienvenue dans Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
- "ThisWizardWillGuideYou": "Cet assistant vous guidera dans le processus de configuration. Pour commencer, SVP s\u00e9lectionnez votre langue pr\u00e9f\u00e9r\u00e9e.",
+ "LabelImageRefreshMode": "Image refresh mode:",
+ "ThisWizardWillGuideYou": "Cet assistant vous guidera dans le processus de configuration. Pour commencer, merci de s\u00e9lectionner votre langue pr\u00e9f\u00e9r\u00e9e.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "Parlez-nous de vous",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "Votre pr\u00e9nom:",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "D'autres utilisateurs pourront \u00eatre ajout\u00e9s ult\u00e9rieurement \u00e0 partir du tableau de bord.",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser supporte nativement les profils utilisateurs, donnant la possibilit\u00e9 pour chaque utilisateur d'avoir ses propres param\u00e8tres d'affichage, \u00e9tats de lecture et param\u00e8tres de contr\u00f4le parental.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Service Windows",
+ "HeaderRefreshMetadata": "Actualiser les m\u00e9tadonn\u00e9es",
"AWindowsServiceHasBeenInstalled": "Un service Windows a \u00e9t\u00e9 install\u00e9.",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser fonctionne normalement en tant qu'application sur le bureau avec une ic\u00f4ne dans la barre des t\u00e2ches, mais si vous pr\u00e9f\u00e9rez le lancer en tant que service d'arri\u00e8re-plan, il peut \u00eatre d\u00e9marr\u00e9 via le gestionnaire de services Windows.",
+ "HeaderIdentifyItem": "Identify Item",
"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, il faut 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.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "C'est tout ce dont nous avons besoin pour l'instant. Media Browser a commenc\u00e9 la collecte d'information sur votre biblioth\u00e8que de m\u00e9dia. Visitez quelques unes de nos applications, ensuite cliquez <b>Terminer<\/b> pour voir le <b>Tableau de bord<\/b>",
+ "HeaderConfirmDeletion": "Confirmer suppression",
"LabelConfigureSettings": "Configurer les param\u00e8tres",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Activer l'extraction d'image des videos",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"VideoImageExtractionHelp": "Pour les vid\u00e9os sans image et pour lesquelles nous n'avons pas trouv\u00e9 d'images sur Internet. Ce processus prolongera la mise \u00e0 jour initiale de la biblioth\u00e8que mais offrira un meilleur rendu visuel.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Extraire les images de chapitre pour les films",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "L'extraction d'images de chapitre permettra aux clients d'afficher des menus visuels pour la s\u00e9lection des sc\u00e8nes. Le processus peut \u00eatre long et consommateur de ressources du processeur et de stockage (plusieurs gigaoctets). Il s'ex\u00e9cute par d\u00e9faut comme t\u00e2che programm\u00e9e \u00e0 4:00 (AM) mais son param\u00e9trage peut \u00eatre modifi\u00e9 dans les options des t\u00e2ches programm\u00e9es. Il est d\u00e9conseill\u00e9 d'ex\u00e9cuter cette t\u00e2che durant les heures d'utilisation normales.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Activer la configuration automatique de port",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP permet la configuration automatique de routeurs pour un acc\u00e8s \u00e0 distance facile. Ceci peut ne pas fonctionner sur certains mod\u00e8les de routeur.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Annuler",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "Nouveau",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Configurer votre biblioth\u00e8que de m\u00e9dia",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "Ajouter r\u00e9pertoire de m\u00e9dia",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Type de r\u00e9pertoire:",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Requiert l'utilisation d'un plug-in, Ex: GameBrowser ou MB BookShelf",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Se r\u00e9f\u00e9rer au wiki des biblioth\u00e8ques de m\u00e9dia",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "Pays:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "Langue:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "Langue pr\u00e9f\u00e9r\u00e9e pour les m\u00e9tadonn\u00e9es:",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "Enregistrer les images et m\u00e9tadonn\u00e9es dans les r\u00e9pertoires de m\u00e9dia",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "Enregistrer les images et m\u00e9tadonn\u00e9es dans les r\u00e9pertoires de m\u00e9dia va les placer \u00e0 un endroit o\u00f9 elles pourront facilement \u00eatre modifi\u00e9es.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "T\u00e9l\u00e9charger les images et m\u00e9tadonn\u00e9es depuis Internet",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser peut t\u00e9l\u00e9charger des m\u00e9tadonn\u00e9es sur vos m\u00e9dia pour en offrir une pr\u00e9sentation plus riche.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "Pr\u00e9f\u00e9rences",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "Mot de Passe",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "Acc\u00e8s aux biblioth\u00e8ques",
+ "LabelBudget": "Budget",
"TabImage": "Image",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "Profil",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "M\u00e9tadonn\u00e9es",
+ "LabelPlayers": "Players:",
"TabImages": "Images",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "Titres",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Afficher les \u00e9pisodes manquants dans les saisons",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Afficher les \u00e9pisodes non diffus\u00e9s dans les saisons",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "Param\u00e8tres de lecture video",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Param\u00e8tres de lecture",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "Param\u00e8tres de langue audio:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "Param\u00e8tres de langue de sous-titre",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Par d\u00e9faut",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Seulement les sous-titres forc\u00e9s",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Toujours afficher les sous-titres",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "Aucun sous-titre",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Les sous-titres correspondants \u00e0 la langue pr\u00e9f\u00e9r\u00e9e seront charg\u00e9s lorsque la langue audio est \u00e9trang\u00e8re.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Seulement les sous-titres forc\u00e9s seront charg\u00e9s.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Les sous-titres correspondants \u00e0 la langue pr\u00e9f\u00e9r\u00e9e seront charg\u00e9s peu importe la langue audio.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Les sous-titres ne seront pas charg\u00e9s par d\u00e9faut.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Profils",
+ "HeaderTags": "Tags",
"TabSecurity": "S\u00e9curit\u00e9",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "Ajouter utilisateur",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "Sauvegarder",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "R\u00e9initialiser Mot de Passe",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "Nouveau mot de passe",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "Confirmation du nouveau mot de passe:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "Cr\u00e9er Mot de Passe",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Mot de passe actuel:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "Note maximale d'\u00e9valuation de contr\u00f4le parental:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "Le contenu avec une note d'\u00e9valuation de contr\u00f4le parental plus \u00e9lev\u00e9e ne sera pas visible par cet utilisateur.",
+ "OptionNoTrailer": "Aucune bande-annonce",
"LibraryAccessHelp": "Selectionnez le r\u00e9pertoire de m\u00e9dia \u00e0 partager avec cet utilisateur. Les administrateurs pourront modifier tous les r\u00e9pertoires en utilisant le gestionnaire de m\u00e9tadonn\u00e9es.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "S\u00e9lectionner les cha\u00eenes \u00e0 partager avec cet utilisateur. Les administrateurs pourront modifier toutes les cha\u00eenes par le gestionnaire de m\u00e9tadonn\u00e9es.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "Supprimer Image",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "S\u00e9lectionner utilisateurs:",
+ "OptionActor": "Actor",
"ButtonUpload": "Envoyer",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Envoyer nouvelle image",
+ "OptionDirector": "Director",
"LabelDropImageHere": "Placer image ici",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "Rapport d'aspect 1:1 recommand\u00e9. Seulement JPG\/PNG.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Rien ici.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "Merci de vous assurer que le t\u00e9l\u00e9chargement des m\u00e9tadonn\u00e9es depuis Internet est bien activ\u00e9.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Sugg\u00e9r\u00e9s",
+ "LabelAirTime": "Air time:",
"TabLatest": "Plus r\u00e9cents",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "\u00c0 venir",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "S\u00e9ries",
"TabEpisodes": "\u00c9pisodes",
"TabGenres": "Genres",
@@ -163,7 +225,7 @@
"OptionAscending": "Ascendant",
"OptionDescending": "Descendant",
"OptionRuntime": "Dur\u00e9e",
- "OptionReleaseDate": "Date de sortie",
+ "OptionReleaseDate": "Release Date",
"OptionPlayCount": "Nombre de lectures",
"OptionDatePlayed": "Date de lecture",
"OptionDateAdded": "Date d'ajout",
@@ -185,7 +247,7 @@
"OptionVideoBitrate": "D\u00e9bit vid\u00e9o",
"OptionResumable": "Reprenable",
"ScheduledTasksHelp": "S\u00e9lectionnez une t\u00e2che pour ajuster sa programmation.",
- "ScheduledTasksTitle": "T\u00e2ches programm\u00e9es",
+ "ScheduledTasksTitle": "T\u00e2ches planifi\u00e9es",
"TabMyPlugins": "Mes Plugins",
"TabCatalog": "Catalogue",
"PluginsTitle": "Plugins",
@@ -212,7 +274,9 @@
"OptionHasThemeVideo": "Vid\u00e9o th\u00e8me",
"TabMovies": "Films",
"TabStudios": "Studios",
- "TabTrailers": "Bande-annonces",
+ "TabTrailers": "Bandes-annonces",
+ "LabelArtists": "Artistes",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "Films les plus r\u00e9cents",
"HeaderLatestTrailers": "Bande-annonces les plus r\u00e9centes",
"OptionHasSpecialFeatures": "Bonus:",
@@ -233,6 +297,7 @@
"OptionFriday": "Vendredi",
"OptionSaturday": "Samedi",
"HeaderManagement": "Gestion:",
+ "LabelManagement": "Gestion :",
"OptionMissingImdbId": "ID IMDb manquant:",
"OptionMissingTvdbId": "ID TVDB manquant:",
"OptionMissingOverview": "R\u00e9sum\u00e9 manquant",
@@ -266,13 +331,12 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "S\u00e9lectionner",
- "ButtonSearch": "Recherche",
"ButtonGroupVersions": "Versions des groupes",
- "ButtonAddToCollection": "Add to Collection",
+ "ButtonAddToCollection": "Ajouter \u00e0 la Collection",
"PismoMessage": "En utilisation de \"Pismo File Mount\" par une license fournie.",
"TangibleSoftwareMessage": "Utilisation de convertisseurs Tangible Solutions Java\/C# par licence fournie.",
"HeaderCredits": "Cr\u00e9dits",
- "PleaseSupportOtherProduces": "SVP, soutenez les autres produits gratuits que nous utilisons:",
+ "PleaseSupportOtherProduces": "Merci de soutenir les autres produits gratuits que nous utilisons :",
"VersionNumber": "Version {0}",
"TabPaths": "Chemins d'acc\u00e8s",
"TabServer": "Serveur",
@@ -290,7 +354,7 @@
"ButtonSelectDirectory": "S\u00e9lectionner le r\u00e9pertoire",
"LabelCustomPaths": "Sp\u00e9cifier des chemins d'acc\u00e8s personnalis\u00e9s si d\u00e9sir\u00e9. Laisser vide pour garder les chemin d'acc\u00e8s par d\u00e9faut.",
"LabelCachePath": "Chemin d'acc\u00e8s du cache temporaire:",
- "LabelCachePathHelp": "Ce r\u00e9pertoire contient les fichier temporaires du serveur, comme, par example, les images.",
+ "LabelCachePathHelp": "Ce r\u00e9pertoire contient les fichier temporaires du serveur, comme, par exemple, les images.",
"LabelImagesByNamePath": "Chemin d'acc\u00e8s de \"Images by Name\":",
"LabelImagesByNamePathHelp": "Ce r\u00e9pertoire contient les images des acteurs, genres et studios.",
"LabelMetadataPath": "Chemin d'acc\u00e8s des m\u00e9tadonn\u00e9es:",
@@ -318,11 +382,11 @@
"ButtonAutoScroll": "D\u00e9fillement automatique",
"LabelImageSavingConvention": "Convention de sauvegarde des images:",
"LabelImageSavingConventionHelp": "Media Browser reconnait les images des autres applications de m\u00e9dia importants. Choisir la convention de t\u00e9l\u00e9chargement peut \u00eatre pratique si vous utilisez aussi d'autres produits.",
- "OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/XBMC",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Se connecter",
"TitleSignIn": "Se connecter",
- "HeaderPleaseSignIn": "SVP se connecter",
+ "HeaderPleaseSignIn": "Merci de vous identifier",
"LabelUser": "Utilisateur:",
"LabelPassword": "Mot de passe:",
"ButtonManualLogin": "Connexion manuelle:",
@@ -332,7 +396,7 @@
"TabCollections": "Collections",
"HeaderChannels": "Cha\u00eenes",
"TabRecordings": "Enregistrements",
- "TabScheduled": "Programm\u00e9s",
+ "TabScheduled": "Planifi\u00e9s",
"TabSeries": "S\u00e9ries",
"TabFavorites": "Favoris",
"TabMyLibrary": "Ma Biblioth\u00e8que",
@@ -347,6 +411,8 @@
"TabStatus": "\u00c9tat",
"TabSettings": "Param\u00e8tres",
"ButtonRefreshGuideData": "Rafra\u00eechir les donn\u00e9es du guide horaire.",
+ "ButtonRefresh": "Actualiser",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priorit\u00e9",
"OptionRecordOnAllChannels": "Enregistrer le programme sur toutes les cha\u00eenes",
"OptionRecordAnytime": "Enregistrer le programme \u00e0 n'importe quelle heure\/journ\u00e9e",
@@ -369,7 +435,7 @@
"LabelActiveServiceHelp": "Plusieurs Plugins de TV peuvent \u00eatre install\u00e9s mais seulement un \u00e0 la fois peut \u00eatre actif.",
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "Un fournisseur de service de TV en direct est requis pour continuer.",
- "LiveTvPluginRequiredHelp": "SVP installer un de nos Plugins disponibles, comme Next Pvr ou ServerWmc.",
+ "LiveTvPluginRequiredHelp": "Merci d'installer un de nos plugins disponibles, comme Next Pvr ou ServerWmc.",
"LabelCustomizeOptionsPerMediaType": "Personnaliser pour le type de m\u00e9dia:",
"OptionDownloadThumbImage": "Vignette",
"OptionDownloadMenuImage": "Menu",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "\u00c9quipe de tournage",
"HeaderAdditionalParts": "Parties Additionelles",
"ButtonSplitVersionsApart": "S\u00e9parer les versions",
+ "ButtonPlayTrailer": "Bande-annonce",
"LabelMissing": "Manquant(s)",
"LabelOffline": "Hors ligne",
"PathSubstitutionHelp": "Les substitutions de chemins d'acc\u00e8s sont utilis\u00e9es pour faire correspondre un chemin d'acc\u00e8s du serveur \u00e0 un chemin d'acc\u00e8s accessible par les clients. En autorisant un acc\u00e8s direct aux m\u00e9dias du serveur, les clients pourront les lire directement du r\u00e9seau et \u00e9viter l'utilisation inutiles des ressources du serveur en demandant du transcodage.",
@@ -471,7 +538,7 @@
"CustomDlnaProfilesHelp": "Cr\u00e9er un profil personnalis\u00e9 pour cibler un appareil ou remplacer un profile syst\u00e8me.",
"SystemDlnaProfilesHelp": "Les profils syst\u00e8mes sont en lecture seule. Pour remplacer un profil syst\u00e8me, cr\u00e9ez un profil personnalis\u00e9 ciblant le m\u00eame appareil.",
"TitleDashboard": "Tableau de bord",
- "TabHome": "Principal",
+ "TabHome": "Portail",
"TabInfo": "Info",
"HeaderLinks": "Liens",
"HeaderSystemPaths": "Chemins d'acc\u00e8s syst\u00e8mes",
@@ -484,8 +551,8 @@
"LabelPreferredDisplayLanguageHelp": "La traduction de Media Browser est un projet en cours et n'est pas compl\u00e9t\u00e9e encore.",
"LabelReadHowYouCanContribute": "Lire comment vous pouvez contribuer.",
"HeaderNewCollection": "Nouvelle collection",
- "HeaderAddToCollection": "Add to Collection",
- "ButtonSubmit": "Submit",
+ "HeaderAddToCollection": "Ajouter \u00e0 la Collection",
+ "ButtonSubmit": "Soumettre",
"NewCollectionNameExample": "Exemple: Collection Star Wars",
"OptionSearchForInternetMetadata": "Rechercher sur Internet les images et m\u00e9tadonn\u00e9es",
"ButtonCreate": "Cr\u00e9er",
@@ -512,8 +579,10 @@
"HeaderProgram": "Programme",
"HeaderClients": "Clients",
"LabelCompleted": "Compl\u00e9t\u00e9",
+ "LabelFailed": "\u00c9chou\u00e9",
"LabelSkipped": "Saut\u00e9",
"HeaderEpisodeOrganization": "Organisation d'\u00e9pisodes",
+ "LabelSeries": "S\u00e9ries:",
"LabelSeasonNumber": "Num\u00e9ro de saison",
"LabelEpisodeNumber": "Num\u00e9ro d'\u00e9pisode",
"LabelEndingEpisodeNumber": "Num\u00e9ro d'\u00e9pisode se terminant",
@@ -522,13 +591,13 @@
"LabelSupportAmount": "Montant (USD)",
"HeaderSupportTheTeamHelp": "Aidez la continuation de ce projet en effectuant un don. Une portion de ce don contribuera au d\u00e9veloppement d'autres produits gratuits sur lesquels nous d\u00e9pendons.",
"ButtonEnterSupporterKey": "Entrer la cl\u00e9 de supporteur",
- "DonationNextStep": "Une fois compl\u00e9t\u00e9, SVP revenir et entrer la cl\u00e9 de supporteur re\u00e7ue par courriel.",
+ "DonationNextStep": "Une fois compl\u00e9t\u00e9, merci de revenir et saisir la cl\u00e9 de supporteur re\u00e7ue par courriel.",
"AutoOrganizeHelp": "L'organisation automatique surveille vos r\u00e9pertoires de t\u00e9l\u00e9chargement et les nouveaux fichiers puis les d\u00e9place dans vos r\u00e9pertoires de m\u00e9dias. ",
"AutoOrganizeTvHelp": "L'organisation de fichiers TV va seulement ajouter des \u00e9pisodes \u00e0 des s\u00e9ries existantes. Ce processus de cr\u00e9\u00e9ra pas de nouveaux r\u00e9pertoires de s\u00e9rie.",
"OptionEnableEpisodeOrganization": "Activer l'organisation des nouvelles \u00e9pisodes",
"LabelWatchFolder": "R\u00e9pertoire surveill\u00e9:",
"LabelWatchFolderHelp": "Le serveur va utiliser ce r\u00e9pertoire pendant la t\u00e2che \"Organiser les nouveaux fichiers de m\u00e9dias\".",
- "ButtonViewScheduledTasks": "Voir les t\u00e2ches programm\u00e9es",
+ "ButtonViewScheduledTasks": "Voir les t\u00e2ches planifi\u00e9es",
"LabelMinFileSizeForOrganize": "Grosseur de fichier minimum (MB):",
"LabelMinFileSizeForOrganizeHelp": "Les fichiers avec une grosseur inf\u00e9rieure seront ignor\u00e9s.",
"LabelSeasonFolderPattern": "Mod\u00e8le de r\u00e9pertoire de saison:",
@@ -553,18 +622,18 @@
"HeaderHelpImproveMediaBrowser": "Aidez-nous \u00e0 am\u00e9liorer Media Browser",
"HeaderRunningTasks": "T\u00e2ches en ex\u00e9cution",
"HeaderActiveDevices": "Appareils actifs",
- "HeaderPendingInstallations": "Installations en suspend",
+ "HeaderPendingInstallations": "Installations en suspens",
"HeaerServerInformation": "Information du serveur",
"ButtonRestartNow": "Red\u00e9marrer maintenant",
"ButtonRestart": "Red\u00e9marrer",
"ButtonShutdown": "\u00c9teindre",
"ButtonUpdateNow": "Mettre \u00e0 jour maintenant",
- "PleaseUpdateManually": "SVP fermer le serveur et mettre \u00e0 jour manuellement.",
+ "PleaseUpdateManually": "Merci d'\u00e9teindre le serveur et de le mettre \u00e0 jour manuellement.",
"NewServerVersionAvailable": "Une nouvelle version de Media Browser Server est disponible!",
"ServerUpToDate": "Media Browser est \u00e0 jour",
"ErrorConnectingToMediaBrowserRepository": "Une erreur est survenue avec la connexion au r\u00e9f\u00e9rentiel de donn\u00e9es de Media Browser.",
"LabelComponentsUpdated": "Les composants suivants ont \u00e9t\u00e9 install\u00e9s ou mis \u00e0 jour.",
- "MessagePleaseRestartServerToFinishUpdating": "SVP red\u00e9marrer le serveur pour appliquer les mises \u00e0 jour.",
+ "MessagePleaseRestartServerToFinishUpdating": "Merci de red\u00e9marrer le serveur pour appliquer les mises \u00e0 jour.",
"LabelDownMixAudioScale": "Boost audio lors de downmix:",
"LabelDownMixAudioScaleHelp": "Boost audio lors de downmix. Mettre \u00e0 1 pour pr\u00e9server la valeur originale du volume.",
"ButtonLinkKeys": "Lier les cl\u00e9s",
@@ -593,7 +662,7 @@
"LabelDefaultUser": "Utilisateur par d\u00e9faut:",
"LabelDefaultUserHelp": "D\u00e9termine quelle biblioth\u00e8que d'utilisateur doit \u00eatre afficher sur les appareils connect\u00e9s. Ces param\u00e8tres peuvent \u00eatre remplac\u00e9s pour chaque appareil par les configurations de profils.",
"TitleDlna": "DLNA",
- "TitleChannels": "Channels",
+ "TitleChannels": "Cha\u00eenes",
"HeaderServerSettings": "Param\u00e8tres du serveur",
"LabelWeatherDisplayLocation": "Emplacement de l'affichage de la m\u00e9t\u00e9o:",
"LabelWeatherDisplayLocationHelp": "Code ZIP US \/ Ville, \u00c9tat, Pays \/ Ville, Pays",
@@ -616,7 +685,7 @@
"NotificationOptionVideoPlaybackStopped": "Lecture vid\u00e9o arr\u00eat\u00e9e",
"NotificationOptionAudioPlaybackStopped": "Lecture audio arr\u00eat\u00e9e",
"NotificationOptionGamePlaybackStopped": "Lecture de jeu arr\u00eat\u00e9e",
- "NotificationOptionTaskFailed": "\u00c9chec de t\u00e2che programm\u00e9e",
+ "NotificationOptionTaskFailed": "\u00c9chec de t\u00e2che planifi\u00e9e",
"NotificationOptionInstallationFailed": "\u00c9chec d'installation",
"NotificationOptionNewLibraryContent": "Nouveau contenu ajout\u00e9",
"NotificationOptionNewLibraryContentMultiple": "Nouveau contenu ajout\u00e9 (multiple)",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Activer cette notification",
"LabelMonitorUsers": "Surveiller les activit\u00e9s de:",
"LabelSendNotificationToUsers": "Envoyer la notification \u00e0:",
- "UsersNotNotifiedAboutSelfActivity": "Les utilisateurs ne seront pas notifi\u00e9s de leurs propres activit\u00e9s.",
"LabelUseNotificationServices": "Utiliser les services suivants:",
"CategoryUser": "Utilisateur",
"CategorySystem": "Syst\u00e8me",
@@ -647,7 +715,8 @@
"ButtonPageUp": "Page suivante",
"ButtonPageDown": "Page pr\u00e9c\u00e9dante",
"PageAbbreviation": "PG",
- "ButtonHome": "Principal",
+ "ButtonHome": "Portail",
+ "ButtonSearch": "Recherche",
"ButtonSettings": "Param\u00e8tres",
"ButtonTakeScreenshot": "Capture d'\u00e9cran",
"ButtonLetterUp": "Lettre haut",
@@ -657,10 +726,12 @@
"TabNowPlaying": "En cours de lecture",
"TabNavigation": "Navigation",
"TabControls": "Contr\u00f4les",
- "ButtonFullscreen": "Plein \u00e9cran",
+ "ButtonFullscreen": "Basculer en plein \u00e9cran",
"ButtonScenes": "Sc\u00e8nes",
"ButtonSubtitles": "Sous-titres",
- "ButtonAudioTracks": "Piste audio",
+ "ButtonAudioTracks": "Pistes audio",
+ "ButtonPreviousTrack": "Piste pr\u00e9c\u00e9dente",
+ "ButtonNextTrack": "Piste suivante",
"ButtonStop": "Arr\u00eat",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Grouper les films en collections",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "S\u00e9par\u00e9s par des virgules. Peut \u00eatre laiss\u00e9 vide pour appliquer tous les conteneurs.",
"HeaderResponseProfile": "Profil de r\u00e9ponse",
"LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Conteneur:",
"LabelProfileVideoCodecs": "Codecs vid\u00e9os:",
"LabelProfileAudioCodecs": "Codecs audios:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "Ces valeurs contr\u00f4lent comment Media Browser sera pr\u00e9sent\u00e9 \u00e0 l'appareil.",
"LabelMaxBitrate": "D\u00e9bit maximum:",
"LabelMaxBitrateHelp": "Sp\u00e9cifiez un d\u00e9bit maximum dans les environnements avec bande passante limit\u00e9e ou si l'appareil impose sa propre limite.",
+ "LabelMaxStreamingBitrate": "D\u00e9bit max de streaming :",
+ "LabelMaxStreamingBitrateHelp": "Sp\u00e9cifiez le d\u00e9bit max lors du streaming.",
+ "LabelMaxStaticBitrate": "D\u00e9bit max de synchronisation :",
+ "LabelMaxStaticBitrateHelp": "Sp\u00e9cifiez un d\u00e9bit max pour la synchronisation de contenu en haute qualit\u00e9.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "D\u00e9bit du transcodage musique :",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Sp\u00e9cifiez le d\u00e9bit max pendant la diffusion de musique",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore le transcodage des demandes de plage d'octets",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "Si activ\u00e9, ces requ\u00eates\/demandes seront honor\u00e9es mais l'ent\u00eate de plage d'octets sera ignor\u00e9. ",
"LabelFriendlyName": "Surnom d'affichage",
@@ -751,15 +832,15 @@
"OptionReportByteRangeSeekingWhenTranscodingHelp": "Ceci est requis pour certains appareils dont le time seek n'est pas tr\u00e8s bon",
"HeaderSubtitleDownloadingHelp": "Lorsque Media Browser balaye vos fichiers vid\u00e9os, le serveur peut rechercher des sous-titres manquants et les t\u00e9l\u00e9charger en utilisant un fournisseur de sous-titre comme OpenSubtitles.org.",
"HeaderDownloadSubtitlesFor": "T\u00e9l\u00e9charger les sous-titres pour:",
- "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.",
+ "MessageNoChapterProviders": "Installer un plugin de fournisseur de chapitre tel que ChapterDb pour activer les options suppl\u00e9mentaires de chapitre.",
"LabelSkipIfGraphicalSubsPresent": "Sauter la vid\u00e9o si elle contient d\u00e9j\u00e0 des sous-titres graphiques",
"LabelSkipIfGraphicalSubsPresentHelp": "Garder des versions textes des sous-titres va \u00eatre plus efficace avec les appareils mobiles.",
"TabSubtitles": "Sous-titres",
- "TabChapters": "Chapters",
- "HeaderDownloadChaptersFor": "Download chapter names for:",
+ "TabChapters": "Chapitres:",
+ "HeaderDownloadChaptersFor": "T\u00e9l\u00e9charger les noms de chapitre pour:",
"LabelOpenSubtitlesUsername": "Nom d'utilisateur de Open Subtitles:",
"LabelOpenSubtitlesPassword": "Mot de passe de Open Subtitles:",
- "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.",
+ "HeaderChapterDownloadingHelp": "Lorsque Media Browser scanne vos fichiers vid\u00e9o, il peut facilement t\u00e9l\u00e9charger les noms de chapitre depuis Internet en utilisant le plugin de chapitre tel que ChapterDb.",
"LabelPlayDefaultAudioTrack": "Utiliser la flux audio par d\u00e9faut peu importe la langue",
"LabelSubtitlePlaybackMode": "Mode de sous-titres:",
"LabelDownloadLanguages": "T\u00e9l\u00e9chargement de langues:",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Afficher les plugins pour:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theatre",
- "TabOtherPlugins": "Autres",
- "LabelEpisodeName": "Nom d'\u00e9pisode",
- "LabelSeriesName": "Nom de s\u00e9ries",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Entrer texte",
"LabelTypeText": "Texte",
"HeaderSearchForSubtitles": "Rechercher des sous-titres",
@@ -791,62 +874,225 @@
"LabelEnableBackdrops": "Activer les images d'arri\u00e8re-plans",
"LabelEnableThemeSongsHelp": "Si activ\u00e9, les chansons themes seront lues en arri\u00e8re-plan pendant la navigation dans les biblioth\u00e8ques.",
"LabelEnableBackdropsHelp": "Si activ\u00e9, les images d'arri\u00e8re-plan seront affich\u00e9es sur certaines pages pendant la navigation dans les biblioth\u00e8ques.",
- "HeaderHomePage": "Page de d\u00e9marrage",
+ "HeaderHomePage": "Portail",
"HeaderSettingsForThisDevice": "Param\u00e8tres pour cet appareil",
"OptionAuto": "Auto",
"OptionYes": "Oui",
"OptionNo": "Non",
- "LabelHomePageSection1": "Section 1 de la page de d\u00e9marrage:",
- "LabelHomePageSection2": "Section 2 de la page de d\u00e9marrage:",
- "LabelHomePageSection3": "Section 3 de la page de d\u00e9marrage:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
+ "LabelHomePageSection1": "Premi\u00e8re section du portail:",
+ "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)",
"OptionResumablemedia": "Reprendre",
"OptionLatestMedia": "Les plus r\u00e9cents",
- "OptionLatestChannelMedia": "Latest channel items",
- "HeaderLatestChannelItems": "Latest Channel Items",
+ "OptionLatestChannelMedia": "Items de cha\u00eene les plus r\u00e9cents",
+ "HeaderLatestChannelItems": "Items de cha\u00eene les plus r\u00e9cents",
"OptionNone": "Aucun",
- "HeaderLiveTv": "TV en directe",
+ "HeaderLiveTv": "TV en direct",
"HeaderReports": "Rapports",
"HeaderMetadataManager": "Gestionnaire de m\u00e9tadonn\u00e9es",
"HeaderPreferences": "Pr\u00e9f\u00e9rences",
"MessageLoadingChannels": "Chargement du contenu de la cha\u00eene...",
+ "MessageLoadingContent": "Chargement du contenu...",
"ButtonMarkRead": "Marquer lu",
"OptionDefaultSort": "Par d\u00e9faut",
"OptionCommunityMostWatchedSort": "Les plus \u00e9cout\u00e9s",
"TabNextUp": "Prochains \u00e0 voir",
"MessageNoMovieSuggestionsAvailable": "Aucune suggestion de film n'est actuellement disponible. Commencez \u00e0 regarder et noter vos films pour avoir des suggestions.",
- "MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the New button to start creating Collections.",
+ "MessageNoCollectionsAvailable": "Les Collections permettent le groupement de films, S\u00e9ries, Albums, Livres et Jeux. Cliquer sur \"Nouveau\" pour commencer la cr\u00e9ation des 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.",
+ "MessageNoPlaylistItemsAvailable": "Cette liste de lecture est pr\u00e9sentement vide.",
"HeaderWelcomeToMediaBrowserWebClient": "Bienvenue au client Web Media Browser",
- "ButtonDismiss": "Dismiss",
- "MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
- "ButtonEditOtherUserPreferences": "Edit this user's personal preferences.",
- "LabelChannelStreamQuality": "Preferred internet stream quality:",
- "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.",
- "OptionBestAvailableStreamQuality": "Best available",
- "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:",
- "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.",
- "LabelChannelDownloadPath": "Channel content download path:",
- "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.",
- "LabelChannelDownloadAge": "Delete content after: (days)",
- "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.",
- "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.",
- "LabelSelectCollection": "Select collection:",
- "ViewTypeMovies": "Movies",
+ "ButtonDismiss": "Annuler",
+ "MessageLearnHowToCustomize": "Apprenez comment personnaliser cette page selon vos propres go\u00fbts. S\u00e9lectionnez votre ic\u00f4ne d'utilisateur dans le coin en haut, \u00e0 droite de l'\u00e9cran pour visionner et mettre \u00e0 jour vos pr\u00e9f\u00e9rences. ",
+ "ButtonEditOtherUserPreferences": "Modifier les pr\u00e9f\u00e9rences personnelles de cet utilisateur.",
+ "LabelChannelStreamQuality": "Qualit\u00e9 de diffusion internet pr\u00e9f\u00e9r\u00e9e :",
+ "LabelChannelStreamQualityHelp": "Avec une bande passante faible, limiter la qualit\u00e9 garantit un confort d'utilisation du streaming.",
+ "OptionBestAvailableStreamQuality": "Meilleur disponible",
+ "LabelEnableChannelContentDownloadingFor": "Activer le t\u00e9l\u00e9chargement de contenu de cha\u00eene pour:",
+ "LabelEnableChannelContentDownloadingForHelp": "Certaines cha\u00eenes supportent la priorit\u00e9 de t\u00e9l\u00e9chargement de contenu lors du visionnage. Activez ceci pour les environnements \u00e0 bande passante faible afin de t\u00e9l\u00e9charger le contenu des cha\u00eenes pendant les horaires d'inactivit\u00e9. Le contenu est t\u00e9l\u00e9charg\u00e9 suivant la programmation de celui-ci dans les t\u00e2ches planifi\u00e9es.",
+ "LabelChannelDownloadPath": "Chemin d'acc\u00e8s de t\u00e9l\u00e9chargement de contenu de cha\u00eene:",
+ "LabelChannelDownloadPathHelp": "Sp\u00e9cifiez un chemin de t\u00e9l\u00e9chargements personnalis\u00e9 si besoin. Laissez vide pour t\u00e9l\u00e9charger dans un r\u00e9pertoire interne du programme.",
+ "LabelChannelDownloadAge": "Supprimer le contenu apr\u00e8s: (jours)",
+ "LabelChannelDownloadAgeHelp": "Le contenu t\u00e9l\u00e9charg\u00e9 plus vieux sera supprim\u00e9. Par contre, il sera toujours disponible par flux Internet (en ligne).",
+ "ChannelSettingsFormHelp": "Installer des cha\u00eenes comme \"Trailers\" and \"Vimeo\" par le catalogue de Plugins.",
+ "LabelSelectCollection": "S\u00e9lectionner collection:",
+ "ViewTypeMovies": "Films",
"ViewTypeTvShows": "TV",
- "ViewTypeGames": "Games",
- "ViewTypeMusic": "Music",
+ "ViewTypeGames": "Jeux",
+ "ViewTypeMusic": "Musique",
"ViewTypeBoxSets": "Collections",
- "ViewTypeChannels": "Channels",
- "ViewTypeLiveTV": "Live TV",
- "HeaderOtherDisplaySettings": "Display Settings",
- "HeaderMyViews": "My Views",
- "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",
- "TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "ViewTypeChannels": "Cha\u00eenes",
+ "ViewTypeLiveTV": "TV en direct",
+ "HeaderOtherDisplaySettings": "Param\u00e8tres d'affichage",
+ "HeaderMyViews": "Mes affichages",
+ "LabelSelectFolderGroups": "Grouper automatiquement le contenu des r\u00e9pertoires suivants dans les vues tels que Films, Musiques et TV :",
+ "LabelSelectFolderGroupsHelp": "Les r\u00e9pertoires qui ne sont pas coch\u00e9s, seront affich\u00e9s tels quels avec leur propre disposition.",
+ "OptionDisplayAdultContent": "Afficher le contenu adulte",
+ "OptionLibraryFolders": "R\u00e9pertoires de m\u00e9dias",
+ "TitleRemoteControl": "Acc\u00e8s \u00e0 distance",
+ "OptionLatestTvRecordings": "Les plus r\u00e9cents enregistrements",
+ "LabelProtocolInfo": "Infos sur le protocol:",
+ "LabelProtocolInfoHelp": "La valeur sera utilis\u00e9e par le p\u00e9riph\u00e9rique pour r\u00e9pondre aux requ\u00eates GetProtocolInfo.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser inclut un support natif pour les m\u00e9tadonn\u00e9es Nfo Xbmc et les images. Pour activer ou d\u00e9sactiver les m\u00e9tadonn\u00e9es Xbmc, utiliser l'onglet Avanc\u00e9 pour configurer les options de vos types de m\u00e9dia.",
+ "LabelXbmcMetadataUser": "Ajouter aux nfo, les donn\u00e9es de surveillance de l'utilisateur :",
+ "LabelXbmcMetadataUserHelp": "Activer ceci pour synchroniser les donn\u00e9es de surveillance entre Media Browser et Xbmc",
+ "LabelXbmcMetadataDateFormat": "Format de la date de sortie :",
+ "LabelXbmcMetadataDateFormatHelp": "Toutes les dates provenant des nfo seront lues et \u00e9crites en utilisant ce format.",
+ "LabelXbmcMetadataSaveImagePaths": "Sauvegarder les chemins d'images dans les fichiers nfo.",
+ "LabelXbmcMetadataSaveImagePathsHelp": "Cela est r\u00e9command\u00e9 si les noms des fichiers d'images ne sont pas conformes aux directives d'Xbmc.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Activer le remplacement de chemin",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Active la substitution de chemin des chemins d'image en utilisant les param\u00e8tres de substitution de chemin du serveur.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "Voir la substitution de chemin.",
+ "LabelGroupChannelsIntoViews": "Afficher directement les cha\u00eenes suivantes dans mes vues.",
+ "LabelGroupChannelsIntoViewsHelp": "Si activ\u00e9, ces cha\u00eenes seront directement affich\u00e9es \u00e0 c\u00f4t\u00e9 des autres vues. Si d\u00e9sactiv\u00e9, elles seront affich\u00e9es dans une vue de cha\u00eenes s\u00e9par\u00e9es.",
+ "LabelDisplayCollectionsView": "Afficher un aper\u00e7u de collections pour montrer les collections de film",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copier l'extrafanart dans les extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "Lors du t\u00e9l\u00e9chargement d'images, elles peuvent \u00eatre sauvegard\u00e9es en tant que extrafanart ou extrathumbs pour une compatibilit\u00e9 maximum avec le skin Xbmc.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Fichiers log du serveur :",
+ "TabBranding": "Slogan",
+ "HeaderBrandingHelp": "Personnaliser l'apparence de Media Browser pour r\u00e9pondre aux besoins de votre groupe ou organisation.",
+ "LabelLoginDisclaimer": "Avertissement sur la page d'accueil :",
+ "LabelLoginDisclaimerHelp": "Ce sera affich\u00e9 en bas de la page de connexion.",
+ "LabelAutomaticallyDonate": "Donner automatiquement ce montant chaque mois.",
+ "LabelAutomaticallyDonateHelp": "Vous pouvez annuler via votre compte Paypal n'importe quand.",
+ "OptionList": "Liste",
+ "TabDashboard": "Tableau de bord",
+ "TitleServer": "Serveur",
+ "LabelCache": "Cache :",
+ "LabelLogs": "Logs :",
+ "LabelMetadata": "M\u00e9tadonn\u00e9es :",
+ "LabelImagesByName": "Images tri\u00e9es par nom :",
+ "LabelTranscodingTemporaryFiles": "Transcodage de fichiers temporaires :",
+ "HeaderLatestMusic": "Derni\u00e8re musique",
+ "HeaderBranding": "Slogan",
+ "HeaderApiKeys": "Cl\u00e9s API",
+ "HeaderApiKeysHelp": "Les applications externes n\u00e9cessitent d'avoir une cl\u00e9 API pour communiquer avec Media Browser. Les cl\u00e9s sont d\u00e9livr\u00e9es en se connectant avec un compte Media Browser, ou en octroyant manuellement la cl\u00e9 depuis l'application.",
+ "HeaderApiKey": "Cl\u00e9 API",
+ "HeaderApp": "App",
+ "HeaderDevice": "P\u00e9riph\u00e9rique",
+ "HeaderUser": "Utilisateur",
+ "HeaderDateIssued": "Date de publication",
+ "LabelChapterName": "Chapitre {0}",
+ "HeaderNewApiKey": "Nouvelle cl\u00e9 API",
+ "LabelAppName": "Nom de l'app",
+ "LabelAppNameExample": "Exemple: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Allouer \u00e0 une application des droits pour communiquer avec Media Browser.",
+ "HeaderHttpHeaders": "Ent\u00eates HTTP",
+ "HeaderIdentificationHeader": "Ent\u00eate d'identification",
+ "LabelValue": "Valeur :",
+ "LabelMatchType": "Type recherch\u00e9 :",
+ "OptionEquals": "Equivalents",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Sous-cha\u00eene",
+ "TabView": "Voir",
+ "TabSort": "Trier",
+ "TabFilter": "Filtrer",
+ "ButtonView": "Voir",
+ "LabelPageSize": "Limite de l'item :",
+ "LabelPath": "Path:",
+ "LabelView": "Voir :",
+ "TabUsers": "Utilisateurs",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Fonctionnalit\u00e9s",
+ "HeaderAdvanced": "Avanc\u00e9",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "T\u00e2ches planifi\u00e9es",
+ "HeaderChapters": "Chapitres",
+ "HeaderResumeSettings": "Reprendre les param\u00e8tres",
+ "TabSync": "Sync",
+ "TitleUsers": "Utilisateurs",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Contexte:",
+ "OptionContextStreaming": "Diffusion",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Ajouter \u00e0 la liste de lecture",
+ "TabPlaylists": "Listes de lecture",
+ "ButtonClose": "Fermer",
+ "LabelAllLanguages": "Toutes les langues",
+ "HeaderBrowseOnlineImages": "Parcourir les images en ligne",
+ "LabelSource": "Source:",
+ "OptionAll": "Tous",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Parcourir les images:",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Arri\u00e8re-plans",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Ajouter\/mettre \u00e0 jour image",
+ "LabelJpgPngOnly": "JPG\/PNG seulement",
+ "LabelImageType": "Type d'image:",
+ "OptionPrimary": "Principal",
+ "OptionArt": "Art",
+ "OptionBox": "Bo\u00eetier",
+ "OptionBoxRear": "Dos de bo\u00eetier",
+ "OptionDisc": "Disque",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Verrouill\u00e9",
+ "OptionUnidentified": "Non identifi\u00e9",
+ "OptionMissingParentalRating": "Note de contr\u00f4le parental manquante",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "\u00c9pisodes:",
+ "OptionSeason0": "Saison 0",
+ "LabelReport": "Rapport:",
+ "OptionReportSongs": "Chansons",
+ "OptionReportSeries": "S\u00e9ries",
+ "OptionReportSeasons": "Saisons",
+ "OptionReportTrailers": "Bandes-annonces",
+ "OptionReportMusicVideos": "Vid\u00e9oclips",
+ "OptionReportMovies": "Films",
+ "OptionReportHomeVideos": "Vid\u00e9os personnelles",
+ "OptionReportGames": "Jeux",
+ "OptionReportEpisodes": "\u00c9pisodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Livres",
+ "OptionReportArtists": "Artistes",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Vid\u00e9os adultes",
+ "ButtonMore": "Voir la suite",
+ "HeaderActivity": "Activit\u00e9",
+ "ScheduledTaskStartedWithName": "{0} a commenc\u00e9",
+ "ScheduledTaskCancelledWithName": "{0} a \u00e9t\u00e9 annul\u00e9",
+ "ScheduledTaskCompletedWithName": "{0} termin\u00e9",
+ "ScheduledTaskFailed": "T\u00e2che planifi\u00e9e termin\u00e9e",
+ "PluginInstalledWithName": "{0} a \u00e9t\u00e9 install\u00e9",
+ "PluginUpdatedWithName": "{0} a \u00e9t\u00e9 mise \u00e0 jour",
+ "PluginUninstalledWithName": "{0} a \u00e9t\u00e9 d\u00e9sinstall\u00e9",
+ "ScheduledTaskFailedWithName": "{0} a \u00e9chou\u00e9",
+ "ItemAddedWithName": "{0} a \u00e9t\u00e9 ajout\u00e9 \u00e0 la biblioth\u00e8que",
+ "ItemRemovedWithName": "{0} a \u00e9t\u00e9 supprim\u00e9 de la biblioth\u00e8que",
+ "DeviceOnlineWithName": "{0} est connect\u00e9",
+ "UserOnlineFromDevice": "{0} s'est connect\u00e9(e) depuis {1}",
+ "DeviceOfflineWithName": "{0} s'est d\u00e9connect\u00e9(e)",
+ "UserOfflineFromDevice": "{0} s'est d\u00e9connect\u00e9(e) depuis {1}",
+ "SubtitlesDownloadedForItem": "Les sous-titres de {0} sont t\u00e9l\u00e9charg\u00e9s",
+ "SubtitleDownloadFailureForItem": "Le t\u00e9l\u00e9chargement des sous-titres pour {0} a \u00e9chou\u00e9.",
+ "LabelRunningTimeValue": "Dur\u00e9e: {0}",
+ "LabelIpAddressValue": "Adresse IP: {0}",
+ "UserConfigurationUpdatedWithName": "La configuration utilisateur de {0} a \u00e9t\u00e9 mise \u00e0 jour",
+ "UserCreatedWithName": "L'utilisateur {0} a \u00e9t\u00e9 cr\u00e9\u00e9.",
+ "UserPasswordChangedWithName": "Le mot de passe pour l'utilisateur {0} a \u00e9t\u00e9 modifi\u00e9.",
+ "UserDeletedWithName": "L'utilisateur {0} a \u00e9t\u00e9 supprim\u00e9.",
+ "MessageServerConfigurationUpdated": "La configuration du serveur a \u00e9t\u00e9 mise \u00e0 jour.",
+ "MessageNamedServerConfigurationUpdatedWithValue": "La configuration de la section {0} du serveur a \u00e9t\u00e9 mise \u00e0 jour.",
+ "MessageApplicationUpdated": "Media Browser Server a \u00e9t\u00e9 mise \u00e0 jour.",
+ "AuthenticationSucceededWithUserName": "{0} s'est authentifi\u00e9 avec succ\u00e8s",
+ "FailedLoginAttemptWithUserName": "Echec d'une tentative de connexion de {0}",
+ "UserStartedPlayingItemWithValues": "{0} vient de commencer \u00e0 lire {1}",
+ "UserStoppedPlayingItemWithValues": "{0} vient d'arr\u00eater de lire {1}",
+ "AppDeviceValues": "Application : {0}, P\u00e9riph\u00e9rique : {1}",
+ "ProviderValue": "Fournisseur : {0}",
+ "LabelChannelDownloadSizeLimit": "Taille limite de t\u00e9l\u00e9chargement (Go) :",
+ "LabelChannelDownloadSizeLimitHelp": "Limiter la taille du dossier de t\u00e9l\u00e9chargement de la cha\u00eene",
+ "HeaderRecentActivity": "Activit\u00e9 R\u00e9cente"
} \ 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 66c33c3d9..70b2bfe84 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/he.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/he.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "\u05e2\u05d9\u05d3\u05db\u05d5\u05e0\u05d9\u05dd",
- "HeaderUpdateLevel": "\u05e8\u05de\u05ea \u05d4\u05e2\u05d9\u05d3\u05db\u05d5\u05df",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "\u05d4\u05e6\u05d2 \u05e8\u05e7 \u05db\u05ea\u05d5\u05d1\u05d9\u05d5\u05ea \u05de\u05d0\u05d5\u05dc\u05e6\u05d5\u05ea",
- "HeaderCustomizeOptionsPerMediaType": "\u05d0\u05e4\u05e9\u05e8\u05d5\u05d9\u05d5\u05ea \u05d4\u05ea\u05d0\u05de\u05d4 \u05dc\u05e4\u05d9 \u05e1\u05d5\u05d2 \u05de\u05d3\u05d9\u05d4",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "\u05d8\u05e8\u05d9\u05d9\u05dc\u05e8\u05d9\u05dd",
- "LabelFailed": "\u05e0\u05db\u05e9\u05dc",
- "LabelSeries": "\u05e1\u05d3\u05e8\u05d4:",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "HeaderMyLibrary": "My Library",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "\u05d9\u05e6\u05d9\u05d0\u05d4",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "\u05d1\u05e7\u05e8 \u05d1\u05e7\u05d4\u05d9\u05dc\u05d4",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "\u05e1\u05e4\u05e8\u05d9\u05d9\u05ea \u05d4\u05e7\u05d5\u05d3",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "\u05e8\u05d2\u05d9\u05dc",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "\u05e8\u05d0\u05d4 \u05de\u05e1\u05de\u05db\u05d9 \u05e2\u05e8\u05db\u05ea \u05e4\u05d9\u05ea\u05d5\u05d7",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "\u05d3\u05e4\u05d3\u05e3 \u05d1\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "\u05d4\u05d2\u05d3\u05e8 \u05d0\u05ea Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "\u05e4\u05ea\u05d7 \u05de\u05e6\u05d9\u05d2 \u05ea\u05d9\u05e7\u05d9\u05d5\u05ea",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "\u05d0\u05ea\u05d7\u05dc \u05d0\u05ea \u05d4\u05e9\u05e8\u05ea",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "\u05d4\u05e8\u05d0\u05d4 \u05d7\u05dc\u05d5\u05df \u05dc\u05d5\u05d2",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "\u05d4\u05e7\u05d5\u05d3\u05dd",
+ "HeaderPassword": "Password",
"LabelFinish": "\u05e1\u05d9\u05d9\u05dd",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "\u05d4\u05d1\u05d0",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "\u05e1\u05d9\u05d9\u05de\u05ea!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "\u05d1\u05e8\u05d5\u05da \u05d4\u05d1\u05d0 \u05dc- Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "\u05d0\u05e9\u05e3 \u05d6\u05d4 \u05d9\u05e2\u05d6\u05d5\u05e8 \u05dc\u05da \u05d1\u05d4\u05ea\u05dc\u05d9\u05da \u05d4\u05d4\u05ea\u05e7\u05e0\u05d4.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "\u05e1\u05e4\u05e8 \u05dc\u05e0\u05d5 \u05e2\u05dc \u05e2\u05e6\u05de\u05da",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "\u05e9\u05de\u05da \u05d4\u05e4\u05e8\u05d8\u05d9:",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "\u05e0\u05d9\u05ea\u05df \u05dc\u05d4\u05d2\u05d3\u05d9\u05e8 \u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05e0\u05d5\u05e1\u05e4\u05d9\u05dd \u05de\u05d0\u05d5\u05d7\u05e8 \u05d9\u05d5\u05ea\u05e8 \u05d3\u05e8\u05da \u05dc\u05d5\u05d7 \u05d4\u05d1\u05e7\u05e8\u05d4.",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser \u05db\u05d5\u05dc\u05dc \u05ea\u05de\u05d9\u05db\u05d4 \u05de\u05d5\u05d1\u05e0\u05ea \u05d1\u05de\u05e1\u05e4\u05e8 \u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd. \u05d5\u05de\u05d0\u05e4\u05e9\u05e8 \u05dc\u05db\u05dc \u05d0\u05d7\u05d3 \u05de\u05d4\u05dd \u05ea\u05e6\u05d5\u05d2\u05ea \u05d4\u05d2\u05d3\u05e8\u05d5\u05ea, \u05de\u05e6\u05d1 \u05e0\u05d2\u05df \u05d5\u05d1\u05e7\u05e8\u05ea \u05d4\u05d5\u05e8\u05d9\u05dd \u05d0\u05d9\u05e9\u05d9\u05ea.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "\u05e9\u05d9\u05e8\u05d5\u05ea \u05d5\u05d5\u05d9\u05e0\u05d3\u05d5\u05e1",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "\u05e9\u05d9\u05e8\u05d5\u05ea \u05d5\u05d5\u05d9\u05e0\u05d3\u05d5\u05e1 \u05d4\u05d5\u05ea\u05e7\u05df",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "\u05e9\u05e8\u05ea Media Browser \u05e8\u05e5 \u05db\u05ea\u05d5\u05db\u05e0\u05ea \u05e9\u05d5\u05dc\u05d7\u05df \u05e2\u05d1\u05d5\u05d3\u05d4 \u05e2\u05dd \u05d0\u05d9\u05e7\u05d5\u05df \u05d1\u05e9\u05d5\u05e8\u05ea \u05d4\u05de\u05e9\u05d9\u05de\u05d5\u05ea, \u05d0\u05d1\u05dc \u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e2\u05d3\u05d9\u05e3 \u05dc\u05d4\u05e8\u05d9\u05e5 \u05d0\u05ea \u05d4\u05e9\u05e8\u05ea \u05db\u05e9\u05d9\u05e8\u05d5\u05ea \u05e8\u05e7\u05e2, \u05e0\u05d9\u05ea\u05df \u05dc\u05d4\u05ea\u05d7\u05d9\u05dc \u05d0\u05ea \u05d4\u05e9\u05e8\u05ea \u05de\u05ea\u05d5\u05da \u05d7\u05dc\u05d5\u05df \u05d4\u05d1\u05e7\u05d4 \u05e9\u05dc \u05e9\u05d9\u05e8\u05d5\u05ea\u05d9 \u05d5\u05d5\u05d9\u05e0\u05d3\u05d5\u05e1 \u05d1\u05de\u05e7\u05d5\u05dd.",
+ "HeaderIdentifyItem": "Identify Item",
"WindowsServiceIntro2": "\u05d0\u05dd \u05d0\u05ea\u05d4 \u05de\u05e4\u05e2\u05d9\u05dc \u05d0\u05ea \u05d4\u05e9\u05d9\u05e8\u05d5\u05ea \u05d5\u05d5\u05d9\u05e0\u05d3\u05d5\u05e1, \u05d1\u05d1\u05e7\u05e9\u05d4 \u05e9\u05d9\u05dd \u05dc\u05d1 \u05e9\u05d4\u05d5\u05d0 \u05dc\u05d0 \u05d9\u05db\u05d5\u05dc \u05dc\u05e8\u05d5\u05e5 \u05d1\u05d0\u05d5\u05ea\u05d5 \u05d6\u05de\u05df \u05e9\u05d4\u05e9\u05e8\u05ea \u05db\u05d1\u05e8 \u05e2\u05d5\u05d1\u05d3 \u05d1\u05e8\u05e7\u05e2. \u05dc\u05db\u05df \u05ea\u05e6\u05d8\u05e8\u05da \u05dc\u05e1\u05d2\u05d5\u05e8 \u05d0\u05ea \u05d4\u05e9\u05e8\u05ea \u05e2\u05dc \u05de\u05e0\u05ea \u05dc\u05d4\u05e4\u05e2\u05d9\u05dc \u05d0\u05ea \u05d4\u05e9\u05d9\u05e8\u05d5\u05ea. \u05d4\u05e9\u05d9\u05e8\u05d5\u05ea \u05d2\u05dd \u05e6\u05e8\u05d9\u05da \u05dc\u05d4\u05d9\u05d5\u05ea \u05de\u05d5\u05d2\u05d3\u05e8 \u05e2\u05dd \u05d4\u05e8\u05e9\u05d0\u05d5\u05ea \u05de\u05e0\u05d4\u05dc \u05d3\u05e8\u05da \u05dc\u05d5\u05d7 \u05d4\u05d1\u05e7\u05e8\u05d4. \u05d1\u05d1\u05e7\u05e9\u05d4 \u05e7\u05d7 \u05d1\u05d7\u05e9\u05d1\u05d5\u05df \u05e9\u05db\u05e8\u05d2\u05e2 \u05d4\u05e9\u05d9\u05e8\u05d5\u05ea \u05dc\u05d0 \u05d9\u05db\u05d5\u05dc \u05dc\u05e2\u05d3\u05db\u05df \u05d0\u05ea \u05e2\u05e6\u05de\u05d5 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea, \u05d5\u05dc\u05db\u05df \u05d2\u05d9\u05e8\u05e1\u05d0\u05d5\u05ea \u05d7\u05d3\u05e9\u05d5\u05ea \u05d9\u05e6\u05e8\u05d9\u05db\u05d5 \u05e2\u05d9\u05d3\u05db\u05d5\u05df \u05d9\u05d3\u05e0\u05d9.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "\u05d6\u05d4 \u05db\u05dc \u05de\u05d4 \u05e9\u05e6\u05e8\u05d9\u05da \u05dc\u05e2\u05db\u05e9\u05d9\u05d5. Media Browser \u05d4\u05d7\u05dc \u05dc\u05d0\u05e1\u05d5\u05e3 \u05de\u05d9\u05d3\u05e2 \u05dc\u05d2\u05d1\u05d9 \u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05d4\u05de\u05d3\u05d9\u05d4 \u05e9\u05dc\u05da. \u05d0\u05dc \u05ea\u05e9\u05db\u05d7 \u05dc\u05d1\u05d3\u05d5\u05e7 \u05d0\u05ea \u05de\u05d2\u05d5\u05d5\u05df \u05d4\u05d0\u05e4\u05dc\u05d9\u05e7\u05e6\u05d9\u05d5\u05ea \u05e9\u05dc\u05e0\u05d5, \u05d5\u05d0\u05d6 \u05dc\u05d7\u05e5 <b>\u05e1\u05d9\u05d9\u05dd<\/b> \u05dc\u05e8\u05d0\u05d5\u05ea \u05d0\u05ea \u05d4<b>\u05dc\u05d5\u05d7 \u05d1\u05e7\u05e8\u05d4<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
"LabelConfigureSettings": "\u05e7\u05d1\u05e2 \u05d0\u05ea \u05ea\u05e6\u05d5\u05e8\u05ea \u05d4\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "\u05d0\u05e4\u05e9\u05e8 \u05e9\u05dc\u05d9\u05e4\u05ea \u05ea\u05de\u05d5\u05e0\u05d4 \u05de\u05e1\u05e8\u05d8",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"VideoImageExtractionHelp": "\u05e2\u05d1\u05d5\u05e8 \u05e1\u05e8\u05d8\u05d9\u05dd \u05e9\u05d0\u05d9\u05df \u05dc\u05d4\u05dd \u05db\u05d1\u05e8 \u05ea\u05de\u05d5\u05e0\u05d4, \u05d5\u05dc\u05d0 \u05e0\u05de\u05e6\u05d0\u05d4 \u05dc\u05d4\u05dd \u05d0\u05d7\u05ea \u05d1\u05d0\u05d9\u05e0\u05d8\u05e8\u05e0\u05d8. \u05d4\u05d2\u05d3\u05e8\u05d4 \u05d6\u05d5 \u05ea\u05d5\u05e1\u05d9\u05e3 \u05de\u05e2\u05d8 \u05d6\u05de\u05df \u05dc\u05ea\u05d4\u05dc\u05d9\u05da \u05e1\u05e8\u05d9\u05e7\u05ea \u05d4\u05ea\u05e7\u05d9\u05d9\u05d4 \u05d4\u05e8\u05d0\u05e9\u05d5\u05e0\u05d9, \u05d0\u05da \u05ea\u05e1\u05e4\u05e7 \u05ea\u05e6\u05d5\u05d2\u05d4 \u05d9\u05d5\u05ea\u05e8 \u05d9\u05e4\u05d4.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "\u05d7\u05dc\u05e5 \u05ea\u05de\u05d5\u05e0\u05ea \u05e4\u05e8\u05e7 \u05dc\u05e1\u05e8\u05d8\u05d9\u05dd",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "\u05d7\u05d9\u05dc\u05d5\u05e5 \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05e4\u05e8\u05e7\u05d9\u05dd \u05d9\u05d0\u05e4\u05e9\u05e8 \u05dc\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05dc\u05e8\u05d0\u05d5\u05ea \u05ea\u05e4\u05e8\u05d9\u05d8 \u05d1\u05d7\u05d9\u05e8\u05ea \u05e1\u05e6\u05e0\u05d5\u05ea \u05d2\u05e8\u05e4\u05d9. \u05d4\u05ea\u05d4\u05dc\u05d9\u05da \u05d9\u05db\u05d5\u05dc \u05dc\u05d4\u05d9\u05d5\u05ea \u05d0\u05d9\u05d8\u05d9, \u05dc\u05d3\u05e8\u05d5\u05e9 \u05de\u05e9\u05d0\u05d1\u05d9 \u05de\u05e2\u05d1\u05d3 \u05e8\u05d1\u05d9\u05dd \u05d5\u05dc\u05ea\u05e4\u05d5\u05e1 \u05e9\u05d8\u05d7 \u05d0\u05d9\u05d7\u05e1\u05d5\u05df \u05e8\u05d1. \u05d0\u05e4\u05e9\u05e8\u05d5\u05ea \u05d6\u05d5 \u05e8\u05e6\u05d4 \u05db\u05de\u05e9\u05d9\u05de\u05d4 \u05de\u05ea\u05d5\u05d6\u05de\u05e0\u05ea \u05d1\u05d0\u05e8\u05d1\u05e2 \u05dc\u05e4\u05e0\u05d5\u05ea \u05d1\u05d5\u05e7\u05e8, \u05d0\u05da \u05d6\u05d4 \u05e0\u05d9\u05ea\u05df \u05dc\u05e9\u05d9\u05e0\u05d5\u05d9 \u05d1\u05d7\u05dc\u05d5\u05df \u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05d4\u05de\u05e9\u05d9\u05de\u05d5\u05ea \u05d4\u05de\u05ea\u05d5\u05d6\u05de\u05e0\u05d5\u05ea. \u05d6\u05d4 \u05dc\u05d0 \u05de\u05de\u05d5\u05dc\u05e5 \u05dc\u05d4\u05e4\u05e2\u05d9\u05dc \u05de\u05e9\u05d9\u05de\u05d4 \u05d6\u05d5 \u05d1\u05e9\u05e2\u05d5\u05ea \u05d4\u05e9\u05d9\u05de\u05d5\u05e9 \u05d4\u05e2\u05d9\u05e7\u05e8\u05d9\u05d5\u05ea \u05d1\u05de\u05d7\u05e9\u05d1.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "\u05d0\u05e4\u05e9\u05e8 \u05de\u05d9\u05e4\u05d5\u05d9 \u05e4\u05d5\u05e8\u05d8\u05d9\u05dd \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP \u05de\u05d0\u05e4\u05e9\u05e8 \u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05d5\u05ea \u05e9\u05dc \u05d4\u05e8\u05d0\u05d5\u05d8\u05e8 \u05dc\u05d0\u05e4\u05e9\u05e8 \u05d2\u05d9\u05e9\u05d4 \u05de\u05e8\u05d5\u05d7\u05e7\u05ea \u05d1\u05e7\u05dc\u05d5\u05ea. \u05d0\u05e4\u05e9\u05e8\u05d5\u05ea \u05d6\u05d5 \u05e2\u05dc\u05d5\u05dc\u05d4 \u05dc\u05d0 \u05dc\u05e2\u05d1\u05d5\u05d3 \u05e2\u05dd \u05db\u05dc \u05d3\u05d2\u05de\u05d9 \u05d4\u05e8\u05d0\u05d5\u05d8\u05e8\u05d9\u05dd.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "\u05d0\u05e9\u05e8",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "\u05d1\u05d8\u05dc",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "\u05d7\u05d3\u05e9",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "\u05d4\u05d2\u05d3\u05e8 \u05d0\u05ea \u05e1\u05e4\u05e8\u05d9\u05d9\u05ea \u05d4\u05de\u05d3\u05d9\u05d4 \u05e9\u05dc\u05da",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "\u05d4\u05d5\u05e1\u05e3 \u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05de\u05d3\u05d9\u05d4",
+ "LabelWebsite": "Website:",
"LabelFolderType": "\u05e1\u05d5\u05d2 \u05d4\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4:",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* \u05de\u05e6\u05e8\u05d9\u05da \u05de\u05d4\u05de\u05e9\u05ea\u05de\u05e9 \u05ea\u05d5\u05e1\u05e3, \u05dc\u05d3\u05d5\u05d2\u05de\u05d0 GameBrowser \u05d0\u05d5 MB Bookshelf",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "\u05e4\u05e0\u05d4 \u05dc\u05de\u05d9\u05d3\u05e2 \u05d0\u05d5\u05d3\u05d5\u05ea \u05e1\u05e4\u05e8\u05d9\u05d9\u05ea \u05d4\u05de\u05d3\u05d9\u05d4.",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "\u05de\u05d3\u05d9\u05e0\u05d4:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "\u05e9\u05e4\u05d4:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "\u05e9\u05e4\u05ea \u05de\u05d9\u05d3\u05e2 \u05de\u05d5\u05e2\u05d3\u05e4\u05ea:",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "\u05e9\u05de\u05d5\u05e8 \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05e8\u05e7\u05e2 \u05d5\u05de\u05d9\u05d3\u05e2 \u05d1\u05ea\u05d5\u05da \u05e1\u05e4\u05e8\u05d9\u05d5\u05ea \u05d4\u05de\u05d3\u05d9\u05d4",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "\u05e9\u05de\u05d9\u05e8\u05ea \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05e8\u05e7\u05e2 \u05d5\u05de\u05d9\u05d3\u05e2 \u05d9\u05e9\u05d9\u05e8\u05d5\u05ea \u05d1\u05e1\u05e4\u05e8\u05d9\u05d5\u05ea \u05d4\u05de\u05d3\u05d9\u05d4 \u05ea\u05d0\u05e4\u05e9\u05e8 \u05e2\u05e8\u05d9\u05db\u05d4 \u05e0\u05d5\u05d7\u05d4 \u05d5\u05e7\u05dc\u05d4 \u05e9\u05dc\u05d4\u05dd.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "\u05d4\u05d5\u05e8\u05d3 \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05e8\u05e7\u05e2 \u05d5\u05de\u05d9\u05d3\u05e2 \u05de\u05d4\u05d0\u05d9\u05e0\u05e8\u05e0\u05d8",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser \u05d9\u05db\u05d5\u05dc \u05dc\u05d4\u05d5\u05e8\u05d9\u05d3 \u05de\u05d9\u05d3\u05e2 \u05dc\u05d2\u05d1\u05d9 \u05e7\u05d1\u05e6\u05d9 \u05d4\u05de\u05d3\u05d9\u05d4 \u05e9\u05dc\u05da \u05db\u05d3\u05d9 \u05d0\u05e4\u05e9\u05e8 \u05ea\u05e6\u05d5\u05d2\u05d4 \u05e2\u05e9\u05d9\u05e8\u05d4.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "\u05d4\u05e2\u05d3\u05e4\u05d5\u05ea",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "\u05e1\u05d9\u05e1\u05de\u05d0",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "\u05d2\u05d9\u05e9\u05d4 \u05dc\u05ea\u05d9\u05e7\u05d9\u05d5\u05ea",
+ "LabelBudget": "Budget",
"TabImage": "\u05ea\u05de\u05d5\u05e0\u05d4",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "\u05e4\u05e8\u05d5\u05e4\u05d9\u05dc",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "\u05ea\u05de\u05d5\u05e0\u05d5\u05ea",
+ "Label3DFormat": "3D format:",
"TabNotifications": "\u05d4\u05ea\u05e8\u05d0\u05d5\u05ea",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "\u05db\u05d5\u05ea\u05e8\u05d9\u05dd",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "\u05d4\u05e6\u05d2 \u05e4\u05e8\u05e7\u05d9\u05dd \u05d7\u05e1\u05e8\u05d9\u05dd \u05d1\u05ea\u05d5\u05da \u05d4\u05e2\u05d5\u05e0\u05d5\u05ea",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "\u05d4\u05e6\u05d2 \u05e4\u05e8\u05e7\u05d9\u05dd \u05e9\u05e2\u05d3\u05d9\u05df \u05d0\u05dc \u05e9\u05d5\u05d3\u05e8\u05d5 \u05d1\u05ea\u05d5\u05da \u05d4\u05e2\u05d5\u05e0\u05d5\u05ea",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05e0\u05d9\u05d2\u05d5\u05df",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "\u05d0\u05e4\u05e9\u05e8\u05d5\u05d9\u05d5\u05ea \u05e0\u05d9\u05d2\u05d5\u05df",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "\u05e9\u05e4\u05ea \u05e7\u05d5\u05dc \u05de\u05d5\u05e2\u05d3\u05e4\u05ea:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "\u05e9\u05e4\u05ea \u05db\u05ea\u05d5\u05d1\u05d9\u05d5\u05ea \u05de\u05d5\u05e2\u05d3\u05e4\u05ea:",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
"TabProfiles": "\u05e4\u05e8\u05d5\u05e4\u05d9\u05dc\u05d9\u05dd",
+ "HeaderTags": "Tags",
"TabSecurity": "\u05d1\u05d8\u05d9\u05d7\u05d5\u05ea",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "\u05d4\u05d5\u05e1\u05e3 \u05de\u05e9\u05ea\u05de\u05e9",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "\u05e9\u05de\u05d5\u05e8",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "\u05d0\u05d9\u05e4\u05d5\u05e1 \u05e1\u05d9\u05e1\u05de\u05d0",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "\u05e1\u05d9\u05e1\u05de\u05d0 \u05d7\u05d3\u05e9\u05d4:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "\u05d0\u05d9\u05de\u05d5\u05ea \u05e1\u05d9\u05e1\u05de\u05d0 \u05d7\u05d3\u05e9\u05d4:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "\u05e6\u05d5\u05e8 \u05e1\u05d9\u05e1\u05de\u05d0",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "\u05e1\u05d9\u05e1\u05de\u05d0 \u05e0\u05d5\u05db\u05d7\u05d9\u05ea:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "\u05d3\u05d9\u05e8\u05d5\u05d2 \u05d4\u05d5\u05e8\u05d9\u05dd \u05de\u05e7\u05e1\u05d9\u05de\u05d0\u05dc\u05d9:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "\u05ea\u05d5\u05db\u05df \u05e2\u05dd \u05d3\u05d9\u05e8\u05d5\u05d2 \u05d2\u05d5\u05d1\u05d4 \u05d9\u05d5\u05ea\u05e8 \u05d9\u05d5\u05e1\u05ea\u05e8 \u05de\u05d4\u05de\u05e9\u05ea\u05de\u05e9.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "\u05d1\u05d7\u05e8 \u05d0\u05ea \u05e1\u05e4\u05e8\u05d9\u05d5\u05ea \u05d4\u05de\u05d3\u05d9\u05d4 \u05d0\u05e9\u05e8 \u05d9\u05e9\u05d5\u05ea\u05e4\u05d5 \u05e2\u05dd \u05d4\u05de\u05e9\u05ea\u05de\u05e9. \u05de\u05e0\u05d4\u05dc\u05d9\u05dd \u05d9\u05d5\u05db\u05dc\u05d5 \u05dc\u05e2\u05e8\u05d5\u05ea \u05d0\u05ea \u05db\u05dc \u05d4\u05ea\u05d9\u05e7\u05d9\u05d5\u05ea \u05d1\u05d0\u05de\u05e6\u05e2\u05d5\u05ea \u05e2\u05d5\u05e8\u05da \u05d4\u05de\u05d9\u05d3\u05e2.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "\u05de\u05d7\u05e7 \u05ea\u05de\u05d5\u05e0\u05d4",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "\u05d1\u05d7\u05e8 \u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd:",
+ "OptionActor": "Actor",
"ButtonUpload": "\u05d4\u05e2\u05dc\u05d4",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "\u05d4\u05e2\u05dc\u05d4 \u05ea\u05de\u05d5\u05e0\u05d4 \u05d7\u05d3\u05e9\u05d4",
+ "OptionDirector": "Director",
"LabelDropImageHere": "\u05e9\u05d7\u05e8\u05e8 \u05ea\u05de\u05d5\u05e0\u05d4 \u05db\u05d0\u05df",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "\u05de\u05d5\u05de\u05dc\u05e5 \u05d9\u05d7\u05e1 \u05d2\u05d5\u05d1\u05d4 \u05e9\u05dc 1:1. \u05e8\u05e7 JPG\/PNG.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "\u05d0\u05d9\u05df \u05db\u05d0\u05df \u05db\u05dc\u05d5\u05dd.",
+ "OptionWriter": "Writer",
"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",
+ "LabelAirDays": "Air days:",
"TabSuggested": "\u05de\u05de\u05d5\u05dc\u05e5",
+ "LabelAirTime": "Air time:",
"TabLatest": "\u05d0\u05d7\u05e8\u05d5\u05df",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "\u05d1\u05e7\u05e8\u05d5\u05d1",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "\u05ea\u05d5\u05db\u05e0\u05d9\u05d5\u05ea",
"TabEpisodes": "\u05e4\u05e8\u05e7\u05d9\u05dd",
"TabGenres": "\u05d6\u05d0\u05e0\u05e8\u05d9\u05dd",
@@ -163,7 +225,7 @@
"OptionAscending": "\u05e1\u05d3\u05e8 \u05e2\u05d5\u05dc\u05d4",
"OptionDescending": "\u05e1\u05d3\u05e8 \u05d9\u05d5\u05e8\u05d3",
"OptionRuntime": "\u05de\u05e9\u05da",
- "OptionReleaseDate": "\u05ea\u05d0\u05e8\u05d9\u05da \u05e9\u05d9\u05d7\u05e8\u05d5\u05e8",
+ "OptionReleaseDate": "Release Date",
"OptionPlayCount": "\u05de\u05e1\u05e4\u05e8 \u05d4\u05e9\u05de\u05e2\u05d5\u05ea",
"OptionDatePlayed": "\u05ea\u05d0\u05e8\u05d9\u05da \u05e0\u05d9\u05d2\u05d5\u05df",
"OptionDateAdded": "\u05ea\u05d0\u05e8\u05d9\u05da \u05d4\u05d5\u05e1\u05e4\u05d4",
@@ -213,6 +275,8 @@
"TabMovies": "\u05e1\u05e8\u05d8\u05d9\u05dd",
"TabStudios": "\u05d0\u05d5\u05dc\u05e4\u05e0\u05d9\u05dd",
"TabTrailers": "\u05d8\u05e8\u05d9\u05d9\u05dc\u05e8\u05d9\u05dd",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "\u05e1\u05e8\u05d8\u05d9\u05dd \u05d0\u05d7\u05e8\u05d5\u05e0\u05d9\u05dd",
"HeaderLatestTrailers": "\u05d8\u05e8\u05d9\u05d9\u05dc\u05d9\u05e8\u05d9\u05dd \u05d0\u05d7\u05e8\u05d5\u05e0\u05d9\u05dd",
"OptionHasSpecialFeatures": "\u05de\u05d0\u05e4\u05d9\u05d9\u05e0\u05d9\u05dd \u05de\u05d9\u05d5\u05d7\u05d3\u05d9\u05dd",
@@ -233,6 +297,7 @@
"OptionFriday": "\u05e9\u05d9\u05e9\u05d9",
"OptionSaturday": "\u05e9\u05d1\u05ea",
"HeaderManagement": "\u05e0\u05d9\u05d4\u05d5\u05dc",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "\u05d7\u05e1\u05e8 \u05de\u05d6\u05d4\u05d4 IMBb",
"OptionMissingTvdbId": "\u05d7\u05e1\u05e8 \u05de\u05d6\u05d4\u05d4 TheTVDB",
"OptionMissingOverview": "\u05d7\u05e1\u05e8\u05d4 \u05e1\u05e7\u05d9\u05e8\u05d4",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "\u05d1\u05d7\u05e8",
- "ButtonSearch": "\u05d7\u05d9\u05e4\u05d5\u05e9",
"ButtonGroupVersions": "\u05e7\u05d1\u05d5\u05e6\u05ea \u05d2\u05e8\u05e1\u05d0\u05d5\u05ea",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "\u05d0\u05e4\u05e9\u05e8 \u05d8\u05e2\u05d9\u05e0\u05ea \u05e7\u05d1\u05e6\u05d9 Pismo \u05d3\u05e8\u05da \u05e8\u05d9\u05e9\u05d9\u05d5\u05df \u05ea\u05e8\u05d5\u05de\u05d4.",
@@ -347,6 +411,8 @@
"TabStatus": "\u05de\u05e6\u05d1",
"TabSettings": "\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea",
"ButtonRefreshGuideData": "\u05e8\u05e2\u05e0\u05df \u05d0\u05ea \u05de\u05d3\u05e8\u05d9\u05da \u05d4\u05e9\u05d9\u05d3\u05d5\u05e8",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "\u05e2\u05d3\u05d9\u05e4\u05d5\u05ea",
"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",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "\u05e9\u05d7\u05e7\u05e0\u05d9\u05dd \u05d5\u05e6\u05d5\u05d5\u05ea",
"HeaderAdditionalParts": "\u05d7\u05dc\u05e7\u05d9\u05dd \u05e0\u05d5\u05e1\u05e4\u05d9\u05dd",
"ButtonSplitVersionsApart": "\u05e4\u05e6\u05dc \u05d2\u05e8\u05e1\u05d0\u05d5\u05ea \u05d1\u05e0\u05e4\u05e8\u05d3",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "\u05d7\u05e1\u05e8",
"LabelOffline": "\u05dc\u05d0 \u05de\u05e7\u05d5\u05d5\u05df",
"PathSubstitutionHelp": "\u05e0\u05ea\u05d9\u05d1\u05d9\u05dd \u05d7\u05dc\u05d5\u05e4\u05d9\u05d9\u05dd \u05d4\u05dd \u05dc\u05e6\u05d5\u05e8\u05da \u05de\u05d9\u05e4\u05d5\u05d9 \u05e0\u05ea\u05d9\u05d1\u05d9\u05dd \u05d1\u05e9\u05e8\u05ea \u05dc\u05e0\u05ea\u05d9\u05d1\u05d9\u05dd \u05e9\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05d9\u05db\u05d5\u05dc\u05d9\u05dd \u05dc\u05d2\u05e9\u05ea \u05d0\u05dc\u05d9\u05d4\u05dd. \u05e2\u05dc \u05d9\u05d3\u05d9 \u05d4\u05e8\u05e9\u05d0\u05d4 \u05dc\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05d2\u05d9\u05e9\u05d4 \u05d9\u05e9\u05d9\u05e8\u05d4 \u05dc\u05de\u05d3\u05d9\u05d4 \u05d1\u05e9\u05e8\u05ea \u05d0\u05dd \u05d9\u05db\u05d5\u05dc\u05d9\u05dd \u05dc\u05e0\u05d2\u05df \u05d0\u05ea \u05d4\u05e7\u05d1\u05e6\u05d9\u05dd \u05d9\u05e9\u05d9\u05e8\u05d5\u05ea \u05e2\u05dc \u05d2\u05d1\u05d9 \u05d4\u05e8\u05e9\u05ea \u05d5\u05dc\u05d4\u05d9\u05de\u05e0\u05e2 \u05de\u05e9\u05d9\u05de\u05d5\u05e9 \u05d1\u05de\u05e9\u05d0\u05d1\u05d9 \u05d4\u05e9\u05e8\u05ea \u05dc\u05e6\u05d5\u05e8\u05da \u05e7\u05d9\u05d3\u05d5\u05d3 \u05d5\u05e9\u05d9\u05d3\u05d5\u05e8.",
@@ -512,8 +579,10 @@
"HeaderProgram": "\u05ea\u05d5\u05db\u05e0\u05d4",
"HeaderClients": "\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd",
"LabelCompleted": "\u05d4\u05d5\u05e9\u05dc\u05dd",
+ "LabelFailed": "Failed",
"LabelSkipped": "\u05d3\u05d5\u05dc\u05d2",
"HeaderEpisodeOrganization": "\u05d0\u05d9\u05e8\u05d2\u05d5\u05df \u05e4\u05e8\u05e7\u05d9\u05dd",
+ "LabelSeries": "Series:",
"LabelSeasonNumber": "\u05de\u05e1\u05e4\u05e8 \u05e2\u05d5\u05e0\u05d4:",
"LabelEpisodeNumber": "\u05de\u05e1\u05e4\u05e8 \u05e4\u05e8\u05e7:",
"LabelEndingEpisodeNumber": "\u05de\u05e1\u05e4\u05e8 \u05e1\u05d9\u05d5\u05dd \u05e4\u05e8\u05e7:",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "\u05d0\u05e4\u05e9\u05e8 \u05d4\u05ea\u05e8\u05d0\u05d4 \u05d6\u05d5",
"LabelMonitorUsers": "\u05e2\u05e7\u05d5\u05d1 \u05d0\u05d7\u05e8 \u05e4\u05e2\u05d9\u05dc\u05d5\u05ea \u05de:",
"LabelSendNotificationToUsers": "\u05e9\u05dc\u05d7 \u05d0\u05ea \u05d4\u05d4\u05ea\u05e8\u05d0\u05d4 \u05dc:",
- "UsersNotNotifiedAboutSelfActivity": "\u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd \u05dc\u05d0 \u05d9\u05e7\u05d1\u05dc\u05d5 \u05d4\u05d5\u05d3\u05e2\u05d5\u05ea \u05dc\u05d2\u05d1\u05d9 \u05d4\u05e4\u05e2\u05d9\u05dc\u05d5\u05ea \u05e9\u05dc\u05d4\u05dd",
"LabelUseNotificationServices": "\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05e9\u05d9\u05e8\u05d5\u05ea\u05d9\u05dd \u05d4\u05d1\u05d0\u05d9\u05dd:",
"CategoryUser": "\u05de\u05e9\u05ea\u05de\u05e9",
"CategorySystem": "\u05de\u05e2\u05e8\u05db\u05ea",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
"ButtonHome": "Home",
+ "ButtonSearch": "\u05d7\u05d9\u05e4\u05d5\u05e9",
"ButtonSettings": "Settings",
"ButtonTakeScreenshot": "Capture Screenshot",
"ButtonLetterUp": "Letter Up",
@@ -661,6 +730,8 @@
"ButtonScenes": "Scenes",
"ButtonSubtitles": "Subtitles",
"ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Group movies into collections",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
"LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "Friendly name",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text",
"HeaderSearchForSubtitles": "Search for Subtitles",
@@ -796,13 +879,13 @@
"OptionAuto": "Auto",
"OptionYes": "Yes",
"OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferences",
"MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Mark Read",
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
"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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
"ButtonDismiss": "Dismiss",
"MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Display adult content",
"OptionLibraryFolders": "Media folders",
"TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 53e13727b..a8ffcc2eb 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/it.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/it.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Aggiornamenti",
- "HeaderUpdateLevel": "Livello",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "Visualizzare solo i sottotitoli forzati",
- "HeaderCustomizeOptionsPerMediaType": "Personalizza le opzioni per i media.",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Personalizzazioni",
- "HeaderAllDevices": "Tutti i dispositivi",
- "HeaderThisDevice": "Questo dispositivo",
- "OptionLibraryButtons": "Bottoni libreria",
- "OptionLibraryTiles": "Files Libreria",
- "OptionSmallLibraryTiles": "Titles Biblioteca (piccolo)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Fallito",
- "LabelSeries": "Serie:",
- "ButtonPreviousTrack": "Precedente",
- "ButtonNextTrack": "Prossimo",
- "HeaderMyLibrary": "Mia Libreria",
- "HeaderLibraryViews": "Biblioteca Visualizzazioni",
+ "HeaderPeople": "Persone",
"LabelExit": "Esci",
+ "HeaderDownloadPeopleMetadataFor": "Scarica biografia e immagini per:",
"LabelVisitCommunity": "Visita Comunit\u00e0",
+ "OptionComposers": "Compositori",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Altri",
"LabelSwagger": "Swagger",
"LabelStandard": "Standard",
+ "HeaderDownloadPeopleMetadataForHelp": "Abilitando il provider scaricher\u00e0 pi\u00f9 informazioni ( la scansione sar\u00e0 pi\u00f9 lenta)",
"LabelViewApiDocumentation": "Documentazione Api",
- "LabelBrowseLibrary": "Apri Media Browser",
+ "ViewTypeFolders": "Cartelle",
+ "LabelBrowseLibrary": "Esplora la libreria",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "Configura Media Browser",
- "LabelOpenLibraryViewer": "Esplora la Libreria",
+ "ViewTypeLiveTvRecordingGroups": "Registrazioni",
+ "LabelOpenLibraryViewer": "Apri visualizzatore libreria",
+ "ViewTypeLiveTvChannels": "canali",
"LabelRestartServer": "Riavvia Server",
+ "LabelAllowLocalAccessWithoutPassword": "Consenti di accedere localmente senza password",
"LabelShowLogWindow": "Mostra Finestra log",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "Quando abilitato la password non \u00e8 necessaria",
"LabelPrevious": "Precedente",
+ "HeaderPassword": "Password",
"LabelFinish": "Finito",
+ "HeaderLocalAccess": "Accesso locale",
"LabelNext": "Prossimo",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "Tu hai Finito!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "Benvenuto in Media browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "Procedura Guidata per l'installazione.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "Parlaci di te",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "Nome",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "Puoi aggiungere altri utenti in un secondo momento all'interno del pannello di configurazione",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser include il supporto integrato per i profili utente, permettendo ad ogni utente di avere le proprie impostazioni di visualizzazione.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Servizio Windows",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "Servizio Windows Installato",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser Server, normalmente viene eseguito come un'applicazione desktop con una icona nella barra, ma se si preferisce farlo funzionare come un servizio in background, pu\u00f2 essere avviato dal pannello di controllo dei servizi di Windows, invece.",
+ "HeaderIdentifyItem": "Identify Item",
"WindowsServiceIntro2": "Se si utilizza il servizio di Windows, si ricorda che non pu\u00f2 essere eseguito allo stesso tempo come 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",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "Questo \u00e8 tutto abbiamo bisogno per ora. Browser Media ha iniziato a raccogliere informazioni sulla vostra libreria multimediale. Scopri alcune delle nostre applicazioni, quindi fare clic su <b>Finito<\/b> per aprire<b>il pannello di controllo<\/b>.",
+ "HeaderConfirmDeletion": "Conferma Cancellazione",
"LabelConfigureSettings": "Configura",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Estrazione immagine video non possibile",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"VideoImageExtractionHelp": "Per i video che sono sprovvisti di immagini,e che non siamo riusciti a trovarle su Internet.Questo aggiunger\u00e0 del tempo addizionale alla scansione della tua libreria ma si tradurr\u00e0 in una presentazione pi\u00f9 piacevole.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Estrazione immagine capitolo estratto per Film",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "L'Estrazione di immagini capitoli permetter\u00e0 ai clienti di visualizzare i menu di selezione delle scene . Il processo pu\u00f2 essere lento e pu\u00f2 richiedere diversi gigabyte di spazio. Viene schedulato alle 04:00, anche se questo \u00e8 configurabile nella zona di operazioni pianificate. Non \u00e8 consigliabile eseguire questa operazione durante le ore di picco.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Abilita mappatura delle porte automatiche",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP consente la configurazione automatica del router per l'accesso remoto facile. Questo potrebbe non funzionare con alcuni modelli di router.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "OK",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Annulla",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "Nuovo",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Configura la tua libreria",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "Aggiungi cartella",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Tipo cartella",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Richiede l'uso di un plugin, ad esempio GameBrowser o MB Bookshelf.",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Fare riferimento alla wiki libreria multimediale.",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "Nazione:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "lingua:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "Lingua dei metadati preferita:",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "Salva immagini e metadati nelle cartelle multimediali",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "Il salvataggio di immagini e dei metadati direttamente nelle cartelle multimediali verranno messe in un posto dove possono essere facilmente modificate.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "Scarica immagini e dei metadati da internet",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser pu\u00f2 scaricare informazioni sui vostri media per consentire presentazioni migliori.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "Preferenze",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "Password",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "Accesso libreria",
+ "LabelBudget": "Budget",
"TabImage": "Immagine",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "Profilo",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "Immagini",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifiche",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "Titolo",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Visualizza gli episodi mancanti nelle stagioni",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Visualizzare episodi mai andati in onda all'interno stagioni",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "Impostazioni di riproduzione video",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Impostazioni di riproduzione",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "Audio preferenze di lingua:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "Sottotitoli preferenze di lingua:",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Predefinito",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Solo i sottotitoli forzati",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Visualizza sempre i sottotitoli",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "Nessun Sottotitolo",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Sottotitoli corrispondenti alla lingua di preferenza saranno caricati quando l'audio \u00e8 in una lingua straniera.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Solo sottotitoli contrassegnati come forzati saranno caricati.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Sottotitoli corrispondenti alla lingua di preferenza saranno caricati a prescindere dalla lingua audio.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "I sottotitoli non verranno caricati di default.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Profili",
+ "HeaderTags": "Tags",
"TabSecurity": "Sicurezza",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "Aggiungi Utente",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "Salva",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "Reset Password",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "Nuova Password:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "Nuova Password Conferma:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "Crea Password",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Password Corrente:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "Massima valutazione dei genitori consentita:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "Contento di un punteggio pi\u00f9 elevato sar\u00e0 nascosto da questo utente.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "Selezionare le cartelle multimediali da condividere con questo utente. Gli amministratori saranno in grado di modificare tutte le cartelle utilizzando il gestore dei metadati.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Selezionare i canali da condividere con questo utente. Gli amministratori saranno in grado di modificare tutti i canali usando il gestore dei metadati",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "Elimina immagine",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "Seleziona Utenti:",
+ "OptionActor": "Actor",
"ButtonUpload": "Carica",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Carica nuova immagine",
- "LabelDropImageHere": "Trascina immagine qui",
+ "OptionDirector": "Director",
+ "LabelDropImageHere": "Trascina l'immagine qui",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Niente qui.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "Assicurarsi che download di metadati internet \u00e8 abilitata.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Suggeriti",
+ "LabelAirTime": "Air time:",
"TabLatest": "Novit\u00e0",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "IN ONDA A BREVE",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Serie",
"TabEpisodes": "Episodi",
"TabGenres": "Generi",
@@ -163,7 +225,7 @@
"OptionAscending": "Ascendente",
"OptionDescending": "Discentente",
"OptionRuntime": "Durata",
- "OptionReleaseDate": "Uscito il",
+ "OptionReleaseDate": "Release Date",
"OptionPlayCount": "Visto N\u00b0",
"OptionDatePlayed": "Visto il",
"OptionDateAdded": "Aggiunto il",
@@ -213,6 +275,8 @@
"TabMovies": "Film",
"TabStudios": "Studios",
"TabTrailers": "Trailer",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "Ultimi Film Aggiunti",
"HeaderLatestTrailers": "Ultimi Trailers Aggiunti",
"OptionHasSpecialFeatures": "Caratteristiche speciali",
@@ -232,7 +296,8 @@
"OptionThursday": "Giovedi",
"OptionFriday": "Venerdi",
"OptionSaturday": "Sabato",
- "HeaderManagement": "Gestione:",
+ "HeaderManagement": "Gestione :",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "IMDB id mancante",
"OptionMissingTvdbId": "TheTVDB Id mancante",
"OptionMissingOverview": "Trama mancante",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Punteggio",
"ButtonSelect": "Seleziona",
- "ButtonSearch": "Cerca",
"ButtonGroupVersions": "Versione Gruppo",
"ButtonAddToCollection": "Aggiungi alla Collezione",
"PismoMessage": "Dona per avere una licenza di Pismo",
@@ -290,13 +354,13 @@
"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": "Questa cartella contiene la cache come files e immagini .",
"LabelImagesByNamePath": "Percorso immagini per nome:",
- "LabelImagesByNamePathHelp": "Questa cartella contiene le immagini degli attori,generi, e studio",
+ "LabelImagesByNamePathHelp": "Specificare un percorso personalizzato per le immagini scaricato attore, artista, genere e in studio.",
"LabelMetadataPath": "Percorso dei file METADATI:",
- "LabelMetadataPathHelp": "Questa cartella contiene i files relativi ai metadati e immagini che non sono stati salvati nella cartella dei Media.",
+ "LabelMetadataPathHelp": "Specificare un percorso personalizzato per opere d'arte scaricato e metadati, se non il salvataggio in cartelle multimediali.",
"LabelTranscodingTempPath": "Cartella temporanea per la trascodifica:",
- "LabelTranscodingTempPathHelp": "Questa cartella contiene i file usati dalla 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": "SerieTv",
"TabGames": "Giochi",
@@ -313,13 +377,13 @@
"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.",
- "ExtractChapterImagesHelp": "Estrazione di immagini capitoli permetter\u00e0 ai clienti di visualizzare i menu di selezione delle scene grafiche. Il processo pu\u00f2 essere lento, e pu\u00f2 richiedere diversi gigabyte di spazio. Funziona come una operazione pianificata alle 04:00, anche se questo \u00e8 configurabile nella zona di operazioni pianificate. Non \u00e8 consigliabile eseguire questa operazione durante le ore diurne.",
+ "ExtractChapterImagesHelp": "Estrazione di immagini capitoli permetter\u00e0 ai clienti di visualizzare i menu di selezione delle scene grafiche. Il processo pu\u00f2 essere lento, cpu-intensive e pu\u00f2 richiedere diversi gigabyte di spazio. Funziona quando vengono scoperti i video, e anche come un compito serale in programma a 04:00. Il programma \u00e8 configurabile nella zona di operazioni pianificate. Non \u00e8 consigliabile eseguire questa operazione durante le ore di picco.",
"LabelMetadataDownloadLanguage": "Lingua preferita per il download:",
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Convenzione per il salvataggio di immagini:",
"LabelImageSavingConventionHelp": "Media Browser riconosce le immagini dalla maggior parte delle principali applicazioni multimediali. Scegliere la convenzione piu adatta a te.",
- "OptionImageSavingCompatible": "Compatibile - MB3\/Plex\/Xbmc",
- "OptionImageSavingStandard": "Standard - MB3\/MB2",
+ "OptionImageSavingCompatible": "Compatibile- Media Browser\/Xbmc\/Plex",
+ "OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Accedi",
"TitleSignIn": "Accedi",
"HeaderPleaseSignIn": "Per favore accedi",
@@ -347,6 +411,8 @@
"TabStatus": "Stato",
"TabSettings": "Impostazioni",
"ButtonRefreshGuideData": "Aggiorna la guida",
+ "ButtonRefresh": "Aggiorna",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priorit\u00e0",
"OptionRecordOnAllChannels": "Registra su tutti i canali",
"OptionRecordAnytime": "Registra a qualsiasi ora",
@@ -372,7 +438,7 @@
"LiveTvPluginRequiredHelp": "Installa un servizio disponibile, come Next Pvr or ServerWMC.",
"LabelCustomizeOptionsPerMediaType": "Personalizza per il tipo di supporto:",
"OptionDownloadThumbImage": "Foto",
- "OptionDownloadMenuImage": "Menu",
+ "OptionDownloadMenuImage": "Men\u00f9",
"OptionDownloadLogoImage": "Logo",
"OptionDownloadBoxImage": "Box",
"OptionDownloadDiscImage": "Disco",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Cast & Crew",
"HeaderAdditionalParts": "Parti addizionali",
"ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "mancante",
"LabelOffline": "Spento",
"PathSubstitutionHelp": "il percorso 'sostituzioni' vengono utilizzati per mappare un percorso sul server per un percorso che i client sono in grado di accedere. Consentendo ai clienti l'accesso diretto ai media sul server possono essere in grado di giocare direttamente attraverso la rete ed evitare di utilizzare le risorse del server per lo streaming e transcodificare tra di loro.",
@@ -512,11 +579,13 @@
"HeaderProgram": "Programma",
"HeaderClients": "Dispositivi",
"LabelCompleted": "Completato",
+ "LabelFailed": "Fallito",
"LabelSkipped": "Saltato",
"HeaderEpisodeOrganization": "Organizzazione Episodi",
- "LabelSeasonNumber": "Numero Stagione:",
- "LabelEpisodeNumber": "Numero Episodio:",
- "LabelEndingEpisodeNumber": "Ultimo Episodio Numero:",
+ "LabelSeries": "Serie:",
+ "LabelSeasonNumber": "Numero Stagione",
+ "LabelEpisodeNumber": "Numero Episodio",
+ "LabelEndingEpisodeNumber": "Ultimo Episodio Numero",
"LabelEndingEpisodeNumberHelp": "\u00e8 richiesto solo se ci sono pi\u00f9 file per espisodio",
"HeaderSupportTheTeam": "Team di supporto di Media Browser",
"LabelSupportAmount": "Ammontare (Dollari)",
@@ -565,7 +634,7 @@
"ErrorConnectingToMediaBrowserRepository": "Si \u00e8 verificato un errore durante la connessione al repository Media Browser remoto.",
"LabelComponentsUpdated": "I seguenti componenti sono stati installati o aggiornati:",
"MessagePleaseRestartServerToFinishUpdating": "Si prega di riavviare il server per completare l'applicazione degli aggiornamenti.",
- "LabelDownMixAudioScale": "Audio Boost Mix Scala:",
+ "LabelDownMixAudioScale": "Audio Boost Mix Scala :",
"LabelDownMixAudioScaleHelp": "Audio Mix: Valore originale 1",
"ButtonLinkKeys": "Lnks Chiavi:",
"LabelOldSupporterKey": "Vecchie Chiavi dl donatore",
@@ -580,8 +649,8 @@
"ButtonRetrieveKey": "Ottieni chiave",
"LabelSupporterKey": "Chiave ( incollala dalla mail ricevuta)",
"LabelSupporterKeyHelp": "Inserisci la chiave per avere nuovi benefit che la comunit\u00e0 di Media Browser ha sviluppato per te",
- "MessageInvalidKey": "Chiave MB3 mancante o invalida",
- "ErrorMessageInvalidKey": "Per avere qualsiasi contenuto premium devi essere registrato. Devi anche essere un donatore. Si prega di donae er sostenere lo sviluppo di MB3.Grazie.",
+ "MessageInvalidKey": "Chiave MB3 mancante o invalida.",
+ "ErrorMessageInvalidKey": "Per qualsiasi contenuto premium devi essere registrato. \u00e8 necessario anche essere un browser Supporter multimediale. Si prega di donare e sostenere il continuo sviluppo del prodotto di base. Grazie.",
"HeaderDisplaySettings": "Configurazione Monitor",
"TabPlayTo": "Riproduci su",
"LabelEnableDlnaServer": "Abilita server Dlna",
@@ -610,9 +679,9 @@
"NotificationOptionPluginUpdateInstalled": "Aggiornamento del plugin installato",
"NotificationOptionPluginInstalled": "plugin installato",
"NotificationOptionPluginUninstalled": "Plugin disinstallato",
- "NotificationOptionVideoPlayback": "Riproduzione video",
- "NotificationOptionAudioPlayback": "Riproduzione Audio",
- "NotificationOptionGamePlayback": "Riproduzione gioco",
+ "NotificationOptionVideoPlayback": "La riproduzione video \u00e8 iniziato",
+ "NotificationOptionAudioPlayback": "Riproduzione audio iniziato",
+ "NotificationOptionGamePlayback": "La riproduzione di gioco \u00e8 parita",
"NotificationOptionVideoPlaybackStopped": "Video Fermato",
"NotificationOptionAudioPlaybackStopped": "Audio Fermato",
"NotificationOptionGamePlaybackStopped": "Gioco Fermato",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Abilita questa notifica",
"LabelMonitorUsers": "Monitorare l'attivit\u00e0 da:",
"LabelSendNotificationToUsers": "Spedisci notifiche a:",
- "UsersNotNotifiedAboutSelfActivity": "Gli utenti non saranno informati sulle proprie attivit\u00e0.",
"LabelUseNotificationServices": "Utilizzare i seguenti servizi:",
"CategoryUser": "Utente",
"CategorySystem": "Sistema",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Pagina Gi\u00f9",
"PageAbbreviation": "PG",
"ButtonHome": "Home",
+ "ButtonSearch": "Cerca",
"ButtonSettings": "Impostazioni",
"ButtonTakeScreenshot": "Cattura schermata",
"ButtonLetterUp": "Lettera Su",
@@ -657,10 +726,12 @@
"TabNowPlaying": "In esecuzione",
"TabNavigation": "Navigazione",
"TabControls": "Controlli",
- "ButtonFullscreen": "Schermo intero",
+ "ButtonFullscreen": "Tutto Schermo",
"ButtonScenes": "Scene",
"ButtonSubtitles": "Sottotitoli",
- "ButtonAudioTracks": "Traccia Audio",
+ "ButtonAudioTracks": "Tracce audio",
+ "ButtonPreviousTrack": "Traccia Precedente",
+ "ButtonNextTrack": "Prossima Traccia",
"ButtonStop": "Stop",
"ButtonPause": "Pausa",
"LabelGroupMoviesIntoCollections": "Raggruppa i film nelle collection",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separati da virgola. Questo pu\u00f2 essere lasciato vuoto da applicare a tutti i contenitori.",
"HeaderResponseProfile": "Risposta Profilo",
"LabelType": "Tipo:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Contenitore:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "Controllano questi valori come Media Browser si presenter\u00e0 al dispositivo.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specificare un bitrate massimo in ambienti larghezza di banda limitata, o se il dispositivo impone il suo limite proprio.",
+ "LabelMaxStreamingBitrate": "Massimo Bitrate streaming",
+ "LabelMaxStreamingBitrateHelp": "Specifica il bitrate massimo per lo streaming",
+ "LabelMaxStaticBitrate": "Massimo sinc. Bitrate",
+ "LabelMaxStaticBitrateHelp": "Specifica il bitrate massimo quando sincronizzi ad alta qualit\u00e0",
+ "LabelMusicStaticBitrate": "Musica sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specifica il max Bitrate quando sincronizzi la musica",
+ "LabelMusicStreamingTranscodingBitrate": "Musica trascodifica bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specifica il max Bitrate per lo streaming musica",
"OptionIgnoreTranscodeByteRangeRequests": "Ignorare le richieste di intervallo di byte di trascodifica",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "Se abilitata, queste richieste saranno onorati, ma ignorano l'intestazione intervallo di byte.",
"LabelFriendlyName": "Nome Condiviso",
@@ -751,7 +832,7 @@
"OptionReportByteRangeSeekingWhenTranscodingHelp": "Questo \u00e8 necessario per alcuni dispositivi che il tempo non cercano molto bene.",
"HeaderSubtitleDownloadingHelp": "Quando Media Browser esegue la scansione dei file video \u00e8 possibile cercare i sottotitoli mancanti, e scaricarli utilizzando un provider sottotitolo come OpenSubtitles.org.",
"HeaderDownloadSubtitlesFor": "Scarica sottotitoli per:",
- "MessageNoChapterProviders": "Installare un plugin fornitore capitolo come ChapterDb o tagChimp per attivare le opzioni capitolo aggiuntivo.",
+ "MessageNoChapterProviders": "Installare un plugin fornitore capitolo come ChapterDb per attivare le opzioni capitolo aggiuntivo.",
"LabelSkipIfGraphicalSubsPresent": "Salta se il video contiene gi\u00e0 i sottotitoli grafici",
"LabelSkipIfGraphicalSubsPresentHelp": "Mantenere le versioni del testo di sottotitoli si tradurr\u00e0 in consegna pi\u00f9 efficiente ai clienti di telefonia mobile.",
"TabSubtitles": "sottotitoli",
@@ -759,7 +840,7 @@
"HeaderDownloadChaptersFor": "Scarica i nomi dei capitoli per:",
"LabelOpenSubtitlesUsername": "Sottotitoli utente:",
"LabelOpenSubtitlesPassword": "Sottotitoli password:",
- "HeaderChapterDownloadingHelp": "Quando Media Browser esegue la scansione dei file video \u00e8 possibile scaricare i nomi dei capitoli amichevoli da internet utilizzando i plugin capitolo come ChapterDb e tagChimp.",
+ "HeaderChapterDownloadingHelp": "Quando Media Browser esegue la scansione dei file video \u00e8 possibile scaricare i nomi dei capitoli amichevoli da internet utilizzando i plugin capitolo come ChapterDb",
"LabelPlayDefaultAudioTrack": "Riprodurre la traccia audio di default indipendentemente dalla lingua",
"LabelSubtitlePlaybackMode": "Modalit\u00e0 Sottotitolo:",
"LabelDownloadLanguages": "Scarica lingue:",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Mostra plugin per:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Altri",
- "LabelEpisodeName": "Nome episodio",
- "LabelSeriesName": "Nome serie",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Nome Serie",
"ValueSeriesNameUnderscore": "Nome Serie",
"ValueEpisodeNamePeriod": "Nome Episodio",
"ValueEpisodeNameUnderscore": "Nome Episodio",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Inserisci il testo",
"LabelTypeText": "Testo",
"HeaderSearchForSubtitles": "Ricerca per sottotitoli",
@@ -796,13 +879,13 @@
"OptionAuto": "Automatico",
"OptionYes": "Si",
"OptionNo": "No",
- "LabelHomePageSection1": "Sezione 1 pagina iniziale",
- "LabelHomePageSection2": "Sezione 2 pagina iniziale",
- "LabelHomePageSection3": "Sezione 3 pagina iniziale",
- "LabelHomePageSection4": "Sezione Home page sezione quattro:",
- "OptionMyLibraryButtons": "Mia libreria",
- "OptionMyLibrary": "Mia libreria",
- "OptionMyLibrarySmall": "Mia libreria",
+ "LabelHomePageSection1": "Sezione 1 pagina iniziale:",
+ "LabelHomePageSection2": "Sezione 2 pagina iniziale:",
+ "LabelHomePageSection3": "Sezione 3 pagina iniziale:",
+ "LabelHomePageSection4": "Sezione 4 pagina iniziale:",
+ "OptionMyViewsButtons": "Mie Viste",
+ "OptionMyViews": "Mie Viste",
+ "OptionMyViewsSmall": "Mie Viste",
"OptionResumablemedia": "Riprendi",
"OptionLatestMedia": "Ultimo media",
"OptionLatestChannelMedia": "Ultime voci del canale",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferenze",
"MessageLoadingChannels": "Sto caricando il contenuto del canale",
+ "MessageLoadingContent": "Caricamento contenuto....",
"ButtonMarkRead": "Segna come letto",
"OptionDefaultSort": "Predefinito",
"OptionCommunityMostWatchedSort": "Pi\u00f9 visti",
"TabNextUp": "Da vedere",
"MessageNoMovieSuggestionsAvailable": "Nessun suggerimento di film sono attualmente disponibili. Iniziare a guardare e valutare i vostri film, e poi tornare per visualizzare le tue segnalazioni.",
"MessageNoCollectionsAvailable": "Collezioni permettono di godere di raggruppamenti personalizzati di film, serie, album, libri e giochi. Fare clic sul pulsante Nuovo per avviare la creazione di 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",
+ "MessageNoPlaylistItemsAvailable": "Questa playlist al momento \u00e8 vuota",
"HeaderWelcomeToMediaBrowserWebClient": "Benvenuti nel Media Browser Web client",
"ButtonDismiss": "Dismetti",
"MessageLearnHowToCustomize": "Ulteriori informazioni su come personalizzare questa pagina ai tuoi gusti personali. Fare clic sull'icona utente in alto a destra dello schermo per visualizzare e aggiornare le vostre preferenze.",
@@ -846,7 +932,167 @@
"LabelSelectFolderGroups": "Automaticamente i contenuti del gruppo dalle seguenti cartelle nella vista come film, musica e TV:",
"LabelSelectFolderGroupsHelp": "Le cartelle che siano deselezionate verranno visualizzati da soli nel loro punto di vista.",
"OptionDisplayAdultContent": "Visualizzazioni contenuti per adulti",
- "OptionLibraryFolders": "Vista",
+ "OptionLibraryFolders": "Cartelle dei media",
"TitleRemoteControl": "Telecomando",
- "OptionLatestTvRecordings": "Ultime registrazioni"
+ "OptionLatestTvRecordings": "Ultime registrazioni",
+ "LabelProtocolInfo": "Info.protocollo:",
+ "LabelProtocolInfoHelp": "Il valore che verr\u00e0 utilizzato quando si risponde a GetProtocolInfo richieste dal dispositivo.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser include il supporto nativo per i metadati XBMC Nfo e immagini. Per attivare o disattivare i metadati XBMC, utilizzare la scheda Avanzate per configurare le opzioni per i tipi di media.",
+ "LabelXbmcMetadataUser": "Aggiungere i dati di orologi utenti per nfo di per:",
+ "LabelXbmcMetadataUserHelp": "Attivare questa opzione per mantenere i dati di orologi sincronizzati tra Media Browser e XBMC.",
+ "LabelXbmcMetadataDateFormat": "Formato Data di rilascio:",
+ "LabelXbmcMetadataDateFormatHelp": "Tutte le date all'interno del nfo verranno letti e scritti utilizzando questo formato.",
+ "LabelXbmcMetadataSaveImagePaths": "Salvare percorsi delle immagini all'interno di file nfo",
+ "LabelXbmcMetadataSaveImagePathsHelp": "Questo \u00e8 consigliato se si dispone di nomi di file di immagine che non sono conformi alle linee guida XBMC.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Abilita sostituzione di percorso",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Consente percorso sostituzione dei percorsi delle immagini utilizzando le impostazioni di sostituzione percorso del server.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "Vedere sostituzione di percorso.",
+ "LabelGroupChannelsIntoViews": "Visualizzare i seguenti canali direttamente dentro le mie visite:",
+ "LabelGroupChannelsIntoViewsHelp": "Se abilitata, questi canali verranno visualizzati direttamente accanto ad altri punti di vista. Se disattivato, saranno visualizzati all'interno di una visione canali separati.",
+ "LabelDisplayCollectionsView": "Visualizzare una vista collezioni di mostrare collezioni di film",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "Quando si scaricano le immagini possono essere salvate in entrambi extrafanart e extrathumbs per la massima compatibilit\u00e0 cutanea XBMC.",
+ "TabServices": "Servizi",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Personalizzare l'aspetto del browser media per soddisfare le esigenze del vostro gruppo o organizzazione.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "Questo verr\u00e0 visualizzato nella parte inferiore della pagina di accesso.",
+ "LabelAutomaticallyDonate": "Donare automaticamente questo importo ogni sei mesi",
+ "LabelAutomaticallyDonateHelp": "\u00c8 possibile annullare in qualsiasi momento tramite il vostro conto PayPal.",
+ "OptionList": "Lista",
+ "TabDashboard": "Pannello Controllo",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Log:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Immagini per nome:",
+ "LabelTranscodingTemporaryFiles": "Transcodifica file temporanei:",
+ "HeaderLatestMusic": "Musica Recente",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Chiavi Api",
+ "HeaderApiKeysHelp": "Le applicazioni estrene richiedono una chiave Api per comunicare con Media Browser. Le chiavi sono create attraverso il log-in con un account Media Browse, o manualmente rilasciando una chiave all'applicazione.",
+ "HeaderApiKey": "Chiave Api",
+ "HeaderApp": "App",
+ "HeaderDevice": "Dispositivo",
+ "HeaderUser": "Utente",
+ "HeaderDateIssued": "data di pubblicazione",
+ "LabelChapterName": "Capitolo {0}",
+ "HeaderNewApiKey": "Nuova Chiave Api",
+ "LabelAppName": "Nome app",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Garantisci all'applicazione il permesso di comunicare con Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "valore:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Uguale",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "Vista",
+ "TabSort": "Ordina",
+ "TabFilter": "Filtra",
+ "ButtonView": "Vista",
+ "LabelPageSize": "Limite articolo:",
+ "LabelPath": "Path:",
+ "LabelView": "Vista:",
+ "TabUsers": "Utenti",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Caratteristiche",
+ "HeaderAdvanced": "Avanzato",
+ "ButtonSync": "Sinc.",
+ "TabScheduledTasks": "Operazioni pianificate",
+ "HeaderChapters": "Capitoli",
+ "HeaderResumeSettings": "Recupera impostazioni",
+ "TabSync": "Sinc",
+ "TitleUsers": "Utenti",
+ "LabelProtocol": "Protocollo:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Contenuto:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sinc",
+ "ButtonAddToPlaylist": "Aggiungi alla playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Chiudi",
+ "LabelAllLanguages": "Tutte le lingue",
+ "HeaderBrowseOnlineImages": "Sfoglia le immagini sul web",
+ "LabelSource": "Origine:",
+ "OptionAll": "Tutto",
+ "LabelImage": "Immagine:",
+ "ButtonBrowseImages": "Sfoglia immagini",
+ "HeaderImages": "Immagini",
+ "HeaderBackdrops": "Sfondi",
+ "HeaderScreenshots": "Immagini",
+ "HeaderAddUpdateImage": "Aggiungi\/aggiorna immagine",
+ "LabelJpgPngOnly": "JPG\/PNG solamente",
+ "LabelImageType": "Tipo immagine",
+ "OptionPrimary": "Primaria",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Immagine",
+ "OptionLocked": "Bloccato",
+ "OptionUnidentified": "Non identificata",
+ "OptionMissingParentalRating": "Voto genitori mancante",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodi:",
+ "OptionSeason0": "Stagione 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Canzoni",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Stagioni",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Video musicali",
+ "OptionReportMovies": "Film",
+ "OptionReportHomeVideos": "Video personali",
+ "OptionReportGames": "Giochi",
+ "OptionReportEpisodes": "Episodi",
+ "OptionReportCollections": "Collezioni",
+ "OptionReportBooks": "Libri",
+ "OptionReportArtists": "Cantanti",
+ "OptionReportAlbums": "Album",
+ "OptionReportAdultVideos": "Video x adulti",
+ "ButtonMore": "Dettagli",
+ "HeaderActivity": "Attivit\u00e0",
+ "ScheduledTaskStartedWithName": "{0} Avviati",
+ "ScheduledTaskCancelledWithName": "{0} cancellati",
+ "ScheduledTaskCompletedWithName": "{0} completati",
+ "ScheduledTaskFailed": "Operazione pianificata completata",
+ "PluginInstalledWithName": "{0} sono stati Installati",
+ "PluginUpdatedWithName": "{0} sono stati aggiornati",
+ "PluginUninstalledWithName": "{0} non sono stati installati",
+ "ScheduledTaskFailedWithName": "{0} Falliti",
+ "ItemAddedWithName": "{0} aggiunti alla libreria",
+ "ItemRemovedWithName": "{0} rimossi dalla libreria",
+ "DeviceOnlineWithName": "{0} \u00e8 connesso",
+ "UserOnlineFromDevice": "{0} \u00e8 online da {1}",
+ "DeviceOfflineWithName": "{0} \u00e8 stato disconesso",
+ "UserOfflineFromDevice": "{0} \u00e8 stato disconesso da {1}",
+ "SubtitlesDownloadedForItem": "Sottotitoli scaricati per {0}",
+ "SubtitleDownloadFailureForItem": "Sottotitoli non scaricati per {0}",
+ "LabelRunningTimeValue": "Durata: {0}",
+ "LabelIpAddressValue": "Indirizzo IP: {0}",
+ "UserConfigurationUpdatedWithName": "Configurazione utente \u00e8 stata aggiornata per {0}",
+ "UserCreatedWithName": "Utente {0} \u00e8 stato creato",
+ "UserPasswordChangedWithName": "Password utente cambiata per {0}",
+ "UserDeletedWithName": "Utente {0} \u00e8 stato cancellato",
+ "MessageServerConfigurationUpdated": "Configurazione server aggioprnata",
+ "MessageNamedServerConfigurationUpdatedWithValue": "La sezione {0} \u00e8 stata aggiornata",
+ "MessageApplicationUpdated": "Media Browser Server \u00e8 stato aggiornato",
+ "AuthenticationSucceededWithUserName": "{0} Autenticati con successo",
+ "FailedLoginAttemptWithUserName": "Login fallito da {0}",
+ "UserStartedPlayingItemWithValues": "{0} \u00e8 partito da {1}",
+ "UserStoppedPlayingItemWithValues": "{0} stoppato {1}",
+ "AppDeviceValues": "App: {0}, Dispositivo: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Dimensione massima Download (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Dimensione massima del canale relativo alla cartella di download",
+ "HeaderRecentActivity": "Attivit\u00e0 recenti"
} \ 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 8122c030c..bf0fd1212 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/kk.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/kk.json
@@ -1,135 +1,197 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "\u041f\u0430\u0439\u0434\u0430\u043b\u0443\u043d\u044b\u0448\u044b\u043b\u0430\u0440 \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u043e\u0439\u043d\u0430\u0442\u049b\u0430\u0434\u0430",
- "HeaderEnableNotificationForEvents": "\u041d\u0435 \u0431\u043e\u043b\u0493\u0430\u043d\u0434\u0430 \u04d9\u043a\u0456\u043c\u0448\u0456\u043b\u0435\u0440\u0434\u0456 \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443:",
- "HeaderEnableNotificationForPlayback": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440 \u043e\u0439\u043d\u0430\u0493\u0430\u043d\u0434\u0430 \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443:",
- "OptionNotifyOnUpdates": "\u0416\u0430\u04a3\u0430\u0440\u0442\u0443\u043b\u0430\u0440 \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456",
- "OptionNotifyOnVideoPlayback": "\u0411\u0435\u0439\u043d\u0435 \u043e\u0439\u043d\u0430\u0442\u0443",
- "OptionNotifyOnAudioPlayback": "\u0414\u044b\u0431\u044b\u0441 \u043e\u0439\u043d\u0430\u0442\u0443",
- "OptionNotifyOnGamePlayback": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440 \u043e\u0439\u043d\u0430\u0442\u0443",
- "OptionNotifyOnFailedTasks": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0441\u04d9\u0442\u0441\u0456\u0437\u0434\u0456\u0433\u0456",
- "OptionNotifyOnNewLibraryContent": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u0493\u0430 \u0436\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d",
- "OptionNotifyOnServerRestartRequired": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u049b\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443 \u049b\u0430\u0436\u0435\u0442",
- "NotificationOptionUpdatesAvailable": "\u0416\u0430\u04a3\u0430\u0440\u0442\u0443\u043b\u0430\u0440 \u049b\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456",
- "NotificationOptionFailedTasks": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0441\u04d9\u0442\u0441\u0456\u0437\u0434\u0456\u0433\u0456",
- "TabUpdates": "\u0416\u0430\u04a3\u0430\u0440\u0442\u0443\u043b\u0430\u0440",
- "HeaderUpdateLevel": "\u0416\u0430\u04a3\u0430\u0440\u0442\u0443 \u0434\u0435\u04a3\u0433\u0435\u0439\u0456",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u043c\u04d9\u0436\u0431\u04af\u0440\u043b\u0456 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
- "HeaderCustomizeOptionsPerMediaType": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u0442\u0430\u0441\u0443\u0448\u044b \u0442\u04af\u0440\u0456 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0442\u0435\u04a3\u0448\u0435\u0443",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "\u0411\u0430\u0440\u043b\u044b\u049b \u0436\u0430\u0431\u0434\u044b\u049b\u0442\u0430\u0440",
- "HeaderThisDevice": "\u041e\u0441\u044b \u0436\u0430\u0431\u0434\u044b\u049b",
- "OptionLibraryButtons": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u043a\u0442\u0435\u0440\u0456",
- "OptionLibraryTiles": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u049b\u0430\u0442\u0430\u0440\u043b\u0430\u0440\u044b (\u04af\u043b\u043a\u0435\u043d)",
- "OptionSmallLibraryTiles": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u049b\u0430\u0442\u0430\u0440\u043b\u0430\u0440\u044b (\u043a\u0456\u0448\u0456)",
- "ButtonPlayTrailer": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440",
- "LabelFailed": "\u0421\u04d9\u0442\u0441\u0456\u0437",
- "LabelSeries": "\u0421\u0435\u0440\u0438\u0430\u043b:",
- "ButtonPreviousTrack": "\u0410\u043b\u0434\u044b\u04a3\u0493\u044b \u0436\u043e\u043b\u0448\u044b\u049b",
- "ButtonNextTrack": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0436\u043e\u043b\u0448\u044b\u049b",
- "HeaderMyLibrary": "\u041c\u0435\u043d\u0456\u04a3 \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043c",
- "HeaderLibraryViews": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u043a\u04e9\u0440\u0456\u043d\u0456\u0441\u0442\u0435\u0440\u0456",
+ "HeaderPeople": "\u0410\u0434\u0430\u043c\u0434\u0430\u0440",
"LabelExit": "\u0428\u044b\u0493\u0443",
+ "HeaderDownloadPeopleMetadataFor": "\u04e8\u043c\u0456\u0440\u0431\u0430\u044f\u043d \u0431\u0435\u043d \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u043c\u0430\u049b\u0441\u0430\u0442\u044b;",
"LabelVisitCommunity": "\u049a\u0430\u0443\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u049b\u049b\u0430 \u0431\u0430\u0440\u0443",
+ "OptionComposers": "\u041a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u043b\u0430\u0440",
"LabelGithubWiki": "Github \u0443\u0438\u043a\u0438\u0456",
+ "OptionOthers": "\u0411\u0430\u0441\u049b\u0430\u043b\u0430\u0440",
"LabelSwagger": "Swagger \u0442\u0456\u043b\u0434\u0435\u0441\u0443\u0456",
"LabelStandard": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0442\u044b",
+ "HeaderDownloadPeopleMetadataForHelp": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u049b\u043e\u0441\u049b\u0430\u043d\u0434\u0430 \u044d\u043a\u0440\u0430\u043d\u0434\u0430\u0493\u044b \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u0442\u044b \u043a\u04e9\u0431\u0456\u0440\u0435\u043a \u04b1\u0441\u044b\u043d\u0430\u0434\u044b, \u0431\u0456\u0440\u0430\u049b \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043d\u044b\u04a3 \u0441\u043a\u0430\u043d\u0435\u0440\u043b\u0435\u0443\u043b\u0435\u0440\u0456 \u0431\u0430\u044f\u0443\u043b\u0430\u0439\u0434\u044b.",
"LabelViewApiDocumentation": "API \u049b\u04b1\u0436\u0430\u0442\u0442\u0430\u043c\u0430\u0441\u044b\u043d \u049b\u0430\u0440\u0430\u0443",
+ "ViewTypeFolders": "\u049a\u0430\u043b\u0442\u0430\u043b\u0430\u0440",
"LabelBrowseLibrary": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043d\u044b \u0448\u0430\u0440\u043b\u0430\u0443",
+ "LabelDisplayFoldersView": "\u0416\u0430\u0439 \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04af\u0448\u0456\u043d \u049a\u0430\u043b\u0442\u0430\u043b\u0430\u0440 \u0430\u0441\u043f\u0435\u043a\u0442\u0456\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
"LabelConfigureMediaBrowser": "Media Browser \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0441\u044b",
+ "ViewTypeLiveTvRecordingGroups": "\u0416\u0430\u0437\u0431\u0430\u043b\u0430\u0440",
"LabelOpenLibraryViewer": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043d\u044b \u049b\u0430\u0440\u0430\u0443 \u049b\u04b1\u0440\u0430\u043b\u044b",
+ "ViewTypeLiveTvChannels": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440",
"LabelRestartServer": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u049b\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443",
+ "LabelAllowLocalAccessWithoutPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0441\u0456\u0437 \u0436\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u049b\u0430\u0442\u044b\u043d\u0441\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
"LabelShowLogWindow": "\u0416\u04b1\u0440\u043d\u0430\u043b \u0442\u0435\u0440\u0435\u0437\u0435\u0441\u0456\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d \u0431\u043e\u043b\u0441\u0430, \u04af\u0439\u0456\u04a3\u0456\u0437\u0434\u0435\u0433\u0456 \u0436\u0435\u043b\u0456 \u0456\u0448\u0456\u043d\u0435\u043d \u043a\u0456\u0440\u0433\u0435\u043d\u0434\u0435 \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437 \u049b\u0430\u0436\u0435\u0442 \u0431\u043e\u043b\u043c\u0430\u0439\u0434\u044b.",
"LabelPrevious": "\u0410\u043b\u0434\u044b\u04a3\u0493\u044b",
+ "HeaderPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437",
"LabelFinish": "\u0410\u044f\u049b\u0442\u0430\u0443",
+ "HeaderLocalAccess": "\u0416\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u049b\u0430\u0442\u044b\u043d\u0430\u0441",
"LabelNext": "\u041a\u0435\u043b\u0435\u0441\u0456",
+ "HeaderViewOrder": "\u0410\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440 \u0440\u0435\u0442\u0456",
"LabelYoureDone": "\u0411\u04d9\u0440\u0456 \u0434\u0430\u0439\u044b\u043d!",
+ "LabelSelectUserViewOrder": "Media Browser \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u044b\u043d\u0434\u0430 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0442\u0456\u043d \u041c\u0435\u043d\u0456\u04a3 \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440\u0456\u043c \u0440\u0435\u0442\u0456\u043d \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437",
"WelcomeToMediaBrowser": "Media Browser-\u0433\u0435 \u049b\u043e\u0448 \u043a\u0435\u043b\u0434\u0456\u04a3\u0456\u0437!",
+ "LabelMetadataRefreshMode": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u043a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443 \u0440\u0435\u0436\u0456\u043c\u0456:",
"TitleMediaBrowser": "Media Browser",
- "ThisWizardWillGuideYou": "\u0411\u04b1\u043b \u043a\u043e\u043c\u0435\u043a\u0448\u0456 \u0431\u0430\u0441\u0442\u0430\u043f\u049b\u044b \u043e\u0440\u043d\u0430\u0442\u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0456 \u0441\u0430\u0442\u044b\u043b\u0430\u0440\u044b\u043c\u0435\u043d \u04e9\u0442\u043a\u0456\u0437\u0435\u0434\u0456. \u0411\u0430\u0441\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u0442\u0456\u043b\u0434\u0456 \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437.",
+ "LabelImageRefreshMode": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u043a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443 \u0440\u0435\u0436\u0456\u043c\u0456:",
+ "ThisWizardWillGuideYou": "\u0411\u04b1\u043b \u043a\u043e\u043c\u0435\u043a\u0448\u0456 \u0431\u0430\u0441\u0442\u0430\u043f\u049b\u044b \u043e\u0440\u043d\u0430\u0442\u0443 \u043f\u0440\u043e\u0446\u0435\u0441\u0456 \u0441\u0430\u0442\u044b\u043b\u0430\u0440\u044b\u043c\u0435\u043d \u04e9\u0442\u043a\u0456\u0437\u0435\u0434\u0456. \u0411\u0430\u0441\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u04e9\u0437\u0456\u04a3\u0456\u0437\u0433\u0435 \u0442\u0456\u043b \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456\u043d \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437.",
+ "OptionDownloadMissingImages": "\u0416\u043e\u049b \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443",
"TellUsAboutYourself": "\u04e8\u0437\u0456\u04a3\u0456\u0437 \u0442\u0443\u0440\u0430\u043b\u044b \u0430\u0439\u0442\u044b\u04a3\u044b\u0437",
+ "OptionReplaceExistingImages": "\u0411\u0430\u0440 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0430\u0443\u044b\u0441\u0442\u044b\u0440\u0443",
"LabelYourFirstName": "\u0410\u0442\u044b\u04a3\u044b\u0437:",
+ "OptionRefreshAllData": "\u0411\u0430\u0440\u043b\u044b\u049b \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u043a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443",
"MoreUsersCanBeAddedLater": "\u041a\u04e9\u0431\u0456\u0440\u0435\u043a \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440\u0434\u044b \u043a\u0435\u0439\u0456\u043d \u0411\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b \u0430\u0440\u049b\u044b\u043b\u044b \u04af\u0441\u0442\u0435\u0443\u0456\u04a3\u0456\u0437 \u043c\u04af\u043c\u043a\u0456\u043d.",
- "UserProfilesIntro": "Media Browser \u0431\u0435\u043a\u0456\u0442\u0456\u043b\u0433\u0435\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u043f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0435\u0440\u0456\u043d \u049b\u0430\u043c\u0442\u0438\u0434\u044b, \u04d9\u0440 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u0493\u0430 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443, \u043e\u0439\u043d\u0430\u0442\u0443 \u043a\u04af\u0439\u0456 \u0436\u04d9\u043d\u0435 \u0436\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442\u044b\u043d \u0431\u0430\u0441\u049b\u0430\u0440\u0443 \u04af\u0448\u0456\u043d \u04e9\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456 \u049b\u043e\u0441\u044b\u043b\u0430\u0434\u044b.",
+ "OptionAddMissingDataOnly": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u0436\u043e\u043a \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u04af\u0441\u0442\u0435\u0443",
+ "UserProfilesIntro": "Media Browser \u0431\u0435\u043a\u0456\u0442\u0456\u043b\u0433\u0435\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u043f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0435\u0440\u0456\u043d \u049b\u0430\u043c\u0442\u0438\u0434\u044b, \u04d9\u0440 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u0493\u0430 \u04e9\u0437\u0456\u043d\u0456\u04a3 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456, \u043e\u0439\u043d\u0430\u0442\u0443 \u043a\u04af\u0439\u0456 \u0436\u04d9\u043d\u0435 \u0436\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442\u044b \u049b\u043e\u0441\u044b\u043b\u0430\u0434\u044b.",
+ "OptionLocalRefreshOnly": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u0436\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u043a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443",
"LabelWindowsService": "Windows \u049b\u044b\u0437\u043c\u0435\u0442\u0456",
+ "HeaderRefreshMetadata": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u043a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443",
"AWindowsServiceHasBeenInstalled": "Windows \u049b\u044b\u0437\u043c\u0435\u0442\u0456 \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0434\u044b.",
+ "HeaderPersonInfo": "\u0422\u04b1\u043b\u0493\u0430 \u0442\u0443\u0440\u0430\u043b\u044b \u0430\u049b\u043f\u0430\u0440\u0430\u0442",
"WindowsServiceIntro1": "Media Browser Server \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u0442\u0430\u049b\u0442\u0430\u0434\u0430\u0493\u044b \u0431\u0435\u043b\u0433\u0456\u0448\u0435\u0441\u0456 \u0431\u0430\u0440 \u0436\u04b1\u043c\u044b\u0441 \u04af\u0441\u0442\u0435\u043b\u0456\u043d\u0456\u04a3 \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u0441\u044b \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u04d9\u0434\u0435\u043f\u043a\u0456 \u043e\u0440\u044b\u043d\u0434\u0430\u043b\u0430\u0434\u044b, \u0431\u0456\u0440\u0430\u049b \u0435\u0433\u0435\u0440 \u0431\u04b1\u043d\u044b \u04e9\u04a3\u0434\u0456\u043a \u049b\u044b\u0437\u043c\u0435\u0442\u0456 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0442\u0435\u04a3\u0448\u0435\u0443\u0434\u0456 \u049b\u0430\u043b\u0430\u0441\u0430\u04a3\u044b\u0437, \u043e\u0440\u043d\u044b\u043d\u0430 \u0431\u04b1\u043b Windows \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0456 \u0430\u0440\u049b\u044b\u043b\u044b \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.",
+ "HeaderIdentifyItem": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u0430\u043d\u044b\u049b\u0442\u0430\u0443",
"WindowsServiceIntro2": "\u0415\u0433\u0435\u0440 Windows \u049b\u044b\u0437\u043c\u0435\u0442\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0434\u0430 \u0431\u043e\u043b\u0441\u0430, \u0435\u0441\u043a\u0435\u0440\u0456\u04a3\u0456\u0437, \u0431\u04b1\u043b \u0441\u043e\u043b \u043c\u0435\u0437\u0433\u0456\u043b\u0434\u0435 \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u0442\u0430\u049b\u0442\u0430\u0434\u0430\u0493\u044b \u0431\u0435\u043b\u0433\u0456\u0448\u0435\u0434\u0435\u0439 \u0436\u04af\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d \u0435\u043c\u0435\u0441, \u0441\u043e\u043d\u044b\u043c\u0435\u043d \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0456 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443 \u04af\u0448\u0456\u043d \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u0442\u0430\u049b\u0442\u0430\u0434\u0430\u043d \u0448\u044b\u0493\u0443\u044b\u04a3\u044b\u0437 \u049b\u0430\u0436\u0435\u0442. \u0421\u043e\u0493\u0430\u043d \u049b\u0430\u0442\u0430\u0440, \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0456 \u04d9\u043a\u0456\u043c\u0448\u0456 \u049b\u04b1\u049b\u044b\u049b\u0442\u0430\u0440\u044b\u043d\u0430 \u0438\u0435 \u0431\u043e\u043b\u044b\u043f \u049a\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0456 \u0430\u0440\u049b\u044b\u043b\u044b \u0442\u0435\u04a3\u0448\u0435\u0443 \u049b\u0430\u0436\u0435\u0442. \u041d\u0430\u0437\u0430\u0440 \u0430\u0443\u0434\u0430\u0440\u044b\u04a3\u044b\u0437! \u049a\u0430\u0437\u0456\u0440\u0433\u0456 \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u0431\u04b1\u043b \u049b\u044b\u0437\u043c\u0435\u0442 \u04e9\u0437\u0456\u043d\u0435\u043d-\u04e9\u0437\u0456 \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u043c\u0430\u0439\u0434\u044b, \u0441\u043e\u043d\u0434\u044b\u049b\u0442\u0430\u043d \u0436\u0430\u04a3\u0430 \u043d\u04b1\u0441\u049b\u0430\u043b\u0430\u0440 \u049b\u043e\u043b\u043c\u0435\u043d \u04e9\u0437\u0430\u0440\u0430 \u04d9\u0440\u0435\u043a\u0435\u0442\u0442\u0435\u0441\u0443\u0434\u0456 \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456.",
+ "HeaderIdentifyItemHelp": "\u0406\u0437\u0434\u0435\u0443\u0434\u0456\u04a3 \u0431\u0456\u0440 \u043d\u0435 \u0431\u0456\u0440\u043d\u0435\u0448\u0435 \u0448\u0430\u0440\u0442\u044b\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437. \u0406\u0437\u0434\u0435\u0443 \u043d\u04d9\u0442\u0438\u0436\u0435\u043b\u0435\u0440\u0456\u043d \u043a\u04e9\u0431\u0435\u0439\u0442\u0443 \u04af\u0448\u0456\u043d \u0448\u0430\u0440\u0442\u0442\u044b \u0430\u043b\u0430\u0441\u0442\u0430\u04a3\u044b\u0437.",
"WizardCompleted": "\u04d8\u0437\u0456\u0440\u0448\u0435 \u0431\u04b1\u043b \u043a\u0435\u0440\u0435\u0433\u0456\u043d\u0456\u04a3 \u0431\u04d9\u0440\u0456. \u0415\u043d\u0434\u0456 Media Browser \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u0442\u0443\u0440\u0430\u043b\u044b \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u0442\u044b \u0436\u0438\u043d\u0430\u0443\u0434\u044b \u0431\u0430\u0441\u0442\u0430\u0434\u044b. \u041a\u0435\u0439\u0431\u0456\u0440 \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u043c\u0435\u043d \u0442\u0430\u043d\u044b\u0441\u044b\u043f \u0448\u044b\u0493\u044b\u04a3\u044b\u0437, \u0436\u04d9\u043d\u0435 \u043a\u0435\u0439\u0456\u043d <b>\u0411\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b\u043d<\/b> \u043a\u04e9\u0440\u0443 \u04af\u0448\u0456\u043d <b>\u0410\u044f\u049b\u0442\u0430\u0443<\/b> \u0442\u04af\u0439\u043c\u0435\u0448\u0456\u0433\u0456\u043d \u043d\u04b1\u049b\u044b\u04a3\u044b\u0437.",
+ "HeaderConfirmDeletion": "\u0416\u043e\u044e\u0434\u044b \u0440\u0430\u0441\u0442\u0430\u0443",
"LabelConfigureSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u043b\u0430\u0443",
+ "LabelFollowingFileWillBeDeleted": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0444\u0430\u0439\u043b \u0436\u043e\u0439\u044b\u043b\u0430\u0434\u044b:",
"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",
+ "LabelIfYouWishToContinueWithDeletion": "\u0415\u0433\u0435\u0440 \u0436\u0430\u043b\u0430\u0441\u0442\u044b\u0440\u0443\u0434\u044b \u049b\u0430\u043b\u0430\u0441\u0430\u04a3\u044b\u0437, \u043c\u044b\u043d\u0430\u043d\u044b\u04a3 \u043c\u04d9\u043d\u0456\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u043f \u0440\u0430\u0441\u0442\u0430\u04a3\u044b\u0437:",
"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\u0443\u0448\u044b\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.",
+ "ButtonIdentify": "\u0410\u043d\u044b\u049b\u0442\u0430\u0443",
"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 4:00 \u0441\u0430\u0493\u0430\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 \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043b\u0430\u0440 \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.",
+ "LabelAlbumArtist": "\u0410\u043b\u044c\u0431\u043e\u043c \u043e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b\u0441\u044b:",
+ "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 4:00 \u0441\u0430\u0493\u0430\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.",
+ "LabelAlbum": "\u0410\u043b\u044c\u0431\u043e\u043c:",
"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",
+ "LabelCommunityRating": "\u049a\u0430\u0443\u044b\u043c \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b:",
"LabelEnableAutomaticPortMappingHelp": "UPnP \u049b\u0430\u0448\u044b\u049b\u0442\u0430\u043d \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443\u0434\u044b \u0436\u0435\u04a3\u0456\u043b\u0434\u0435\u0442\u0443 \u04af\u0448\u0456\u043d \u0440\u043e\u0443\u0442\u0435\u0440\u0434\u0456 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u043b\u0430\u0443\u0493\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0435\u0434\u0456. \u0411\u04b1\u043b \u043a\u0435\u0439\u0431\u0456\u0440 \u0440\u043e\u0443\u0442\u0435\u0440 \u04b1\u043b\u0433\u0456\u043b\u0435\u0440\u0456\u043c\u0435\u043d \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u043c\u0435\u0439\u0442\u0456\u043d\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.",
+ "LabelVoteCount": "\u0414\u0430\u0443\u044b\u0441 \u0441\u0430\u043d\u044b:",
"ButtonOk": "\u0416\u0430\u0440\u0430\u0439\u0434\u044b",
+ "LabelMetascore": "Metascore \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b:",
"ButtonCancel": "\u0411\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443",
+ "LabelCriticRating": "\u0421\u044b\u043d\u0448\u044b\u043b\u0430\u0440 \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b:",
"ButtonNew": "\u0416\u0430\u0441\u0430\u0443",
+ "LabelCriticRatingSummary": "\u0421\u044b\u043d\u0448\u044b\u043b\u0430\u0440 \u0431\u0430\u0493\u0430\u043b\u0430\u0443 \u0430\u049b\u043f\u0430\u0440\u044b:",
"HeaderSetupLibrary": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043d\u044b \u0440\u0435\u0442\u0442\u0435\u0443",
+ "LabelAwardSummary": "\u041c\u0430\u0440\u0430\u043f\u0430\u0442 \u0430\u049b\u043f\u0430\u0440\u044b:",
"ButtonAddMediaFolder": "\u0422\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d \u04af\u0441\u0442\u0435\u0443",
+ "LabelWebsite": "\u0492\u0430\u043b\u0430\u043c\u0442\u043e\u0440 \u0441\u0430\u0439\u0442\u044b:",
"LabelFolderType": "\u049a\u0430\u043b\u0442\u0430 \u0442\u04af\u0440\u0456:",
+ "LabelTagline": "\u041d\u0435\u0433\u0456\u0437\u0433\u0456 \u0441\u04e9\u0439\u043b\u0435\u043c:",
"MediaFolderHelpPluginRequired": "* \u041f\u043b\u0430\u0433\u0438\u043d\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u04a3\u044b\u0437, \u043c\u044b\u0441\u0430\u043b\u044b, GameBrowser, \u043d\u0435 MB Bookshelf.",
+ "LabelOverview": "\u0416\u0430\u043b\u043f\u044b \u0448\u043e\u043b\u0443:",
"ReferToMediaLibraryWiki": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u0442\u0443\u0440\u0430\u043b\u044b \u0443\u0438\u043a\u0438 \u0456\u0448\u0456\u043d\u0435\u043d \u049b\u0430\u0440\u0430\u04a3\u044b\u0437.",
+ "LabelShortOverview": "\u049a\u044b\u0441\u049b\u0430 \u0448\u043e\u043b\u0443:",
"LabelCountry": "\u0415\u043b:",
+ "LabelReleaseDate": "\u0428\u044b\u0493\u0430\u0440\u0443 \u043a\u04af\u043d-\u0430\u0439\u044b:",
"LabelLanguage": "\u0422\u0456\u043b:",
- "HeaderPreferredMetadataLanguage": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0442\u0456\u043b\u0456\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:",
+ "LabelYear": "\u0416\u044b\u043b\u044b:",
+ "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:",
+ "LabelPlaceOfBirth": "\u0422\u0443\u0493\u0430\u043d \u0436\u0435\u0440\u0456:",
"LabelSaveLocalMetadata": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435 v\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0456 \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b \u0456\u0448\u0456\u043d\u0434\u0435 \u0441\u0430\u049b\u0442\u0430\u0443",
+ "LabelEndDate": "\u0410\u044f\u049b\u0442\u0430\u043b\u0443 \u043a\u04af\u043d-\u0430\u0439\u044b:",
"LabelSaveLocalMetadataHelp": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435 \u043c\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0456 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u0442\u0430\u0441\u0443\u0448\u044b \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.",
+ "LabelAirDate": "\u042d\u0444\u0438\u0440 \u043a\u04af\u043d\u0434\u0435\u0440\u0456:",
"LabelDownloadInternetMetadata": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435 \u043c\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0456 \u0438\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 Media Browser \u0442\u0430\u0441\u0443\u0448\u044b \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.",
+ "LabelAirTime:": "\u042d\u0444\u0438\u0440 \u0443\u0430\u049b\u044b\u0442\u044b",
+ "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 Media Browser \u0442\u0430\u0441\u0443\u0448\u044b\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.",
+ "LabelRuntimeMinutes": "\u041e\u0440\u044b\u043d\u0434\u0430\u043b\u0443 \u0443\u0430\u049b\u044b\u0442\u044b, \u043c\u0438\u043d:",
"TabPreferences": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440",
+ "LabelParentalRating": "\u0416\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442\u044b:",
"TabPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437",
+ "LabelCustomRating": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u044b\u049b \u0441\u0430\u043d\u0430\u0442\u044b:",
"TabLibraryAccess": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u0493\u0430 \u049b\u0430\u0442\u044b\u043d\u0430\u0441",
+ "LabelBudget": "\u0411\u044e\u0434\u0436\u0435\u0442\u0456",
"TabImage": "\u0421\u0443\u0440\u0435\u0442",
+ "LabelRevenue": "\u0422\u04af\u0441\u0456\u043c\u0456, $:",
"TabProfile": "\u041f\u0440\u043e\u0444\u0438\u043b\u044c",
+ "LabelOriginalAspectRatio": "\u0411\u0430\u0441\u0442\u0430\u043f\u049b\u044b \u043f\u0456\u0448\u0456\u043c\u0434\u0456\u043a \u0430\u0440\u0430\u049b\u0430\u0442\u044b\u043d\u0430\u0441\u044b:",
"TabMetadata": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a",
+ "LabelPlayers": "\u041e\u0439\u044b\u043d\u0448\u044b\u043b\u0430\u0440:",
"TabImages": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u0440",
- "TabNotifications": "\u0425\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443",
- "TabCollectionTitles": "\u0410\u0442\u0430\u0443\u043b\u0430\u0440",
+ "Label3DFormat": "3D \u043f\u0456\u0448\u0456\u043c\u0456:",
+ "TabNotifications": "\u0425\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443\u043b\u0430\u0440",
+ "HeaderAlternateEpisodeNumbers": "\u0411\u0430\u043b\u0430\u043c\u0430\u043b\u044b \u044d\u043f\u0438\u0437\u043e\u0434 \u043d\u04e9\u043c\u0456\u0440\u043b\u0435\u0440\u0456",
+ "TabCollectionTitles": "\u0422\u0443\u044b\u043d\u0434\u044b\u043b\u0430\u0440",
+ "HeaderSpecialEpisodeInfo": "\u0410\u0440\u043d\u0430\u0439\u044b \u044d\u043f\u0438\u0437\u043e\u0434 \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u044b",
"LabelDisplayMissingEpisodesWithinSeasons": "\u0416\u043e\u049b \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440\u0434\u044b \u043c\u0430\u0443\u0441\u044b\u043c \u0456\u0448\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
+ "HeaderExternalIds": "\u0421\u044b\u0440\u0442\u049b\u044b \u0441\u04d9\u0439\u043a\u0435\u0441\u0442\u0435\u043d\u0434\u0456\u0440\u0433\u0456\u0448\u0442\u0435\u0440:",
"LabelUnairedMissingEpisodesWithinSeasons": "\u041a\u04e9\u0440\u0441\u0435\u0442\u0456\u043b\u043c\u0435\u0433\u0435\u043d \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440\u0434\u044b \u043c\u0430\u0443\u0441\u044b\u043c \u0456\u0448\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
+ "LabelDvdSeasonNumber": "DVD \u043c\u0430\u0443\u0441\u044b\u043c \u043d\u04e9\u043c\u0456\u0440\u0456",
"HeaderVideoPlaybackSettings": "\u0411\u0435\u0439\u043d\u0435 \u043e\u0439\u043d\u0430\u0442\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456",
+ "LabelDvdEpisodeNumber": "DVD \u044d\u043f\u0438\u0437\u043e\u0434 \u043d\u04e9\u043c\u0456\u0440\u0456",
"HeaderPlaybackSettings": "\u041e\u0439\u043d\u0430\u0442\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456",
+ "LabelAbsoluteEpisodeNumber": "\u041d\u0430\u049b\u043f\u0430-\u043d\u0430\u049b \u044d\u043f\u0438\u0437\u043e\u0434 \u043d\u04e9\u043c\u0456\u0440\u0456",
"LabelAudioLanguagePreference": "\u0414\u044b\u0431\u044b\u0441 \u0442\u0456\u043b\u0456\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:",
+ "LabelAirsBeforeSeason": "\"Airs before\" \u043c\u0430\u0443\u0441\u044b\u043c\u044b",
"LabelSubtitleLanguagePreference": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440 \u0442\u0456\u043b\u0456\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:",
+ "LabelAirsAfterSeason": "\"Airs after\" \u043c\u0430\u0443\u0441\u044b\u043c\u044b",
"OptionDefaultSubtitles": "\u04d8\u0434\u0435\u043f\u043a\u0456",
+ "LabelAirsBeforeEpisode": "\"Airs after\" \u044d\u043f\u0438\u0437\u043e\u0434\u044b",
"OptionOnlyForcedSubtitles": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u043c\u04d9\u0436\u0431\u04af\u0440\u043b\u0456 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440",
+ "LabelTreatImageAs": "\u0421\u0443\u0440\u0435\u0442\u0442\u0456 \u0431\u044b\u043b\u0430\u0439 \u043a\u04e9\u0440\u0443:",
"OptionAlwaysPlaySubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u04d9\u0440\u049b\u0430\u0448\u0430\u043d \u043e\u0439\u043d\u0430\u0442\u0443",
+ "LabelDisplayOrder": "\u0411\u0435\u0439\u043d\u0435\u043b\u0435\u0443 \u0440\u0435\u0442\u0456:",
"OptionNoSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 \u0436\u043e\u049b",
+ "LabelDisplaySpecialsWithinSeasons": "\u0410\u0440\u043d\u0430\u0439\u044b\u043b\u0430\u0440\u0434\u044b \u044d\u0444\u0438\u0440\u0434\u0435 \u0431\u043e\u043b\u0493\u0430\u043d \u043c\u0430\u0443\u0441\u044b\u043c \u0456\u0448\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
"OptionDefaultSubtitlesHelp": "\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 \u0448\u0435\u0442\u0435\u043b \u0442\u0456\u043b\u0456\u043d\u0434\u0435 \u0431\u043e\u043b\u0493\u0430\u043d\u0434\u0430 \u0436\u04af\u043a\u0442\u0435\u043b\u0435\u0434\u0456.",
+ "HeaderCountries": "\u0415\u043b\u0434\u0435\u0440",
"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.",
+ "HeaderGenres": "\u0416\u0430\u043d\u0440\u043b\u0430\u0440",
"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.",
+ "HeaderPlotKeywords": "\u0421\u044e\u0436\u0435\u0442\u0442\u0456\u043d \u043a\u0456\u043b\u0442 \u0441\u04e9\u0437\u0434\u0435\u0440\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.",
+ "HeaderStudios": "\u0421\u0442\u0443\u0434\u0438\u044f\u043b\u0430\u0440",
"TabProfiles": "\u041f\u0440\u043e\u0444\u0438\u043b\u044c\u0434\u0435\u0440",
+ "HeaderTags": "\u0422\u0435\u0433\u0442\u0435\u0440",
"TabSecurity": "\u049a\u0430\u0443\u0456\u043f\u0441\u0456\u0437\u0434\u0456\u043a",
+ "HeaderMetadataSettings": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456",
"ButtonAddUser": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b \u04af\u0441\u0442\u0435\u0443",
+ "LabelLockItemToPreventChanges": "\u041e\u0441\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u043a\u0435\u043b\u0435\u0448\u0435\u043a \u04e9\u0437\u0433\u0435\u0440\u0442\u0443\u043b\u0435\u0440\u0434\u0435\u043d \u049b\u04b1\u0440\u0441\u0430\u0443\u043b\u0430\u0443",
"ButtonSave": "\u0421\u0430\u049b\u0442\u0430\u0443",
+ "MessageLeaveEmptyToInherit": "\u0422\u0435\u043a\u0442\u0456\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u043d, \u043d\u0435\u043c\u0435\u0441\u0435 \u0493\u0430\u043b\u0430\u043c\u0434\u044b\u049b \u04d9\u0434\u0435\u043f\u043a\u0456 \u043c\u04d9\u043d\u0456\u043d\u0435\u043d\u0456. \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440 \u043c\u04b1\u0440\u0430\u0441\u044b\u043d\u0430 \u0438\u0435\u043b\u0435\u043d\u0443 \u04af\u0448\u0456\u043d \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u04a3\u044b\u0437.",
"ButtonResetPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u044b\u0441\u044b\u0440\u0443",
+ "TabSupporterClub": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u043b\u0443\u0431\u044b",
"LabelNewPassword": "\u0416\u0430\u04a3\u0430 \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437",
+ "HeaderDonationType": "\u049a\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b \u0442\u04af\u0440\u0456:",
"LabelNewPasswordConfirm": "\u0416\u0430\u04a3\u0430 \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u0440\u0430\u0441\u0442\u0430\u0443:",
+ "OptionMakeOneTimeDonation": "\u0411\u0456\u0440 \u0440\u0435\u0442 \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b \u0436\u0430\u0441\u0430\u0443",
"HeaderCreatePassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u0436\u0430\u0441\u0430\u0443",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "\u0410\u0493\u044b\u043c\u0434\u0430\u0493\u044b \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437:",
+ "OptionLifeTimeSupporterClubMembership": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u043b\u0443\u0431\u044b\u043d\u044b\u04a3 \u0493\u04b1\u043c\u044b\u0440\u043b\u044b\u049b \u043c\u04af\u0448\u0435\u043b\u0456\u0433\u0456",
"LabelMaxParentalRating": "\u0420\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0456\u043b\u0433\u0435\u043d \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u0436\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442\u044b:",
+ "HeaderSupporterBenefit": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u043b\u0443\u0431\u044b\u043d\u044b\u04a3 \u043c\u04af\u0448\u0435\u0441\u0456 \u0431\u043e\u043b\u0430 \u0442\u04b1\u0440\u0443 \u049b\u043e\u0441\u044b\u043c\u0448\u0430 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u0440\u0434\u044b \u049b\u0430\u043c\u0442\u0430\u043c\u0430\u0441\u044b\u0437 \u0435\u0442\u0435\u0434\u0456, \u043c\u044b\u0441\u0430\u043b\u044b, \u0435\u0440\u0435\u043a\u0448\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440, \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0430\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u044b\u04a3 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b \u0436\u04d9\u043d\u0435 \u043e\u0434\u0430\u043d \u0434\u0430 \u043a\u04e9\u0431\u0456\u0440\u0435\u043a.",
"MaxParentalRatingHelp": "\u0411\u04b1\u043b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u0434\u0430\u043d \u0436\u043e\u0493\u0430\u0440\u044b\u043b\u0430\u0443 \u0436\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442\u044b \u0431\u0430\u0440 \u043c\u0430\u0437\u043c\u04b1\u043d \u0436\u0430\u0441\u044b\u0440\u044b\u043b\u0430\u0434\u044b",
+ "OptionNoTrailer": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u0441\u0456\u0437",
"LibraryAccessHelp": "\u0411\u04b1\u043b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043c\u0435\u043d \u043e\u0440\u0442\u0430\u049b\u0442\u0430\u0441\u0443 \u04af\u0448\u0456\u043d \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u0434\u044b \u0431\u04e9\u043b\u0435\u043a\u0442\u0435\u04a3\u0456\u0437. \u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0431\u0430\u0441\u049b\u0430\u0440\u0443\u0448\u044b\u043d\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043f \u04d9\u043a\u0456\u043c\u0448\u0456\u043b\u0435\u0440 \u0431\u0430\u0440\u043b\u044b\u049b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u0434\u044b \u04e9\u04a3\u0434\u0435\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.",
+ "OptionNoThemeSong": "\u0422\u0430\u049b\u044b\u0440\u044b\u043f \u04d9\u0443\u0435\u043d\u0456\u0441\u0456\u0437",
"ChannelAccessHelp": "\u0411\u04b1\u043b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043c\u0435\u043d \u043e\u0440\u0442\u0430\u049b\u0442\u0430\u0441\u0443 \u04af\u0448\u0456\u043d \u0430\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u044b \u0431\u04e9\u043b\u0435\u043a\u0442\u0435\u04a3\u0456\u0437. \u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0431\u0430\u0441\u049b\u0430\u0440\u0443\u0448\u044b\u043d\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043f \u04d9\u043a\u0456\u043c\u0448\u0456\u043b\u0435\u0440 \u0431\u0430\u0440\u043b\u044b\u049b \u0430\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u044b \u04e9\u04a3\u0434\u0435\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.",
+ "OptionNoThemeVideo": "\u0422\u0430\u049b\u044b\u0440\u044b\u043f \u0431\u0435\u0439\u043d\u0435\u0441\u0456\u0441\u0456\u0437",
"ButtonDeleteImage": "\u0421\u0443\u0440\u0435\u0442\u0442\u0456 \u0436\u043e\u044e",
+ "LabelOneTimeDonationAmount": "\u049a\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b \u049b\u043e\u0440\u044b\u0442\u044b\u043d\u0434\u044b\u0441\u044b:",
"LabelSelectUsers": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440\u0434\u044b \u0442\u0430\u04a3\u0434\u0430\u0443:",
+ "OptionActor": "\u0410\u043a\u0442\u0435\u0440",
"ButtonUpload": "\u041a\u0435\u0440\u0456 \u049b\u043e\u0442\u0430\u0440\u0443",
+ "OptionComposer": "\u041a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u043e\u0440",
"HeaderUploadNewImage": "\u0416\u0430\u04a3\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0456 \u043a\u0435\u0440\u0456 \u049b\u043e\u0442\u0430\u0440\u0443",
+ "OptionDirector": "\u0420\u0435\u0436\u0438\u0441\u0441\u0435\u0440",
"LabelDropImageHere": "\u0421\u0443\u0440\u0435\u0442\u0442\u0456 \u043c\u04b1\u043d\u0434\u0430 \u0441\u04af\u0439\u0440\u0435\u0442\u0456\u04a3\u0456\u0437",
+ "OptionGuestStar": "\u0428\u0430\u049b\u044b\u0440\u044b\u043b\u0493\u0430\u043d \u0430\u043a\u0442\u0435\u0440",
"ImageUploadAspectRatioHelp": "1:1 \u043f\u0456\u0448\u0456\u043c\u0434\u0456\u043a \u0430\u0440\u0430\u049b\u0430\u0442\u044b\u043d\u0430\u0441\u044b \u04b1\u0441\u044b\u043d\u044b\u043b\u0430\u0434\u044b. \u0422\u0435\u043a \u049b\u0430\u043d\u0430 JPG\/PNG.",
+ "OptionProducer": "\u041f\u0440\u043e\u0434\u044e\u0441\u0435\u0440",
"MessageNothingHere": "\u041e\u0441\u044b\u043d\u0434\u0430 \u0435\u0448\u0442\u0435\u043c\u0435 \u0436\u043e\u049b.",
+ "OptionWriter": "\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439\u0448\u0456",
"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 \u0442\u0435\u043a\u0441\u0435\u0440\u0456\u04a3\u0456\u0437.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "\u04b0\u0441\u044b\u043d\u044b\u043b\u0493\u0430\u043d",
+ "LabelAirTime": "Air time:",
"TabLatest": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "\u041a\u04af\u0442\u0456\u043b\u0433\u0435\u043d",
- "TabShows": "\u0421\u0435\u0440\u0438\u0430\u043b\u0434\u0430\u0440",
+ "HeaderPhotoInfo": "Photo Info",
+ "TabShows": "\u041a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c\u0434\u0435\u0440",
"TabEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440",
"TabGenres": "\u0416\u0430\u043d\u0440\u043b\u0430\u0440",
"TabPeople": "\u0410\u0434\u0430\u043c\u0434\u0430\u0440",
@@ -141,12 +203,12 @@
"OptionLikes": "\u04b0\u043d\u0430\u0442\u0443\u043b\u0430\u0440",
"OptionDislikes": "\u04b0\u043d\u0430\u0442\u043f\u0430\u0443\u043b\u0430\u0440",
"OptionActors": "\u0410\u043a\u0442\u0435\u0440\u043b\u0435\u0440",
- "OptionGuestStars": "\u049a\u043e\u043d\u0430\u049b \u0436\u04b1\u043b\u0434\u044b\u0437\u0434\u0430\u0440",
+ "OptionGuestStars": "\u0428\u0430\u049b\u044b\u0440\u044b\u043b\u0493\u0430\u043d \u0430\u043a\u0442\u0435\u0440\u043b\u0435\u0440",
"OptionDirectors": "\u0420\u0435\u0436\u0438\u0441\u0441\u0435\u0440\u043b\u0435\u0440",
- "OptionWriters": "\u0416\u0430\u0437\u0443\u0448\u044b\u043b\u0430\u0440",
+ "OptionWriters": "\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0439\u0448\u0456\u043b\u0435\u0440",
"OptionProducers": "\u041f\u0440\u043e\u0434\u044e\u0441\u0435\u0440\u043b\u0435\u0440",
"HeaderResume": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443",
- "HeaderNextUp": "\u0410\u043b\u0434\u0430\u0493\u044b",
+ "HeaderNextUp": "\u041a\u0435\u0437\u0435\u043a\u0442\u0435\u0433\u0456\u043b\u0435\u0440",
"NoNextUpItemsMessage": "\u0415\u0448\u0442\u0435\u043c\u0435 \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0434\u044b. \u041a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u049b\u0430\u0440\u0430\u0439 \u0431\u0430\u0441\u0442\u0430\u04a3\u044b\u0437!",
"HeaderLatestEpisodes": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440",
"HeaderPersonTypes": "\u0410\u0434\u0430\u043c \u0442\u04af\u0440\u043b\u0435\u0440\u0456:",
@@ -163,7 +225,7 @@
"OptionAscending": "\u0410\u0440\u0442\u0443\u044b \u0431\u043e\u0439\u044b\u043d\u0448\u0430",
"OptionDescending": "\u041a\u0435\u043c\u0443\u0456 \u0431\u043e\u0439\u044b\u043d\u0448\u0430",
"OptionRuntime": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443 \u0443\u0430\u049b\u044b\u0442\u044b",
- "OptionReleaseDate": "\u0428\u044b\u0493\u0430\u0440\u044b\u043b\u0493\u0430\u043d \u043a\u04af\u043d-\u0430\u0439\u044b",
+ "OptionReleaseDate": "\u0428\u044b\u0493\u0430\u0440\u0443 \u043a\u04af\u043d-\u0430\u0439\u044b",
"OptionPlayCount": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0441\u0430\u043d\u044b",
"OptionDatePlayed": "\u041e\u0439\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d \u043a\u04af\u043d-\u0430\u0439\u044b",
"OptionDateAdded": "\u04ae\u0441\u0442\u0435\u043b\u0433\u0435\u043d \u043a\u04af\u043d-\u0430\u0439\u044b",
@@ -171,7 +233,7 @@
"OptionArtist": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b",
"OptionAlbum": "\u0410\u043b\u044c\u0431\u043e\u043c",
"OptionTrackName": "\u0416\u043e\u043b\u0448\u044b\u049b \u0430\u0442\u044b",
- "OptionCommunityRating": "\u049a\u043e\u0493\u0430\u043c\u0434\u044b\u049b \u0431\u0430\u0493\u0430\u043b\u0430\u0443",
+ "OptionCommunityRating": "\u049a\u0430\u0443\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u049b \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b",
"OptionNameSort": "\u0410\u0442\u044b",
"OptionFolderSort": "\u049a\u0430\u043b\u0442\u0430\u043b\u0430\u0440",
"OptionBudget": "\u0411\u044e\u0434\u0436\u0435\u0442",
@@ -185,7 +247,7 @@
"OptionVideoBitrate": "\u0411\u0435\u0439\u043d\u0435 \u049b\u0430\u0440\u049b\u044b\u043d\u044b",
"OptionResumable": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0430\u043b\u0430\u0442\u044b\u043d",
"ScheduledTasksHelp": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0443\u044b\u043d \u043b\u0430\u0439\u044b\u049b\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043d\u044b \u043d\u04b1\u049b\u044b\u04a3\u044b\u0437.",
- "ScheduledTasksTitle": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043b\u0430\u0440",
+ "ScheduledTasksTitle": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0443\u0448\u044b",
"TabMyPlugins": "\u041c\u0435\u043d\u0456\u04a3 \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440\u0456\u043c",
"TabCatalog": "\u041a\u0430\u0442\u0430\u043b\u043e\u0433",
"PluginsTitle": "\u041f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440",
@@ -201,7 +263,7 @@
"OptionDvd": "DVD",
"OptionIso": "ISO",
"Option3D": "3D",
- "LabelFeatures": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430\u043b\u0430\u0440:",
+ "LabelFeatures": "\u041c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440:",
"LabelService": "\u049a\u044b\u0437\u043c\u0435\u0442:",
"LabelStatus": "\u041a\u04af\u0439:",
"LabelVersion": "\u041d\u04b1\u0441\u049b\u0430:",
@@ -213,18 +275,20 @@
"TabMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
"TabStudios": "\u0421\u0442\u0443\u0434\u0438\u044f\u043b\u0430\u0440",
"TabTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440",
+ "LabelArtists": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b\u043b\u0430\u0440:",
+ "LabelArtistsHelp": "\u0411\u0456\u0440\u043d\u0435\u0448\u0443\u0456\u043d (;) \u0430\u0440\u049b\u044b\u043b\u044b \u0431\u04e9\u043b\u0456\u04a3\u0456\u0437",
"HeaderLatestMovies": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0444\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
"HeaderLatestTrailers": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440",
- "OptionHasSpecialFeatures": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430\u043b\u0430\u0440",
+ "OptionHasSpecialFeatures": "\u041c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440",
"OptionImdbRating": "IMDb \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b",
"OptionParentalRating": "\u0416\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442",
"OptionPremiereDate": "\u0422\u04b1\u0441\u0430\u0443\u043a\u0435\u0441\u0435\u0440 \u043a\u04af\u043d-\u0430\u0439\u044b",
"TabBasic": "\u041d\u0435\u0433\u0456\u0437\u0433\u0456\u043b\u0435\u0440",
- "TabAdvanced": "\u041a\u0435\u04a3\u0435\u0439\u0442\u0456\u043b\u0433\u0435\u043d\u0434\u0435\u0440",
+ "TabAdvanced": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430",
"HeaderStatus": "\u041a\u04af\u0439",
"OptionContinuing": "\u0416\u0430\u043b\u0493\u0430\u0441\u0443\u0434\u0430",
"OptionEnded": "\u0410\u044f\u049b\u0442\u0430\u043b\u0434\u044b",
- "HeaderAirDays": "\u042d\u0444\u0438\u0440 \u043a\u04af\u043d\u0434\u0435\u0440\u0456:",
+ "HeaderAirDays": "\u042d\u0444\u0438\u0440 \u043a\u04af\u043d\u0434\u0435\u0440\u0456",
"OptionSunday": "\u0436\u0435\u043a\u0441\u0435\u043d\u0431\u0456",
"OptionMonday": "\u0434\u04af\u0439\u0441\u0435\u043d\u0431\u0456",
"OptionTuesday": "\u0441\u0435\u0439\u0441\u0435\u043d\u0431\u0456",
@@ -232,10 +296,11 @@
"OptionThursday": "\u0431\u0435\u0439\u0441\u0435\u043d\u0431\u0456",
"OptionFriday": "\u0436\u04b1\u043c\u0430",
"OptionSaturday": "\u0441\u0435\u043d\u0431\u0456",
- "HeaderManagement": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a:",
+ "HeaderManagement": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440",
+ "LabelManagement": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440",
"OptionMissingImdbId": "IMDb Id \u0436\u043e\u049b",
"OptionMissingTvdbId": "TheTVDB Id \u0436\u043e\u049b",
- "OptionMissingOverview": "\u0428\u043e\u043b\u0443 \u0436\u043e\u049b",
+ "OptionMissingOverview": "\u0416\u0430\u043b\u043f\u044b \u0448\u043e\u043b\u0443 \u0436\u043e\u049b",
"OptionFileMetadataYearMismatch": "\u0424\u0430\u0439\u043b\/\u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0436\u044b\u043b\u044b \u0441\u04d9\u0439\u043a\u0435\u0441 \u0435\u043c\u0435\u0441",
"TabGeneral": "\u0416\u0430\u043b\u043f\u044b",
"TitleSupport": "\u049a\u043e\u043b\u0434\u0430\u0443",
@@ -256,7 +321,7 @@
"LabelName": "\u0410\u0442\u044b:",
"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": "\u041c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u043a\u0442\u0435\u0440\u0433\u0435 \u049b\u0430\u0442\u044b\u043d\u0430\u0441",
- "OptionAllowMediaPlayback": "\u0422\u0430\u0441\u0443\u0448\u044b \u043e\u0439\u043d\u0430\u0442\u0443\u044b\u043d\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
+ "OptionAllowMediaPlayback": "\u0422\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u043e\u0439\u043d\u0430\u0442\u0443\u044b\u043d\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
"OptionAllowBrowsingLiveTv": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414 \u0448\u0430\u0440\u043b\u0430\u0443\u044b\u043d\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
"OptionAllowDeleteLibraryContent": "\u0411\u04b1\u043b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u0493\u0430 \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0436\u043e\u044e \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
"OptionAllowManageLiveTv": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414 \u0436\u0430\u0437\u0443\u0434\u044b \u0431\u0430\u0441\u049b\u0430\u0440\u0443\u044b\u043d\u0430 \u0440\u0443\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b",
"ButtonSelect": "\u0411\u04e9\u043b\u0435\u043a\u0442\u0435\u0443",
- "ButtonSearch": "\u0406\u0437\u0434\u0435\u0443",
"ButtonGroupVersions": "\u041d\u04b1\u0441\u049b\u0430\u043b\u0430\u0440\u0434\u044b \u0442\u043e\u043f\u0442\u0430\u0441\u0442\u044b\u0440\u0443",
"ButtonAddToCollection": "\u0422\u043e\u043f\u0442\u0430\u043c\u0430\u0493\u0430 \u049b\u043e\u0441\u0443",
"PismoMessage": "\u0421\u044b\u0439\u043b\u0430\u043d\u0493\u0430\u043d \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u044f \u0430\u0440\u049b\u044b\u043b\u044b Pismo File Mount \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0434\u0430.",
@@ -277,7 +341,7 @@
"TabPaths": "\u0416\u043e\u043b\u0434\u0430\u0440",
"TabServer": "\u0421\u0435\u0440\u0432\u0435\u0440",
"TabTranscoding": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443",
- "TitleAdvanced": "\u041a\u0435\u04a3\u0435\u0439\u0442\u0456\u043b\u0433\u0435\u043d \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440",
+ "TitleAdvanced": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430",
"LabelAutomaticUpdateLevel": "\u0410\u0432\u0442\u043e\u0436\u0430\u04a3\u0430\u0440\u0442\u0443 \u0434\u0435\u04a3\u0433\u0435\u0439\u0456",
"OptionRelease": "\u0420\u0435\u0441\u043c\u0438 \u0448\u044b\u0493\u0430\u0440\u044b\u043b\u044b\u043c",
"OptionBeta": "\u0411\u0435\u0442\u0430 \u043d\u04b1\u0441\u049b\u0430",
@@ -288,15 +352,15 @@
"LabelRunServerAtStartup": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0443\u0434\u0430\u043d \u0431\u0430\u0441\u0442\u0430\u043f \u043e\u0440\u044b\u043d\u0434\u0430\u0443",
"LabelRunServerAtStartupHelp": "\u0411\u04b1\u043b Windows \u0436\u04b1\u043c\u044b\u0441\u044b\u043d \u0431\u0430\u0441\u0442\u0430\u0493\u0430\u043d\u0434\u0430 \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u0442\u0430\u049b\u0442\u0430\u0434\u0430\u0493\u044b \u0431\u0435\u043b\u0433\u0456\u0448\u0435 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0430\u0434\u044b. Windows \u049b\u044b\u0437\u043c\u0435\u0442\u0456\u043d \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443 \u04af\u0448\u0456\u043d, \u049b\u04b1\u0441\u0431\u0435\u043b\u0433\u0456\u043d\u0456 \u0430\u043b\u044b\u04a3\u044b\u0437 \u0436\u04d9\u043d\u0435 \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0456 Windows \u049a\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0456 \u0430\u0440\u049b\u044b\u043b\u044b \u043e\u0440\u044b\u043d\u0434\u0430\u04a3\u044b\u0437. \u041d\u0430\u0437\u0430\u0440 \u0430\u0443\u0434\u0430\u0440\u044b\u04a3\u044b\u0437! \u0411\u04b1\u043b \u0435\u043a\u0435\u0443\u0456\u043d \u0441\u043e\u043b \u043c\u0435\u0437\u0433\u0456\u043b\u0434\u0435 \u0431\u0456\u0440\u0433\u0435 \u043e\u0440\u044b\u043d\u0434\u0430\u0443 \u043c\u04af\u043c\u043a\u0456\u043d \u0435\u043c\u0435\u0441, \u0441\u043e\u043d\u044b\u043c\u0435\u043d \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0456 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443 \u0430\u043b\u0434\u044b\u043d\u0430\u043d \u0436\u04af\u0439\u0435\u043b\u0456\u043a \u0442\u0430\u049b\u0442\u0430\u0434\u0430\u0493\u044b \u0431\u0435\u043b\u0433\u0456\u0448\u0435\u0434\u0435\u043d \u0448\u044b\u0493\u044b\u04a3\u044b\u0437.",
"ButtonSelectDirectory": "\u049a\u0430\u0442\u0430\u043b\u043e\u0433\u0442\u044b \u0431\u04e9\u043b\u0435\u043a\u0442\u0435\u0443",
- "LabelCustomPaths": "\u049a\u0430\u043b\u0430\u0443 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u043e\u043b\u0434\u0430\u0440\u0434\u044b \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u04a3\u0456\u0437. \u04d8\u0434\u0435\u043f\u043a\u0456\u043b\u0435\u0440\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u04e9\u0440\u0456\u0441\u0442\u0435\u0440\u0434\u0456 \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u04a3\u044b\u0437.",
+ "LabelCustomPaths": "\u049a\u0430\u043b\u0430\u0443\u044b\u04a3\u044b\u0437 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u043e\u043b\u0434\u0430\u0440\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437. \u04d8\u0434\u0435\u043f\u043a\u0456\u043b\u0435\u0440\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u04e9\u0440\u0456\u0441\u0442\u0435\u0440\u0434\u0456 \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u04a3\u044b\u0437.",
"LabelCachePath": "Cache \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d\u044b\u04a3 \u0436\u043e\u043b\u044b:",
- "LabelCachePathHelp": "\u0411\u04b1\u043b \u049b\u0430\u043b\u0442\u0430 \u049b\u04b1\u0440\u0430\u043c\u044b\u043d\u0434\u0430 \u0441\u0443\u0440\u0435\u0442 \u0441\u0438\u044f\u049b\u0442\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u043a\u044d\u0448 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u0431\u0430\u0440.",
+ "LabelCachePathHelp": "\u0421\u0443\u0440\u0435\u0442 \u0441\u0438\u044f\u049b\u0442\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u043a\u044d\u0448 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u0430\u0439\u0493\u0430\u0441\u044b\u043c\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.",
"LabelImagesByNamePath": "Images by name \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d\u044b\u04a3 \u0436\u043e\u043b\u044b:",
- "LabelImagesByNamePathHelp": "\u0411\u04b1\u043b \u049b\u0430\u043b\u0442\u0430 \u049b\u04b1\u0440\u0430\u043c\u044b\u043d\u0434\u0430 \u0430\u043a\u0442\u0435\u0440, \u043e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b, \u0436\u0430\u043d\u0440, \u0436\u04d9\u043d\u0435 \u0441\u0442\u0443\u0434\u0438\u044f \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456 \u0431\u0430\u0440.",
+ "LabelImagesByNamePathHelp": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0493\u0430\u043d \u0430\u043a\u0442\u0435\u0440, \u043e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b, \u0436\u0430\u043d\u0440, \u0436\u04d9\u043d\u0435 \u0441\u0442\u0443\u0434\u0438\u044f \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456 \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u0430\u0439\u0493\u0430\u0441\u044b\u043c\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.",
"LabelMetadataPath": "Metadata \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d\u044b\u04a3 \u0436\u043e\u043b\u044b:",
- "LabelMetadataPathHelp": "\u0411\u04b1\u043b \u0436\u0430\u0439\u0493\u0430\u0441\u044b\u043c \u0456\u0448\u0456\u043d\u0434\u0435 \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b\u043d\u0434\u0430 \u0441\u0430\u049b\u0442\u0430\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0441\u044b \u0456\u0441\u0442\u0435\u043b\u043c\u0435\u0433\u0435\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0493\u0430\u043d \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u043c\u0435 \u043c\u0435\u043d \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0431\u0430\u0440.",
+ "LabelMetadataPathHelp": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0493\u0430\u043d \u0441\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 \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u0430\u0439\u0493\u0430\u0441\u044b\u043c\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.",
"LabelTranscodingTempPath": "Transcoding temporary \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d\u044b\u04a3 \u0436\u043e\u043b\u044b:",
- "LabelTranscodingTempPathHelp": "\u0411\u04b1\u043b \u049b\u0430\u043b\u0442\u0430 \u049b\u04b1\u0440\u0430\u043c\u044b\u043d\u0434\u0430 \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u049b\u04b1\u0440\u0430\u043b\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0430\u0442\u044b\u043d \u0436\u04b1\u043c\u044b\u0441 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u0431\u0430\u0440.",
+ "LabelTranscodingTempPathHelp": "\u0411\u04b1\u043b \u049b\u0430\u043b\u0442\u0430 \u049b\u04b1\u0440\u0430\u043c\u044b\u043d\u0434\u0430 \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u049b\u04b1\u0440\u0430\u043b\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0430\u0442\u044b\u043d \u0436\u04b1\u043c\u044b\u0441 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u0431\u0430\u0440. \u0422\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u043e\u043b\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437, \u043d\u0435\u043c\u0435\u0441\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u049b\u0430\u043b\u0442\u0430\u0441\u044b \u0456\u0448\u0456\u043d\u0434\u0435\u0433\u0456 \u04d9\u0434\u0435\u043f\u043a\u0456\u0441\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u04a3\u044b\u0437.",
"TabBasics": "\u041d\u0435\u0433\u0456\u0437\u0433\u0456\u043b\u0435\u0440",
"TabTV": "\u0422\u0414",
"TabGames": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440",
@@ -313,12 +377,12 @@
"LabelAutomaticUpdatesFanartHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0436\u0430\u04a3\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 fanart.tv \u0434\u0435\u0440\u0435\u049b\u043e\u0440\u044b\u043d\u0430 \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d \u0431\u043e\u0439\u0434\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0436\u04af\u043a\u0442\u0435\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0430\u0434\u044b. \u0411\u0430\u0440 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 \u0430\u0443\u044b\u0441\u0442\u044b\u0440\u044b\u043b\u043c\u0430\u0439\u0434\u044b.",
"LabelAutomaticUpdatesTmdbHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0436\u0430\u04a3\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 TheMovieDB.org \u0434\u0435\u0440\u0435\u049b\u043e\u0440\u044b\u043d\u0430 \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d \u0431\u043e\u0439\u0434\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0436\u04af\u043a\u0442\u0435\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0430\u0434\u044b. \u0411\u0430\u0440 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 \u0430\u0443\u044b\u0441\u0442\u044b\u0440\u044b\u043b\u043c\u0430\u0439\u0434\u044b.",
"LabelAutomaticUpdatesTvdbHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0436\u0430\u04a3\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 TheTVDB.com \u0434\u0435\u0440\u0435\u049b\u043e\u0440\u044b\u043d\u0430 \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d \u0431\u043e\u0439\u0434\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0436\u04af\u043a\u0442\u0435\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0430\u0434\u044b. \u0411\u0430\u0440 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440 \u0430\u0443\u044b\u0441\u0442\u044b\u0440\u044b\u043b\u043c\u0430\u0439\u0434\u044b.",
- "ExtractChapterImagesHelp": "\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 4:00 \u0441\u0430\u0493\u0430\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 \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043b\u0430\u0440 \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 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0442\u043a\u0456\u0437\u0443 \u04b1\u0441\u044b\u043d\u044b\u043b\u043c\u0430\u0439\u0434\u044b.",
- "LabelMetadataDownloadLanguage": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0442\u0456\u043b\u0456\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:",
+ "ExtractChapterImagesHelp": "\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. \u041e\u043b \u0431\u0435\u0439\u043d\u0435\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u0442\u0430\u0431\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0436\u04d9\u043d\u0435 \u0442\u0430\u04a3\u0493\u044b 4:00 \u0441\u0430\u0493\u0430\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. \u041e\u0440\u044b\u043d\u0434\u0430\u0443 \u043a\u0435\u0441\u0442\u0435\u0441\u0456 \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 \u0436\u04b1\u043c\u044b\u0441 \u0456\u0441\u0442\u0435\u0442\u043a\u0456\u0437\u0443 \u04b1\u0441\u044b\u043d\u044b\u043b\u043c\u0430\u0439\u0434\u044b.",
+ "LabelMetadataDownloadLanguage": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u0442\u0456\u043b\u0456\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:",
"ButtonAutoScroll": "\u0410\u0432\u0442\u043e\u0430\u0439\u043d\u0430\u043b\u0434\u044b\u0440\u0443",
"LabelImageSavingConvention": "\u0421\u0443\u0440\u0435\u0442 \u0441\u0430\u049b\u0442\u0430\u0443 \u043a\u0435\u043b\u0456\u0441\u0456\u043c\u0456:",
"LabelImageSavingConventionHelp": "Media Browser \u043a\u0435\u04a3 \u0442\u0430\u0440\u0430\u0493\u0430\u043d \u043c\u0443\u043b\u044c\u0442\u0438\u043c\u0435\u0434\u0438\u0430 \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u044b\u043d\u0430\u043d \u0430\u043b\u044b\u043d\u0493\u0430\u043d \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0442\u0430\u043d\u0438\u0434\u044b. \u0421\u043e\u043d\u044b\u043c\u0435\u043d \u049b\u0430\u0442\u0430\u0440 \u0431\u0430\u0441\u049b\u0430 \u04e9\u043d\u0456\u043c\u0434\u0435\u0440 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0434\u0430 \u0431\u043e\u043b\u0441\u0430, \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u043a\u0435\u043b\u0456\u0441\u0456\u043c\u0456\u043d \u0442\u0430\u04a3\u0434\u0430\u0443 \u043f\u0430\u0439\u0434\u0430\u043b\u044b.",
- "OptionImageSavingCompatible": "\u0421\u044b\u0439\u044b\u0441\u044b\u043c\u0434\u044b - Media Browser\/Plex\/XBMC",
+ "OptionImageSavingCompatible": "\u0421\u044b\u0439\u044b\u0441\u044b\u043c\u0434\u044b - Media Browser\/XBMC\/Plex",
"OptionImageSavingStandard": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0442\u044b - MB2",
"ButtonSignIn": "\u041a\u0456\u0440\u0443",
"TitleSignIn": "\u041a\u0456\u0440\u0443",
@@ -346,7 +410,9 @@
"HeaderUpcomingTV": "\u041a\u04af\u0442\u0456\u043b\u0433\u0435\u043d \u0422\u0414",
"TabStatus": "\u041a\u04af\u0439",
"TabSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440",
- "ButtonRefreshGuideData": "\u0422\u0414 \u043a\u0435\u0441\u0442\u0435\u0441\u0456 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043d \u0436\u0430\u04a3\u0430\u0440\u0442\u0443",
+ "ButtonRefreshGuideData": "\u0422\u0414 \u043a\u0435\u0441\u0442\u0435\u0441\u0456 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043d \u043a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443",
+ "ButtonRefresh": "\u041a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\u0442\u0443",
+ "ButtonAdvancedRefresh": "\u041a\u0435\u04a3\u0435\u0439\u0442\u0456\u043b\u0433\u0435\u043d \u043a\u04e9\u043a\u0435\u0439\u0442\u0435\u0441\u0442\u0456 \u0435\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",
@@ -380,7 +446,7 @@
"OptionDownloadBackImage": "\u0410\u0440\u0442\u049b\u044b \u043c\u04b1\u049b\u0430\u0431\u0430",
"OptionDownloadArtImage": "\u041e\u044e \u0441\u0443\u0440\u0435\u0442",
"OptionDownloadPrimaryImage": "\u0411\u0430\u0441\u0442\u0430\u043f\u049b\u044b",
- "HeaderFetchImages": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0448\u044b\u0493\u0430\u0440\u044b\u043f \u0430\u043b\u0443:",
+ "HeaderFetchImages": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0456\u0440\u0456\u043a\u0442\u0435\u0443:",
"HeaderImageSettings": "\u0421\u0443\u0440\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456",
"TabOther": "\u0411\u0430\u0441\u049b\u0430\u043b\u0430\u0440",
"LabelMaxBackdropsPerItem": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0430\u0440\u0442\u049b\u044b \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456\u04a3 \u0435\u04a3 \u043a\u04e9\u043f \u0441\u0430\u043d\u044b:",
@@ -426,13 +492,14 @@
"HeaderAwardsAndReviews": "\u041c\u0430\u0440\u0430\u043f\u0430\u0442\u0442\u0430\u0440 \u043c\u0435\u043d \u043f\u0456\u043a\u0456\u0440\u043b\u0435\u0440",
"HeaderSoundtracks": "\u0424\u0438\u043b\u044c\u043c\u0434\u0456\u04a3 \u043c\u0443\u0437\u044b\u043a\u0430\u0441\u044b",
"HeaderMusicVideos": "\u0411\u0435\u0439\u043d\u0435\u043a\u043b\u0438\u043f\u0442\u0435\u0440",
- "HeaderSpecialFeatures": "\u0410\u0440\u043d\u0430\u0439\u044b \u049b\u043e\u0441\u044b\u043c\u0448\u0430\u043b\u0430\u0440",
+ "HeaderSpecialFeatures": "\u0410\u0440\u043d\u0430\u0439\u044b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440",
"HeaderCastCrew": "\u0422\u04af\u0441\u0456\u0440\u0443\u0433\u0435 \u049b\u0430\u0442\u044b\u0441\u049b\u0430\u043d\u0434\u0430\u0440",
"HeaderAdditionalParts": "\u0416\u0430\u043b\u0493\u0430\u0441\u0430\u0442\u044b\u043d \u0431\u04e9\u043b\u0456\u043c\u0434\u0435\u0440",
"ButtonSplitVersionsApart": "\u041d\u04af\u0441\u049b\u0430\u043b\u0430\u0440\u0434\u044b \u049b\u0430\u0439\u0442\u0430 \u0431\u04e9\u043b\u0443",
+ "ButtonPlayTrailer": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440",
"LabelMissing": "\u0416\u043e\u049b",
"LabelOffline": "\u049a\u043e\u0441\u044b\u043b\u043c\u0430\u0493\u0430\u043d",
- "PathSubstitutionHelp": "\u0416\u043e\u043b \u0430\u043b\u043c\u0430\u0441\u0442\u044b\u0440\u0443\u043b\u0430\u0440\u044b\u043d \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0435\u0433\u0456 \u0436\u043e\u043b\u0434\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0430 \u0430\u043b\u0430\u0442\u044b\u043d \u0436\u043e\u043b\u043c\u0435\u043d \u0441\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b. \u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0435\u0433\u0456 \u0442\u0430\u0441\u0443\u0448\u044b\u043b\u0430\u0440\u0493\u0430 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443 \u04af\u0448\u0456\u043d \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440\u0433\u0435 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0456\u043b\u0433\u0435\u043d\u0434\u0435, \u0431\u04b1\u043b\u0430\u0440 \u0442\u0430\u0441\u0443\u0448\u044b\u043d\u044b \u0436\u0435\u043b\u0456 \u0430\u0440\u049b\u044b\u043b\u044b \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d \u0436\u04d9\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0435\u0441\u0443\u0440\u0441\u0442\u0430\u0440\u044b\u043d \u0430\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u04af\u0448\u0456\u043d \u0436\u04d9\u043d\u0435 \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0434\u0430\u043d \u0436\u0430\u043b\u0442\u0430\u0440\u0430\u0434\u044b.",
+ "PathSubstitutionHelp": "\u0416\u043e\u043b \u0430\u043b\u043c\u0430\u0441\u0442\u044b\u0440\u0443\u043b\u0430\u0440\u044b\u043d \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0435\u0433\u0456 \u0436\u043e\u043b\u0434\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0430 \u0430\u043b\u0430\u0442\u044b\u043d \u0436\u043e\u043b\u043c\u0435\u043d \u0441\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b. \u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0435\u0433\u0456 \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0433\u0435 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443 \u04af\u0448\u0456\u043d \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440\u0433\u0435 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0456\u043b\u0433\u0435\u043d\u0434\u0435, \u0431\u04b1\u043b\u0430\u0440 \u0442\u0430\u0441\u0443\u0448\u044b\u043d\u044b \u0436\u0435\u043b\u0456 \u0430\u0440\u049b\u044b\u043b\u044b \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d \u0436\u04d9\u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440 \u0440\u0435\u0441\u0443\u0440\u0441\u0442\u0430\u0440\u044b\u043d \u0430\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u04af\u0448\u0456\u043d \u0436\u04d9\u043d\u0435 \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0434\u0430\u043d \u0436\u0430\u043b\u0442\u0430\u0440\u0430\u0434\u044b.",
"HeaderFrom": "\u049a\u0430\u0439\u0434\u0430\u043d",
"HeaderTo": "\u049a\u0430\u0439\u0434\u0430",
"LabelFrom": "\u049a\u0430\u0439\u0434\u0430\u043d:",
@@ -443,7 +510,7 @@
"OptionSpecialEpisode": "\u0410\u0440\u043d\u0430\u0439\u044b\u043b\u0430\u0440",
"OptionMissingEpisode": "\u0416\u043e\u049b \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440",
"OptionUnairedEpisode": "\u041a\u04e9\u0440\u0441\u0435\u0442\u0456\u043b\u043c\u0435\u0433\u0435\u043d \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440",
- "OptionEpisodeSortName": "\u042d\u043f\u0438\u0437\u043e\u0434 \u0441\u04b1\u0440\u044b\u043f\u0442\u0430\u0443 \u0430\u0442\u044b",
+ "OptionEpisodeSortName": "\u042d\u043f\u0438\u0437\u043e\u0434\u0442\u044b\u04a3 \u0441\u04b1\u0440\u044b\u043f\u0442\u0430\u043b\u0430\u0442\u044b\u043d \u0430\u0442\u044b",
"OptionSeriesSortName": "\u0421\u0435\u0440\u0438\u0430\u043b \u0430\u0442\u044b",
"OptionTvdbRating": "Tvdb \u0431\u0430\u0493\u0430\u043b\u0430\u0443\u044b",
"HeaderTranscodingQualityPreference": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u0441\u0430\u043f\u0430\u0441\u044b\u043d\u044b\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:",
@@ -459,13 +526,13 @@
"OptionUpscaling": "\u041a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440\u0433\u0435 \u0430\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u044b\u043c\u0434\u044b\u0493\u044b \u043a\u04e9\u0442\u0435\u0440\u0456\u043b\u0433\u0435\u043d \u0431\u0435\u0439\u043d\u0435\u043d\u0456 \u0441\u04b1\u0440\u0430\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0435\u0434\u0456",
"OptionUpscalingHelp": "\u041a\u0435\u0439\u0431\u0456\u0440 \u0436\u0430\u0493\u0434\u0430\u0439\u043b\u0430\u0440\u0434\u0430 \u0431\u04b1\u043d\u044b\u04a3 \u043d\u04d9\u0442\u0438\u0436\u0435\u0441\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435 \u0441\u0430\u043f\u0430\u0441\u044b \u0436\u0430\u049b\u0441\u0430\u0440\u0442\u044b\u043b\u0430\u0434\u044b, \u0431\u0456\u0440\u0430\u049b \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u049b\u043e\u043b\u0434\u0430\u043d\u044b\u0441\u044b \u0430\u0440\u0442\u044b\u0439\u0434\u044b.",
"EditCollectionItemsHelp": "\u0411\u04b1\u043b \u0442\u043e\u043f\u0442\u0430\u043c\u0430\u0493\u0430 \u049b\u0430\u043b\u0430\u0443\u044b\u04a3\u044b\u0437 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u0442\u043e\u043f\u0442\u0430\u0441\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u04d9\u0440\u049b\u0430\u0439\u0441\u044b \u0444\u0438\u043b\u044c\u043c\u0434\u0435\u0440\u0434\u0456, \u0441\u0435\u0440\u0438\u0430\u043b\u0434\u0430\u0440\u0434\u044b, \u0430\u043b\u044c\u0431\u043e\u043c\u0434\u0430\u0440\u0434\u044b, \u043a\u0456\u0442\u0430\u043f\u0442\u0430\u0440\u0434\u044b \u043d\u0435 \u043e\u0439\u044b\u043d\u0434\u0430\u0440\u0434\u044b \u04af\u0441\u0442\u0435\u04a3\u0456\u0437 \u043d\u0435\u043c\u0435\u0441\u0435 \u0430\u043b\u0430\u0441\u0442\u0430\u04a3\u044b\u0437.",
- "HeaderAddTitles": "\u0410\u0442\u0430\u0443\u043b\u0430\u0440\u0434\u044b \u04af\u0441\u0442\u0435\u0443",
+ "HeaderAddTitles": "\u0422\u0443\u044b\u043d\u0434\u044b\u043b\u0430\u0440\u0434\u044b \u04af\u0441\u0442\u0435\u0443",
"LabelEnableDlnaPlayTo": "DLNA \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u0441\u044b\u043d\u0434\u0430 \u043e\u0439\u043d\u0430\u0442\u0443\u0434\u044b \u049b\u043e\u0441\u0443",
"LabelEnableDlnaPlayToHelp": "Media Browser \u0436\u0435\u043b\u0456\u0434\u0435\u0433\u0456 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440\u0434\u044b \u0442\u0430\u0431\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d \u0436\u04d9\u043d\u0435 \u0431\u04b1\u043b\u0430\u0440\u0434\u044b \u049b\u0430\u0448\u044b\u049b\u0442\u0430\u043d \u0431\u0430\u0441\u049b\u0430\u0440\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u043d \u04b1\u0441\u044b\u043d\u0430\u0434\u044b.",
"LabelEnableDlnaDebugLogging": "DLNA \u043a\u04af\u0439\u043a\u0435\u043b\u0442\u0456\u0440\u0443 \u0436\u0430\u0437\u0431\u0430\u043b\u0430\u0440\u044b\u043d \u0436\u04b1\u0440\u043d\u0430\u043b\u0434\u0430 \u049b\u043e\u0441\u0443",
"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": "\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\u0441\u044b\u043d\u0434\u0430\u0493\u044b \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\u0443.",
+ "LabelEnableDlnaClientDiscoveryIntervalHelp": "\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\u0441\u044b\u043d\u0434\u0430\u0493\u044b \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.",
@@ -482,7 +549,7 @@
"LabelFriendlyServerNameHelp": "\u0411\u04b1\u043b \u0430\u0442\u0430\u0443 \u043e\u0441\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u0430\u043d\u044b\u049b\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b. \u0415\u0433\u0435\u0440 \u04e9\u0440\u0456\u0441 \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u043b\u0441\u0430, \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440 \u0430\u0442\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b.",
"LabelPreferredDisplayLanguage": "\u0411\u0435\u0439\u043d\u0435\u043b\u0435\u0443 \u0442\u0456\u043b\u0456\u043d\u0456\u04a3 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456",
"LabelPreferredDisplayLanguageHelp": "Media Browser \u0442\u04d9\u0440\u0436\u0456\u043c\u0435\u043b\u0435\u0443\u0456 \u0434\u0430\u043c\u044b\u0442\u043f\u0430\u043b\u044b \u0436\u043e\u0431\u0430 \u0431\u043e\u043b\u044b\u043f \u0442\u0430\u0431\u044b\u043b\u0430\u0434\u044b, \u0436\u04d9\u043d\u0435 \u0431\u04b1\u043b \u04d9\u043b\u0456 \u0434\u0435 \u0430\u044f\u049b\u0442\u0430\u043b\u0493\u0430\u043d \u0435\u043c\u0435\u0441.",
- "LabelReadHowYouCanContribute": "\u049a\u0430\u043b\u0430\u0439 \u0456\u0441\u043a\u0435\u0440\u043b\u0435\u0441\u0435 \u0430\u043b\u0430\u0442\u044b\u04a3\u044b\u0437 \u0442\u0443\u0440\u0430\u043b\u044b \u043e\u049b\u044b\u04a3\u044b\u0437.",
+ "LabelReadHowYouCanContribute": "\u049a\u0430\u043b\u0430\u0439 \u0456\u0441\u043a\u0435\u0440\u043b\u0435\u0441\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u04a3\u0456\u0437 \u0442\u0443\u0440\u0430\u043b\u044b \u043e\u049b\u044b\u04a3\u044b\u0437.",
"HeaderNewCollection": "\u0416\u0430\u04a3\u0430 \u0442\u043e\u043f\u0442\u0430\u043c\u0430",
"HeaderAddToCollection": "\u0422\u043e\u043f\u0442\u0430\u043c\u0430\u0493\u0430 \u049b\u043e\u0441\u0443",
"ButtonSubmit": "\u0416\u0456\u0431\u0435\u0440\u0443",
@@ -500,9 +567,9 @@
"LabelMinResumePercentage": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u0435\u04a3 \u0430\u0437 \u043f\u0430\u0439\u044b\u0437\u044b:",
"LabelMaxResumePercentage": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u0435\u04a3 \u043a\u04e9\u043f \u043f\u0430\u0439\u044b\u0437\u044b:",
"LabelMinResumeDuration": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u0435\u04a3 \u0430\u0437 \u04b1\u0437\u0430\u049b\u0442\u044b\u0493\u044b (\u0441\u0435\u043a\u0443\u043d\u0434):",
- "LabelMinResumePercentageHelp": "\u0411\u04b1\u043b \u043a\u0435\u0437\u0434\u0435\u043d \u0431\u04b1\u0440\u044b\u043d \u0442\u043e\u049b\u0442\u0430\u0442\u044b\u043b\u0441\u0430 \u0430\u0442\u0430\u0443\u043b\u0430\u0440 \u043e\u0439\u043d\u0430\u0442\u044b\u043b\u043c\u0430\u0493\u0430\u043d \u0434\u0435\u043f \u0431\u043e\u043b\u0436\u0430\u043b\u0434\u044b",
- "LabelMaxResumePercentageHelp": "\u0411\u04b1\u043b \u043a\u0435\u0437\u0434\u0435\u043d \u043a\u0435\u0439\u0456\u043d \u0442\u043e\u049b\u0442\u0430\u0442\u044b\u043b\u0441\u0430 \u0430\u0442\u0430\u0443\u043b\u0430\u0440 \u0442\u043e\u043b\u044b\u049b \u043e\u0439\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d \u0434\u0435\u043f \u0431\u043e\u043b\u0436\u0430\u043b\u0434\u044b",
- "LabelMinResumeDurationHelp": "\u0411\u04b1\u0434\u0430\u043d \u049b\u044b\u0441\u049b\u0430 \u0430\u0442\u0430\u0443\u043b\u0430\u0440 \u0436\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u044b\u043b\u043c\u0430\u0439\u0434\u044b",
+ "LabelMinResumePercentageHelp": "\u0411\u04b1\u043b \u043a\u0435\u0437\u0434\u0435\u043d \u0431\u04b1\u0440\u044b\u043d \u0442\u043e\u049b\u0442\u0430\u0442\u044b\u043b\u0441\u0430 \u0442\u0443\u044b\u043d\u0434\u044b\u043b\u0430\u0440 \u043e\u0439\u043d\u0430\u0442\u044b\u043b\u043c\u0430\u0493\u0430\u043d \u0434\u0435\u043f \u0431\u043e\u043b\u0436\u0430\u043b\u0434\u044b",
+ "LabelMaxResumePercentageHelp": "\u0411\u04b1\u043b \u043a\u0435\u0437\u0434\u0435\u043d \u043a\u0435\u0439\u0456\u043d \u0442\u043e\u049b\u0442\u0430\u0442\u044b\u043b\u0441\u0430 \u0442\u0443\u044b\u043d\u0434\u044b\u043b\u0430\u0440 \u0442\u043e\u043b\u044b\u049b \u043e\u0439\u043d\u0430\u0442\u044b\u043b\u0493\u0430\u043d \u0434\u0435\u043f \u0431\u043e\u043b\u0436\u0430\u043b\u0434\u044b",
+ "LabelMinResumeDurationHelp": "\u0411\u04b1\u0434\u0430\u043d \u049b\u044b\u0441\u049b\u0430 \u0442\u0443\u044b\u043d\u0434\u044b\u043b\u0430\u0440 \u0436\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u044b\u043b\u043c\u0430\u0439\u0434\u044b",
"TitleAutoOrganize": "\u0410\u0432\u0442\u043e\u04b1\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443",
"TabActivityLog": "\u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0435\u0440 \u0436\u04b1\u0440\u043d\u0430\u043b\u044b",
"HeaderName": "\u0410\u0442\u044b",
@@ -512,21 +579,23 @@
"HeaderProgram": "\u0411\u0435\u0440\u0456\u043b\u0456\u043c",
"HeaderClients": "\u041a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440",
"LabelCompleted": "\u0410\u044f\u049b\u0442\u0430\u043b\u0493\u0430\u043d",
+ "LabelFailed": "\u0421\u04d9\u0442\u0441\u0456\u0437",
"LabelSkipped": "\u04e8\u0442\u043a\u0456\u0437\u0456\u043b\u0433\u0435\u043d",
"HeaderEpisodeOrganization": "\u042d\u043f\u0438\u0437\u043e\u0434\u0442\u044b \u04b1\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443",
- "LabelSeasonNumber": "\u041c\u0430\u0443\u0441\u044b\u043c \u043d\u04e9\u043c\u0456\u0440\u0456",
- "LabelEpisodeNumber": "\u042d\u043f\u0438\u0437\u043e\u0434 \u043d\u04e9\u043c\u0456\u0440\u0456",
- "LabelEndingEpisodeNumber": "\u0410\u044f\u049b\u0442\u0430\u0443\u0448\u044b \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u044b\u04a3 \u043d\u04e9\u043c\u0456\u0440\u0456",
+ "LabelSeries": "\u0421\u0435\u0440\u0438\u0430\u043b:",
+ "LabelSeasonNumber": "\u041c\u0430\u0443\u0441\u044b\u043c \u043d\u04e9\u043c\u0456\u0440\u0456:",
+ "LabelEpisodeNumber": "\u042d\u043f\u0438\u0437\u043e\u0434 \u043d\u04e9\u043c\u0456\u0440\u0456:",
+ "LabelEndingEpisodeNumber": "\u0410\u044f\u049b\u0442\u0430\u0443\u0448\u044b \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u044b\u04a3 \u043d\u04e9\u043c\u0456\u0440\u0456:",
"LabelEndingEpisodeNumberHelp": "\u0411\u04b1\u043b \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u0431\u0456\u0440\u043d\u0435\u0448\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0431\u0430\u0440 \u0444\u0430\u0439\u043b\u0434\u0430\u0440 \u04af\u0448\u0456\u043d",
"HeaderSupportTheTeam": "Media Browser \u0442\u043e\u0431\u044b\u043d \u049b\u043e\u043b\u0434\u0430\u0443",
"LabelSupportAmount": "\u0421\u043e\u043c\u0430\u0441\u044b (USD)",
- "HeaderSupportTheTeamHelp": "\u0411\u04b1\u043b \u0436\u043e\u0431\u0430 \u04d9\u0437\u0456\u0440\u043b\u0435\u0443\u0456 \u0436\u0430\u043b\u0493\u0430\u0441\u0430\u0442\u044b\u043d\u0430 \u043a\u04e9\u0437 \u0436\u0435\u0442\u043a\u0456\u0437\u0443 \u04af\u0448\u0456\u043d \u04af\u043b\u0435\u0441 \u049b\u043e\u0441\u044b\u043f \u043a\u04e9\u043c\u0435\u043a \u0431\u0435\u0440\u0456\u04a3\u0456\u0437. \u0411\u0430\u0440\u043b\u044b\u049b \u043a\u04e9\u043c\u0435\u043a\u0442\u0435\u0440\u0434\u0456\u04a3 \u04d9\u043b\u0434\u0435\u049b\u0430\u043d\u0448\u0430 \u0431\u04e9\u043b\u0456\u0433\u0456\u043d \u0442\u04d9\u0443\u0435\u043b\u0434\u0456\u043c\u0456\u0437 \u0431\u0430\u0441\u049b\u0430 \u0430\u0448\u044b\u049b \u049b\u04b1\u0440\u0430\u043b\u0434\u0430\u0440\u044b \u04af\u0448\u0456\u043d \u0456\u0441\u043a\u0435\u0440\u043b\u0435\u0441\u0435\u043c\u0456\u0437.",
+ "HeaderSupportTheTeamHelp": "\u0411\u04b1\u043b \u0436\u043e\u0431\u0430 \u04d9\u0437\u0456\u0440\u043b\u0435\u0443\u0456 \u0436\u0430\u043b\u0493\u0430\u0441\u0430\u0442\u044b\u043d\u0430 \u043a\u04e9\u0437 \u0436\u0435\u0442\u043a\u0456\u0437\u0443 \u04af\u0448\u0456\u043d \u04af\u043b\u0435\u0441 \u049b\u043e\u0441\u044b\u043f \u043a\u04e9\u043c\u0435\u043a \u0431\u0435\u0440\u0456\u04a3\u0456\u0437. \u0411\u0430\u0440\u043b\u044b\u049b \u049b\u0430\u0439\u044b\u0440\u043c\u0430\u043b\u0434\u044b\u049b\u0442\u044b\u04a3 \u04d9\u043b\u0434\u0435\u049b\u0430\u043d\u0448\u0430 \u0431\u04e9\u043b\u0456\u0433\u0456\u043d \u0442\u04d9\u0443\u0435\u043b\u0434\u0456\u043c\u0456\u0437 \u0431\u0430\u0441\u049b\u0430 \u0430\u0448\u044b\u049b \u049b\u04b1\u0440\u0430\u043b\u0434\u0430\u0440\u044b \u04af\u0448\u0456\u043d \u0456\u0441\u043a\u0435\u0440\u043b\u0435\u0441\u0435\u043c\u0456\u0437.",
"ButtonEnterSupporterKey": "\u049a\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u043d \u0435\u043d\u0433\u0456\u0437\u0443",
"DonationNextStep": "\u0410\u044f\u049b\u0442\u0430\u043b\u044b\u0441\u044b\u043c\u0435\u043d, \u043a\u0435\u0440\u0456 \u049b\u0430\u0439\u0442\u044b\u04a3\u044b\u0437 \u0436\u0430\u043d\u0435 \u042d-\u043f\u043e\u0448\u0442\u0430 \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u043b\u044b\u043d\u0493\u0430\u043d \u049b\u043e\u043b\u0434\u0430\u0443\u0448\u044b \u043a\u0456\u043b\u0442\u0456\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437.",
"AutoOrganizeHelp": "\u0410\u0432\u0442\u043e\u04b1\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443 \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b\u043d\u0434\u0430\u0493\u044b \u0436\u0430\u04a3\u0430 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u0434\u044b \u0431\u0430\u049b\u044b\u043b\u0430\u0439\u0434\u044b \u0436\u04d9\u043d\u0435 \u0431\u04b1\u043b\u0430\u0440\u0434\u044b \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b\u043d\u0430 \u0436\u044b\u043b\u0436\u044b\u0442\u0430\u0434\u044b.",
"AutoOrganizeTvHelp": "\u0422\u0414 \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u04b1\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440 \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u0431\u0430\u0440 \u0441\u0435\u0440\u0438\u0430\u043b\u0434\u0430\u0440\u0493\u0430 \u04af\u0441\u0442\u0435\u043b\u0456\u043d\u0435\u0434\u0456.",
"OptionEnableEpisodeOrganization": "\u0416\u0430\u04a3\u0430 \u044d\u043f\u0438\u0437\u043e\u0434 \u04b1\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443\u044b\u043d \u049b\u043e\u0441\u0443",
- "LabelWatchFolder": "\u0411\u0430\u049b\u044b\u043b\u0430\u0443\u0434\u0430\u0493\u044b \u049b\u0430\u043b\u0442\u0430:",
+ "LabelWatchFolder": "\u049a\u0430\u0434\u0430\u0493\u0430\u043b\u0430\u0443\u0434\u0430\u0493\u044b \u049b\u0430\u043b\u0442\u0430:",
"LabelWatchFolderHelp": "\"\u0416\u0430\u04a3\u0430 \u0442\u0430\u0441\u0443\u0448\u044b \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u04b1\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443\" \u0434\u0435\u0433\u0435\u043d \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u043e\u0440\u044b\u043d\u0434\u0430\u043b\u0493\u0430\u043d \u043a\u0435\u0437\u0434\u0435 \u0441\u0435\u0440\u0432\u0435\u0440 \u0431\u04b1\u043b \u049b\u0430\u043b\u0442\u0430\u043d\u044b \u0441\u0430\u0443\u0430\u043b\u0434\u0430\u043f \u0442\u04b1\u0440\u0430\u0434\u044b.",
"ButtonViewScheduledTasks": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043b\u0430\u0440\u0434\u044b \u049b\u0430\u0440\u0430\u0443",
"LabelMinFileSizeForOrganize": "\u0415\u04a3 \u0430\u0437 \u0444\u0430\u0439\u043b \u0430\u0443\u049b\u044b\u043c\u044b (\u041c\u0411):",
@@ -537,18 +606,18 @@
"LabelEpisodePattern": "\u042d\u043f\u0438\u0437\u043e\u0434 \u04af\u043b\u0433\u0456\u0441\u0456:",
"LabelMultiEpisodePattern": "\u0411\u0456\u0440\u043d\u0435\u0448\u0435 \u044d\u043f\u0438\u0437\u043e\u0434 \u04af\u043b\u0433\u0456\u0441\u0456:",
"HeaderSupportedPatterns": "\u049a\u043e\u043b\u0434\u0430\u043d\u044b\u0441\u0442\u0430\u0493\u044b \u04af\u043b\u0433\u0456\u043b\u0435\u0440",
- "HeaderTerm": "\u0410\u0442\u0430\u043b\u044b\u043c",
+ "HeaderTerm": "\u04b0\u0493\u044b\u043c",
"HeaderPattern": "\u04ae\u043b\u0433\u0456",
"HeaderResult": "\u041d\u04d9\u0442\u0438\u0436\u0435",
"LabelDeleteEmptyFolders": "\u04b0\u0439\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u0440\u0443\u0434\u0430\u043d \u043a\u0435\u0439\u0456\u043d \u0431\u043e\u0441 \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u0434\u044b \u0436\u043e\u044e",
"LabelDeleteEmptyFoldersHelp": "\u0416\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d \u0442\u0430\u0437\u0430 \u04b1\u0441\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u0431\u04b1\u043d\u044b \u049b\u043e\u0441\u044b\u04a3\u044b\u0437.",
"LabelDeleteLeftOverFiles": "\u041a\u0435\u043b\u0435\u0441\u0456 \u043a\u0435\u04a3\u0435\u0439\u0442\u0456\u043c\u0434\u0435\u0440\u0456 \u0431\u0430\u0440 \u049b\u0430\u043b\u0493\u0430\u043d \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u0434\u044b \u0436\u043e\u044e:",
- "LabelDeleteLeftOverFilesHelp": "(;) \u0430\u0440\u049b\u044b\u043b\u044b \u0431\u04e9\u043b\u0456\u043f \u0430\u043b\u044b\u04a3\u044b\u0437. \u041c\u044b\u0441\u0430\u043b\u044b: .nfo;.txt",
+ "LabelDeleteLeftOverFilesHelp": "\u041c\u044b\u043d\u0430\u043d\u044b (;) \u0430\u0440\u049b\u044b\u043b\u044b \u0431\u04e9\u043b\u0456\u043f \u0430\u043b\u044b\u04a3\u044b\u0437. \u041c\u044b\u0441\u0430\u043b\u044b: .nfo;.txt",
"OptionOverwriteExistingEpisodes": "\u0411\u0430\u0440 \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440\u0434\u044b \u049b\u0430\u0439\u0442\u0430 \u0436\u0430\u0437\u0443",
"LabelTransferMethod": "\u0422\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u04d9\u0434\u0456\u0441\u0456",
"OptionCopy": "\u041a\u04e9\u0448\u0456\u0440\u0443",
"OptionMove": "\u0416\u044b\u043b\u0436\u044b\u0442\u0443",
- "LabelTransferMethodHelp": "\u0411\u0430\u049b\u044b\u043b\u0430\u0443\u0434\u0430\u0493\u044b \u049b\u0430\u043b\u0442\u0430\u0434\u0430\u043d \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u0434\u044b \u043a\u04e9\u0448\u0456\u0440\u0443 \u043d\u0435 \u0436\u044b\u043b\u0436\u044b\u0442\u0443",
+ "LabelTransferMethodHelp": "\u049a\u0430\u0434\u0430\u0493\u0430\u043b\u0430\u0443\u0434\u0430\u0493\u044b \u049b\u0430\u043b\u0442\u0430\u0434\u0430\u043d \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u0434\u044b \u043a\u04e9\u0448\u0456\u0440\u0443 \u043d\u0435 \u0436\u044b\u043b\u0436\u044b\u0442\u0443",
"HeaderLatestNews": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u04a3\u0433\u0456 \u0436\u0430\u04a3\u0430\u043b\u044b\u049b\u0442\u0430\u0440",
"HeaderHelpImproveMediaBrowser": "Media Browser \u04e9\u043d\u0456\u043c\u0434\u0435\u0440\u0456\u043d \u0436\u0435\u0442\u0456\u043b\u0434\u0456\u0440\u0443\u0433\u0435 \u043a\u04e9\u043c\u0435\u043a",
"HeaderRunningTasks": "\u041e\u0440\u044b\u043d\u0434\u0430\u043b\u044b\u043f \u0436\u0430\u0442\u049b\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043b\u0430\u0440",
@@ -564,7 +633,7 @@
"ServerUpToDate": "Media Browser Server \u043a\u04af\u0439\u0456: \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0493\u0430\u043d",
"ErrorConnectingToMediaBrowserRepository": "\u0410\u043b\u044b\u0441\u0442\u0430\u0493\u044b Media Browser \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0456\u043d\u0435 \u049b\u043e\u0441\u044b\u043b\u0443\u0434\u0430 \u049b\u0430\u0442\u0435 \u0431\u043e\u043b\u0434\u044b.",
"LabelComponentsUpdated": "\u041a\u0435\u043b\u0435\u0441\u0456 \u049b\u04b1\u0440\u0430\u043c\u0434\u0430\u0441\u0442\u0430\u0440 \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0434\u044b \u043d\u0435 \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b:",
- "MessagePleaseRestartServerToFinishUpdating": "\u04e8\u0437\u0433\u0435\u0440\u0442\u0443\u043b\u0435\u0440 \u049b\u043e\u043b\u0434\u0430\u043d\u0443\u044b\u043d \u0430\u044f\u049b\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u049b\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u04a3\u044b\u0437",
+ "MessagePleaseRestartServerToFinishUpdating": "\u0416\u0430\u04a3\u0430\u0440\u0442\u0443\u043b\u0430\u0440\u0434\u044b\u04a3 \u049b\u043e\u043b\u0434\u0430\u043d\u0443\u044b\u043d \u0430\u044f\u049b\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u049b\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u04a3\u044b\u0437",
"LabelDownMixAudioScale": "\u041a\u0435\u043c\u0456\u0442\u0456\u043b\u0456\u043f \u043c\u0438\u043a\u0448\u0435\u0440\u043b\u0435\u043d\u0433\u0435\u043d \u0434\u044b\u0431\u044b\u0441 \u0434\u0435\u04a3\u0433\u0435\u0439\u0456\u043d \u0440\u0435\u0442\u0442\u0435\u0443:",
"LabelDownMixAudioScaleHelp": "\u041a\u0435\u0440\u0456 \u0430\u0440\u0430\u043b\u0430\u0441\u0442\u044b\u0440\u044b\u043b\u0493\u0430\u043d\u0434\u0430 \u0434\u044b\u0431\u044b\u0441 \u04af\u043d\u0434\u0456\u043b\u0456\u0433\u0456\u043d \u043a\u04e9\u0442\u0435\u0440\u0443. \u0411\u0430\u0441\u0442\u0430\u043f\u049b\u044b \u0434\u0435\u04a3\u0433\u0435\u0439 \u043c\u04d9\u043d\u0456\u043d \u04e9\u0437\u0433\u0435\u0440\u0442\u043f\u0435\u0443 \u04af\u0448\u0456\u043d 1 \u0441\u0430\u043d\u044b\u043d \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437..",
"ButtonLinkKeys": "\u041a\u0456\u043b\u0442\u0442\u0435\u0440\u0434\u0456 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u0443",
@@ -589,10 +658,10 @@
"LabelEnableBlastAliveMessages": "\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\u0434\u044b \u0436\u0438\u0435\u043b\u0456\u0442\u0443",
"LabelEnableBlastAliveMessagesHelp": "\u0415\u0433\u0435\u0440 \u0436\u0435\u043b\u0456\u0434\u0435\u0433\u0456 \u0431\u0430\u0441\u049b\u0430 UPnP \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440\u044b\u043c\u0435\u043d \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u044b\u049b \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0441\u0430 \u0431\u04b1\u043d\u044b \u049b\u043e\u0441\u044b\u04a3\u044b\u0437.",
"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": "Media Browser \u043e\u0440\u044b\u043d\u0434\u0430\u0439\u0442\u044b\u043d SSDP \u0441\u0430\u0443\u0430\u043b\u0434\u0430\u0440 \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\u0443.",
+ "LabelBlastMessageIntervalHelp": "Media Browser \u043e\u0440\u044b\u043d\u0434\u0430\u0439\u0442\u044b\u043d SSDP \u0441\u0430\u0443\u0430\u043b\u0434\u0430\u0440 \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\u0443\u0448\u044b\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\u0443. \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 \u0430\u043d\u044b\u049b\u0442\u0430\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.",
- "TitleDlna": "DLNA \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440",
+ "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\u0443\u0448\u044b\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.",
+ "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",
"LabelWeatherDisplayLocation": "\u0410\u0443\u0430 \u0440\u0430\u0439\u044b \u0435\u043b\u0434\u0456\u043c\u0435\u043a\u0435\u043d\u0456:",
@@ -619,13 +688,12 @@
"NotificationOptionTaskFailed": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0441\u04d9\u0442\u0441\u0456\u0437\u0434\u0456\u0433\u0456",
"NotificationOptionInstallationFailed": "\u041e\u0440\u043d\u0430\u0442\u0443 \u0441\u04d9\u0442\u0441\u0456\u0437\u0434\u0456\u0433\u0456",
"NotificationOptionNewLibraryContent": "\u0416\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u04af\u0441\u0442\u0435\u043b\u0433\u0435\u043d",
- "NotificationOptionNewLibraryContentMultiple": "\u0416\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u049b\u043e\u0441\u044b\u043b\u0434\u044b (\u0431\u0456\u0440\u043d\u0435\u0448\u0435)",
- "SendNotificationHelp": "\u0425\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u043c\u0430\u043b\u0430\u0440 \u0431\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b\u043d\u0434\u0430\u0493\u044b \u04d9\u0434\u0435\u043f\u043a\u0456 \u043a\u0456\u0440\u0456\u0441 \u0436\u04d9\u0448\u0456\u0433\u0456\u043d\u0435 \u0436\u0435\u0442\u043a\u0456\u0437\u0456\u043b\u0435\u0434\u0456. \u049a\u043e\u0441\u044b\u043c\u0448\u0430 \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443 \u049b\u04b1\u0440\u0430\u043b\u0434\u0430\u0440\u044b\u043d \u043e\u0440\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0456\u043d \u0448\u0430\u0440\u043b\u0430\u04a3\u044b\u0437.",
+ "NotificationOptionNewLibraryContentMultiple": "\u0416\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u049b\u043e\u0441\u044b\u043b\u0434\u044b (\u043a\u04e9\u043f\u0442\u0435\u0433\u0435\u043d)",
+ "SendNotificationHelp": "\u0425\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443\u043b\u0430\u0440 \u0431\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b\u043d\u0434\u0430\u0493\u044b \u04d9\u0434\u0435\u043f\u043a\u0456 \u043a\u0456\u0440\u0456\u0441 \u0436\u04d9\u0448\u0456\u0433\u0456\u043d\u0435 \u0436\u0435\u0442\u043a\u0456\u0437\u0456\u043b\u0435\u0434\u0456. \u049a\u043e\u0441\u044b\u043c\u0448\u0430 \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443 \u049b\u04b1\u0440\u0430\u043b\u0434\u0430\u0440\u044b\u043d \u043e\u0440\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0456\u043d \u0448\u043e\u043b\u044b\u04a3\u044b\u0437.",
"NotificationOptionServerRestartRequired": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u049b\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443 \u049b\u0430\u0436\u0435\u0442",
"LabelNotificationEnabled": "\u0411\u04b1\u043b \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u043c\u0430\u043d\u044b \u049b\u043e\u0441\u0443",
"LabelMonitorUsers": "\u041c\u044b\u043d\u0430\u043d\u044b\u04a3 \u04d9\u0440\u0435\u043a\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u0431\u0430\u049b\u044b\u043b\u0430\u0443:",
"LabelSendNotificationToUsers": "\u041c\u044b\u043d\u0430\u0493\u0430\u043d \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u043c\u0430\u043d\u044b \u0436\u0456\u0431\u0435\u0440\u0443:",
- "UsersNotNotifiedAboutSelfActivity": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440\u0493\u0430 \u04e9\u0437\u0456\u043d\u0456\u04a3 \u04d9\u0440\u0435\u043a\u0435\u0442\u0442\u0435\u0440\u0456 \u0442\u0443\u0440\u0430\u043b\u044b \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443 \u0435\u0442\u0456\u043b\u043c\u0435\u0439\u0434\u0456.",
"LabelUseNotificationServices": "\u041a\u0435\u043b\u0435\u0441\u0456 \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443:",
"CategoryUser": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b",
"CategorySystem": "\u0416\u04af\u0439\u0435",
@@ -633,7 +701,7 @@
"CategoryPlugin": "\u041f\u043b\u0430\u0433\u0438\u043d",
"LabelMessageTitle": "\u0425\u0430\u0431\u0430\u0440\u0434\u044b\u04a3 \u0431\u0430\u0441\u0442\u0430\u049b\u044b\u0440\u044b\u0431\u044b",
"LabelAvailableTokens": "\u049a\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0442\u0430\u04a3\u0431\u0430\u043b\u0430\u0443\u044b\u0448\u0442\u0430\u0440:",
- "AdditionalNotificationServices": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430 \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443 \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0456\u043d \u0448\u0430\u0440\u043b\u0430\u04a3\u044b\u0437.",
+ "AdditionalNotificationServices": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430 \u0445\u0430\u0431\u0430\u0440\u043b\u0430\u043d\u0434\u044b\u0440\u0443 \u049b\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u043f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0456\u043d \u0448\u043e\u043b\u044b\u04a3\u044b\u0437.",
"OptionAllUsers": "\u0411\u0430\u0440\u043b\u044b\u049b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440",
"OptionAdminUsers": "\u04d8\u043a\u0456\u043c\u0448\u0456\u043b\u0435\u0440",
"OptionCustomUsers": "\u0422\u0435\u04a3\u0448\u0435\u0443\u043b\u0456",
@@ -648,6 +716,7 @@
"ButtonPageDown": "\u0422\u04e9\u043c\u0435\u043d\u0433\u0456 \u0431\u0435\u0442\u043a\u0435",
"PageAbbreviation": "\u0411\u0415\u0422",
"ButtonHome": "\u0411\u0430\u0441\u0442\u044b",
+ "ButtonSearch": "\u0406\u0437\u0434\u0435\u0443",
"ButtonSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440",
"ButtonTakeScreenshot": "\u042d\u043a\u0440\u0430\u043d\u0434\u044b \u0442\u04af\u0441\u0456\u0440\u0443",
"ButtonLetterUp": "\u04d8\u0440\u0456\u043f\u043a\u0435 \u0436\u043e\u0493\u0430\u0440\u0493\u044b\u043b\u0430\u0442\u0443",
@@ -661,6 +730,8 @@
"ButtonScenes": "\u0421\u0430\u0445\u043d\u0430\u043b\u0430\u0440",
"ButtonSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440",
"ButtonAudioTracks": "\u0414\u044b\u0431\u044b\u0441 \u0436\u043e\u043b\u0448\u044b\u049b\u0442\u0430\u0440\u044b",
+ "ButtonPreviousTrack": "\u0410\u043b\u0434\u044b\u04a3\u0493\u044b \u0436\u043e\u043b\u0448\u044b\u049b",
+ "ButtonNextTrack": "\u041a\u0435\u043b\u0435\u0441\u0456 \u0436\u043e\u043b\u0448\u044b\u049b",
"ButtonStop": "\u0422\u043e\u049b\u0442\u0430\u0442\u0443",
"ButtonPause": "\u04ae\u0437\u0456\u043b\u0456\u0441",
"LabelGroupMoviesIntoCollections": "\u0422\u043e\u043f\u0442\u0430\u043c\u0430\u043b\u0430\u0440 \u0456\u0448\u0456\u043d\u0434\u0435\u0433\u0456 \u0444\u0438\u043b\u044c\u043c\u0434\u0435\u0440\u0434\u0456 \u0442\u043e\u043f\u0442\u0430\u0441\u0442\u044b\u0440\u0443",
@@ -669,13 +740,15 @@
"ButtonVolumeUp": "\u04ae\u043d\u0434\u0456\u043b\u0456\u043a\u0442\u0456 \u0436\u043e\u0493\u0430\u0440\u044b\u043b\u0430\u0442\u0443",
"ButtonVolumeDown": "\u04ae\u043d\u0434\u0456\u043b\u0456\u043a\u0442\u0456 \u0442\u04e9\u043c\u0435\u043d\u0434\u0435\u0442\u0443",
"ButtonMute": "\u0414\u044b\u0431\u044b\u0441\u0442\u044b \u04e9\u0448\u0456\u0440\u0443",
- "HeaderLatestMedia": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0442\u0430\u0441\u0443\u0448\u044b\u043b\u0430\u0440",
- "OptionSpecialFeatures": "\u0410\u0440\u043d\u0430\u0439\u044b \u049b\u043e\u0441\u044b\u043c\u0448\u0430\u043b\u0430\u0440",
+ "HeaderLatestMedia": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440",
+ "OptionSpecialFeatures": "\u0410\u0440\u043d\u0430\u0439\u044b \u043c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440",
"HeaderCollections": "\u0422\u043e\u043f\u0442\u0430\u043c\u0430\u043b\u0430\u0440",
"LabelProfileCodecsHelp": "\u04ae\u0442\u0456\u0440 \u0430\u0440\u049b\u044b\u043b\u044b \u0431\u04e9\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0493\u0430\u043d. \u0411\u0430\u0440\u043b\u044b\u049b \u043a\u043e\u0434\u0435\u043a\u0442\u0435\u0440\u0433\u0435 \u049b\u043e\u043b\u0434\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0431\u04b1\u043b \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u043b\u0443 \u043c\u04af\u043c\u043a\u0456\u043d.",
"LabelProfileContainersHelp": "\u04ae\u0442\u0456\u0440 \u0430\u0440\u049b\u044b\u043b\u044b \u0431\u04e9\u043b\u0456\u043f \u0430\u043b\u044b\u043d\u0493\u0430\u043d. \u0411\u0430\u0440\u043b\u044b\u049b \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043b\u0435\u0440\u0433\u0435 \u049b\u043e\u043b\u0434\u0430\u043d\u0443 \u04af\u0448\u0456\u043d \u0431\u04b1\u043b \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u043b\u0443 \u043c\u04af\u043c\u043a\u0456\u043d.",
"HeaderResponseProfile": "\u04ae\u043d \u049b\u0430\u0442\u0443 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u044b",
"LabelType": "\u0422\u04af\u0440\u0456:",
+ "LabelPersonRole": "\u0420\u04e9\u043b\u0456:",
+ "LabelPersonRoleHelp": "\u0420\u04e9\u043b, \u0436\u0430\u043b\u043f\u044b \u0430\u043b\u0493\u0430\u043d\u0434\u0430, \u0442\u0435\u043a \u049b\u0430\u043d\u0430 \u0430\u043a\u0442\u0435\u0440\u043b\u0435\u0440\u0433\u0435 \u049b\u043e\u043b\u0430\u0439\u043b\u044b.",
"LabelProfileContainer": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440:",
"LabelProfileVideoCodecs": "\u0411\u0435\u0439\u043d\u0435\u043b\u0456\u043a \u043a\u043e\u0434\u0435\u043a\u0442\u0435\u0440:",
"LabelProfileAudioCodecs": "\u0414\u044b\u0431\u044b\u0441\u0442\u044b\u049b \u043a\u043e\u0434\u0435\u043a\u0442\u0435\u0440:",
@@ -683,9 +756,9 @@
"HeaderDirectPlayProfile": "\u0422\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u044b",
"HeaderTranscodingProfile": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u044b",
"HeaderCodecProfile": "\u041a\u043e\u0434\u0435\u043a \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u044b",
- "HeaderCodecProfileHelp": "\u041a\u043e\u0434\u0435\u043a \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u043d\u0430\u049b\u0442\u044b \u043a\u043e\u0434\u0435\u043a\u0442\u0435\u0440 \u0430\u0440\u049b\u044b\u043b\u044b \u043e\u0439\u043d\u0430\u0442\u049b\u0430\u043d\u0434\u0430 \u0436\u0430\u0431\u0434\u044b\u049b\u0442\u044b\u04a3 \u0448\u0435\u043a\u0442\u0435\u0443\u043b\u0435\u0440\u0456\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0435\u0434\u0456. \u0415\u0433\u0435\u0440 \u0448\u0435\u043a\u0442\u0435\u0443 \u049b\u043e\u043b\u0434\u0430\u043d\u044b\u043b\u0441\u0430, \u0441\u043e\u043d\u0434\u0430 \u043a\u043e\u0434\u0435\u043a \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0441\u0435\u0434\u0435 \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u043b\u044b\u043d\u0430\u0434\u044b.",
+ "HeaderCodecProfileHelp": "\u041a\u043e\u0434\u0435\u043a \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u043d\u0430\u049b\u0442\u044b \u043a\u043e\u0434\u0435\u043a\u0442\u0435\u0440 \u0430\u0440\u049b\u044b\u043b\u044b \u043e\u0439\u043d\u0430\u0442\u049b\u0430\u043d\u0434\u0430 \u0436\u0430\u0431\u0434\u044b\u049b\u0442\u044b\u04a3 \u0448\u0435\u043a\u0442\u0435\u0443\u043b\u0435\u0440\u0456\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0435\u0434\u0456. \u0415\u0433\u0435\u0440 \u0448\u0435\u043a\u0442\u0435\u0443 \u049b\u043e\u043b\u0434\u0430\u043d\u044b\u043b\u0441\u0430, \u0441\u043e\u043d\u0434\u0430 \u043a\u043e\u0434\u0435\u043a \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0441\u0435\u0434\u0435 \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u043b\u044b\u043d\u0430\u0434\u044b.",
"HeaderContainerProfile": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u044b",
- "HeaderContainerProfileHelp": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u043d\u0430\u049b\u0442\u044b \u043f\u0456\u0448\u0456\u043c\u0434\u0435\u0440 \u0430\u0440\u049b\u044b\u043b\u044b \u043e\u0439\u043d\u0430\u0442\u049b\u0430\u043d\u0434\u0430 \u0436\u0430\u0431\u0434\u044b\u049b\u0442\u044b\u04a3 \u0448\u0435\u043a\u0442\u0435\u0443\u043b\u0435\u0440\u0456\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0435\u0434\u0456. \u0415\u0433\u0435\u0440 \u0448\u0435\u043a\u0442\u0435\u0443 \u049b\u043e\u043b\u0434\u0430\u043d\u044b\u043b\u0441\u0430, \u0441\u043e\u043d\u0434\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0441\u0435\u0434\u0435 \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u043b\u044b\u043d\u0430\u0434\u044b.",
+ "HeaderContainerProfileHelp": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u043d\u0430\u049b\u0442\u044b \u043f\u0456\u0448\u0456\u043c\u0434\u0435\u0440 \u0430\u0440\u049b\u044b\u043b\u044b \u043e\u0439\u043d\u0430\u0442\u049b\u0430\u043d\u0434\u0430 \u0436\u0430\u0431\u0434\u044b\u049b\u0442\u044b\u04a3 \u0448\u0435\u043a\u0442\u0435\u0443\u043b\u0435\u0440\u0456\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0435\u0434\u0456. \u0415\u0433\u0435\u0440 \u0448\u0435\u043a\u0442\u0435\u0443 \u049b\u043e\u043b\u0434\u0430\u043d\u044b\u043b\u0441\u0430, \u0441\u043e\u043d\u0434\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u043b\u0441\u0435\u0434\u0435 \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u043b\u044b\u043d\u0430\u0434\u044b.",
"OptionProfileVideo": "\u0411\u0435\u0439\u043d\u0435",
"OptionProfileAudio": "\u0414\u044b\u0431\u044b\u0441",
"OptionProfileVideoAudio": "\u0411\u0435\u0439\u043d\u0435 \u0414\u044b\u0431\u044b\u0441",
@@ -696,15 +769,15 @@
"OptionPlainStorageFoldersHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0431\u0430\u0440\u043b\u044b\u049b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440 DIDL \u0456\u0448\u0456\u043d\u0434\u0435 \"object.container.person.musicArtist\" \u0441\u0438\u044f\u049b\u0442\u044b \u043d\u0430\u049b\u0442\u044b\u043b\u0430\u0443 \u0442\u04af\u0440\u0456\u043d\u0456\u04a3 \u043e\u0440\u043d\u044b\u043d\u0430 \"object.container.storageFolder\" \u0431\u043e\u043b\u044b\u043f \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456.",
"OptionPlainVideoItems": "\u0411\u0430\u0440\u043b\u044b\u049b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0434\u0456 \u0436\u0430\u0439 \u0431\u0435\u0439\u043d\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440\u0456 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
"OptionPlainVideoItemsHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0431\u0430\u0440\u043b\u044b\u049b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440 DIDL \u0456\u0448\u0456\u043d\u0434\u0435 \"object.item.videoItem.movie\" \u0441\u0438\u044f\u049b\u0442\u044b \u043d\u0430\u049b\u0442\u044b\u043b\u0430\u0443 \u0442\u04af\u0440\u0456\u043d\u0456\u04a3 \u043e\u0440\u043d\u044b\u043d\u0430 \"object.item.videoItem\" \u0431\u043e\u043b\u044b\u043f \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456.",
- "LabelSupportedMediaTypes": "\u049a\u043e\u043b\u0434\u0430\u0443\u0434\u0430\u0493\u044b \u0442\u0430\u0441\u0443\u0448\u044b \u0442\u04af\u0440\u043b\u0435\u0440\u0456:",
- "TabIdentification": "\u0410\u043d\u044b\u049b\u0442\u0430\u043f \u0430\u043b\u0443",
+ "LabelSupportedMediaTypes": "\u049a\u043e\u043b\u0434\u0430\u0443\u0434\u0430\u0493\u044b \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u0442\u04af\u0440\u043b\u0435\u0440\u0456:",
+ "TabIdentification": "\u0410\u043d\u044b\u049b\u0442\u0430\u0443",
"TabDirectPlay": "\u0422\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443",
"TabContainers": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043b\u0435\u0440",
"TabCodecs": "\u041a\u043e\u0434\u0435\u043a\u0442\u0435\u0440",
"TabResponses": "\u04ae\u043d \u049b\u0430\u0442\u0443\u043b\u0430\u0440",
"HeaderProfileInformation": "\u041f\u0440\u043e\u0444\u0430\u0439\u043b \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u044b",
"LabelEmbedAlbumArtDidl": "Didl \u0456\u0448\u0456\u043d\u0435 \u0430\u043b\u044c\u0431\u043e\u043c \u0441\u0443\u0440\u0435\u0442\u0456\u043d \u0435\u043d\u0434\u0456\u0440\u0443",
- "LabelEmbedAlbumArtDidlHelp": "\u041a\u0435\u0439\u0431\u0456\u0440 \u0436\u0430\u0431\u0434\u044b\u049b\u0442\u0430\u0440\u0493\u0430 \u0430\u043b\u044c\u0431\u043e\u043c \u0441\u0443\u0440\u0435\u0442\u0456\u043d \u0430\u043b\u0443 \u04af\u0448\u0456\u043d \u043e\u0441\u044b \u04d9\u0434\u0456\u0441 \u049b\u0430\u0436\u0435\u0442. \u0411\u0430\u0441\u049b\u0430\u043b\u0430\u0440 \u0430\u0440\u049b\u044b\u043b\u044b, \u043e\u0441\u044b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u043e\u0439\u043d\u0430\u0442\u0443 \u0441\u04d9\u0442\u0441\u0456\u0437 \u0431\u043e\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.",
+ "LabelEmbedAlbumArtDidlHelp": "\u041a\u0435\u0439\u0431\u0456\u0440 \u0436\u0430\u0431\u0434\u044b\u049b\u0442\u0430\u0440\u0493\u0430 \u0430\u043b\u044c\u0431\u043e\u043c \u0441\u0443\u0440\u0435\u0442\u0456\u043d \u0430\u043b\u0443 \u04af\u0448\u0456\u043d \u043e\u0441\u044b \u04d9\u0434\u0456\u0441 \u049b\u0430\u0436\u0435\u0442. \u0411\u0430\u0441\u049b\u0430\u043b\u0430\u0440 \u04af\u0448\u0456\u043d, \u043e\u0441\u044b \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u043e\u0439\u043d\u0430\u0442\u0443 \u0441\u04d9\u0442\u0441\u0456\u0437 \u0431\u043e\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.",
"LabelAlbumArtPN": "\u0410\u043b\u044c\u0431\u043e\u043c \u0441\u0443\u0440\u0435\u0442\u0456 PN:",
"LabelAlbumArtHelp": "PN \u0430\u043b\u044c\u0431\u043e\u043c \u0441\u0443\u0440\u0435\u0442\u0456 \u04af\u0448\u0456\u043d upnp:albumArtURI \u0456\u0448\u0456\u043d\u0434\u0435\u0433\u0456 dlna:profileID \u0442\u04e9\u043b\u0441\u0438\u043f\u0430\u0442\u044b\u043c\u0435\u043d \u0431\u0456\u0440\u0433\u0435 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b. \u041a\u0435\u0439\u0431\u0456\u0440 \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440 \u04af\u0448\u0456\u043d \u0441\u0443\u0440\u0435\u0442\u0442\u0456\u04a3 \u04e9\u043b\u0448\u0435\u043c\u0456\u043d\u0435 \u0430\u04a3\u0493\u0430\u0440\u0443\u0441\u044b\u0437 \u043d\u0430\u049b\u0442\u044b \u043c\u04d9\u043d \u049b\u0430\u0436\u0435\u0442.",
"LabelAlbumArtMaxWidth": "\u0410\u043b\u044c\u0431\u043e\u043c \u0441\u0443\u0440\u0435\u0442\u0456\u043d\u0456\u04a3 \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u0435\u043d\u0456:",
@@ -718,7 +791,15 @@
"LabelIdentificationFieldHelp": "\u0420\u0435\u0433\u0438\u0441\u0442\u0440 \u0435\u0441\u043a\u0435\u0440\u043c\u0435\u0439\u0442\u0456\u043d \u0456\u0448\u043a\u0456 \u0436\u043e\u043b \u043d\u0435\u043c\u0435\u0441\u0435 \u04b1\u0434\u0430\u0439\u044b \u04e9\u0440\u043d\u0435\u043a.",
"HeaderProfileServerSettingsHelp": "\u0411\u04b1\u043b \u043c\u04d9\u043d\u0434\u0435\u0440 Media Browser \u049b\u0430\u043b\u0430\u0439 \u04e9\u0437\u0456\u043d \u0436\u0430\u0431\u0434\u044b\u049b\u0442\u0430 \u043a\u04e9\u0440\u0441\u0435\u0442\u0435\u0442\u0456\u043d\u0456\u04a3 \u0431\u0430\u0441\u049b\u0430\u0440\u0430\u0434\u044b.",
"LabelMaxBitrate": "\u0415\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d:",
- "LabelMaxBitrateHelp": "\u04e8\u0442\u043a\u0456\u0437\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456 \u0448\u0435\u043a\u0442\u0435\u043b\u0433\u0435\u043d \u043e\u0440\u0442\u0430\u043b\u0430\u0440\u0434\u0430\u0493\u044b \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.",
+ "LabelMaxBitrateHelp": "\u04e8\u0442\u043a\u0456\u0437\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456 \u0448\u0435\u043a\u0442\u0435\u043b\u0433\u0435\u043d \u043e\u0440\u0442\u0430\u043b\u0430\u0440\u0434\u0430\u0493\u044b \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u044b\u043d, \u043d\u0435\u043c\u0435\u0441\u0435 \u0436\u0430\u0431\u0434\u044b\u049b\u049b\u0430 \u049b\u0430\u0436\u0435\u0442 \u0431\u043e\u043b\u0441\u0430 - \u04e9\u0437 \u0448\u0435\u0433\u0456\u043d \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.",
+ "LabelMaxStreamingBitrate": "\u0415\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u0430\u0493\u044b\u043d \u049b\u0430\u0440\u049b\u044b\u043d\u044b:",
+ "LabelMaxStreamingBitrateHelp": "\u0410\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.",
+ "LabelMaxStaticBitrate": "\u0415\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b:",
+ "LabelMaxStaticBitrateHelp": "\u0416\u043e\u0493\u0430\u0440\u044b \u0441\u0430\u043f\u0430\u043c\u0435\u043d \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.",
+ "LabelMusicStaticBitrate": "\u041c\u0443\u0437\u044b\u043a\u0430\u043d\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b:",
+ "LabelMusicStaticBitrateHelp": "\u041c\u0443\u0437\u044b\u043a\u0430\u043d\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u0443",
+ "LabelMusicStreamingTranscodingBitrate": "\u041c\u0443\u0437\u044b\u043a\u0430\u043d\u044b \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u049b\u0430\u0440\u049b\u044b\u043d\u044b:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "\u041c\u0443\u0437\u044b\u043a\u0430\u043d\u044b \u0430\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u043a\u0435\u0437\u0456\u043d\u0434\u0435 \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u049b\u0430\u0440\u049b\u044b\u043d\u0434\u044b \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437",
"OptionIgnoreTranscodeByteRangeRequests": "\u049a\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u0431\u0430\u0439\u0442 \u0430\u0443\u049b\u044b\u043c\u044b \u0441\u04b1\u0440\u0430\u043d\u044b\u0441\u0442\u0430\u0440\u044b\u043d \u0435\u043b\u0435\u043c\u0435\u0443",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u043e\u0441\u044b \u0441\u04b1\u0440\u0430\u043d\u044b\u0441\u0442\u0430\u0440\u043c\u0435\u043d \u0441\u0430\u043d\u0430\u0441\u0443 \u0431\u043e\u043b\u0430\u0434\u044b, \u0431\u0456\u0440\u0430\u049b \u0431\u0430\u0439\u0442 \u0430\u0443\u049b\u044b\u043c\u044b\u043d\u044b\u04a3 \u0431\u0430\u0441 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u043c\u0435\u0441\u0456 \u0435\u043b\u0435\u043f \u0435\u0441\u043a\u0435\u0440\u0456\u043b\u043c\u0435\u0439\u0434\u0456.",
"LabelFriendlyName": "\u0422\u04af\u0441\u0456\u043d\u0456\u043a\u0442\u0456 \u0430\u0442\u044b",
@@ -730,16 +811,16 @@
"LabelModelUrl": "\u041c\u043e\u0434\u0435\u043b\u044c url",
"LabelSerialNumber": "\u0421\u0435\u0440\u0438\u044f\u043b\u044b\u049b \u043d\u04e9\u043c\u0456\u0440\u0456",
"LabelDeviceDescription": "\u0416\u0430\u0431\u0434\u044b\u049b \u0441\u0438\u043f\u0430\u0442\u0442\u0430\u043c\u0430\u0441\u044b",
- "HeaderIdentificationCriteriaHelp": "\u0415\u04a3 \u043a\u0435\u043c\u0456\u043d\u0434\u0435 \u0431\u0456\u0440 \u0430\u043d\u044b\u049b\u0442\u0430\u0443 \u0448\u0430\u0440\u0442\u044b\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437.",
+ "HeaderIdentificationCriteriaHelp": "\u0415\u04a3 \u043a\u0435\u043c\u0456\u043d\u0434\u0435 \u0430\u043d\u044b\u049b\u0442\u0430\u0443\u0434\u044b\u04a3 \u0431\u0456\u0440 \u0448\u0430\u0440\u0442\u044b\u043d \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437.",
"HeaderDirectPlayProfileHelp": "\u0416\u0430\u0431\u0434\u044b\u049b\u0442\u044b\u04a3 \u049b\u0430\u043d\u0434\u0430\u0439 \u043f\u0456\u0448\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u04d9\u0434\u0435\u043f\u043a\u0456 \u04e9\u04a3\u0434\u0435\u0442\u0435\u0442\u0456\u043d \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04b1\u0448\u0456\u043d \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u049b\u043e\u0441\u0443.",
"HeaderTranscodingProfileHelp": "\u049a\u0430\u0436\u0435\u0442 \u0431\u043e\u043b\u0493\u0430\u043d\u0434\u0430 \u049b\u0430\u043d\u0434\u0430\u0439 \u043f\u0456\u0448\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443 \u043c\u0456\u043d\u0434\u0435\u0442\u0456\u043b\u0456\u0433\u0456\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04b1\u0448\u0456\u043d \u049b\u0430\u0439\u0442\u0430 \u043a\u043e\u0434\u0442\u0430\u0443 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d \u049b\u043e\u0441\u0443.",
- "HeaderResponseProfileHelp": "\u041a\u0435\u0439\u0431\u0456\u0440 \u0442\u0430\u0441\u0443\u0448\u044b \u0442\u04af\u0440\u043b\u0435\u0440\u0456\u043d \u043e\u0439\u043d\u0430\u0442\u049b\u0430\u043d\u0434\u0430 \u04af\u043d \u049b\u0430\u0442\u0443 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u0436\u0430\u0431\u0434\u044b\u049b\u049b\u0430 \u0436\u0456\u0431\u0435\u0440\u0456\u043b\u0435\u0442\u0456\u043d \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u0442\u044b \u0442\u0435\u04a3\u0448\u0435\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b \u0431\u0435\u0440\u0435\u0434\u0456.",
+ "HeaderResponseProfileHelp": "\u041a\u0435\u0439\u0431\u0456\u0440 \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u0442\u04af\u0440\u043b\u0435\u0440\u0456\u043d \u043e\u0439\u043d\u0430\u0442\u049b\u0430\u043d\u0434\u0430 \u04af\u043d \u049b\u0430\u0442\u0443 \u043f\u0440\u043e\u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b \u0436\u0430\u0431\u0434\u044b\u049b\u049b\u0430 \u0436\u0456\u0431\u0435\u0440\u0456\u043b\u0435\u0442\u0456\u043d \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u0442\u044b \u0442\u0435\u04a3\u0448\u0435\u0443 \u04af\u0448\u0456\u043d \u0436\u043e\u043b \u0431\u0435\u0440\u0435\u0434\u0456.",
"LabelXDlnaCap": "X-Dlna \u0441\u0438\u043f\u0430\u0442\u0442\u0430\u0440\u044b:",
- "LabelXDlnaCapHelp": "urn:schemas-dlna-org:device-1-0 \u0430\u0442\u0430\u0443\u043b\u0430\u0440 \u043a\u0435\u04a3\u0456\u0441\u0442\u0456\u0433\u0456\u043d\u0434\u0435\u0433\u0456 X_DLNACAP \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0456 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.",
+ "LabelXDlnaCapHelp": "urn:schemas-dlna-org:device-1-0 \u0430\u0442\u0430\u0443\u043b\u0430\u0440 \u043a\u0435\u04a3\u0456\u0441\u0442\u0456\u0433\u0456\u043d\u0434\u0435\u0433\u0456 X_DLNACAP \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0456 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0430\u043d\u044b\u049b\u0442\u0430\u0439\u0434\u044b.",
"LabelXDlnaDoc": "X-Dlna \u0442\u04d9\u0441\u0456\u043c\u0456:",
- "LabelXDlnaDocHelp": "urn:schemas-dlna-org:device-1-0 \u0430\u0442\u0430\u0443\u043b\u0430\u0440 \u043a\u0435\u04a3\u0456\u0441\u0442\u0456\u0433\u0456\u043d\u0434\u0435\u0433\u0456 X_DLNADOC \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0456 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.",
+ "LabelXDlnaDocHelp": "urn:schemas-dlna-org:device-1-0 \u0430\u0442\u0430\u0443\u043b\u0430\u0440 \u043a\u0435\u04a3\u0456\u0441\u0442\u0456\u0433\u0456\u043d\u0434\u0435\u0433\u0456 X_DLNADOC \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0456 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0430\u043d\u044b\u049b\u0442\u0430\u0439\u0434\u044b.",
"LabelSonyAggregationFlags": "Sony \u0431\u0456\u0440\u0456\u043a\u0442\u0456\u0440\u0443 \u0436\u0430\u043b\u0430\u0443\u0448\u0430\u043b\u0430\u0440\u044b:",
- "LabelSonyAggregationFlagsHelp": "urn:schemas-sonycom:av \u0430\u0442\u0430\u0443\u043b\u0430\u0440 \u043a\u0435\u04a3\u0456\u0441\u0442\u0456\u0433\u0456\u043d\u0434\u0435\u0433\u0456 aggregationFlags \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0456 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437.",
+ "LabelSonyAggregationFlagsHelp": "urn:schemas-sonycom:av \u0430\u0442\u0430\u0443\u043b\u0430\u0440 \u043a\u0435\u04a3\u0456\u0441\u0442\u0456\u0433\u0456\u043d\u0434\u0435\u0433\u0456 aggregationFlags \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0456 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0430\u043d\u044b\u049b\u0442\u0430\u0439\u0434\u044b.",
"LabelTranscodingContainer": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440:",
"LabelTranscodingVideoCodec": "\u0411\u0435\u0439\u043d\u0435\u043b\u0456\u043a \u043a\u043e\u0434\u0435\u043a:",
"LabelTranscodingVideoProfile": "\u0411\u0435\u0439\u043d\u0435\u043b\u0456\u043a \u043f\u0440\u043e\u0444\u0430\u0439\u043b:",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "\u041f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440\u0434\u0456 \u043c\u044b\u043d\u0430\u0493\u0430\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "\u0411\u0430\u0441\u049b\u0430\u043b\u0430\u0440",
- "LabelEpisodeName": "\u042d\u043f\u0438\u0437\u043e\u0434 \u0430\u0442\u044b",
- "LabelSeriesName": "\u0421\u0435\u0440\u0438\u0430\u043b \u0430\u0442\u044b",
+ "LabelEpisodeNamePlain": "\u042d\u043f\u0438\u0437\u043e\u0434 \u0430\u0442\u0430\u0443\u044b",
+ "LabelSeriesNamePlain": "\u0421\u0435\u0440\u0438\u0430\u043b \u0430\u0442\u0430\u0443\u044b",
"ValueSeriesNamePeriod": "\u0421\u0435\u0440\u0438\u0430\u043b.\u0430\u0442\u044b",
"ValueSeriesNameUnderscore": "\u0421\u0435\u0440\u0438\u0430\u043b_\u0430\u0442\u044b",
"ValueEpisodeNamePeriod": "\u042d\u043f\u0438\u0437\u043e\u0434.\u0430\u0442\u044b",
"ValueEpisodeNameUnderscore": "\u042d\u043f\u0438\u0437\u043e\u0434_\u0430\u0442\u044b",
+ "LabelSeasonNumberPlain": "\u041c\u0430\u0443\u0441\u044b\u043c \u043d\u04e9\u043c\u0456\u0440\u0456",
+ "LabelEpisodeNumberPlain": "\u042d\u043f\u0438\u0437\u043e\u043b \u043d\u04e9\u043c\u0456\u0440\u0456",
+ "LabelEndingEpisodeNumberPlain": "\u0410\u044f\u049b\u0442\u0430\u0443\u0448\u044b \u044d\u043f\u0438\u0437\u043e\u0434\u0442\u044b\u04a3 \u043d\u04e9\u043c\u0456\u0440\u0456",
"HeaderTypeText": "\u041c\u04d9\u0442\u0456\u043d\u0434\u0456 \u0435\u043d\u0433\u0456\u0437\u0443",
"LabelTypeText": "\u041c\u04d9\u0442\u0456\u043d",
"HeaderSearchForSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u0456\u0437\u0434\u0435\u0443",
@@ -800,9 +883,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:",
- "OptionMyLibraryButtons": "\u041c\u0435\u043d\u0456\u04a3 \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043c (\u0442\u04af\u0439\u043c\u0435\u0448\u0456\u043a\u0442\u0435\u0440)",
- "OptionMyLibrary": "\u041c\u0435\u043d\u0456\u04a3 \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043c",
- "OptionMyLibrarySmall": "\u041c\u0435\u043d\u0456\u04a3 \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043c (\u043a\u0456\u0448\u0456)",
+ "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)",
"OptionResumablemedia": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443",
"OptionLatestMedia": "\u0415\u04a3 \u0441\u043e\u04a3\u0493\u044b \u0442\u0430\u0441\u0443\u0448\u044b\u043b\u0430\u0440",
"OptionLatestChannelMedia": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u044b\u04a3 \u0435\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440\u0456",
@@ -813,23 +896,26 @@
"HeaderMetadataManager": "\u041c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a \u0431\u0430\u0441\u049b\u0430\u0440\u0443\u0448\u044b",
"HeaderPreferences": "\u0422\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440",
"MessageLoadingChannels": "\u0410\u0440\u043d\u0430\u043d\u044b\u04a3 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0436\u04af\u043a\u0442\u0435\u0443\u0434\u0435...",
+ "MessageLoadingContent": "\u041c\u0430\u0437\u043c\u04b1\u043d \u0436\u04af\u043a\u0442\u0435\u043b\u0443\u0434\u0435...",
"ButtonMarkRead": "\u041e\u049b\u044b\u043b\u0493\u0430\u043d \u0434\u0435\u043f \u0431\u0435\u043b\u0433\u0456\u043b\u0435\u0443",
"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": "\u0410\u043b\u0434\u0430\u0493\u044b",
+ "TabNextUp": "\u041a\u0435\u0437\u0435\u043a\u0442\u0435\u0433\u0456\u043b\u0435\u0440",
"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": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440\u0434\u0456, \u0441\u0435\u0440\u0438\u0430\u043b\u0434\u0430\u0440\u0434\u044b, \u0430\u043b\u044c\u0431\u043e\u043c\u0434\u0430\u0440\u0434\u044b, \u043a\u0456\u0442\u0430\u043f\u0442\u0430\u0440\u0434\u044b \u0436\u04d9\u043d\u0435 \u043e\u0439\u044b\u043d\u0434\u0430\u0440\u0434\u044b \u0436\u0435\u043a\u0435\u043b\u0435\u043d\u0433\u0435\u043d \u0442\u043e\u043f\u0442\u0430\u0441\u0442\u044b\u0440\u0443 \u04af\u0448\u0456\u043d \u0442\u043e\u043f\u0442\u0430\u043c\u0430\u043b\u0430\u0440 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u043a \u0431\u0435\u0440\u0435\u0434\u0456. \u0422\u043e\u043f\u0442\u0430\u043c\u0430\u043b\u0430\u0440\u0434\u044b \u0436\u0430\u0441\u0430\u0439 \u0431\u0430\u0441\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \"\u0416\u0430\u0441\u0430\u0443\" \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 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440\u0434\u0456 \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.",
+ "MessageNoPlaylistItemsAvailable": "\u041e\u0441\u044b \u043e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c \u0430\u0493\u044b\u043c\u0434\u0430\u0493\u044b \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u0431\u043e\u0441.",
"HeaderWelcomeToMediaBrowserWebClient": "Media Browser \u0432\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442 \u0431\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430\u0441\u044b\u043d\u0430 \u0445\u043e\u0448 \u043a\u0435\u043b\u0434\u0456\u04a3\u0456\u0437!",
"ButtonDismiss": "\u0416\u0430\u0441\u044b\u0440\u0443",
"MessageLearnHowToCustomize": "\u041e\u0441\u044b \u0431\u0435\u0442\u0442\u0456 \u0436\u0435\u043a\u0435 \u043a\u04e9\u04a3\u0456\u043b\u0433\u0435 \u04b1\u043d\u0430\u0442\u0443 \u0431\u043e\u0439\u044b\u043d\u0448\u0430 \u049b\u0430\u043b\u0430\u0439 \u0442\u0435\u04a3\u0448\u0435\u0443\u0456\u043d \u04af\u0439\u0440\u0435\u043d\u0456\u04a3\u0456\u0437. \u0422\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u04a3\u0456\u0437\u0434\u0456 \u049b\u0430\u0440\u0430\u0443 \u0436\u04d9\u043d\u0435 \u0436\u0430\u04a3\u0430\u0440\u0442\u0443 \u04af\u0448\u0456\u043d \u044d\u043a\u0440\u0430\u043d\u0434\u0430\u0493\u044b \u0436\u043e\u0493\u0430\u0440\u0493\u044b \u043e\u04a3 \u0431\u04b1\u0440\u044b\u0448\u044b\u043d\u0434\u0430\u0493\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u044b\u049b \u0431\u0435\u043b\u0433\u0456\u0448\u0435\u04a3\u0456\u0437\u0434\u0456 \u0431\u0430\u0441\u044b\u04a3\u044b\u0437.",
"ButtonEditOtherUserPreferences": "\u041e\u0441\u044b \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0456\u043d \u04e9\u04a3\u0434\u0435\u0443.",
"LabelChannelStreamQuality": "\u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0456:",
- "LabelChannelStreamQualityHelp": "\u04e8\u0442\u043a\u0456\u0437\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456 \u0442\u04e9\u043c\u0435\u043d \u043e\u0440\u0442\u0430\u043b\u0430\u0440\u0434\u0430, \u0441\u0430\u043f\u0430\u043d\u044b \u0448\u0435\u043a\u0442\u0435\u0443 \u0436\u0430\u0442\u044b\u049b \u0430\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u04af\u0448\u0456\u043d \u049b\u0430\u043c\u0442\u0430\u043c\u0430\u0441\u044b\u0437 \u0435\u0442\u0433\u0435 \u043a\u04e9\u043c\u0435\u043a\u0442\u0435\u0441\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.",
+ "LabelChannelStreamQualityHelp": "\u04e8\u0442\u043a\u0456\u0437\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456 \u0442\u04e9\u043c\u0435\u043d \u043e\u0440\u0442\u0430\u0434\u0430, \u0441\u0430\u043f\u0430\u0441\u044b\u043d \u0448\u0435\u043a\u0442\u0435\u0443\u0456 \u0436\u0430\u0442\u044b\u049b\u0442\u0430\u0443 \u0430\u0493\u044b\u043d\u0434\u044b\u049b \u043e\u0439\u043d\u0430\u0442\u0443 \u04d9\u0441\u0435\u0440\u0456\u043d \u049b\u0430\u043c\u0442\u0430\u043c\u0430\u0441\u044b\u0437 \u0435\u0442\u0443\u0456\u043d\u0435 \u043a\u04e9\u043c\u0435\u043a\u0442\u0435\u0441\u0443\u0456 \u043c\u04af\u043c\u043a\u0456\u043d.",
"OptionBestAvailableStreamQuality": "\u049a\u043e\u043b \u0436\u0435\u0442\u0456\u043c\u0434\u0456 \u0435\u04a3 \u0436\u0430\u049b\u0441\u044b",
"LabelEnableChannelContentDownloadingFor": "\u0411\u04b1\u043b \u04af\u0448\u0456\u043d \u0430\u0440\u043d\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443\u0434\u044b \u049b\u043e\u0441\u0443:",
"LabelEnableChannelContentDownloadingForHelp": "\u041a\u0435\u0439\u0431\u0456\u0440 \u0430\u0440\u043d\u0430\u043b\u0430\u0440 \u049b\u0430\u0440\u0430\u0443\u0434\u044b\u04a3 \u0430\u043b\u0434\u044b\u043d\u0434\u0430 \u043c\u0430\u0437\u043c\u04af\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443\u0434\u044b \u049b\u043e\u043b\u0434\u0430\u0439\u0434\u044b. \u04e8\u0442\u043a\u0456\u0437\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456 \u0442\u04e9\u043c\u0435\u043d \u043e\u0440\u0442\u0430\u043b\u0430\u0440\u0434\u0430 \u0430\u0440\u043d\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0436\u04b1\u043c\u044b\u0441\u0442\u0430\u043d \u0431\u043e\u0441 \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u04af\u0448\u0456\u043d \u0431\u04b1\u043d\u044b \u049b\u043e\u0441\u044b\u04a3\u044b\u0437. \u041c\u0430\u0437\u043c\u04af\u043d \u0430\u0440\u043d\u0430 \u0436\u04af\u043a\u0442\u0435\u0443 \u0436\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u0441\u044b \u0431\u04e9\u043b\u0456\u0433\u0456 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0436\u04af\u043a\u0442\u0435\u043b\u0435\u0434\u0456.",
"LabelChannelDownloadPath": "\u0410\u0440\u043d\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u0436\u043e\u043b\u044b:",
- "LabelChannelDownloadPathHelp": "\u041a\u0435\u0440\u0435\u043a \u0431\u043e\u043b\u0441\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u0436\u043e\u043b\u044b\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u04a3\u0456\u0437. \u0411\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043d\u0456\u04a3 \u0456\u0448\u043a\u0456 \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d\u0430 \u0436\u04af\u043a\u0442\u0435\u0443 \u04af\u0448\u0456\u043d \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u04a3\u044b\u0437.",
+ "LabelChannelDownloadPathHelp": "\u041a\u0435\u0440\u0435\u043a \u0431\u043e\u043b\u0441\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u0436\u043e\u043b\u044b\u043d \u0430\u043d\u044b\u049b\u0442\u0430\u04a3\u044b\u0437. \u0411\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043d\u0456\u04a3 \u0456\u0448\u043a\u0456 \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d\u0430 \u0436\u04af\u043a\u0442\u0435\u0443 \u04af\u0448\u0456\u043d \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u04a3\u044b\u0437.",
"LabelChannelDownloadAge": "\u041c\u0430\u0437\u043c\u04b1\u043d \u0436\u043e\u0439\u044b\u043b\u0443\u044b \u043a\u0435\u043b\u0435\u0441\u0456\u0434\u0435\u043d \u043a\u0435\u0439\u0456\u043d, \u043a\u04af\u043d:",
"LabelChannelDownloadAgeHelp": "\u0411\u04b1\u0434\u0430\u043d \u0431\u04b1\u0440\u044b\u043d\u0493\u044b \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0493\u0430\u043d \u043c\u0430\u0437\u043c\u04af\u043d \u0436\u043e\u0439\u044b\u043b\u0430\u0434\u044b. \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443 \u04d9\u0434\u0456\u0441\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043f \u043e\u0439\u043d\u0430\u0442\u0443 \u0456\u0441\u0442\u0435 \u049b\u0430\u043b\u0430\u0434\u044b.",
"ChannelSettingsFormHelp": "\u041f\u043b\u0430\u0433\u0438\u043d \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0456\u043d\u0434\u0435\u0433\u0456 Trailers \u0436\u04d9\u043d\u0435 Vimeo \u0441\u0438\u044f\u049b\u0442\u044b \u0430\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u044b \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437.",
@@ -842,11 +928,171 @@
"ViewTypeChannels": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440",
"ViewTypeLiveTV": "\u042d\u0444\u0438\u0440\u043b\u0456\u043a \u0422\u0414",
"HeaderOtherDisplaySettings": "\u0411\u0435\u0439\u043d\u0435\u043b\u0435\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456",
- "HeaderMyViews": "\u041c\u0435\u043d\u0456\u04a3 \u043a\u04e9\u0440\u0456\u043d\u0456\u0441\u0442\u0435\u0440\u0456\u043c",
- "LabelSelectFolderGroups": "\u041a\u0435\u043b\u0435\u0441\u0456 \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u0434\u0430\u0493\u044b \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u041a\u0438\u043d\u043e, \u041c\u0443\u0437\u044b\u043a\u0430 \u0436\u04d9\u043d\u0435 \u0422\u0414 \u0441\u0438\u044f\u049b\u0442\u044b \u043a\u04e9\u0440\u0456\u043d\u0456\u0441\u0442\u0435\u0440\u0433\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0442\u043e\u043f\u0442\u0430\u0441\u0442\u044b\u0440\u0443:",
- "LabelSelectFolderGroupsHelp": "\u0411\u0435\u043b\u0433\u0456\u043b\u0435\u043d\u0431\u0435\u0433\u0435\u043d \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440 \u04e9\u0437 \u0431\u0435\u0442\u0456\u043c\u0435\u043d \u04e9\u0437\u0456\u043d\u0456\u04a3 \u043a\u04e9\u0440\u0456\u043d\u0456\u0441\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456.",
- "OptionDisplayAdultContent": "\u0415\u0440\u0435\u0441\u0435\u043a\u0442\u0435\u0440\u0433\u0435 \u0430\u0440\u043d\u0430\u043b\u0493\u0430\u043d \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u043a\u04e9\u0440\u0441\u0435\u0442\u0443",
+ "HeaderMyViews": "\u041c\u0435\u043d\u0456\u04a3 \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440\u0456\u043c",
+ "LabelSelectFolderGroups": "\u041a\u0435\u043b\u0435\u0441\u0456 \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u0434\u0430\u0493\u044b \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u041a\u0438\u043d\u043e, \u041c\u0443\u0437\u044b\u043a\u0430 \u0436\u04d9\u043d\u0435 \u0422\u0414 \u0441\u0438\u044f\u049b\u0442\u044b \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440\u0433\u0435 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0442\u043e\u043f\u0442\u0430\u0441\u0442\u044b\u0440\u0443:",
+ "LabelSelectFolderGroupsHelp": "\u0411\u0435\u043b\u0433\u0456\u043b\u0435\u043d\u0431\u0435\u0433\u0435\u043d \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440 \u04e9\u0437 \u0431\u0435\u0442\u0456\u043c\u0435\u043d \u04e9\u0437\u0456\u043d\u0456\u04a3 \u0430\u0441\u043f\u0435\u043a\u0442\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456.",
+ "OptionDisplayAdultContent": "\u0415\u0440\u0435\u0441\u0435\u043a \u043c\u0430\u0437\u043c\u04b1\u043d\u044b\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443",
"OptionLibraryFolders": "\u0422\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b",
"TitleRemoteControl": "\u049a\u0430\u0448\u044b\u049b\u0442\u0430\u043d \u0431\u0430\u0441\u049b\u0430\u0440\u0443",
- "OptionLatestTvRecordings": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0436\u0430\u0437\u0431\u0430\u043b\u0430\u0440"
+ "OptionLatestTvRecordings": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0436\u0430\u0437\u0431\u0430\u043b\u0430\u0440",
+ "LabelProtocolInfo": "\u041f\u0440\u043e\u0442\u043e\u049b\u043e\u043b \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u044b:",
+ "LabelProtocolInfoHelp": "\u0411\u04b1\u043b \u043c\u04d9\u043d \u0436\u0430\u0431\u0434\u044b\u049b\u0442\u044b\u04a3 GetProtocolInfo \u0441\u04b1\u0440\u0430\u043d\u044b\u0441\u0442\u0430\u0440\u044b\u043d\u0430 \u0436\u0430\u0443\u0430\u043f \u0431\u0435\u0440\u0433\u0435\u043d\u0434\u0435 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043b\u0430\u0434\u044b.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser \u0431\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430\u0441\u044b Xbmc Nfo \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0442\u0435\u0440\u0456\u043d\u0456\u04a3 \u0436\u04d9\u043d\u0435 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456\u043d\u0456\u04a3 \u043a\u0456\u0440\u0456\u043a\u0442\u0456\u0440\u043c\u0435 \u049b\u043e\u043b\u0434\u0430\u0443\u044b\u043d \u049b\u0430\u043c\u0442\u0438\u0434\u044b. Xbmc \u043c\u0435\u0442\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043d \u049b\u043e\u0441\u0443 \u043d\u0435\u043c\u0435\u0441\u0435 \u04e9\u0448\u0456\u0440\u0443 \u04af\u0448\u0456\u043d \u049a\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440 \u049b\u043e\u0439\u044b\u043d\u0434\u044b\u0441\u044b\u043d\u0434\u0430\u0493\u044b \u0442\u0430\u0441\u0443\u0448\u044b \u0442\u04af\u0440\u043b\u0435\u0440\u0456\u043d\u0435 \u0430\u0440\u043d\u0430\u043b\u0493\u0430\u043d \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u04a3\u044b\u0437.",
+ "LabelXbmcMetadataUser": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043d\u044b\u04a3 \u049b\u0430\u0440\u0430\u0443 \u043a\u04af\u0439\u0456\u043d nfo \u04af\u0448\u0456\u043d \u043c\u044b\u043d\u0430\u0493\u0430\u043d \u049b\u043e\u0441\u0443:",
+ "LabelXbmcMetadataUserHelp": "\u041a\u04e9\u0440\u0456\u043b\u0433\u0435\u043d \u043a\u04af\u0439\u0434\u0456 Media Browser \u0436\u04d9\u043d\u0435 Xbmc \u0430\u0440\u0430\u0441\u044b\u043d\u0434\u0430 \u04af\u0439\u043b\u0435\u0441\u0442\u0456\u0440\u0456\u043f \u0442\u04b1\u0440\u0443 \u04af\u0448\u0456\u043d \u0431\u04b1\u043d\u044b \u049b\u043e\u0441\u044b\u04a3\u044b\u0437.",
+ "LabelXbmcMetadataDateFormat": "\u0428\u044b\u0493\u0430\u0440\u0443 \u043a\u04af\u043d-\u0430\u0439\u044b\u043d\u044b\u04a3 \u043f\u0456\u0448\u0456\u043c\u0456:",
+ "LabelXbmcMetadataDateFormatHelp": "\u041e\u0441\u044b \u043f\u0456\u0448\u0456\u043c\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043f nfo \u0456\u0448\u0456\u043d\u0434\u0435\u0433\u0456 \u0431\u0430\u0440\u043b\u044b\u049b \u043a\u04af\u043d-\u0430\u0439\u043b\u0430\u0440 \u043e\u049b\u044b\u043b\u0430\u0434\u044b \u0436\u04d9\u043d\u0435 \u0436\u0430\u0437\u044b\u043b\u0430\u0434\u044b.",
+ "LabelXbmcMetadataSaveImagePaths": "\u0421\u0443\u0440\u0435\u0442 \u0436\u043e\u043b\u044b\u043d nfo \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b\u043d\u0434\u0430 \u0441\u0430\u049b\u0442\u0430\u0443",
+ "LabelXbmcMetadataSaveImagePathsHelp": "\u0415\u0433\u0435\u0440 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456\u04a3 Xbmc \u043d\u04b1\u0441\u049b\u0430\u0443\u043b\u044b\u049b \u04b1\u0441\u0442\u0430\u043d\u044b\u043c\u0434\u0430\u0440\u044b\u043d\u0430 \u0441\u0430\u0439 \u043a\u0435\u043b\u043c\u0435\u0433\u0435\u043d \u0430\u0442\u0430\u0443\u043b\u0430\u0440\u044b \u0431\u043e\u043b\u0441\u0430, \u0431\u04b1\u043b \u04b1\u0441\u044b\u043d\u044b\u043b\u0430\u0434\u044b.",
+ "LabelXbmcMetadataEnablePathSubstitution": "\u0416\u043e\u043b \u0430\u043b\u043c\u0430\u0441\u0442\u044b\u0440\u0443\u0434\u044b \u049b\u043e\u0441\u0443",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u0436\u043e\u043b \u0430\u043b\u043c\u0430\u0441\u0442\u044b\u0440\u0443 \u0442\u0435\u04a3\u0448\u0435\u0443\u0456\u043d \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u043f \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456\u04a3 \u0436\u043e\u043b \u0430\u043b\u043c\u0430\u0441\u0442\u044b\u0440\u0443\u044b\u043d \u049b\u043e\u0441\u0430\u0434\u044b.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "\u0416\u043e\u043b \u0430\u043b\u043c\u0430\u0441\u0442\u044b\u0440\u0443\u0434\u044b \u049b\u0430\u0440\u0430\u0443.",
+ "LabelGroupChannelsIntoViews": "\u041c\u0435\u043d\u0456\u04a3 \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440\u0456\u043c\u0434\u0435 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043a\u0435\u043b\u0435\u0441\u0456 \u0430\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u044b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443:",
+ "LabelGroupChannelsIntoViewsHelp": "\u0415\u0433\u0435\u0440 \u049b\u043e\u0441\u044b\u043b\u0441\u0430, \u043e\u0441\u044b \u0430\u0440\u043d\u0430\u043b\u0430\u0440 \u0431\u0430\u0441\u049b\u0430 \u0430\u0441\u043f\u0435\u043a\u0442\u0442\u0435\u0440\u043c\u0435\u043d \u049b\u0430\u0442\u0430\u0440 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456. \u0415\u0433\u0435\u0440 \u0430\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u0441\u0430, \u043e\u043b\u0430\u0440 \u0431\u04e9\u043b\u0435\u043a \u0410\u0440\u043d\u0430\u043b\u0430\u0440 \u043a\u04e9\u0440\u0456\u043d\u0456\u0441\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456.",
+ "LabelDisplayCollectionsView": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440 \u0436\u0438\u043d\u0430\u049b\u0442\u0430\u0440\u044b\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04af\u0448\u0456\u043d \u0416\u0438\u043d\u0430\u049b\u0442\u0430\u0440 \u0430\u0441\u043f\u0435\u043a\u0442\u0456\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
+ "LabelXbmcMetadataEnableExtraThumbs": "\u04d8\u0434\u0435\u043f\u043a\u0456 extrafanart \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0456\u043d extrathumbs \u0456\u0448\u0456\u043d\u0435 \u043a\u04e9\u0448\u0456\u0440\u0443",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0436\u04af\u043a\u0442\u0435\u0433\u0435\u043d \u043a\u0435\u0437\u0434\u0435, \u043e\u043b\u0430\u0440 Xbmc \u049b\u0430\u0431\u044b\u0493\u044b\u043c\u0435\u043d \u0435\u04a3 \u0436\u043e\u0493\u0430\u0440\u044b \u0441\u0438\u044b\u0441\u044b\u043c\u0434\u044b\u0493\u044b \u04af\u0448\u0456\u043d extrafanart \u0436\u04d9\u043d\u0435 extrathumbs \u0435\u043a\u0435\u0443\u0456\u043d\u0434\u0435 \u0441\u0430\u049b\u0442\u0430\u043b\u0430\u0434\u044b.",
+ "TabServices": "\u049a\u044b\u0437\u043c\u0435\u0442\u0442\u0435\u0440",
+ "TabLogs": "\u0416\u04b1\u0440\u043d\u0430\u043b\u0434\u0430\u0440",
+ "HeaderServerLogFiles": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u0436\u04b1\u0440\u043d\u0430\u043b \u0444\u0430\u0439\u043b\u0434\u0430\u0440\u044b:",
+ "TabBranding": "\u0411\u0440\u0435\u043d\u0434\u0438\u043d\u0433",
+ "HeaderBrandingHelp": "\u0422\u043e\u0431\u044b\u04a3\u044b\u0437\u0434\u044b\u04a3 \u043d\u0435 \u04b1\u0439\u044b\u043c\u044b\u04a3\u044b\u0437\u0434\u044b\u04a3 \u043c\u04b1\u049b\u0442\u0430\u0436\u0434\u044b\u049b\u0442\u0430\u0440\u044b\u043d\u0430 \u04af\u0439\u043b\u0435\u0441\u0456\u043c\u0434\u0456 Media Browser \u0431\u0435\u0437\u0435\u043d\u0434\u0456\u0440\u0443\u0456\u043d \u0442\u0435\u04a3\u0448\u0435\u0443.",
+ "LabelLoginDisclaimer": "\u041a\u0456\u0440\u0433\u0435\u043d\u0434\u0435\u0433\u0456 \u0435\u0441\u043a\u0435\u0440\u0442\u0443:",
+ "LabelLoginDisclaimerHelp": "\u0411\u04b1\u043b \u043a\u0456\u0440\u0443 \u0431\u0435\u0442\u0456\u043d\u0456\u04a3 \u0442\u04e9\u043c\u0435\u043d\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456.",
+ "LabelAutomaticallyDonate": "\u041e\u0441\u044b \u0441\u043e\u043c\u0430\u043d\u044b \u04d9\u0440 \u0430\u0439 \u0441\u0430\u0439\u044b\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0441\u044b\u0439\u043b\u0430\u0443",
+ "LabelAutomaticallyDonateHelp": "PayPal \u0435\u0441\u0435\u043f \u0448\u043e\u0442\u044b\u04a3\u044b\u0437 \u0430\u0440\u049b\u044b\u043b\u044b \u043a\u0435\u0437 \u043a\u0435\u043b\u0433\u0435\u043d \u0443\u0430\u049b\u044b\u0442\u0442\u0430 \u0434\u043e\u0493\u0430\u0440\u0443 \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u04a3\u0456\u0437 \u0431\u0430\u0440.",
+ "OptionList": "\u0422\u0456\u0437\u0456\u043c",
+ "TabDashboard": "\u0411\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b",
+ "TitleServer": "\u0421\u0435\u0440\u0432\u0435\u0440",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u043c\u0443\u0437\u044b\u043a\u0430",
+ "HeaderBranding": "\u0411\u0440\u0435\u043d\u0434\u0438\u04a3\u0433",
+ "HeaderApiKeys": "API \u043a\u0456\u043b\u0442\u0442\u0435\u0440\u0456",
+ "HeaderApiKeysHelp": "\u0421\u044b\u0440\u0442\u049b\u044b \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440 Media Browser \u0431\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430\u0441\u044b\u043c\u0435\u043d \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443 \u04af\u0448\u0456\u043d API \u043a\u0456\u043b\u0442\u0456 \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456. \u041a\u0456\u043b\u0442\u0442\u0435\u0440 Media Browser \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0456\u0441\u0456\u043d\u0435 \u043a\u0456\u0440\u0433\u0435\u043d\u0434\u0435, \u043d\u0435\u043c\u0435\u0441\u0435 \u043a\u0456\u043b\u0442\u0442\u0456 \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u0493\u0430 \u049b\u043e\u043b\u043c\u0435\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0456\u043b\u0433\u0435\u043d\u0434\u0435 \u0431\u0435\u0440\u0456\u043b\u0435\u0434\u0456.",
+ "HeaderApiKey": "API \u043a\u0456\u043b\u0442\u0456",
+ "HeaderApp": "\u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430",
+ "HeaderDevice": "\u0416\u0430\u0431\u0434\u044b\u049b",
+ "HeaderUser": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b",
+ "HeaderDateIssued": "\u0411\u0435\u0440\u0456\u043b\u0433\u0435\u043d \u043a\u04af\u043d-\u0430\u0439\u044b",
+ "LabelChapterName": "{0}-\u0441\u0430\u0445\u043d\u0430",
+ "HeaderNewApiKey": "\u0416\u0430\u04a3\u0430 API \u043a\u0456\u043b\u0442\u0456",
+ "LabelAppName": "\u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430 \u0430\u0442\u044b",
+ "LabelAppNameExample": "\u041c\u044b\u0441\u0430\u043b\u044b: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Media Browser \u0431\u0430\u0493\u0434\u0430\u0440\u043b\u0430\u043c\u0430\u0441\u044b\u043c\u0435\u043d \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443 \u049b\u04b1\u049b\u044b\u049b\u044b\u0493\u044b \u04af\u0448\u0456\u043d \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u0493\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443.",
+ "HeaderHttpHeaders": "HTTP \u04af\u0441\u0442\u0456\u04a3\u0433\u0456 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u043c\u0435\u043b\u0435\u0440\u0456",
+ "HeaderIdentificationHeader": "\u0410\u043d\u044b\u049b\u0442\u0430\u0443\u0434\u044b\u04a3 \u04af\u0441\u0442\u0456\u04a3\u0433\u0456 \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u043c\u0435\u0441\u0456",
+ "LabelValue": "\u041c\u04d9\u043d\u0456:",
+ "LabelMatchType": "\u0421\u04d9\u0439\u043a\u0435\u0441 \u0442\u04af\u0440\u0456:",
+ "OptionEquals": "\u0422\u0435\u04a3",
+ "OptionRegex": "\u04b0\u0434\u0430\u0439\u044b \u04e9\u0440\u043d\u0435\u043a",
+ "OptionSubstring": "\u0406\u0448\u043a\u0456 \u0436\u043e\u043b",
+ "TabView": "\u041a\u04e9\u0440\u0456\u043d\u0456\u0441",
+ "TabSort": "\u0421\u04b1\u0440\u044b\u043f\u0442\u0430\u0443",
+ "TabFilter": "\u0421\u04af\u0437\u0443",
+ "ButtonView": "\u049a\u0430\u0440\u0430\u0443",
+ "LabelPageSize": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440 \u0448\u0435\u0433\u0456:",
+ "LabelPath": "\u0416\u043e\u043b\u044b:",
+ "LabelView": "\u041a\u04e9\u0440\u0456\u043d\u0456\u0441:",
+ "TabUsers": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440",
+ "LabelSortName": "\u0421\u04b1\u0440\u044b\u043f\u0442\u0430\u043b\u0430\u0442\u044b\u043d \u0430\u0442\u044b:",
+ "LabelDateAdded": "\u04ae\u0441\u0442\u0435\u043b\u0433\u0435\u043d \u043a\u04af\u043d-\u0430\u0439\u044b",
+ "HeaderFeatures": "\u041c\u04d9\u043b\u0456\u043c\u0435\u0442\u0442\u0435\u0440",
+ "HeaderAdvanced": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430",
+ "ButtonSync": "\u0421\u0438\u043d\u0445\u0440\u043e",
+ "TabScheduledTasks": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0443\u0448\u044b",
+ "HeaderChapters": "\u0421\u0430\u0445\u043d\u0430\u043b\u0430\u0440",
+ "HeaderResumeSettings": "\u0416\u0430\u043b\u0493\u0430\u0441\u0442\u044b\u0440\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440\u0456",
+ "TabSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443",
+ "TitleUsers": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440",
+ "LabelProtocol": "\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http \u0422\u0456\u043a\u0435\u043b\u0435\u0439 \u0410\u0493\u044b\u043d (HLS)",
+ "LabelContext": "\u041c\u04d9\u0442\u0456\u043d\u043c\u04d9\u043d:",
+ "OptionContextStreaming": "\u0410\u0493\u044b\u043d\u043c\u0435\u043d \u0442\u0430\u0441\u044b\u043c\u0430\u043b\u0434\u0430\u0443",
+ "OptionContextStatic": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443",
+ "ButtonAddToPlaylist": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0456\u043d\u0435 \u04af\u0441\u0442\u0435\u0443",
+ "TabPlaylists": "\u041e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0434\u0435\u0440\u0456",
+ "ButtonClose": "\u0416\u0430\u0431\u0443",
+ "LabelAllLanguages": "\u0411\u0430\u0440\u043b\u044b\u049b \u0442\u0456\u043b\u0434\u0435\u0440",
+ "HeaderBrowseOnlineImages": "\u0416\u0435\u043b\u0456\u043b\u0456\u043a \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0448\u043e\u043b\u0443",
+ "LabelSource": "\u049a\u0430\u0439\u043d\u0430\u0440 \u043a\u04e9\u0437\u0456:",
+ "OptionAll": "\u0411\u04d9\u0440\u0456",
+ "LabelImage": "\u0421\u0443\u0440\u0435\u0442:",
+ "ButtonBrowseImages": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0448\u043e\u043b\u0443",
+ "HeaderImages": "\u0421\u0443\u0440\u0435\u0442\u0442\u0435\u0440",
+ "HeaderBackdrops": "\u0410\u0440\u0442\u049b\u044b \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440",
+ "HeaderScreenshots": "\u042d\u043a\u0440\u0430\u043d \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456",
+ "HeaderAddUpdateImage": "\u0421\u0443\u0440\u0435\u0442\u0442\u0456 \u04af\u0441\u0442\u0435\u0443\/\u0436\u0430\u04a3\u0430\u0440\u0442\u0443",
+ "LabelJpgPngOnly": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 JPG\/PNG",
+ "LabelImageType": "\u0421\u0443\u0440\u0435\u0442 \u0442\u04af\u0440\u0456:",
+ "OptionPrimary": "\u0411\u0430\u0441\u0442\u0430\u043f\u049b\u044b",
+ "OptionArt": "\u041e\u044e \u0441\u0443\u0440\u0435\u0442",
+ "OptionBox": "\u049a\u043e\u0440\u0430\u043f",
+ "OptionBoxRear": "\u049a\u043e\u0440\u0430\u043f \u0430\u0440\u0442\u044b",
+ "OptionDisc": "\u0414\u0438\u0441\u043a\u0456",
+ "OptionLogo": "\u041b\u043e\u0433\u043e\u0442\u0438\u043f",
+ "OptionMenu": "\u041c\u04d9\u0437\u0456\u0440",
+ "OptionScreenshot": "\u042d\u043a\u0440\u0430\u043d \u0441\u0443\u0440\u0435\u0442\u0456",
+ "OptionLocked": "\u049a\u04b1\u0440\u0441\u0430\u0443\u043b\u0430\u043d\u0493\u0430\u043d\u0434\u0430\u0440",
+ "OptionUnidentified": "\u0410\u043d\u044b\u049b\u0442\u0430\u043b\u043c\u0430\u0493\u0430\u043d\u0434\u0430\u0440",
+ "OptionMissingParentalRating": "\u0416\u0430\u0441\u0442\u0430\u0441 \u0441\u0430\u043d\u0430\u0442 \u0436\u043e\u049b",
+ "OptionStub": "\u0422\u044b\u0493\u044b\u043d",
+ "HeaderEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440:",
+ "OptionSeason0": "0-\u043c\u0430\u0443\u0441\u044b\u043c",
+ "LabelReport": "\u0415\u0441\u0435\u043f:",
+ "OptionReportSongs": "\u04d8\u0443\u0435\u043d\u0434\u0435\u0440",
+ "OptionReportSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u0434\u0430\u0440",
+ "OptionReportSeasons": "\u041c\u0430\u0443\u0441\u044b\u043c\u0434\u0430\u0440",
+ "OptionReportTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440",
+ "OptionReportMusicVideos": "\u041a\u043b\u0438\u043f\u0442\u0435\u0440",
+ "OptionReportMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
+ "OptionReportHomeVideos": "\u04ae\u0439 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0456",
+ "OptionReportGames": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440",
+ "OptionReportEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440",
+ "OptionReportCollections": "\u0416\u0438\u043d\u0430\u049b\u0442\u0430\u0440",
+ "OptionReportBooks": "\u041a\u0456\u0442\u0430\u043f\u0442\u0430\u0440",
+ "OptionReportArtists": "\u041e\u0440\u044b\u043d\u0434\u0430\u0443\u0448\u044b\u043b\u0430\u0440",
+ "OptionReportAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u0434\u0430\u0440",
+ "OptionReportAdultVideos": "\u0415\u0440\u0435\u0441\u0435\u043a \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0456",
+ "ButtonMore": "\u041a\u04e9\u0431\u0456\u0440\u0435\u043a",
+ "HeaderActivity": "\u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0435\u0440",
+ "ScheduledTaskStartedWithName": "{0} \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0434\u044b",
+ "ScheduledTaskCancelledWithName": "{0} \u0431\u043e\u043b\u0434\u044b\u0440\u044b\u043b\u043c\u0430\u0434\u044b",
+ "ScheduledTaskCompletedWithName": "{0} \u0430\u044f\u049b\u0442\u0430\u043b\u0434\u044b",
+ "ScheduledTaskFailed": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0430\u044f\u049b\u0442\u0430\u043b\u0434\u044b",
+ "PluginInstalledWithName": "{0} \u043e\u0440\u043d\u0430\u0442\u044b\u043b\u0434\u044b",
+ "PluginUpdatedWithName": "{0} \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b",
+ "PluginUninstalledWithName": "{0} \u0436\u043e\u0439\u044b\u043b\u0434\u044b",
+ "ScheduledTaskFailedWithName": "{0} \u0441\u04d9\u0442\u0441\u0456\u0437",
+ "ItemAddedWithName": "{0} (\u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u0493\u0430 \u04af\u0441\u0442\u0435\u043b\u0456\u043d\u0434\u0456)",
+ "ItemRemovedWithName": "{0} (\u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u0434\u0430\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u043b\u0434\u044b)",
+ "DeviceOnlineWithName": "{0} \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d",
+ "UserOnlineFromDevice": "{0} - {1} \u0430\u0440\u049b\u044b\u043b\u044b \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d",
+ "DeviceOfflineWithName": "{0} \u0430\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u0493\u0430\u043d",
+ "UserOfflineFromDevice": "{0} - {1} \u0430\u0440\u049b\u044b\u043b\u044b \u0430\u0436\u044b\u0440\u0430\u0442\u044b\u043b\u0493\u0430\u043d",
+ "SubtitlesDownloadedForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 {0} \u04af\u0448\u0456\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0434\u044b",
+ "SubtitleDownloadFailureForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 {0} \u04af\u0448\u0456\u043d \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u044b\u043d\u0443\u044b \u0441\u04d9\u0442\u0441\u0456\u0437",
+ "LabelRunningTimeValue": "\u0406\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0443 \u0443\u0430\u049b\u044b\u0442\u044b: {0}",
+ "LabelIpAddressValue": "IP \u043c\u0435\u043a\u0435\u043d\u0436\u0430\u0439\u044b: {0}",
+ "UserConfigurationUpdatedWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u04af\u0448\u0456\u043d \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b",
+ "UserCreatedWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u0436\u0430\u0441\u0430\u043b\u0493\u0430\u043d",
+ "UserPasswordChangedWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u04af\u0448\u0456\u043d \u049b\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437 \u04e9\u0437\u0433\u0435\u0440\u0442\u0456\u043b\u0434\u0456",
+ "UserDeletedWithName": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b {0} \u0436\u043e\u0439\u044b\u043b\u0493\u0430\u043d",
+ "MessageServerConfigurationUpdated": "\u0421\u0435\u0440\u0432\u0435\u0440 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0441\u044b \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b",
+ "MessageNamedServerConfigurationUpdatedWithValue": "\u0421\u0435\u0440\u0432\u0435\u0440 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0441\u044b (\u0431\u04e9\u043b\u0456\u043c {0}) \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b",
+ "MessageApplicationUpdated": "Media Browser Server \u0436\u0430\u04a3\u0430\u0440\u0442\u044b\u043b\u0434\u044b",
+ "AuthenticationSucceededWithUserName": "{0} \u0442\u04af\u043f\u043d\u04b1\u0441\u049b\u0430\u043b\u044b\u0493\u044b\u043d \u0440\u0430\u0441\u0442\u0430\u043b\u0443\u044b \u0441\u04d9\u0442\u0442\u0456",
+ "FailedLoginAttemptWithUserName": "{0} \u043a\u0456\u0440\u0443 \u04d9\u0440\u0435\u043a\u0435\u0442\u0456 \u0441\u04d9\u0442\u0441\u0456\u0437",
+ "UserStartedPlayingItemWithValues": "{0} - {1} \u043e\u0439\u043d\u0430\u0442\u0443\u044b \u0431\u0430\u0441\u0442\u0430\u043b\u0434\u044b",
+ "UserStoppedPlayingItemWithValues": "{0} - {1} \u043e\u0439\u043d\u0430\u0442\u0443\u044b \u0442\u043e\u049b\u0442\u0430\u043b\u0434\u044b",
+ "AppDeviceValues": "\u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430: {0}, \u0416\u0430\u0431\u0434\u044b\u049b: {1}",
+ "ProviderValue": "\u0416\u0435\u0442\u043a\u0456\u0437\u0443\u0448\u0456: {0}",
+ "LabelChannelDownloadSizeLimit": "\u0416\u04af\u043a\u0442\u0435\u043c\u0435 \u04e9\u043b\u0448\u0435\u043c\u0456\u043d\u0456\u04a3 \u0448\u0435\u0433\u0456 (GB)",
+ "LabelChannelDownloadSizeLimitHelp": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440\u0434\u044b \u0436\u04af\u043a\u0442\u0435\u043f \u0430\u043b\u0443 \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d\u044b\u04a3 \u04e9\u043b\u0448\u0435\u043c\u0456\u043d \u0448\u0435\u043a\u0442\u0435\u0439\u0434\u0456",
+ "HeaderRecentActivity": "\u041a\u0435\u0438\u0456\u043d\u0433\u0456 \u04d9\u0440\u0435\u043a\u0435\u0442\u0442\u0435\u0440"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ko.json b/MediaBrowser.Server.Implementations/Localization/Server/ko.json
new file mode 100644
index 000000000..3a322eba7
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ko.json
@@ -0,0 +1,1098 @@
+{
+ "HeaderPeople": "People",
+ "LabelExit": "Schweinsteiger",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
+ "LabelVisitCommunity": "Visit Community",
+ "OptionComposers": "Composers",
+ "LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
+ "LabelSwagger": "Swagger",
+ "LabelStandard": "Standard",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
+ "LabelViewApiDocumentation": "View Api Documentation",
+ "ViewTypeFolders": "Folders",
+ "LabelBrowseLibrary": "Browse Library",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
+ "LabelConfigureMediaBrowser": "Configure Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
+ "LabelOpenLibraryViewer": "Open Library Viewer",
+ "ViewTypeLiveTvChannels": "Channels",
+ "LabelRestartServer": "Restart Server",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
+ "LabelShowLogWindow": "Show Log Window",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
+ "LabelPrevious": "Previous",
+ "HeaderPassword": "Password",
+ "LabelFinish": "Finish",
+ "HeaderLocalAccess": "Local Access",
+ "LabelNext": "Next",
+ "HeaderViewOrder": "View Order",
+ "LabelYoureDone": "You're Done!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
+ "WelcomeToMediaBrowser": "Welcome to Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
+ "TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
+ "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.",
+ "OptionDownloadMissingImages": "Download missing images",
+ "TellUsAboutYourself": "Tell us about yourself",
+ "OptionReplaceExistingImages": "Replace existing images",
+ "LabelYourFirstName": "Your first name:",
+ "OptionRefreshAllData": "Refresh all data",
+ "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.",
+ "OptionAddMissingDataOnly": "Add missing data only",
+ "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.",
+ "OptionLocalRefreshOnly": "Local refresh only",
+ "LabelWindowsService": "Windows Service",
+ "HeaderRefreshMetadata": "Refresh Metadata",
+ "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.",
+ "HeaderPersonInfo": "Person Info",
+ "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.",
+ "HeaderIdentifyItem": "Identify Item",
+ "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.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
+ "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Dashboard<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
+ "LabelConfigureSettings": "Configure settings",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
+ "LabelEnableVideoImageExtraction": "Enable video image extraction",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
+ "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.",
+ "ButtonIdentify": "Identify",
+ "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
+ "LabelAlbumArtist": "Album artist:",
+ "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelAlbum": "Album:",
+ "LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
+ "LabelCommunityRating": "Community rating:",
+ "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "LabelVoteCount": "Vote count:",
+ "ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
+ "ButtonCancel": "Cancel",
+ "LabelCriticRating": "Critic rating:",
+ "ButtonNew": "New",
+ "LabelCriticRatingSummary": "Critic rating summary:",
+ "HeaderSetupLibrary": "Setup your media library",
+ "LabelAwardSummary": "Award summary:",
+ "ButtonAddMediaFolder": "Add media folder",
+ "LabelWebsite": "Website:",
+ "LabelFolderType": "Folder type:",
+ "LabelTagline": "Tagline:",
+ "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
+ "LabelOverview": "Overview:",
+ "ReferToMediaLibraryWiki": "Refer to the media library wiki.",
+ "LabelShortOverview": "Short overview:",
+ "LabelCountry": "Country:",
+ "LabelReleaseDate": "Release date:",
+ "LabelLanguage": "Language:",
+ "LabelYear": "Year:",
+ "HeaderPreferredMetadataLanguage": "Preferred metadata language:",
+ "LabelPlaceOfBirth": "Place of birth:",
+ "LabelSaveLocalMetadata": "Save artwork and metadata into media folders",
+ "LabelEndDate": "End date:",
+ "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.",
+ "LabelAirDate": "Air days:",
+ "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet",
+ "LabelAirTime:": "Air time:",
+ "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
+ "TabPreferences": "Preferences",
+ "LabelParentalRating": "Parental rating:",
+ "TabPassword": "Password",
+ "LabelCustomRating": "Custom rating:",
+ "TabLibraryAccess": "Library Access",
+ "LabelBudget": "Budget",
+ "TabImage": "Image",
+ "LabelRevenue": "Revenue ($):",
+ "TabProfile": "Profile",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
+ "TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
+ "TabImages": "Images",
+ "Label3DFormat": "3D format:",
+ "TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
+ "TabCollectionTitles": "Titles",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
+ "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons",
+ "HeaderExternalIds": "External Id's:",
+ "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons",
+ "LabelDvdSeasonNumber": "Dvd season number:",
+ "HeaderVideoPlaybackSettings": "Video Playback Settings",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
+ "HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
+ "LabelAudioLanguagePreference": "Audio language preference:",
+ "LabelAirsBeforeSeason": "Airs before season:",
+ "LabelSubtitleLanguagePreference": "Subtitle language preference:",
+ "LabelAirsAfterSeason": "Airs after season:",
+ "OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
+ "OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
+ "OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
+ "OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
+ "OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
+ "OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
+ "OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
+ "OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
+ "TabProfiles": "Profiles",
+ "HeaderTags": "Tags",
+ "TabSecurity": "Security",
+ "HeaderMetadataSettings": "Metadata Settings",
+ "ButtonAddUser": "Add User",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
+ "ButtonSave": "Save",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
+ "ButtonResetPassword": "Reset Password",
+ "TabSupporterClub": "Supporter Club",
+ "LabelNewPassword": "New password:",
+ "HeaderDonationType": "Donation type:",
+ "LabelNewPasswordConfirm": "New password confirm:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
+ "HeaderCreatePassword": "Create Password",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
+ "LabelCurrentPassword": "Current password:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
+ "LabelMaxParentalRating": "Maximum allowed parental rating:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
+ "MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.",
+ "OptionNoTrailer": "No Trailer",
+ "LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.",
+ "OptionNoThemeSong": "No Theme Song",
+ "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
+ "ButtonDeleteImage": "Delete Image",
+ "LabelOneTimeDonationAmount": "Donation amount:",
+ "LabelSelectUsers": "Select users:",
+ "OptionActor": "Actor",
+ "ButtonUpload": "Upload",
+ "OptionComposer": "Composer",
+ "HeaderUploadNewImage": "Upload New Image",
+ "OptionDirector": "Director",
+ "LabelDropImageHere": "Drop image here",
+ "OptionGuestStar": "Guest star",
+ "ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.",
+ "OptionProducer": "Producer",
+ "MessageNothingHere": "Nothing here.",
+ "OptionWriter": "Writer",
+ "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
+ "LabelAirDays": "Air days:",
+ "TabSuggested": "Suggested",
+ "LabelAirTime": "Air time:",
+ "TabLatest": "Latest",
+ "HeaderMediaInfo": "Media Info",
+ "TabUpcoming": "Upcoming",
+ "HeaderPhotoInfo": "Photo Info",
+ "TabShows": "Shows",
+ "TabEpisodes": "Episodes",
+ "TabGenres": "Genres",
+ "TabPeople": "People",
+ "TabNetworks": "Networks",
+ "HeaderUsers": "Users",
+ "HeaderFilters": "Filters:",
+ "ButtonFilter": "Filter",
+ "OptionFavorite": "Favorites",
+ "OptionLikes": "Likes",
+ "OptionDislikes": "Dislikes",
+ "OptionActors": "Actors",
+ "OptionGuestStars": "Guest Stars",
+ "OptionDirectors": "Directors",
+ "OptionWriters": "Writers",
+ "OptionProducers": "Producers",
+ "HeaderResume": "Resume",
+ "HeaderNextUp": "Next Up",
+ "NoNextUpItemsMessage": "None found. Start watching your shows!",
+ "HeaderLatestEpisodes": "Latest Episodes",
+ "HeaderPersonTypes": "Person Types:",
+ "TabSongs": "Songs",
+ "TabAlbums": "Albums",
+ "TabArtists": "Artists",
+ "TabAlbumArtists": "Album Artists",
+ "TabMusicVideos": "Music Videos",
+ "ButtonSort": "Sort",
+ "HeaderSortBy": "Sort By:",
+ "HeaderSortOrder": "Sort Order:",
+ "OptionPlayed": "Played",
+ "OptionUnplayed": "Unplayed",
+ "OptionAscending": "Ascending",
+ "OptionDescending": "Descending",
+ "OptionRuntime": "Runtime",
+ "OptionReleaseDate": "Release Date",
+ "OptionPlayCount": "Play Count",
+ "OptionDatePlayed": "Date Played",
+ "OptionDateAdded": "Date Added",
+ "OptionAlbumArtist": "Album Artist",
+ "OptionArtist": "Artist",
+ "OptionAlbum": "Album",
+ "OptionTrackName": "Track Name",
+ "OptionCommunityRating": "Community Rating",
+ "OptionNameSort": "Name",
+ "OptionFolderSort": "Folders",
+ "OptionBudget": "Budget",
+ "OptionRevenue": "Revenue",
+ "OptionPoster": "Poster",
+ "OptionBackdrop": "Backdrop",
+ "OptionTimeline": "Timeline",
+ "OptionThumb": "Thumb",
+ "OptionBanner": "Banner",
+ "OptionCriticRating": "Critic Rating",
+ "OptionVideoBitrate": "Video Bitrate",
+ "OptionResumable": "Resumable",
+ "ScheduledTasksHelp": "Click a task to adjust its schedule.",
+ "ScheduledTasksTitle": "Scheduled Tasks",
+ "TabMyPlugins": "My Plugins",
+ "TabCatalog": "Catalog",
+ "PluginsTitle": "Plugins",
+ "HeaderAutomaticUpdates": "Automatic Updates",
+ "HeaderNowPlaying": "Now Playing",
+ "HeaderLatestAlbums": "Latest Albums",
+ "HeaderLatestSongs": "Latest Songs",
+ "HeaderRecentlyPlayed": "Recently Played",
+ "HeaderFrequentlyPlayed": "Frequently Played",
+ "DevBuildWarning": "Dev builds are the bleeding edge. Released often, these build have not been tested. The application may crash and entire features may not work at all.",
+ "LabelVideoType": "Video Type:",
+ "OptionBluray": "Bluray",
+ "OptionDvd": "Dvd",
+ "OptionIso": "Iso",
+ "Option3D": "3D",
+ "LabelFeatures": "Features:",
+ "LabelService": "Service:",
+ "LabelStatus": "Status:",
+ "LabelVersion": "Version:",
+ "LabelLastResult": "Last result:",
+ "OptionHasSubtitles": "Subtitles",
+ "OptionHasTrailer": "Trailer",
+ "OptionHasThemeSong": "Theme Song",
+ "OptionHasThemeVideo": "Theme Video",
+ "TabMovies": "Movies",
+ "TabStudios": "Studios",
+ "TabTrailers": "Trailers",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
+ "HeaderLatestMovies": "Latest Movies",
+ "HeaderLatestTrailers": "Latest Trailers",
+ "OptionHasSpecialFeatures": "Special Features",
+ "OptionImdbRating": "IMDb Rating",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPremiereDate": "Premiere Date",
+ "TabBasic": "Basic",
+ "TabAdvanced": "Advanced",
+ "HeaderStatus": "Status",
+ "OptionContinuing": "Continuing",
+ "OptionEnded": "Ended",
+ "HeaderAirDays": "Air Days",
+ "OptionSunday": "Sunday",
+ "OptionMonday": "Monday",
+ "OptionTuesday": "Tuesday",
+ "OptionWednesday": "Wednesday",
+ "OptionThursday": "Thursday",
+ "OptionFriday": "Friday",
+ "OptionSaturday": "Saturday",
+ "HeaderManagement": "Management",
+ "LabelManagement": "Management:",
+ "OptionMissingImdbId": "Missing IMDb Id",
+ "OptionMissingTvdbId": "Missing TheTVDB Id",
+ "OptionMissingOverview": "Missing Overview",
+ "OptionFileMetadataYearMismatch": "File\/Metadata Years Mismatched",
+ "TabGeneral": "General",
+ "TitleSupport": "Support",
+ "TabLog": "Log",
+ "TabAbout": "About",
+ "TabSupporterKey": "Supporter Key",
+ "TabBecomeSupporter": "Become a Supporter",
+ "MediaBrowserHasCommunity": "Media Browser has a thriving community of users and contributors.",
+ "CheckoutKnowledgeBase": "Check out our knowledge base to help you get the most out of Media Browser.",
+ "SearchKnowledgeBase": "Search the Knowledge Base",
+ "VisitTheCommunity": "Visit the Community",
+ "VisitMediaBrowserWebsite": "Visit the Media Browser Web Site",
+ "VisitMediaBrowserWebsiteLong": "Visit the Media Browser Web site to catch the latest news and keep up with the developer blog.",
+ "OptionHideUser": "Hide this user from login screens",
+ "OptionDisableUser": "Disable this user",
+ "OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.",
+ "HeaderAdvancedControl": "Advanced Control",
+ "LabelName": "Name:",
+ "OptionAllowUserToManageServer": "Allow this user to manage the server",
+ "HeaderFeatureAccess": "Feature Access",
+ "OptionAllowMediaPlayback": "Allow media playback",
+ "OptionAllowBrowsingLiveTv": "Allow browsing of live tv",
+ "OptionAllowDeleteLibraryContent": "Allow this user to delete library content",
+ "OptionAllowManageLiveTv": "Allow management of live tv recordings",
+ "OptionAllowRemoteControlOthers": "Allow this user to remote control other users",
+ "OptionMissingTmdbId": "Missing Tmdb Id",
+ "OptionIsHD": "HD",
+ "OptionIsSD": "SD",
+ "OptionMetascore": "Metascore",
+ "ButtonSelect": "Select",
+ "ButtonGroupVersions": "Group Versions",
+ "ButtonAddToCollection": "Add to Collection",
+ "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",
+ "TabTranscoding": "Transcoding",
+ "TitleAdvanced": "Advanced",
+ "LabelAutomaticUpdateLevel": "Automatic update level",
+ "OptionRelease": "Official Release",
+ "OptionBeta": "Beta",
+ "OptionDev": "Dev (Unstable)",
+ "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates",
+ "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods, when no users are active.",
+ "LabelEnableDebugLogging": "Enable debug logging",
+ "LabelRunServerAtStartup": "Run server at startup",
+ "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",
+ "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.",
+ "LabelImagesByNamePath": "Images by name path:",
+ "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.",
+ "LabelMetadataPath": "Metadata path:",
+ "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",
+ "HeaderExtractChapterImagesFor": "Extract chapter images for:",
+ "OptionMovies": "Movies",
+ "OptionEpisodes": "Episodes",
+ "OptionOtherVideos": "Other Videos",
+ "TitleMetadata": "Metadata",
+ "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv",
+ "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.",
+ "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
+ "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
+ "ExtractChapterImagesHelp": "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 when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelMetadataDownloadLanguage": "Preferred download language:",
+ "ButtonAutoScroll": "Auto-scroll",
+ "LabelImageSavingConvention": "Image saving convention:",
+ "LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
+ "OptionImageSavingStandard": "Standard - MB2",
+ "ButtonSignIn": "Sign In",
+ "TitleSignIn": "Sign In",
+ "HeaderPleaseSignIn": "Please sign in",
+ "LabelUser": "User:",
+ "LabelPassword": "Password:",
+ "ButtonManualLogin": "Manual Login",
+ "PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
+ "TabGuide": "Guide",
+ "TabChannels": "Channels",
+ "TabCollections": "Collections",
+ "HeaderChannels": "Channels",
+ "TabRecordings": "Recordings",
+ "TabScheduled": "Scheduled",
+ "TabSeries": "Series",
+ "TabFavorites": "Favorites",
+ "TabMyLibrary": "My Library",
+ "ButtonCancelRecording": "Cancel Recording",
+ "HeaderPrePostPadding": "Pre\/Post Padding",
+ "LabelPrePaddingMinutes": "Pre-padding minutes:",
+ "OptionPrePaddingRequired": "Pre-padding is required in order to record.",
+ "LabelPostPaddingMinutes": "Post-padding minutes:",
+ "OptionPostPaddingRequired": "Post-padding is required in order to record.",
+ "HeaderWhatsOnTV": "What's On",
+ "HeaderUpcomingTV": "Upcoming TV",
+ "TabStatus": "Status",
+ "TabSettings": "Settings",
+ "ButtonRefreshGuideData": "Refresh Guide Data",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
+ "OptionPriority": "Priority",
+ "OptionRecordOnAllChannels": "Record program on all channels",
+ "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderDays": "Days",
+ "HeaderActiveRecordings": "Active Recordings",
+ "HeaderLatestRecordings": "Latest Recordings",
+ "HeaderAllRecordings": "All Recordings",
+ "ButtonPlay": "Play",
+ "ButtonEdit": "Edit",
+ "ButtonRecord": "Record",
+ "ButtonDelete": "Delete",
+ "ButtonRemove": "Remove",
+ "OptionRecordSeries": "Record Series",
+ "HeaderDetails": "Details",
+ "TitleLiveTV": "Live TV",
+ "LabelNumberOfGuideDays": "Number of days of guide data to download:",
+ "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.",
+ "LabelActiveService": "Active Service:",
+ "LabelActiveServiceHelp": "Multiple tv plugins can be installed but only one can be active at a time.",
+ "OptionAutomatic": "Auto",
+ "LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
+ "LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
+ "LabelCustomizeOptionsPerMediaType": "Customize for media type:",
+ "OptionDownloadThumbImage": "Thumb",
+ "OptionDownloadMenuImage": "Menu",
+ "OptionDownloadLogoImage": "Logo",
+ "OptionDownloadBoxImage": "Box",
+ "OptionDownloadDiscImage": "Disc",
+ "OptionDownloadBannerImage": "Banner",
+ "OptionDownloadBackImage": "Back",
+ "OptionDownloadArtImage": "Art",
+ "OptionDownloadPrimaryImage": "Primary",
+ "HeaderFetchImages": "Fetch Images:",
+ "HeaderImageSettings": "Image Settings",
+ "TabOther": "Other",
+ "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
+ "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
+ "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
+ "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:",
+ "ButtonAddScheduledTaskTrigger": "Add Task Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Task Trigger",
+ "ButtonAdd": "Add",
+ "LabelTriggerType": "Trigger Type:",
+ "OptionDaily": "Daily",
+ "OptionWeekly": "Weekly",
+ "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:",
+ "HeaderTvTuners": "Tuners",
+ "HeaderGallery": "Gallery",
+ "HeaderLatestGames": "Latest Games",
+ "HeaderRecentlyPlayedGames": "Recently Played Games",
+ "TabGameSystems": "Game Systems",
+ "TitleMediaLibrary": "Media Library",
+ "TabFolders": "Folders",
+ "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",
+ "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",
+ "ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
+ "LabelMissing": "Missing",
+ "LabelOffline": "Offline",
+ "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",
+ "HeaderTo": "To",
+ "LabelFrom": "From:",
+ "LabelFromHelp": "Example: D:\\Movies (on the server)",
+ "LabelTo": "To:",
+ "LabelToHelp": "Example: \\\\MyServer\\Movies (a path clients can access)",
+ "ButtonAddPathSubstitution": "Add Substitution",
+ "OptionSpecialEpisode": "Specials",
+ "OptionMissingEpisode": "Missing Episodes",
+ "OptionUnairedEpisode": "Unaired Episodes",
+ "OptionEpisodeSortName": "Episode Sort Name",
+ "OptionSeriesSortName": "Series Name",
+ "OptionTvdbRating": "Tvdb Rating",
+ "HeaderTranscodingQualityPreference": "Transcoding Quality Preference:",
+ "OptionAutomaticTranscodingHelp": "The server will decide quality and speed",
+ "OptionHighSpeedTranscodingHelp": "Lower quality, but faster encoding",
+ "OptionHighQualityTranscodingHelp": "Higher quality, but slower encoding",
+ "OptionMaxQualityTranscodingHelp": "Best quality with slower encoding and high CPU usage",
+ "OptionHighSpeedTranscoding": "Higher speed",
+ "OptionHighQualityTranscoding": "Higher quality",
+ "OptionMaxQualityTranscoding": "Max quality",
+ "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging",
+ "OptionEnableDebugTranscodingLoggingHelp": "This will create very large log files and is only recommended as needed for troubleshooting purposes.",
+ "OptionUpscaling": "Allow clients to request upscaled video",
+ "OptionUpscalingHelp": "In some cases this will result in improved video quality but will increase CPU usage.",
+ "EditCollectionItemsHelp": "Add or remove any movies, series, albums, books or games you wish to group within this collection.",
+ "HeaderAddTitles": "Add Titles",
+ "LabelEnableDlnaPlayTo": "Enable DLNA Play To",
+ "LabelEnableDlnaPlayToHelp": "Media Browser can detect devices within your network and offer the ability to remote control them.",
+ "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging",
+ "LabelEnableDlnaDebugLoggingHelp": "This will create large log files and should only be used as needed for troubleshooting purposes.",
+ "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)",
+ "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Media Browser.",
+ "HeaderCustomDlnaProfiles": "Custom Profiles",
+ "HeaderSystemDlnaProfiles": "System Profiles",
+ "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.",
+ "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.",
+ "TitleDashboard": "Dashboard",
+ "TabHome": "Home",
+ "TabInfo": "Info",
+ "HeaderLinks": "Links",
+ "HeaderSystemPaths": "System Paths",
+ "LinkCommunity": "Community",
+ "LinkGithub": "Github",
+ "LinkApiDocumentation": "Api Documentation",
+ "LabelFriendlyServerName": "Friendly server name:",
+ "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.",
+ "LabelPreferredDisplayLanguage": "Preferred display language",
+ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.",
+ "LabelReadHowYouCanContribute": "Read about how you can contribute.",
+ "HeaderNewCollection": "New Collection",
+ "HeaderAddToCollection": "Add to Collection",
+ "ButtonSubmit": "Submit",
+ "NewCollectionNameExample": "Example: Star Wars Collection",
+ "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata",
+ "ButtonCreate": "Create",
+ "LabelHttpServerPortNumber": "Http server port number:",
+ "LabelWebSocketPortNumber": "Web socket port number:",
+ "LabelEnableAutomaticPortHelp": "UPnP allows automated router configuration for remote access. This may not work with some router models.",
+ "LabelExternalDDNS": "External DDNS:",
+ "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.",
+ "TabResume": "Resume",
+ "TabWeather": "Weather",
+ "TitleAppSettings": "App Settings",
+ "LabelMinResumePercentage": "Min resume percentage:",
+ "LabelMaxResumePercentage": "Max resume percentage:",
+ "LabelMinResumeDuration": "Min resume duration (seconds):",
+ "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time",
+ "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time",
+ "LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable",
+ "TitleAutoOrganize": "Auto-Organize",
+ "TabActivityLog": "Activity Log",
+ "HeaderName": "Name",
+ "HeaderDate": "Date",
+ "HeaderSource": "Source",
+ "HeaderDestination": "Destination",
+ "HeaderProgram": "Program",
+ "HeaderClients": "Clients",
+ "LabelCompleted": "Completed",
+ "LabelFailed": "Failed",
+ "LabelSkipped": "Skipped",
+ "HeaderEpisodeOrganization": "Episode Organization",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
+ "LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
+ "HeaderSupportTheTeam": "Support the Media Browser Team",
+ "LabelSupportAmount": "Amount (USD)",
+ "HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.",
+ "ButtonEnterSupporterKey": "Enter supporter key",
+ "DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.",
+ "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.",
+ "AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.",
+ "OptionEnableEpisodeOrganization": "Enable new episode organization",
+ "LabelWatchFolder": "Watch folder:",
+ "LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.",
+ "ButtonViewScheduledTasks": "View scheduled tasks",
+ "LabelMinFileSizeForOrganize": "Minimum file size (MB):",
+ "LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.",
+ "LabelSeasonFolderPattern": "Season folder pattern:",
+ "LabelSeasonZeroFolderName": "Season zero folder name:",
+ "HeaderEpisodeFilePattern": "Episode file pattern",
+ "LabelEpisodePattern": "Episode pattern:",
+ "LabelMultiEpisodePattern": "Multi-Episode pattern:",
+ "HeaderSupportedPatterns": "Supported Patterns",
+ "HeaderTerm": "Term",
+ "HeaderPattern": "Pattern",
+ "HeaderResult": "Result",
+ "LabelDeleteEmptyFolders": "Delete empty folders after organizing",
+ "LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.",
+ "LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:",
+ "LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt",
+ "OptionOverwriteExistingEpisodes": "Overwrite existing episodes",
+ "LabelTransferMethod": "Transfer method",
+ "OptionCopy": "Copy",
+ "OptionMove": "Move",
+ "LabelTransferMethodHelp": "Copy or move files from the watch folder",
+ "HeaderLatestNews": "Latest News",
+ "HeaderHelpImproveMediaBrowser": "Help Improve Media Browser",
+ "HeaderRunningTasks": "Running Tasks",
+ "HeaderActiveDevices": "Active Devices",
+ "HeaderPendingInstallations": "Pending Installations",
+ "HeaerServerInformation": "Server Information",
+ "ButtonRestartNow": "Restart Now",
+ "ButtonRestart": "Restart",
+ "ButtonShutdown": "Shutdown",
+ "ButtonUpdateNow": "Update Now",
+ "PleaseUpdateManually": "Please shutdown the server and update manually.",
+ "NewServerVersionAvailable": "A new version of Media Browser Server is available!",
+ "ServerUpToDate": "Media Browser Server is up to date",
+ "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.",
+ "LabelComponentsUpdated": "The following components have been installed or updated:",
+ "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.",
+ "LabelDownMixAudioScale": "Audio boost when downmixing:",
+ "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.",
+ "ButtonLinkKeys": "Link Keys",
+ "LabelOldSupporterKey": "Old supporter key",
+ "LabelNewSupporterKey": "New supporter key",
+ "HeaderMultipleKeyLinking": "Multiple Key Linking",
+ "MultipleKeyLinkingHelp": "If you have more than one supporter key, use this form to link the old key's registrations with your new one.",
+ "LabelCurrentEmailAddress": "Current email address",
+ "LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.",
+ "HeaderForgotKey": "Forgot Key",
+ "LabelEmailAddress": "Email address",
+ "LabelSupporterEmailAddress": "The email address that was used to purchase the key.",
+ "ButtonRetrieveKey": "Retrieve Key",
+ "LabelSupporterKey": "Supporter Key (paste from email)",
+ "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
+ "MessageInvalidKey": "Supporter key is missing or invalid.",
+ "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
+ "HeaderDisplaySettings": "Display Settings",
+ "TabPlayTo": "Play To",
+ "LabelEnableDlnaServer": "Enable Dlna server",
+ "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Media Browser content.",
+ "LabelEnableBlastAliveMessages": "Blast alive messages",
+ "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.",
+ "LabelBlastMessageInterval": "Alive message interval (seconds)",
+ "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.",
+ "LabelDefaultUser": "Default user:",
+ "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.",
+ "TitleDlna": "DLNA",
+ "TitleChannels": "Channels",
+ "HeaderServerSettings": "Server Settings",
+ "LabelWeatherDisplayLocation": "Weather display location:",
+ "LabelWeatherDisplayLocationHelp": "US zip code \/ City, State, Country \/ City, Country",
+ "LabelWeatherDisplayUnit": "Weather display unit:",
+ "OptionCelsius": "Celsius",
+ "OptionFahrenheit": "Fahrenheit",
+ "HeaderRequireManualLogin": "Require manual username entry for:",
+ "HeaderRequireManualLoginHelp": "When disabled clients may present a login screen with a visual selection of users.",
+ "OptionOtherApps": "Other apps",
+ "OptionMobileApps": "Mobile apps",
+ "HeaderNotificationList": "Click on a notification to configure it's sending options.",
+ "NotificationOptionApplicationUpdateAvailable": "Application update available",
+ "NotificationOptionApplicationUpdateInstalled": "Application update installed",
+ "NotificationOptionPluginUpdateInstalled": "Plugin update installed",
+ "NotificationOptionPluginInstalled": "Plugin installed",
+ "NotificationOptionPluginUninstalled": "Plugin uninstalled",
+ "NotificationOptionVideoPlayback": "Video playback started",
+ "NotificationOptionAudioPlayback": "Audio playback started",
+ "NotificationOptionGamePlayback": "Game playback started",
+ "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
+ "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
+ "NotificationOptionGamePlaybackStopped": "Game playback stopped",
+ "NotificationOptionTaskFailed": "Scheduled task failure",
+ "NotificationOptionInstallationFailed": "Installation failure",
+ "NotificationOptionNewLibraryContent": "New content added",
+ "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
+ "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.",
+ "NotificationOptionServerRestartRequired": "Server restart required",
+ "LabelNotificationEnabled": "Enable this notification",
+ "LabelMonitorUsers": "Monitor activity from:",
+ "LabelSendNotificationToUsers": "Send the notification to:",
+ "LabelUseNotificationServices": "Use the following services:",
+ "CategoryUser": "User",
+ "CategorySystem": "System",
+ "CategoryApplication": "Application",
+ "CategoryPlugin": "Plugin",
+ "LabelMessageTitle": "Message title:",
+ "LabelAvailableTokens": "Available tokens:",
+ "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.",
+ "OptionAllUsers": "All users",
+ "OptionAdminUsers": "Administrators",
+ "OptionCustomUsers": "Custom",
+ "ButtonArrowUp": "Up",
+ "ButtonArrowDown": "Down",
+ "ButtonArrowLeft": "Left",
+ "ButtonArrowRight": "Right",
+ "ButtonBack": "Back",
+ "ButtonInfo": "Info",
+ "ButtonOsd": "On screen display",
+ "ButtonPageUp": "Page Up",
+ "ButtonPageDown": "Page Down",
+ "PageAbbreviation": "PG",
+ "ButtonHome": "Home",
+ "ButtonSearch": "Search",
+ "ButtonSettings": "Settings",
+ "ButtonTakeScreenshot": "Capture Screenshot",
+ "ButtonLetterUp": "Letter Up",
+ "ButtonLetterDown": "Letter Down",
+ "PageButtonAbbreviation": "PG",
+ "LetterButtonAbbreviation": "A",
+ "TabNowPlaying": "Now Playing",
+ "TabNavigation": "Navigation",
+ "TabControls": "Controls",
+ "ButtonFullscreen": "Toggle fullscreen",
+ "ButtonScenes": "Scenes",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
+ "ButtonStop": "Stop",
+ "ButtonPause": "Pause",
+ "LabelGroupMoviesIntoCollections": "Group movies into collections",
+ "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.",
+ "NotificationOptionPluginError": "Plugin failure",
+ "ButtonVolumeUp": "Volume up",
+ "ButtonVolumeDown": "Volume down",
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
+ "LabelProfileContainer": "Container:",
+ "LabelProfileVideoCodecs": "Video codecs:",
+ "LabelProfileAudioCodecs": "Audio codecs:",
+ "LabelProfileCodecs": "Codecs:",
+ "HeaderDirectPlayProfile": "Direct Play Profile",
+ "HeaderTranscodingProfile": "Transcoding Profile",
+ "HeaderCodecProfile": "Codec Profile",
+ "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.",
+ "HeaderContainerProfile": "Container Profile",
+ "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.",
+ "OptionProfileVideo": "Video",
+ "OptionProfileAudio": "Audio",
+ "OptionProfileVideoAudio": "Video Audio",
+ "OptionProfilePhoto": "Photo",
+ "LabelUserLibrary": "User library:",
+ "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.",
+ "OptionPlainStorageFolders": "Display all folders as plain storage folders",
+ "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".",
+ "OptionPlainVideoItems": "Display all videos as plain video items",
+ "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".",
+ "LabelSupportedMediaTypes": "Supported Media Types:",
+ "TabIdentification": "Identification",
+ "TabDirectPlay": "Direct Play",
+ "TabContainers": "Containers",
+ "TabCodecs": "Codecs",
+ "TabResponses": "Responses",
+ "HeaderProfileInformation": "Profile Information",
+ "LabelEmbedAlbumArtDidl": "Embed album art in Didl",
+ "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.",
+ "LabelAlbumArtPN": "Album art PN:",
+ "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.",
+ "LabelAlbumArtMaxWidth": "Album art max width:",
+ "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "Album art max height:",
+ "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
+ "LabelIconMaxWidth": "Icon max width:",
+ "LabelIconMaxWidthHelp": "Max resolution of icons exposed via upnp:icon.",
+ "LabelIconMaxHeight": "Icon max height:",
+ "LabelIconMaxHeightHelp": "Max resolution of icons exposed via upnp:icon.",
+ "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.",
+ "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
+ "LabelMaxBitrate": "Max bitrate:",
+ "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
+ "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
+ "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
+ "LabelFriendlyName": "Friendly name",
+ "LabelManufacturer": "Manufacturer",
+ "LabelManufacturerUrl": "Manufacturer url",
+ "LabelModelName": "Model name",
+ "LabelModelNumber": "Model number",
+ "LabelModelDescription": "Model description",
+ "LabelModelUrl": "Model url",
+ "LabelSerialNumber": "Serial number",
+ "LabelDeviceDescription": "Device description",
+ "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.",
+ "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.",
+ "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.",
+ "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.",
+ "LabelXDlnaCap": "X-Dlna cap:",
+ "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.",
+ "LabelXDlnaDoc": "X-Dlna doc:",
+ "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.",
+ "LabelSonyAggregationFlags": "Sony aggregation flags:",
+ "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.",
+ "LabelTranscodingContainer": "Container:",
+ "LabelTranscodingVideoCodec": "Video codec:",
+ "LabelTranscodingVideoProfile": "Video profile:",
+ "LabelTranscodingAudioCodec": "Audio codec:",
+ "OptionEnableM2tsMode": "Enable M2ts mode",
+ "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.",
+ "OptionEstimateContentLength": "Estimate content length when transcoding",
+ "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.",
+ "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "Download subtitles for:",
+ "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "TabChapters": "Chapters",
+ "HeaderDownloadChaptersFor": "Download chapter names for:",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.",
+ "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
+ "LabelSubtitlePlaybackMode": "Subtitle mode:",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:",
+ "MessageNoAvailablePlugins": "No available plugins.",
+ "LabelDisplayPluginsFor": "Display plugins for:",
+ "PluginTabMediaBrowserClassic": "MB Classic",
+ "PluginTabMediaBrowserTheater": "MB Theater",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
+ "ValueSeriesNamePeriod": "Series.name",
+ "ValueSeriesNameUnderscore": "Series_name",
+ "ValueEpisodeNamePeriod": "Episode.name",
+ "ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
+ "HeaderTypeText": "Enter Text",
+ "LabelTypeText": "Text",
+ "HeaderSearchForSubtitles": "Search for Subtitles",
+ "MessageNoSubtitleSearchResultsFound": "No search results founds.",
+ "TabDisplay": "Display",
+ "TabLanguages": "Languages",
+ "TabWebClient": "Web Client",
+ "LabelEnableThemeSongs": "Enable theme songs",
+ "LabelEnableBackdrops": "Enable backdrops",
+ "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.",
+ "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.",
+ "HeaderHomePage": "Home Page",
+ "HeaderSettingsForThisDevice": "Settings for This Device",
+ "OptionAuto": "Auto",
+ "OptionYes": "Yes",
+ "OptionNo": "No",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
+ "OptionResumablemedia": "Resume",
+ "OptionLatestMedia": "Latest media",
+ "OptionLatestChannelMedia": "Latest channel items",
+ "HeaderLatestChannelItems": "Latest Channel Items",
+ "OptionNone": "None",
+ "HeaderLiveTv": "Live TV",
+ "HeaderReports": "Reports",
+ "HeaderMetadataManager": "Metadata Manager",
+ "HeaderPreferences": "Preferences",
+ "MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
+ "ButtonMarkRead": "Mark Read",
+ "OptionDefaultSort": "Default",
+ "OptionCommunityMostWatchedSort": "Most Watched",
+ "TabNextUp": "Next Up",
+ "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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
+ "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
+ "ButtonDismiss": "Dismiss",
+ "MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
+ "ButtonEditOtherUserPreferences": "Edit this user's personal preferences.",
+ "LabelChannelStreamQuality": "Preferred internet stream quality:",
+ "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.",
+ "OptionBestAvailableStreamQuality": "Best available",
+ "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:",
+ "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.",
+ "LabelChannelDownloadPath": "Channel content download path:",
+ "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.",
+ "LabelChannelDownloadAge": "Delete content after: (days)",
+ "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.",
+ "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.",
+ "LabelSelectCollection": "Select collection:",
+ "ViewTypeMovies": "Movies",
+ "ViewTypeTvShows": "TV",
+ "ViewTypeGames": "Games",
+ "ViewTypeMusic": "Music",
+ "ViewTypeBoxSets": "Collections",
+ "ViewTypeChannels": "Channels",
+ "ViewTypeLiveTV": "Live TV",
+ "HeaderOtherDisplaySettings": "Display Settings",
+ "HeaderMyViews": "My Views",
+ "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",
+ "TitleRemoteControl": "Remote Control",
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
+} \ 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 ff3ea24f1..0180f0060 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ms.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ms.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Updates",
- "HeaderUpdateLevel": "Update Level",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
- "HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Failed",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "HeaderMyLibrary": "My Library",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "Tutup",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "Melawat Masyarakat",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "Biasa",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "Melihat Dokumentasi Api",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "Imbas Pengumpulan",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "Konfigurasi Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "Open Library Viewer",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "Restart Server",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "Show Log Window",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "Sebelumnya",
+ "HeaderPassword": "Password",
"LabelFinish": "Habis",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "Seterusnya",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "Kamu Selesai!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "Welcome to Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "Tell us about yourself",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "Your first name:",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Windows Service",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.",
+ "HeaderIdentifyItem": "Identify Item",
"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.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Dashboard<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
"LabelConfigureSettings": "Configure settings",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Enable video image extraction",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"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.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Cancel",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "New",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Setup your media library",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "Add media folder",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Folder type:",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Refer to the media library wiki.",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "Country:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "Language:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "Preferred metadata language:",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "Save artwork and metadata into media folders",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "Download artwork and metadata from the internet",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "Preferences",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "Password",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "Library Access",
+ "LabelBudget": "Budget",
"TabImage": "Image",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "Profile",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "Images",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "Titles",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "Video Playback Settings",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "Audio language preference:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "Subtitle language preference:",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Profiles",
+ "HeaderTags": "Tags",
"TabSecurity": "Security",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "Add User",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "Save",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "Reset Password",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "New password:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "New password confirm:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "Create Password",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Current password:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "Maximum allowed parental rating:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "Delete Image",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "Select users:",
+ "OptionActor": "Actor",
"ButtonUpload": "Upload",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Upload New Image",
- "LabelDropImageHere": "Drop Image Here",
+ "OptionDirector": "Director",
+ "LabelDropImageHere": "Drop image here",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Nothing here.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Suggested",
+ "LabelAirTime": "Air time:",
"TabLatest": "Latest",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "Upcoming",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Shows",
"TabEpisodes": "Episodes",
"TabGenres": "Genres",
@@ -213,6 +275,8 @@
"TabMovies": "Movies",
"TabStudios": "Studios",
"TabTrailers": "Trailers",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "Latest Movies",
"HeaderLatestTrailers": "Latest Trailers",
"OptionHasSpecialFeatures": "Special Features",
@@ -224,7 +288,7 @@
"HeaderStatus": "Status",
"OptionContinuing": "Continuing",
"OptionEnded": "Ended",
- "HeaderAirDays": "Air Days:",
+ "HeaderAirDays": "Air Days",
"OptionSunday": "Sunday",
"OptionMonday": "Monday",
"OptionTuesday": "Tuesday",
@@ -232,7 +296,8 @@
"OptionThursday": "Thursday",
"OptionFriday": "Friday",
"OptionSaturday": "Saturday",
- "HeaderManagement": "Management:",
+ "HeaderManagement": "Management",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "Missing IMDb Id",
"OptionMissingTvdbId": "Missing TheTVDB Id",
"OptionMissingOverview": "Missing Overview",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "Select",
- "ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
@@ -290,13 +354,13 @@
"ButtonSelectDirectory": "Select Directory",
"LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.",
"LabelCachePath": "Cache path:",
- "LabelCachePathHelp": "This folder contains server cache files, such as images.",
+ "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.",
"LabelImagesByNamePath": "Images by name path:",
- "LabelImagesByNamePathHelp": "This folder contains actor, artist, genre and studio images.",
+ "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.",
"LabelMetadataPath": "Metadata path:",
- "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.",
+ "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.",
+ "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",
@@ -313,12 +377,12 @@
"LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.",
"LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
"LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
- "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "ExtractChapterImagesHelp": "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 when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
"LabelMetadataDownloadLanguage": "Preferred download language:",
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
- "OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
@@ -347,6 +411,8 @@
"TabStatus": "Status",
"TabSettings": "Settings",
"ButtonRefreshGuideData": "Refresh Guide Data",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
"OptionRecordOnAllChannels": "Record program on all channels",
"OptionRecordAnytime": "Record program at any time",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Cast & Crew",
"HeaderAdditionalParts": "Additional Parts",
"ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Missing",
"LabelOffline": "Offline",
"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.",
@@ -512,11 +579,13 @@
"HeaderProgram": "Program",
"HeaderClients": "Clients",
"LabelCompleted": "Completed",
+ "LabelFailed": "Failed",
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeasonNumber": "Season number",
- "LabelEpisodeNumber": "Episode number",
- "LabelEndingEpisodeNumber": "Ending episode number",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Enable this notification",
"LabelMonitorUsers": "Monitor activity from:",
"LabelSendNotificationToUsers": "Send the notification to:",
- "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.",
"LabelUseNotificationServices": "Use the following services:",
"CategoryUser": "User",
"CategorySystem": "System",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
"ButtonHome": "Home",
+ "ButtonSearch": "Search",
"ButtonSettings": "Settings",
"ButtonTakeScreenshot": "Capture Screenshot",
"ButtonLetterUp": "Letter Up",
@@ -661,6 +730,8 @@
"ButtonScenes": "Scenes",
"ButtonSubtitles": "Subtitles",
"ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Group movies into collections",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
"LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "Friendly name",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text",
"HeaderSearchForSubtitles": "Search for Subtitles",
@@ -796,13 +879,13 @@
"OptionAuto": "Auto",
"OptionYes": "Yes",
"OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferences",
"MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Mark Read",
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
"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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
"ButtonDismiss": "Dismiss",
"MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Display adult content",
"OptionLibraryFolders": "Media folders",
"TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 0f97aa95e..21236b292 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/nb.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/nb.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Oppdateringer",
- "HeaderUpdateLevel": "Oppdaterings-niv\u00e5",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
- "HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Failed",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "HeaderMyLibrary": "Mitt bibliotek",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "Exit",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "Bes\u00f8k oss",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "Standard",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "Se Api-dokumentasjon",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "Browse biblioteket",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "Konfigurer Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "\u00c5pne Biblioteket",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "Restart serveren",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "Se logg-vinduet",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "Forrige",
+ "HeaderPassword": "Password",
"LabelFinish": "Ferdig",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "neste",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "Ferdig!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "Velkommen til Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "Denne wizarden vil guide deg gjennom server-konfigurasjonen. For \u00e5 begynne, vennligst velg ditt foretrukne spr\u00e5k.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "Fortell om deg selv",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "Ditt fornavn",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "Du kan legge til flere brukere senere via Dashboard",
- "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.",
+ "OptionAddMissingDataOnly": "Add missing data only",
+ "UserProfilesIntro": "Media Browser inkluderer innebygd st\u00f8tte for bruker profiler som tilbyr brukere innstillinger for visning, avspillerstatus og begrensning p\u00e5 innhold.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Windows Service",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "Windows Service har blitt installert",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser Server kj\u00f8rer normalt som en desktop-applikasjon med et tray-ikon, men om du foretrekker at det kj\u00f8res som en bakgrunnsprosess, kan du i stedet starte den fra windows service control panel.",
- "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.",
- "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Dashboard<\/b>.",
+ "HeaderIdentifyItem": "Identify Item",
+ "WindowsServiceIntro2": "Hvis du bruker Windows, v\u00e6r oppmerksom p\u00e5 at det ikke kan kj\u00f8res samtidig som ikonet, slik at du trenger \u00e5 g\u00e5 ut av \"trayen\" for \u00e5 kj\u00f8re tjenesten. Tjenesten m\u00e5 ogs\u00e5 konfigureres med administratorrettigheter via kontrollpanelet. V\u00e6r oppmerksom p\u00e5 at p\u00e5 denne tiden tjenesten ikke er i stand til selv-oppdatering, s\u00e5 nye versjoner vil kreve manuell interaksjon.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
+ "WizardCompleted": "Det er alt vi trenger for n\u00e5. Media Browser har begynt \u00e5 samle informasjon om mediebiblioteket. Sjekk ut noen av v\u00e5re programmer, og klikk deretter p\u00e5 <b> Fullf\u00f8r <\/b> for \u00e5 se <b> Dashboard <\/b>.",
+ "HeaderConfirmDeletion": "Bekreft Kansellering",
"LabelConfigureSettings": "Konfigurer innstillinger",
- "LabelEnableVideoImageExtraction": "Enable video image extraction",
- "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.",
- "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
- "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
- "LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
- "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
+ "LabelEnableVideoImageExtraction": "Aktiver videobildet utvinning",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
+ "VideoImageExtractionHelp": "For videoer som ikke allerede har bilder, og at vi ikke klarer \u00e5 finne internettbilder for. Dette vil tilf\u00f8re noen ytterligere tid til den opprinnelige biblioteket s\u00f8king, men vil resultere i en mer tiltalende presentasjon.",
+ "ButtonIdentify": "Identify",
+ "LabelEnableChapterImageExtractionForMovies": "Pakk ut kapittelbilde utvinning for Filmer",
+ "LabelAlbumArtist": "Album artist:",
+ "LabelChapterImageExtractionForMoviesHelp": "Utpakking i kapittelbilder vil tillate kunder \u00e5 vise grafiske scenevalgmenyer. Prosessen kan v\u00e6re treg, cpu-intensive og kan kreve flere Gigabyte med plass. Den kj\u00f8rer som en nattlig planlagt oppgave p\u00e5 04.00 AM, selv om dette er konfigurerbart i planlagte oppgaver omr\u00e5det. Det er ikke anbefalt \u00e5 kj\u00f8re denne oppgaven il\u00f8pet av toppbelastede timer.",
+ "LabelAlbum": "Album:",
+ "LabelEnableAutomaticPortMapping": "Sl\u00e5 p\u00e5 automatisk port mapping",
+ "LabelCommunityRating": "Community rating:",
+ "LabelEnableAutomaticPortMappingHelp": "UPnP tillater automatiserte routere konfigurasjoner for enkel ekstern tilgang. Denne funksjonen s\u00f8ttes ikke av alle routere.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "avbryt",
- "ButtonNew": "New",
+ "LabelCriticRating": "Critic rating:",
+ "ButtonNew": "Ny",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Konfigurer media-biblioteket",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "Legg til media-mappe",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Mappe typpe",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* P\u00e5krever bruk av en plugin, e.g. GameBrowser or MB Bookshelf",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Se i media-bibliotek wikien",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "LAnd",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "Spr\u00e5k:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "Foretrukket spr\u00e5k for metadata",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "Lagre cover og metadata i medie-mappene",
- "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.",
+ "LabelEndDate": "End date:",
+ "LabelSaveLocalMetadataHelp": "Lagring av artwork og metadata direkte gjennom media mapper vil legge dem en plass hvor de lett kan editeres.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "Last ned cover og metadata fra internett",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "MEdia Browser kan laste ned informasjon om mediet for en rikere presentasjon",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "Innstillinger",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "Passord",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "Bibliotektilgang",
+ "LabelBudget": "Budget",
"TabImage": "Bilde",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "profil",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
- "TabImages": "Images",
- "TabNotifications": "Notifications",
- "TabCollectionTitles": "Titles",
+ "LabelPlayers": "Players:",
+ "TabImages": "Bilder",
+ "Label3DFormat": "3D format:",
+ "TabNotifications": "Varsliner",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
+ "TabCollectionTitles": "Titler",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Vis episoder som sesongen mangler",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Vis episoder som enn\u00e5 ikke har blitt sendt",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "Innstillinger for video-avspilling",
- "HeaderPlaybackSettings": "Playback Settings",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
+ "HeaderPlaybackSettings": "Avspillings Innstillinger",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "\u00d8nsket spr\u00e5k for lydspor:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "\u00d8nsket spr\u00e5k for undertekster:",
- "OptionDefaultSubtitles": "Default",
- "OptionOnlyForcedSubtitles": "Only forced subtitles",
- "OptionAlwaysPlaySubtitles": "Always play subtitles",
- "OptionNoSubtitles": "No Subtitles",
- "OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
- "OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
- "OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
- "OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "LabelAirsAfterSeason": "Airs after season:",
+ "OptionDefaultSubtitles": "Standard",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
+ "OptionOnlyForcedSubtitles": "Kun tvunget undertekster",
+ "LabelTreatImageAs": "Treat image as:",
+ "OptionAlwaysPlaySubtitles": "Alltid spill undertekster",
+ "LabelDisplayOrder": "Display order:",
+ "OptionNoSubtitles": "Ingen Undertekster",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
+ "OptionDefaultSubtitlesHelp": "Undertekster som matcher spr\u00e5kpreferansene vil bli lastet n\u00e5r lyd er i utenlandsk spr\u00e5k.",
+ "HeaderCountries": "Countries",
+ "OptionOnlyForcedSubtitlesHelp": "Kun undertekster marker som tvunget vil bli lastet.",
+ "HeaderGenres": "Genres",
+ "OptionAlwaysPlaySubtitlesHelp": "Undertekster som matcher spr\u00e5kets innstillinger vil bli lastet uavhengig lydens spr\u00e5k.",
+ "HeaderPlotKeywords": "Plot Keywords",
+ "OptionNoSubtitlesHelp": "Undertekster vil ikke bli lastet som standard.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Profiler",
+ "HeaderTags": "Tags",
"TabSecurity": "Sikkerhet",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "Ny bruker",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "lagre",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "Resett passord",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "Nytt passord",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "Bekreft nytt passord",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "Lag nytt passord",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "N\u00e5v\u00e6rende passord",
- "LabelMaxParentalRating": "Maximum allowed parental rating:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
+ "LabelMaxParentalRating": "Maks tillatt sensur.",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "Innhold med h\u00f8yere aldersgrense vil bli skjult for brukeren",
- "LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.",
- "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoTrailer": "No Trailer",
+ "LibraryAccessHelp": "Velg media mappe som skal deles med denne brukren. Administrator vil ha mulighet for \u00e5 endre alle mapper ved \u00e5 bruke metadata behandler.",
+ "OptionNoThemeSong": "No Theme Song",
+ "ChannelAccessHelp": "Velg kanaler som skal deler med denne brukeren. Administratorer har mulighet til \u00e5 editere p\u00e5 alle kanaler som benytter metadata behandleren.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "Slett bilde",
- "LabelSelectUsers": "Select users:",
+ "LabelOneTimeDonationAmount": "Donation amount:",
+ "LabelSelectUsers": "Velg brukere:",
+ "OptionActor": "Actor",
"ButtonUpload": "Last opp",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Last opp nytt bilde",
- "LabelDropImageHere": "Slipp bilde her",
- "ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.",
+ "OptionDirector": "Director",
+ "LabelDropImageHere": "Slipp bilde her.",
+ "OptionGuestStar": "Guest star",
+ "ImageUploadAspectRatioHelp": "1:1 aspekt ratio anbefales. Kun JPG\/PNG.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Ingeting her",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "P\u00e5se at nedlasting av internet-metadata er sl\u00e5tt p\u00e5",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Forslag",
+ "LabelAirTime": "Air time:",
"TabLatest": "Siste",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "Kommer",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Show",
"TabEpisodes": "Episoder",
"TabGenres": "Sjanger",
@@ -141,7 +203,7 @@
"OptionLikes": "Liker",
"OptionDislikes": "Misliker",
"OptionActors": "Skuespiller",
- "OptionGuestStars": "Guest Stars",
+ "OptionGuestStars": "Gjeste-opptredelser",
"OptionDirectors": "Regis\u00f8r",
"OptionWriters": "Manus",
"OptionProducers": "Produsent",
@@ -149,31 +211,31 @@
"HeaderNextUp": "Neste",
"NoNextUpItemsMessage": "Ingen funnet. Begyn \u00e5 se det du har",
"HeaderLatestEpisodes": "Nye episoder",
- "HeaderPersonTypes": "Person Types:",
+ "HeaderPersonTypes": "Person Typer:",
"TabSongs": "Sanger",
"TabAlbums": "Album",
"TabArtists": "Artister",
- "TabAlbumArtists": "Album Artists",
+ "TabAlbumArtists": "Album Artister",
"TabMusicVideos": "Musikk-videoer",
"ButtonSort": "Sorter",
"HeaderSortBy": "Sorter etter",
- "HeaderSortOrder": "Sort Order:",
+ "HeaderSortOrder": "Sorter Etter:",
"OptionPlayed": "Sett",
"OptionUnplayed": "Ikke sett",
"OptionAscending": "Oppover",
"OptionDescending": "Nedover",
"OptionRuntime": "Spilletid",
- "OptionReleaseDate": "Slipp-dato",
- "OptionPlayCount": "Play Count",
+ "OptionReleaseDate": "Release Date",
+ "OptionPlayCount": "Antall avspillinger",
"OptionDatePlayed": "Dato spilt",
"OptionDateAdded": "Dato lagt til",
"OptionAlbumArtist": "Album Artist",
"OptionArtist": "Artist",
"OptionAlbum": "Album",
"OptionTrackName": "L\u00e5navn",
- "OptionCommunityRating": "Community Rating",
+ "OptionCommunityRating": "Community Rangering",
"OptionNameSort": "Navn",
- "OptionFolderSort": "Folders",
+ "OptionFolderSort": "Mapper",
"OptionBudget": "Budsjett",
"OptionRevenue": "Inntjening",
"OptionPoster": "Poster",
@@ -181,50 +243,52 @@
"OptionTimeline": "Tidslinje",
"OptionThumb": "Thumb",
"OptionBanner": "Banner",
- "OptionCriticRating": "Critic Rating",
+ "OptionCriticRating": "Kritiker Vurdering",
"OptionVideoBitrate": "Video bitrate",
- "OptionResumable": "Resumable",
- "ScheduledTasksHelp": "Click a task to adjust its schedule.",
- "ScheduledTasksTitle": "Scheduled Tasks",
- "TabMyPlugins": "My Plugins",
+ "OptionResumable": "Fortsettelse",
+ "ScheduledTasksHelp": "Klikk p\u00e5 en oppgave for \u00e5 tilpasse tidsplan",
+ "ScheduledTasksTitle": "Tidsplan Oppgaver",
+ "TabMyPlugins": "Mine Plugins",
"TabCatalog": "Katalog",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Automatiske oppdateringer",
"HeaderNowPlaying": "Spiller n\u00e5",
"HeaderLatestAlbums": "Siste album",
- "HeaderLatestSongs": "siste l\u00e5ter",
+ "HeaderLatestSongs": "Siste l\u00e5ter",
"HeaderRecentlyPlayed": "Nylig avspilt",
"HeaderFrequentlyPlayed": "Ofte avspilt",
- "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.",
+ "DevBuildWarning": "Dev builds er \u00e5 anses som p\u00e5 kanten. Disse har ikke blitt testet. Dette vil kunne medf\u00f8re til at applikasjonen kan krasje og komplette funksjoner ikke fungerer.",
"LabelVideoType": "Video-type",
"OptionBluray": "Bluray",
"OptionDvd": "Dvd",
"OptionIso": "iso",
"Option3D": "3d",
- "LabelFeatures": "Features:",
+ "LabelFeatures": "Funksjoner:",
"LabelService": "Service:",
"LabelStatus": "Status:",
- "LabelVersion": "Version:",
- "LabelLastResult": "Last result:",
+ "LabelVersion": "Versjon:",
+ "LabelLastResult": "Siste resultat:",
"OptionHasSubtitles": "undertekster",
- "OptionHasTrailer": "trailer",
+ "OptionHasTrailer": "Trailer",
"OptionHasThemeSong": "Temasang",
"OptionHasThemeVideo": "Temavideo",
"TabMovies": "Filmer",
"TabStudios": "Studio",
"TabTrailers": "Trailere",
- "HeaderLatestMovies": "Latest Movies",
- "HeaderLatestTrailers": "Latest Trailers",
- "OptionHasSpecialFeatures": "Special Features",
- "OptionImdbRating": "IMDb Rating",
- "OptionParentalRating": "Parental Rating",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
+ "HeaderLatestMovies": "Siste Filmer",
+ "HeaderLatestTrailers": "Siste Trailers",
+ "OptionHasSpecialFeatures": "Spesial Funksjoner",
+ "OptionImdbRating": "IMDB Rangering",
+ "OptionParentalRating": "Foreldresensur",
"OptionPremiereDate": "premieredato",
"TabBasic": "Basic",
"TabAdvanced": "Avansert",
"HeaderStatus": "Status",
"OptionContinuing": "Fortsetter",
"OptionEnded": "Avsluttet",
- "HeaderAirDays": "Air Days:",
+ "HeaderAirDays": "Lanseringsdager",
"OptionSunday": "S\u00f8ndag",
"OptionMonday": "Mandag",
"OptionTuesday": "Tirsdag",
@@ -232,621 +296,803 @@
"OptionThursday": "Torsdag",
"OptionFriday": "Fredag",
"OptionSaturday": "L\u00f8rdag",
- "HeaderManagement": "Management:",
+ "HeaderManagement": "Strying",
+ "LabelManagement": "Administrasjon",
"OptionMissingImdbId": "Mangler IMDb id",
- "OptionMissingTvdbId": "Missing TheTVDB Id",
+ "OptionMissingTvdbId": "Mangler TVDB id",
"OptionMissingOverview": "Mangler oversikt",
- "OptionFileMetadataYearMismatch": "File\/Metadata Years Mismatched",
+ "OptionFileMetadataYearMismatch": "Fil\/Metadata \u00e5r Mismatch",
"TabGeneral": "Genrelt",
"TitleSupport": "Support",
"TabLog": "Logg",
"TabAbout": "Om",
"TabSupporterKey": "Supporter-n\u00f8kkel",
"TabBecomeSupporter": "Bli en supporter",
- "MediaBrowserHasCommunity": "Media Browser has a thriving community of users and contributors.",
- "CheckoutKnowledgeBase": "Check out our knowledge base to help you get the most out of Media Browser.",
+ "MediaBrowserHasCommunity": "Media Browser har ett blomstrende fellesskap av brukere og bidragsytere.",
+ "CheckoutKnowledgeBase": "Sjekk ut v\u00e5r kunnskaps base for \u00e5 hjelpe deg med \u00e5 f\u00e5 best utbytte av Media Browser",
"SearchKnowledgeBase": "S\u00f8k kunnskapsbasen",
"VisitTheCommunity": "Bes\u00f8k oss",
"VisitMediaBrowserWebsite": "Bes\u00f8k Media Browsers nettside",
- "VisitMediaBrowserWebsiteLong": "Visit the Media Browser Web site to catch the latest news and keep up with the developer blog.",
+ "VisitMediaBrowserWebsiteLong": "Bes\u00f8k Media Browser sin side for \u00e5 f\u00e5 de siste nyhetene og for \u00e5 f\u00f8lge med p\u00e5 utviklerbloggen.",
"OptionHideUser": "Skjul brukere fra logginn-skjermen",
"OptionDisableUser": "Deaktiver denne brukeren",
- "OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.",
- "HeaderAdvancedControl": "Advanced Control",
+ "OptionDisableUserHelp": "Hvis avsl\u00e5tt, serveren vil ikke godta noen forbindelser fra denne brukeren. eksisterende forbindelser vil bli br\u00e5tt avsluttet.",
+ "HeaderAdvancedControl": "Avansert Kontroll",
"LabelName": "Navn",
"OptionAllowUserToManageServer": "TIllatt denne brukeren \u00e5 administrere serveren",
- "HeaderFeatureAccess": "Feature Access",
+ "HeaderFeatureAccess": "Funksjon Tilgang",
"OptionAllowMediaPlayback": "Tillatt medieavspilling",
- "OptionAllowBrowsingLiveTv": "Allow browsing of live tv",
+ "OptionAllowBrowsingLiveTv": "Tillat surfing av Live TV",
"OptionAllowDeleteLibraryContent": "Tillatt denne brukeren \u00e5 slette bibliotek-elementer",
- "OptionAllowManageLiveTv": "Allow management of live tv recordings",
+ "OptionAllowManageLiveTv": "Tillat styring av Live TV opptak",
"OptionAllowRemoteControlOthers": "Tillatt denne brukeren \u00e5 fjernstyre andre",
- "OptionMissingTmdbId": "Missing Tmdb Id",
+ "OptionMissingTmdbId": "Mangler Tmdb id",
"OptionIsHD": "HD",
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
- "ButtonSelect": "Select",
- "ButtonSearch": "Search",
- "ButtonGroupVersions": "Group Versions",
- "ButtonAddToCollection": "Add to Collection",
- "PismoMessage": "Utilizing Pismo File Mount through a donated license.",
- "TangibleSoftwareMessage": "Utilizing Tangible Solutions Java\/C# converters through a donated license.",
+ "ButtonSelect": "Velg",
+ "ButtonGroupVersions": "Gruppe Versjoner",
+ "ButtonAddToCollection": "Legg Til I Samling",
+ "PismoMessage": "Utnytte Pismo File Mount gjennom en donert lisens.",
+ "TangibleSoftwareMessage": "Utnytte konkrete l\u00f8sninger Java \/ C # omformere gjennom en donert lisens.",
"HeaderCredits": "Credits",
- "PleaseSupportOtherProduces": "Please support other free products we utilize:",
- "VersionNumber": "Version {0}",
- "TabPaths": "Paths",
+ "PleaseSupportOtherProduces": "Vennligst gi st\u00f8tte til andre gratis produkter vi benytter:",
+ "VersionNumber": "Versjon {0}",
+ "TabPaths": "Stier",
"TabServer": "Server",
"TabTranscoding": "Transcoding",
- "TitleAdvanced": "Advanced",
- "LabelAutomaticUpdateLevel": "Automatic update level",
- "OptionRelease": "Sluppet",
+ "TitleAdvanced": "Avansert",
+ "LabelAutomaticUpdateLevel": "Automatisk oppdaterings niv\u00e5",
+ "OptionRelease": "Offisiell utgivelse",
"OptionBeta": "Beta",
"OptionDev": "Dev (Ustabil)",
- "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates",
- "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods, when no users are active.",
- "LabelEnableDebugLogging": "Enable debug logging",
- "LabelRunServerAtStartup": "Run server at startup",
- "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",
- "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.",
- "LabelCachePath": "Cache path:",
- "LabelCachePathHelp": "This folder contains server cache files, such as images.",
- "LabelImagesByNamePath": "Images by name path:",
- "LabelImagesByNamePathHelp": "This folder contains actor, artist, genre and studio images.",
- "LabelMetadataPath": "Metadata path:",
- "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.",
- "LabelTranscodingTempPath": "Transcoding temporary path:",
- "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder.",
- "TabBasics": "Basics",
+ "LabelAllowServerAutoRestart": "Tillat at serveren restartes automatisk for \u00e5 gjennomf\u00f8re oppdateringer",
+ "LabelAllowServerAutoRestartHelp": "Serveren vil kun restartes i inaktiv perioder, n\u00e5r ingen brukere er aktive.",
+ "LabelEnableDebugLogging": "Sl\u00e5 p\u00e5 debug logging.",
+ "LabelRunServerAtStartup": "Start server ved maskin-oppstart",
+ "LabelRunServerAtStartupHelp": "Dette vil starte ikonet ved oppstart av Windows. For \u00e5 starte Windows-tjeneste, fjerner du denne markering og kj\u00f8rer tjenesten fra kontrollpanelet i Windows. V\u00e6r oppmerksom p\u00e5 at du ikke kan kj\u00f8re begge p\u00e5 samme tid, s\u00e5 du m\u00e5 g\u00e5 ut av ikonet f\u00f8r du starter tjenesten.",
+ "ButtonSelectDirectory": "Velg Katalog",
+ "LabelCustomPaths": "Definer tilpasset stier hvor \u00f8nsket. La feltet s\u00e5 tomt for bruk av default innstillinger.",
+ "LabelCachePath": "Cache sti:",
+ "LabelCachePathHelp": "Definer en tilpasset lokalisering for server cashe filer, som bilder.",
+ "LabelImagesByNamePath": "Bilder etter navn sti:",
+ "LabelImagesByNamePathHelp": "Definer en tilpasset lokalisering for nedlastede skuespillere, sjanger og studio bilder.",
+ "LabelMetadataPath": "Metadata sti:",
+ "LabelMetadataPathHelp": "Definer en tilpasset lokalisering for nedlastede artwork og metadata, hvis ikke skjer lagring innen media mappene.",
+ "LabelTranscodingTempPath": "Transcoding midlertidig sti",
+ "LabelTranscodingTempPathHelp": "Denne mappen inneholder fungerende filer som blir brukt av transcoderen. Spesifiser en tilpasset sti eller la det st\u00e5 tomt for \u00e5 benytte serverens standard sti.",
+ "TabBasics": "Basic",
"TabTV": "TV",
- "TabGames": "Games",
- "TabMusic": "Music",
- "TabOthers": "Others",
- "HeaderExtractChapterImagesFor": "Extract chapter images for:",
- "OptionMovies": "Movies",
- "OptionEpisodes": "Episodes",
- "OptionOtherVideos": "Other Videos",
+ "TabGames": "Spill",
+ "TabMusic": "Musikk",
+ "TabOthers": "Andre",
+ "HeaderExtractChapterImagesFor": "Pakk ut kapittel bilder for:",
+ "OptionMovies": "Filmer",
+ "OptionEpisodes": "Episoder",
+ "OptionOtherVideos": "Andre Videoer",
"TitleMetadata": "Metadata",
- "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv",
- "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.",
- "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
- "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
- "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
- "LabelMetadataDownloadLanguage": "Preferred download language:",
+ "LabelAutomaticUpdatesFanart": "Aktiver automatisk oppdatering fra FanArt.tv",
+ "LabelAutomaticUpdatesTmdb": "Aktiver automatisk oppdateringer fra TheMovieDB.org",
+ "LabelAutomaticUpdatesTvdb": "Aktiver automatisk oppdateringer fra TheTVDB.com",
+ "LabelAutomaticUpdatesFanartHelp": "Hvis aktivert vil nye bilder bli nedlastet automatisk n\u00e5r de blir lagt til fanar.tv. Eksisterende bilder vil ikke bli erstattet.",
+ "LabelAutomaticUpdatesTmdbHelp": "Hvis aktivert vil nye bilder bli nedlastet automatisk n\u00e5r de blir lagt til i TheMovieDB.org. Ekisterende bilder vil ikke bli erstattet.",
+ "LabelAutomaticUpdatesTvdbHelp": "Hvis aktivert vil nye bilder bli nedlastet automatisk n\u00e5r de blir lagt til i TheTVDB.com. Ekisterende bilder vil ikke bli erstattet.",
+ "ExtractChapterImagesHelp": "Utpakking av kapittelbilder vil tillate kunder \u00e5 vise grafiske scenevalgmenyer. Prosessen kan v\u00e6re treg, cpu-intensive og kan kreve flere Gigabyte med plass. Det kj\u00f8rer n\u00e5r videoene blir oppdaget, og ogs\u00e5 som en nattlig planlagt oppgave p\u00e5 04.00 AM. Tidsplanen er konfigurerbart i planlagte oppgaver omr\u00e5det. Det er ikke anbefalt \u00e5 kj\u00f8re denne oppgaven ved toppbelastede timer.",
+ "LabelMetadataDownloadLanguage": "Foretrukket nedlastingsspr\u00e5k:",
"ButtonAutoScroll": "Auto-scroll",
- "LabelImageSavingConvention": "Image saving convention:",
- "LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
- "OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
+ "LabelImageSavingConvention": "Bilde besparende konvensjon:",
+ "LabelImageSavingConventionHelp": "Media Browser gjengjenner bilder fra de fleste media applikasjonene. Ved valg av dine nedlastings konvensjoner er nyttig hvis du i tillegg benytter andre produkter.",
+ "OptionImageSavingCompatible": "Kompatibel - Media Browser\/Xbmc\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
- "ButtonSignIn": "Sign In",
- "TitleSignIn": "Sign In",
- "HeaderPleaseSignIn": "Please sign in",
- "LabelUser": "User:",
- "LabelPassword": "Password:",
- "ButtonManualLogin": "Manual Login",
- "PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
+ "ButtonSignIn": "Logg inn",
+ "TitleSignIn": "Logg Inn",
+ "HeaderPleaseSignIn": "Vennligst Logg inn",
+ "LabelUser": "Bruker:",
+ "LabelPassword": "Passord:",
+ "ButtonManualLogin": "Manuell Login",
+ "PasswordLocalhostMessage": "Passord er ikke n\u00f8dvendig n\u00e5r du logger inn fra lokalhost.",
"TabGuide": "Guide",
- "TabChannels": "Channels",
- "TabCollections": "Collections",
- "HeaderChannels": "Channels",
- "TabRecordings": "Recordings",
- "TabScheduled": "Scheduled",
- "TabSeries": "Series",
- "TabFavorites": "Favorites",
- "TabMyLibrary": "My Library",
- "ButtonCancelRecording": "Cancel Recording",
+ "TabChannels": "Kanaler",
+ "TabCollections": "Samlinger",
+ "HeaderChannels": "Kanaler",
+ "TabRecordings": "Opptak",
+ "TabScheduled": "Planlagt",
+ "TabSeries": "Serier",
+ "TabFavorites": "Favoritter",
+ "TabMyLibrary": "Mitt Bibliotek",
+ "ButtonCancelRecording": "Avbryt Opptak",
"HeaderPrePostPadding": "Pre\/Post Padding",
- "LabelPrePaddingMinutes": "Pre-padding minutes:",
- "OptionPrePaddingRequired": "Pre-padding is required in order to record.",
- "LabelPostPaddingMinutes": "Post-padding minutes:",
- "OptionPostPaddingRequired": "Post-padding is required in order to record.",
- "HeaderWhatsOnTV": "What's On",
- "HeaderUpcomingTV": "Upcoming TV",
+ "LabelPrePaddingMinutes": "Pre-padding minutter:",
+ "OptionPrePaddingRequired": "Pre-padding beh\u00f8ves for \u00e5 kunne gj\u00f8re opptak",
+ "LabelPostPaddingMinutes": "post-padding minutter:",
+ "OptionPostPaddingRequired": "Post-padding beh\u00f8ves for \u00e5 kunne gj\u00f8re opptak.",
+ "HeaderWhatsOnTV": "Hva er p\u00e5",
+ "HeaderUpcomingTV": "Kommende TV",
"TabStatus": "Status",
- "TabSettings": "Settings",
- "ButtonRefreshGuideData": "Refresh Guide Data",
- "OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
- "OptionRecordOnlyNewEpisodes": "Record only new episodes",
- "HeaderDays": "Days",
- "HeaderActiveRecordings": "Active Recordings",
- "HeaderLatestRecordings": "Latest Recordings",
- "HeaderAllRecordings": "All Recordings",
- "ButtonPlay": "Play",
- "ButtonEdit": "Edit",
- "ButtonRecord": "Record",
- "ButtonDelete": "Delete",
- "ButtonRemove": "Remove",
- "OptionRecordSeries": "Record Series",
- "HeaderDetails": "Details",
+ "TabSettings": "Innstillinger",
+ "ButtonRefreshGuideData": "Oppdater Guide Data",
+ "ButtonRefresh": "Oppdater",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
+ "OptionPriority": "Prioritet",
+ "OptionRecordOnAllChannels": "Ta opptak p\u00e5 alle kanaler",
+ "OptionRecordAnytime": "Ta opptak n\u00e5r som helst",
+ "OptionRecordOnlyNewEpisodes": "Ta opptak kun av nye episoder",
+ "HeaderDays": "Dager",
+ "HeaderActiveRecordings": "Aktive opptak",
+ "HeaderLatestRecordings": "Siste Opptak",
+ "HeaderAllRecordings": "Alle Opptak",
+ "ButtonPlay": "Spill",
+ "ButtonEdit": "Rediger",
+ "ButtonRecord": "Opptak",
+ "ButtonDelete": "Slett",
+ "ButtonRemove": "Fjern",
+ "OptionRecordSeries": "Ta opptak av Serier",
+ "HeaderDetails": "Detaljer",
"TitleLiveTV": "Live TV",
- "LabelNumberOfGuideDays": "Number of days of guide data to download:",
- "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.",
- "LabelActiveService": "Active Service:",
- "LabelActiveServiceHelp": "Multiple tv plugins can be installed but only one can be active at a time.",
+ "LabelNumberOfGuideDays": "Antall dager av guide data som skal lastes ned",
+ "LabelNumberOfGuideDaysHelp": "Nedlasting av guide data for flere dager gir muligheten for \u00e5 planlegge i forveien og for \u00e5 se flere listinger. Dette vil ogs\u00e5 ta lengre tid for nedlasting. Auto vil velge basert p\u00e5 antall kanaler.",
+ "LabelActiveService": "Aktive Tjenester:",
+ "LabelActiveServiceHelp": "Flere TV plugins kan bli installert, men kun en kan v\u00e6re aktiv.",
"OptionAutomatic": "Auto",
- "LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
- "LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
- "LabelCustomizeOptionsPerMediaType": "Customize for media type:",
+ "LiveTvPluginRequired": "En Live TV tilbyder trengs for \u00e5 kunne fortsette.",
+ "LiveTvPluginRequiredHelp": "Vennligst installer en av v\u00e5re tilgjengelige plugins, eksempel Next Pvr eller ServerWmc.",
+ "LabelCustomizeOptionsPerMediaType": "Tilpass for media type:",
"OptionDownloadThumbImage": "Thumb",
- "OptionDownloadMenuImage": "Menu",
+ "OptionDownloadMenuImage": "Meny",
"OptionDownloadLogoImage": "Logo",
- "OptionDownloadBoxImage": "Box",
- "OptionDownloadDiscImage": "Disc",
+ "OptionDownloadBoxImage": "Boks",
+ "OptionDownloadDiscImage": "Disk",
"OptionDownloadBannerImage": "Banner",
- "OptionDownloadBackImage": "Back",
+ "OptionDownloadBackImage": "Tilbake",
"OptionDownloadArtImage": "Art",
- "OptionDownloadPrimaryImage": "Primary",
- "HeaderFetchImages": "Fetch Images:",
- "HeaderImageSettings": "Image Settings",
- "TabOther": "Other",
- "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
- "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
- "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
- "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:",
- "ButtonAddScheduledTaskTrigger": "Add Task Trigger",
- "HeaderAddScheduledTaskTrigger": "Add Task Trigger",
- "ButtonAdd": "Add",
+ "OptionDownloadPrimaryImage": "Prim\u00e6r",
+ "HeaderFetchImages": "Hent Bilder:",
+ "HeaderImageSettings": "Bilde Innstillinger",
+ "TabOther": "Andre",
+ "LabelMaxBackdropsPerItem": "Maks antall av backdrops for hvert element:",
+ "LabelMaxScreenshotsPerItem": "Maks antall av screenshots for hvert element:",
+ "LabelMinBackdropDownloadWidth": "Minimum backdrop nedlastings bredde:",
+ "LabelMinScreenshotDownloadWidth": "Minimum nedlasted screenshot bredde:",
+ "ButtonAddScheduledTaskTrigger": "Legg Til Oppgave Trigger",
+ "HeaderAddScheduledTaskTrigger": "Legg til Oppgave Trigger",
+ "ButtonAdd": "Legg Til",
"LabelTriggerType": "Trigger Type:",
- "OptionDaily": "Daily",
- "OptionWeekly": "Weekly",
- "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:",
- "HeaderTvTuners": "Tuners",
- "HeaderGallery": "Gallery",
- "HeaderLatestGames": "Latest Games",
- "HeaderRecentlyPlayedGames": "Recently Played Games",
- "TabGameSystems": "Game Systems",
+ "OptionDaily": "Daglig",
+ "OptionWeekly": "Ukentlig",
+ "OptionOnInterval": "P\u00e5 ett intervall",
+ "OptionOnAppStartup": "Ved applikasjon oppstart",
+ "OptionAfterSystemEvent": "Etter ett system hendelse",
+ "LabelDay": "Dag:",
+ "LabelTime": "Tid:",
+ "LabelEvent": "Hendelse:",
+ "OptionWakeFromSleep": "V\u00e5kne fra dvale",
+ "LabelEveryXMinutes": "Hver",
+ "HeaderTvTuners": "Tunere",
+ "HeaderGallery": "Galleri",
+ "HeaderLatestGames": "Siste Spill",
+ "HeaderRecentlyPlayedGames": "Nylig Spilte Spill",
+ "TabGameSystems": "Spill Systemer",
"TitleMediaLibrary": "Media-bibliotek",
- "TabFolders": "Folders",
- "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",
+ "TabFolders": "Mapper",
+ "TabPathSubstitution": "Sti Erstatter",
+ "LabelSeasonZeroDisplayName": "Sesong 0 visningsnavn",
+ "LabelEnableRealtimeMonitor": "Aktiver sanntids monitorering",
+ "LabelEnableRealtimeMonitorHelp": "Endinger vil bli prossesert umiddelbart, til st\u00f8ttede file systemer.",
+ "ButtonScanLibrary": "S\u00f8k Gjennom Bibliotek",
+ "HeaderNumberOfPlayers": "Spillere:",
+ "OptionAnyNumberOfPlayers": "Noen",
"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",
- "ButtonSplitVersionsApart": "Split Versions Apart",
- "LabelMissing": "Missing",
+ "HeaderMediaFolders": "Media Mapper",
+ "HeaderThemeVideos": "Tema Videoer",
+ "HeaderThemeSongs": "Tema Sanger",
+ "HeaderScenes": "Scener",
+ "HeaderAwardsAndReviews": "Utmerkelser og anmeldsler",
+ "HeaderSoundtracks": "Lydspor",
+ "HeaderMusicVideos": "Musikk Videoer",
+ "HeaderSpecialFeatures": "Spesielle Funksjoner",
+ "HeaderCastCrew": "Mannskap",
+ "HeaderAdditionalParts": "Tilleggsdeler",
+ "ButtonSplitVersionsApart": "Splitt versjoner fra hverandre",
+ "ButtonPlayTrailer": "Trailer",
+ "LabelMissing": "Mangler",
"LabelOffline": "Offline",
- "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",
- "HeaderTo": "To",
- "LabelFrom": "From:",
- "LabelFromHelp": "Example: D:\\Movies (on the server)",
- "LabelTo": "To:",
- "LabelToHelp": "Example: \\\\MyServer\\Movies (a path clients can access)",
- "ButtonAddPathSubstitution": "Add Substitution",
- "OptionSpecialEpisode": "Specials",
- "OptionMissingEpisode": "Missing Episodes",
- "OptionUnairedEpisode": "Unaired Episodes",
- "OptionEpisodeSortName": "Episode Sort Name",
- "OptionSeriesSortName": "Series Name",
- "OptionTvdbRating": "Tvdb Rating",
+ "PathSubstitutionHelp": "Sti erstatninger er brukt for \u00e5 kartlegge en bane p\u00e5 serveren til en bane som kundene er i stand til \u00e5 f\u00e5 tilgang. Ved \u00e5 la kundene direkte tilgang til media p\u00e5 serveren kan de v\u00e6re i stand til \u00e5 spille dem direkte over nettverket, og unng\u00e5 \u00e5 bruke server ressurser til \u00e5 streame og omkode dem.",
+ "HeaderFrom": "Fra",
+ "HeaderTo": "Til",
+ "LabelFrom": "Fra:",
+ "LabelFromHelp": "Eksempel: D:\\Filmer (P\u00e5 serveren)",
+ "LabelTo": "Til:",
+ "LabelToHelp": "Eksempel: \\\\MinServerFilmer (en sti som klienter kan f\u00e5 tilgang til)",
+ "ButtonAddPathSubstitution": "Legg til substutisjon",
+ "OptionSpecialEpisode": "Spesielle",
+ "OptionMissingEpisode": "Mangler Episoder",
+ "OptionUnairedEpisode": "Kommende Episoder",
+ "OptionEpisodeSortName": "Episode Etter Navn",
+ "OptionSeriesSortName": "Serie Navn",
+ "OptionTvdbRating": "Tvdb Rangering",
"HeaderTranscodingQualityPreference": "\u00d8nsket kvalitet for transkoding",
- "OptionAutomaticTranscodingHelp": "The server will decide quality and speed",
- "OptionHighSpeedTranscodingHelp": "Lower quality, but faster encoding",
- "OptionHighQualityTranscodingHelp": "Higher quality, but slower encoding",
- "OptionMaxQualityTranscodingHelp": "Best quality with slower encoding and high CPU usage",
- "OptionHighSpeedTranscoding": "Higher speed",
- "OptionHighQualityTranscoding": "Higher quality",
- "OptionMaxQualityTranscoding": "Max quality",
- "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging",
- "OptionEnableDebugTranscodingLoggingHelp": "This will create very large log files and is only recommended as needed for troubleshooting purposes.",
- "OptionUpscaling": "Allow clients to request upscaled video",
- "OptionUpscalingHelp": "In some cases this will result in improved video quality but will increase CPU usage.",
- "EditCollectionItemsHelp": "Add or remove any movies, series, albums, books or games you wish to group within this collection.",
- "HeaderAddTitles": "Add Titles",
- "LabelEnableDlnaPlayTo": "Enable DLNA Play To",
- "LabelEnableDlnaPlayToHelp": "Media Browser can detect devices within your network and offer the ability to remote control them.",
- "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging",
- "LabelEnableDlnaDebugLoggingHelp": "This will create large log files and should only be used as needed for troubleshooting purposes.",
- "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)",
- "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Media Browser.",
- "HeaderCustomDlnaProfiles": "Custom Profiles",
- "HeaderSystemDlnaProfiles": "System Profiles",
- "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.",
- "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.",
- "TitleDashboard": "Dashboard",
- "TabHome": "Home",
+ "OptionAutomaticTranscodingHelp": "Serveren vil bestemme kvalitet og hastighet",
+ "OptionHighSpeedTranscodingHelp": "Lavere kvalitet, men raskere encoding",
+ "OptionHighQualityTranscodingHelp": "H\u00f8yere kvalitet, men saktere encoding",
+ "OptionMaxQualityTranscodingHelp": "Beste kvalitet med saktere encoding og h\u00f8y CPU bruk",
+ "OptionHighSpeedTranscoding": "H\u00f8yere hastighet",
+ "OptionHighQualityTranscoding": "H\u00f8yere kvalitet",
+ "OptionMaxQualityTranscoding": "Maks kvalitet",
+ "OptionEnableDebugTranscodingLogging": "Sl\u00e5 p\u00e5 debug transcoding logging",
+ "OptionEnableDebugTranscodingLoggingHelp": "Dette vil lage veldig lange log filer og er kun anbefalt for feils\u00f8king.",
+ "OptionUpscaling": "Tillat klienter \u00e5 gi foresp\u00f8rsler for oppskalert video",
+ "OptionUpscalingHelp": "I noen tilfeller f\u00f8rer dette til resultat i forbedret video kvalitet men vil \u00f8ke CPU bruk.",
+ "EditCollectionItemsHelp": "Legg til eller fjern hvilken som helst film, serie, album, bok eller spill som du \u00f8nsker \u00e5 gruppere innen denne samlingen.",
+ "HeaderAddTitles": "Legg til Titler",
+ "LabelEnableDlnaPlayTo": "Sl\u00e5 p\u00e5 DLNA Play To",
+ "LabelEnableDlnaPlayToHelp": "Media Browser kan detektere enheter innen ditt nettverk og tilbyr mulighetene til \u00e5 kunne gi ekstern tilgang for \u00e5 kontrollere enhetene.",
+ "LabelEnableDlnaDebugLogging": "Sl\u00e5 p\u00e5 DLNA debug logging",
+ "LabelEnableDlnaDebugLoggingHelp": "Dette vil lage store log filer og burde kun benyttes for feils\u00f8king.",
+ "LabelEnableDlnaClientDiscoveryInterval": "Klient oppdaterings interval (Sekunder)",
+ "LabelEnableDlnaClientDiscoveryIntervalHelp": "Bestemmer varigheten i sekunder mellom SSDP s\u00f8k utf\u00f8rt av Media Browser.",
+ "HeaderCustomDlnaProfiles": "Tilpassede Profiler",
+ "HeaderSystemDlnaProfiles": "System Profiler",
+ "CustomDlnaProfilesHelp": "Lag en tilpasset profil for \u00e5 sette en ny enhet til \u00e5 overkj\u00f8re en system profil.",
+ "SystemDlnaProfilesHelp": "System profiler er read-only. Endinger til ett system profil vil bli lagret til en ny tilpasset profil.",
+ "TitleDashboard": "Dashbord",
+ "TabHome": "Hjem",
"TabInfo": "Info",
- "HeaderLinks": "Links",
- "HeaderSystemPaths": "System Paths",
- "LinkCommunity": "Community",
+ "HeaderLinks": "Linker",
+ "HeaderSystemPaths": "System Stier",
+ "LinkCommunity": "Samfunn",
"LinkGithub": "Github",
- "LinkApiDocumentation": "Api Documentation",
- "LabelFriendlyServerName": "Friendly server name:",
- "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.",
- "LabelPreferredDisplayLanguage": "Preferred display language",
- "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.",
- "LabelReadHowYouCanContribute": "Read about how you can contribute.",
- "HeaderNewCollection": "New Collection",
- "HeaderAddToCollection": "Add to Collection",
- "ButtonSubmit": "Submit",
- "NewCollectionNameExample": "Example: Star Wars Collection",
- "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata",
- "ButtonCreate": "Create",
- "LabelHttpServerPortNumber": "Http server port number:",
- "LabelWebSocketPortNumber": "Web socket port number:",
- "LabelEnableAutomaticPortHelp": "UPnP allows automated router configuration for remote access. This may not work with some router models.",
- "LabelExternalDDNS": "External DDNS:",
- "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.",
- "TabResume": "Resume",
- "TabWeather": "Weather",
- "TitleAppSettings": "App Settings",
- "LabelMinResumePercentage": "Min resume percentage:",
- "LabelMaxResumePercentage": "Max resume percentage:",
- "LabelMinResumeDuration": "Min resume duration (seconds):",
- "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time",
- "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time",
- "LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable",
- "TitleAutoOrganize": "Auto-Organize",
- "TabActivityLog": "Activity Log",
- "HeaderName": "Name",
- "HeaderDate": "Date",
- "HeaderSource": "Source",
- "HeaderDestination": "Destination",
+ "LinkApiDocumentation": "Api Dokumentering",
+ "LabelFriendlyServerName": "Vennlig server navn:",
+ "LabelFriendlyServerNameHelp": "Dette navnet vil bli brukt for \u00e5 identifisere denne serveren. Hvis feltet er tomt, vil maskinens navn bli brukt.",
+ "LabelPreferredDisplayLanguage": "Foretrukket visningsspr\u00e5k",
+ "LabelPreferredDisplayLanguageHelp": "Oversetting av Media Browser er ett p\u00e5g\u00e5ende prosjekt og er enda ikke fullstendig ferdig.",
+ "LabelReadHowYouCanContribute": "Les mer om hvordan du kan bidra.",
+ "HeaderNewCollection": "Ny Samling",
+ "HeaderAddToCollection": "Legg Til I Samling",
+ "ButtonSubmit": "Send",
+ "NewCollectionNameExample": "Eksempel: Star Wars Samling",
+ "OptionSearchForInternetMetadata": "S\u00f8k p\u00e5 internet for artwork og metadata",
+ "ButtonCreate": "Opprett",
+ "LabelHttpServerPortNumber": "Http server port nummer:",
+ "LabelWebSocketPortNumber": "Web socker port nummer:",
+ "LabelEnableAutomaticPortHelp": "UPnP tillater automatiserte routere konfigurering for ekstern tilgang. Dette fungerer n\u00f8dvendigvis ikke p\u00e5 alle modeller.",
+ "LabelExternalDDNS": "Ekstern DDNS:",
+ "LabelExternalDDNSHelp": "Hvis du har en dynamisk DNS, skriv den her. Media Browser applikasjoner vil bruke denne n\u00e5r ekstern forbindelse opprettes.",
+ "TabResume": "Forsett",
+ "TabWeather": "V\u00e6r",
+ "TitleAppSettings": "App Innstillinger",
+ "LabelMinResumePercentage": "Minimum fortsettelses prosent:",
+ "LabelMaxResumePercentage": "Maksimum fortsettelses prosent:",
+ "LabelMinResumeDuration": "Minmimum fortsettelses varighet (sekunder)",
+ "LabelMinResumePercentageHelp": "Titler blir antatt som ikke avspilt hvis de stopper f\u00f8r denne tiden",
+ "LabelMaxResumePercentageHelp": "Titler blir antatt som fullstendig avspilt hvis de stopper etter denne tiden",
+ "LabelMinResumeDurationHelp": "Titler kortere enn dette vil ikke forsette.",
+ "TitleAutoOrganize": "Auto-Organisering",
+ "TabActivityLog": "Aktivitetslog",
+ "HeaderName": "Navn",
+ "HeaderDate": "Dato",
+ "HeaderSource": "Kilde",
+ "HeaderDestination": "Destinasjon",
"HeaderProgram": "Program",
- "HeaderClients": "Clients",
- "LabelCompleted": "Completed",
- "LabelSkipped": "Skipped",
- "HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeasonNumber": "Season number",
- "LabelEpisodeNumber": "Episode number",
- "LabelEndingEpisodeNumber": "Ending episode number",
- "LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
- "HeaderSupportTheTeam": "Support the Media Browser Team",
- "LabelSupportAmount": "Amount (USD)",
- "HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.",
- "ButtonEnterSupporterKey": "Enter supporter key",
- "DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.",
- "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.",
- "AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.",
- "OptionEnableEpisodeOrganization": "Enable new episode organization",
- "LabelWatchFolder": "Watch folder:",
- "LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.",
- "ButtonViewScheduledTasks": "View scheduled tasks",
- "LabelMinFileSizeForOrganize": "Minimum file size (MB):",
- "LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.",
- "LabelSeasonFolderPattern": "Season folder pattern:",
- "LabelSeasonZeroFolderName": "Season zero folder name:",
- "HeaderEpisodeFilePattern": "Episode file pattern",
- "LabelEpisodePattern": "Episode pattern:",
- "LabelMultiEpisodePattern": "Multi-Episode pattern:",
- "HeaderSupportedPatterns": "Supported Patterns",
+ "HeaderClients": "Klienter",
+ "LabelCompleted": "Fullf\u00f8rt",
+ "LabelFailed": "Failed",
+ "LabelSkipped": "Hoppet over",
+ "HeaderEpisodeOrganization": "Episode Organisering",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Sesong nummer",
+ "LabelEpisodeNumber": "Episode nummer",
+ "LabelEndingEpisodeNumber": "Ending av episode nummer",
+ "LabelEndingEpisodeNumberHelp": "Kun n\u00f8dvendig for multi-episode filer",
+ "HeaderSupportTheTeam": "St\u00f8tt Media Browser Teamet",
+ "LabelSupportAmount": "Sum (USD)",
+ "HeaderSupportTheTeamHelp": "Bidra til \u00e5 sikre fortsatt utvikling av dette prosjektet ved \u00e5 donere. En del av alle donasjoner vil v\u00e6re bidratt til andre gratis verkt\u00f8y vi er avhengige av.",
+ "ButtonEnterSupporterKey": "Skriv supporter n\u00f8kkel",
+ "DonationNextStep": "N\u00e5r du er ferdig, kan du g\u00e5 tilbake og skriv inn din support n\u00f8kkel, som du vil motta p\u00e5 e-post.",
+ "AutoOrganizeHelp": "Auto-organisere monitorerer dine nedlastingsmapper for nye filer og flytter dem til medie kataloger.",
+ "AutoOrganizeTvHelp": "TV file organisering vil kun legge til episoder til eksisterende episoder. Den vil ikke lage nye serie mapper.",
+ "OptionEnableEpisodeOrganization": "Aktiver ny episode organisering",
+ "LabelWatchFolder": "Se p\u00e5 Mappe:",
+ "LabelWatchFolderHelp": "Serveren vil hente denne mappen under 'Organiser nye mediefiler' planlagte oppgaven.",
+ "ButtonViewScheduledTasks": "Se p\u00e5 planlagte oppgaver",
+ "LabelMinFileSizeForOrganize": "Minimum fil st\u00f8rrelse (MB):",
+ "LabelMinFileSizeForOrganizeHelp": "Filer under denne st\u00f8rrelsen vil bli ignorert.",
+ "LabelSeasonFolderPattern": "Sesong mappe m\u00f8nster:",
+ "LabelSeasonZeroFolderName": "Sesong null mappe navn:",
+ "HeaderEpisodeFilePattern": "Episode fil m\u00f8nster",
+ "LabelEpisodePattern": "Episode m\u00f8nster",
+ "LabelMultiEpisodePattern": "Multi-Episode m\u00f8nster:",
+ "HeaderSupportedPatterns": "St\u00f8ttede m\u00f8nster",
"HeaderTerm": "Term",
- "HeaderPattern": "Pattern",
- "HeaderResult": "Result",
- "LabelDeleteEmptyFolders": "Delete empty folders after organizing",
- "LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.",
- "LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:",
- "LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt",
- "OptionOverwriteExistingEpisodes": "Overwrite existing episodes",
- "LabelTransferMethod": "Transfer method",
- "OptionCopy": "Copy",
- "OptionMove": "Move",
- "LabelTransferMethodHelp": "Copy or move files from the watch folder",
- "HeaderLatestNews": "Latest News",
- "HeaderHelpImproveMediaBrowser": "Help Improve Media Browser",
- "HeaderRunningTasks": "Running Tasks",
- "HeaderActiveDevices": "Active Devices",
- "HeaderPendingInstallations": "Pending Installations",
- "HeaerServerInformation": "Server Information",
- "ButtonRestartNow": "Restart Now",
+ "HeaderPattern": "M\u00f8nster",
+ "HeaderResult": "Resultat",
+ "LabelDeleteEmptyFolders": "Slett tomme mapper etter organisering",
+ "LabelDeleteEmptyFoldersHelp": "Aktiver denne for \u00e5 holde nedlastings-katalogen ren.",
+ "LabelDeleteLeftOverFiles": "Slett gjenv\u00e6rende filer etter f\u00f8lgende utvidelser:",
+ "LabelDeleteLeftOverFilesHelp": "Seprarer med ;. For eksempel: .nfk;.txt",
+ "OptionOverwriteExistingEpisodes": "Skriv over eksisterende episoder",
+ "LabelTransferMethod": "overf\u00f8ringsmetoder",
+ "OptionCopy": "Kopier",
+ "OptionMove": "Flytt",
+ "LabelTransferMethodHelp": "Kopier eller flytt filer fra watch mappen",
+ "HeaderLatestNews": "Siste nyheter",
+ "HeaderHelpImproveMediaBrowser": "Hjelp \u00e5 forbedre Media Browser",
+ "HeaderRunningTasks": "Kj\u00f8rende oppgaver",
+ "HeaderActiveDevices": "Aktive enheter",
+ "HeaderPendingInstallations": "ventede installasjoner",
+ "HeaerServerInformation": "Server informasjon",
+ "ButtonRestartNow": "Restart N\u00e5",
"ButtonRestart": "Restart",
- "ButtonShutdown": "Shutdown",
- "ButtonUpdateNow": "Update Now",
- "PleaseUpdateManually": "Please shutdown the server and update manually.",
- "NewServerVersionAvailable": "A new version of Media Browser Server is available!",
- "ServerUpToDate": "Media Browser Server is up to date",
- "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.",
- "LabelComponentsUpdated": "The following components have been installed or updated:",
- "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.",
- "LabelDownMixAudioScale": "Audio boost when downmixing:",
- "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.",
- "ButtonLinkKeys": "Link Keys",
- "LabelOldSupporterKey": "Old supporter key",
- "LabelNewSupporterKey": "New supporter key",
- "HeaderMultipleKeyLinking": "Multiple Key Linking",
- "MultipleKeyLinkingHelp": "If you have more than one supporter key, use this form to link the old key's registrations with your new one.",
- "LabelCurrentEmailAddress": "Current email address",
- "LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.",
- "HeaderForgotKey": "Forgot Key",
- "LabelEmailAddress": "Email address",
- "LabelSupporterEmailAddress": "The email address that was used to purchase the key.",
- "ButtonRetrieveKey": "Retrieve Key",
- "LabelSupporterKey": "Supporter Key (paste from email)",
- "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
- "MessageInvalidKey": "Supporter key is missing or invalid.",
- "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
- "HeaderDisplaySettings": "Display Settings",
- "TabPlayTo": "Play To",
- "LabelEnableDlnaServer": "Enable Dlna server",
- "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Media Browser content.",
- "LabelEnableBlastAliveMessages": "Blast alive messages",
- "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.",
- "LabelBlastMessageInterval": "Alive message interval (seconds)",
- "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.",
- "LabelDefaultUser": "Default user:",
- "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.",
+ "ButtonShutdown": "Sl\u00e5 Av",
+ "ButtonUpdateNow": "Oppdater N\u00e5",
+ "PleaseUpdateManually": "Vennligst sl\u00e5 av serveren og oppdater manuelt.",
+ "NewServerVersionAvailable": "En ny versjon av Media Browser er tilgjengelig!",
+ "ServerUpToDate": "Media Browser Server er oppdatert",
+ "ErrorConnectingToMediaBrowserRepository": "Det var en feil ved forbindelse opp mot ekstern Media Browser repository.",
+ "LabelComponentsUpdated": "F\u00f8lgende komponenter har blitt installert eller oppdatert:",
+ "MessagePleaseRestartServerToFinishUpdating": "Vennligst restart serveren for \u00e5 fullf\u00f8re installasjon av oppdateringer.",
+ "LabelDownMixAudioScale": "Lyd boost n\u00e5r downmixing:",
+ "LabelDownMixAudioScaleHelp": "Boost lyd n\u00e5r downmixing. Set til 1 for \u00e5 bevare orginal volum verdi.",
+ "ButtonLinkKeys": "Link N\u00f8kler",
+ "LabelOldSupporterKey": "Gammel supporter n\u00f8kkel",
+ "LabelNewSupporterKey": "Ny supporter n\u00f8kkel",
+ "HeaderMultipleKeyLinking": "Flere n\u00f8kkel-linkinger",
+ "MultipleKeyLinkingHelp": "Hvis du har mer en en supporter n\u00f8kkel, bruk denne formen for \u00e5 linke til den gamle n\u00f8kkelens registrering med den nye.",
+ "LabelCurrentEmailAddress": "Gjeldende email adresse",
+ "LabelCurrentEmailAddressHelp": "Den aktuelle e-postadressen som den nye n\u00f8kkelen ble sendt.",
+ "HeaderForgotKey": "Glemt N\u00f8kkel",
+ "LabelEmailAddress": "e-postadresse",
+ "LabelSupporterEmailAddress": "e-postadressen som ble brukt for \u00e5 kj\u00f8pe n\u00f8kkelen.",
+ "ButtonRetrieveKey": "Motta N\u00f8kkel",
+ "LabelSupporterKey": "Supporter N\u00f8kkel (Lim inn fra e-postadresse)",
+ "LabelSupporterKeyHelp": "Skriv inn din supporter n\u00f8kkel for \u00e5 kunne nyte flere fordeler som samfunnet har utviklet for Media Browser.",
+ "MessageInvalidKey": "Supporter n\u00f8kkel mangler eller er feil.",
+ "ErrorMessageInvalidKey": "For eventuelt premiuminnhold for \u00e5 bli registrert, m\u00e5 du ogs\u00e5 v\u00e6re en Media Browser Supporter. Vennligst doner og st\u00f8tt det videre-utviklede av kjerneproduktet. Takk.",
+ "HeaderDisplaySettings": "Visnings Innstillinger",
+ "TabPlayTo": "Spill Til",
+ "LabelEnableDlnaServer": "Sl\u00e5 p\u00e5 Dlna server",
+ "LabelEnableDlnaServerHelp": "Tillat UPnP enheter p\u00e5 ditt nettverk for \u00e5 s\u00f8ke gjennom spill Media Browser innhold.",
+ "LabelEnableBlastAliveMessages": "Spreng levende meldinger",
+ "LabelEnableBlastAliveMessagesHelp": "Sl\u00e5 p\u00e5 hvis serveren ikke detekterer p\u00e5litelighet fra andre UPnP enheter p\u00e5 ditt nettverk.",
+ "LabelBlastMessageInterval": "Levende meldinger invertall (sekunder)",
+ "LabelBlastMessageIntervalHelp": "Avgj\u00f8r tiden i sekunder mellom server levende meldinger.",
+ "LabelDefaultUser": "Standard bruker:",
+ "LabelDefaultUserHelp": "Avgj\u00f8r hvilket bruker bibliotek som skal bli vist p\u00e5 koblede enheter. Dette kan bli overskrevet for hver enhet som bruker profiler.",
"TitleDlna": "DLNA",
- "TitleChannels": "Channels",
- "HeaderServerSettings": "Server Settings",
- "LabelWeatherDisplayLocation": "Weather display location:",
- "LabelWeatherDisplayLocationHelp": "US zip code \/ City, State, Country \/ City, Country",
- "LabelWeatherDisplayUnit": "Weather display unit:",
+ "TitleChannels": "Kanaler",
+ "HeaderServerSettings": "Server Innstillinger",
+ "LabelWeatherDisplayLocation": "V\u00e6r-visning lokalisering:",
+ "LabelWeatherDisplayLocationHelp": "US zip kode \/ By, Stat, Land \/ By, Land",
+ "LabelWeatherDisplayUnit": "V\u00e6r-visning enhet:",
"OptionCelsius": "Celsius",
"OptionFahrenheit": "Fahrenheit",
- "HeaderRequireManualLogin": "Require manual username entry for:",
- "HeaderRequireManualLoginHelp": "When disabled clients may present a login screen with a visual selection of users.",
- "OptionOtherApps": "Other apps",
- "OptionMobileApps": "Mobile apps",
- "HeaderNotificationList": "Click on a notification to configure it's sending options.",
- "NotificationOptionApplicationUpdateAvailable": "Application update available",
- "NotificationOptionApplicationUpdateInstalled": "Application update installed",
- "NotificationOptionPluginUpdateInstalled": "Plugin update installed",
- "NotificationOptionPluginInstalled": "Plugin installed",
- "NotificationOptionPluginUninstalled": "Plugin uninstalled",
- "NotificationOptionVideoPlayback": "Video playback started",
- "NotificationOptionAudioPlayback": "Audio playback started",
- "NotificationOptionGamePlayback": "Game playback started",
- "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
- "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
- "NotificationOptionGamePlaybackStopped": "Game playback stopped",
- "NotificationOptionTaskFailed": "Scheduled task failure",
- "NotificationOptionInstallationFailed": "Installation failure",
+ "HeaderRequireManualLogin": "Krev manuell brukernavn oppf\u00f8ring for:",
+ "HeaderRequireManualLoginHelp": "N\u00e5r deaktiverte brukere kan presentere en innloggingskjerm med ett visuelt utvalg av brukere.",
+ "OptionOtherApps": "Andre applikasjoner",
+ "OptionMobileApps": "Mobile applikasjoner",
+ "HeaderNotificationList": "Klikk p\u00e5 en varsling for \u00e5 konfigurere dens sending-alternativer.",
+ "NotificationOptionApplicationUpdateAvailable": "Applikasjon oppdatering tilgjengelig",
+ "NotificationOptionApplicationUpdateInstalled": "Applikasjon oppdatering installert",
+ "NotificationOptionPluginUpdateInstalled": "Plugin oppdatering installert",
+ "NotificationOptionPluginInstalled": "Plugin installert",
+ "NotificationOptionPluginUninstalled": "Plugin er fjernet",
+ "NotificationOptionVideoPlayback": "Video avspilling startet",
+ "NotificationOptionAudioPlayback": "Lyd avspilling startet",
+ "NotificationOptionGamePlayback": "Spill avspilling startet",
+ "NotificationOptionVideoPlaybackStopped": "Video avspilling stoppet",
+ "NotificationOptionAudioPlaybackStopped": "Lyd avspilling stoppet",
+ "NotificationOptionGamePlaybackStopped": "Spill avspilling stoppet",
+ "NotificationOptionTaskFailed": "Tidsplan oppgave feilet",
+ "NotificationOptionInstallationFailed": "Installasjon feilet",
"NotificationOptionNewLibraryContent": "Nytt innhold er lagt til",
- "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
- "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.",
- "NotificationOptionServerRestartRequired": "Server restart required",
- "LabelNotificationEnabled": "Enable this notification",
- "LabelMonitorUsers": "Monitor activity from:",
- "LabelSendNotificationToUsers": "Send the notification to:",
- "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.",
- "LabelUseNotificationServices": "Use the following services:",
- "CategoryUser": "User",
+ "NotificationOptionNewLibraryContentMultiple": "Nytt innhold lagt til (flere)",
+ "SendNotificationHelp": "Som standard blir varslinger sent til dashbord inboksen. Bla igjennom plugin katalogen for \u00e5 installere valgfrie varslings-alternativer.",
+ "NotificationOptionServerRestartRequired": "Server omstart beh\u00f8ves",
+ "LabelNotificationEnabled": "Sl\u00e5 p\u00e5 denne varslingen",
+ "LabelMonitorUsers": "Monitorer aktivitet fra:",
+ "LabelSendNotificationToUsers": "Send varslingen til:",
+ "LabelUseNotificationServices": "Bruk f\u00f8lgende tjeneste:",
+ "CategoryUser": "Bruker",
"CategorySystem": "System",
- "CategoryApplication": "Application",
+ "CategoryApplication": "Applikasjon",
"CategoryPlugin": "Plugin",
- "LabelMessageTitle": "Message title:",
- "LabelAvailableTokens": "Available tokens:",
- "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.",
- "OptionAllUsers": "All users",
- "OptionAdminUsers": "Administrators",
- "OptionCustomUsers": "Custom",
- "ButtonArrowUp": "Up",
- "ButtonArrowDown": "Down",
- "ButtonArrowLeft": "Left",
- "ButtonArrowRight": "Right",
- "ButtonBack": "Back",
+ "LabelMessageTitle": "Meldingstittel:",
+ "LabelAvailableTokens": "Tilgjengelige tokens:",
+ "AdditionalNotificationServices": "Bla gjennom plugin katalogen for \u00e5 installere valgfrie varslingstjenester.",
+ "OptionAllUsers": "Alle brukere:",
+ "OptionAdminUsers": "Administratorer",
+ "OptionCustomUsers": "Tilpasset",
+ "ButtonArrowUp": "Opp",
+ "ButtonArrowDown": "Ned",
+ "ButtonArrowLeft": "Venstre",
+ "ButtonArrowRight": "H\u00f8yre",
+ "ButtonBack": "Tilbake",
"ButtonInfo": "Info",
- "ButtonOsd": "On screen display",
- "ButtonPageUp": "Page Up",
- "ButtonPageDown": "Page Down",
+ "ButtonOsd": "P\u00e5 skjermvisning",
+ "ButtonPageUp": "Side Opp",
+ "ButtonPageDown": "Side Ned",
"PageAbbreviation": "PG",
- "ButtonHome": "Home",
- "ButtonSettings": "Settings",
- "ButtonTakeScreenshot": "Capture Screenshot",
- "ButtonLetterUp": "Letter Up",
- "ButtonLetterDown": "Letter Down",
+ "ButtonHome": "Hjem",
+ "ButtonSearch": "S\u00f8k",
+ "ButtonSettings": "Innstillinger",
+ "ButtonTakeScreenshot": "Ta Skjermbilde",
+ "ButtonLetterUp": "Pil Opp",
+ "ButtonLetterDown": "Pil Ned",
"PageButtonAbbreviation": "PG",
"LetterButtonAbbreviation": "A",
- "TabNowPlaying": "Now Playing",
- "TabNavigation": "Navigation",
- "TabControls": "Controls",
- "ButtonFullscreen": "Toggle fullscreen",
- "ButtonScenes": "Scenes",
- "ButtonSubtitles": "Subtitles",
- "ButtonAudioTracks": "Audio tracks",
- "ButtonStop": "Stop",
+ "TabNowPlaying": "Spilles Av",
+ "TabNavigation": "Navigering",
+ "TabControls": "Kontrollerer",
+ "ButtonFullscreen": "Veksle fullskjerm",
+ "ButtonScenes": "Scener",
+ "ButtonSubtitles": "Undertekster",
+ "ButtonAudioTracks": "Lyd spor",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
+ "ButtonStop": "Stopp",
"ButtonPause": "Pause",
- "LabelGroupMoviesIntoCollections": "Group movies into collections",
- "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.",
- "NotificationOptionPluginError": "Plugin failure",
- "ButtonVolumeUp": "Volume up",
- "ButtonVolumeDown": "Volume down",
+ "LabelGroupMoviesIntoCollections": "Grupper filmer inni samlinger",
+ "LabelGroupMoviesIntoCollectionsHelp": "Ved visning av filmlister vil filmer som tilh\u00f8rer en samling vil bli vist som ett grupperende element.",
+ "NotificationOptionPluginError": "Plugin feil",
+ "ButtonVolumeUp": "Volum opp",
+ "ButtonVolumeDown": "Volum ned",
"ButtonMute": "Mute",
- "HeaderLatestMedia": "Latest Media",
- "OptionSpecialFeatures": "Special Features",
- "HeaderCollections": "Collections",
- "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
- "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
- "HeaderResponseProfile": "Response Profile",
+ "HeaderLatestMedia": "Siste Media",
+ "OptionSpecialFeatures": "Spesielle Funksjoner",
+ "HeaderCollections": "Samlinger",
+ "LabelProfileCodecsHelp": "Separert med komma. Dette feltet kan forbli tomt for \u00e5 gjelde alle kodeker.",
+ "LabelProfileContainersHelp": "Separert med komma. Dette feltet kan forbli tomt for \u00e5 gjelde alle kontainere.",
+ "HeaderResponseProfile": "Respons Profil",
"LabelType": "Type:",
- "LabelProfileContainer": "Container:",
- "LabelProfileVideoCodecs": "Video codecs:",
- "LabelProfileAudioCodecs": "Audio codecs:",
- "LabelProfileCodecs": "Codecs:",
- "HeaderDirectPlayProfile": "Direct Play Profile",
- "HeaderTranscodingProfile": "Transcoding Profile",
- "HeaderCodecProfile": "Codec Profile",
- "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.",
- "HeaderContainerProfile": "Container Profile",
- "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
+ "LabelProfileContainer": "Kontainer:",
+ "LabelProfileVideoCodecs": "Video kodek:",
+ "LabelProfileAudioCodecs": "Lyd kodek:",
+ "LabelProfileCodecs": "Kodeker:",
+ "HeaderDirectPlayProfile": "Direkte Avspilling Profil",
+ "HeaderTranscodingProfile": "Transcoding Profil",
+ "HeaderCodecProfile": "Kodek Profil",
+ "HeaderCodecProfileHelp": "Kodek profiler indikerer p\u00e5 at begrensninger p\u00e5 en enhet n\u00e5r den spiller av spesifikk kodeker. Hvis en begrensning gjelder vil media bli transcodet, til og med hvis kodeken er konfigurert for direkte avspilling.",
+ "HeaderContainerProfile": "Kontainer Profil",
+ "HeaderContainerProfileHelp": "Container profiler indikerer begrensningene i en enhet n\u00e5r du spiller bestemte formater. Hvis en begrensning gjelder da vil media bli transcodet, selv om formatet er konfigurert for direkte avspilling.",
"OptionProfileVideo": "Video",
- "OptionProfileAudio": "Audio",
- "OptionProfileVideoAudio": "Video Audio",
- "OptionProfilePhoto": "Photo",
+ "OptionProfileAudio": "Lyd",
+ "OptionProfileVideoAudio": "Video Lyd",
+ "OptionProfilePhoto": "Bilde",
"LabelUserLibrary": "Bruker bibliotek:",
- "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.",
- "OptionPlainStorageFolders": "Display all folders as plain storage folders",
- "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".",
- "OptionPlainVideoItems": "Display all videos as plain video items",
- "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".",
- "LabelSupportedMediaTypes": "Supported Media Types:",
- "TabIdentification": "Identification",
- "TabDirectPlay": "Direct Play",
- "TabContainers": "Containers",
- "TabCodecs": "Codecs",
- "TabResponses": "Responses",
- "HeaderProfileInformation": "Profile Information",
- "LabelEmbedAlbumArtDidl": "Embed album art in Didl",
- "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.",
+ "LabelUserLibraryHelp": "Velg hvilket brukerbibliotek som skal vises til enheten. La det st\u00e5 tomt for standard innstillinger.",
+ "OptionPlainStorageFolders": "Vis alle mapper som rene lagringsmapper",
+ "OptionPlainStorageFoldersHelp": "Hvis aktivert, vil alle mapper bli representert i DIDL som \"object.container.storageFolder\" istedet for en mer spesifikk type, som \"object.container.person.musicArtist\".",
+ "OptionPlainVideoItems": "Vis alle videoer som ren video elementer",
+ "OptionPlainVideoItemsHelp": "Hvis aktivert, blir alle videoer representert i DIDL som \"object.item.videoItem\" i stedet for en mer bestemt type, for eksempel \"object.item.videoItem.movie\".",
+ "LabelSupportedMediaTypes": "St\u00f8ttede Media Typer:",
+ "TabIdentification": "Identifisering",
+ "TabDirectPlay": "Direkte Avspill",
+ "TabContainers": "Kontainere",
+ "TabCodecs": "Kodeker",
+ "TabResponses": "Svar",
+ "HeaderProfileInformation": "Profil Informasjon",
+ "LabelEmbedAlbumArtDidl": "Bygg inn albumbilder i Didl",
+ "LabelEmbedAlbumArtDidlHelp": "Noen enheter foretrekker denne metoden for \u00e5 motta album art. Andre vil kunne feile \u00e5 avspille hvis dette alternativet er aktivert.",
"LabelAlbumArtPN": "Album art PN:",
- "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.",
- "LabelAlbumArtMaxWidth": "Album art max width:",
- "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
- "LabelAlbumArtMaxHeight": "Album art max height:",
- "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
- "LabelIconMaxWidth": "Icon max width:",
- "LabelIconMaxWidthHelp": "Max resolution of icons exposed via upnp:icon.",
- "LabelIconMaxHeight": "Icon max height:",
- "LabelIconMaxHeightHelp": "Max resolution of icons exposed via upnp:icon.",
- "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.",
- "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
- "LabelMaxBitrate": "Max bitrate:",
- "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
- "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
- "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
- "LabelFriendlyName": "Friendly name",
- "LabelManufacturer": "Manufacturer",
- "LabelManufacturerUrl": "Manufacturer url",
- "LabelModelName": "Model name",
- "LabelModelNumber": "Model number",
- "LabelModelDescription": "Model description",
+ "LabelAlbumArtHelp": "PN brukes for album art, innenfor DLNA: profileID attributtet p\u00e5 upnp: albumArtURI. Noen klienter krever en bestemt verdi, uavhengig av st\u00f8rrelsen p\u00e5 bildet.",
+ "LabelAlbumArtMaxWidth": "Album art mat bredde:",
+ "LabelAlbumArtMaxWidthHelp": "Maks oppl\u00f8sning av album art utnyttet via upnp:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "Album art maks h\u00f8yde:",
+ "LabelAlbumArtMaxHeightHelp": "Maks oppl\u00f8sning av album er eksonert via upnp:albumARtURI.",
+ "LabelIconMaxWidth": "Ikon maks bredde:",
+ "LabelIconMaxWidthHelp": "Maks oppl\u00f8sning av ikoner utsatt via upnp:icon.",
+ "LabelIconMaxHeight": "Ikon maks h\u00f8yde:",
+ "LabelIconMaxHeightHelp": "Maks oppl\u00f8sning av ikoner utsatt via upnp:icon.",
+ "LabelIdentificationFieldHelp": "Ett case-insensitive substring eller regex uttrykk.",
+ "HeaderProfileServerSettingsHelp": "Disse verdiene kontrollerer hvordan Media Browser vil presentere seg selv til enheten.",
+ "LabelMaxBitrate": "Maks bitrate:",
+ "LabelMaxBitrateHelp": "Spesifiser en maks bitrate i for begrensede b\u00e5ndbredde milj\u00f8er, eller hvis enheten p\u00e5legger sin egen begrensning.",
+ "LabelMaxStreamingBitrate": "Maks streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Spesifiser en maks bitrate n\u00e5r streaming.",
+ "LabelMaxStaticBitrate": "Maks synk bitrate:",
+ "LabelMaxStaticBitrateHelp": "Spesifiser en maks bitrate ved synkronisering av innhold i h\u00f8y kvalitet.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
+ "OptionIgnoreTranscodeByteRangeRequests": "Ignorer Transcode byte rekkevidde foresp\u00f8rsler",
+ "OptionIgnoreTranscodeByteRangeRequestsHelp": "Hvis aktivert vil disse foresp\u00f8rslene bli honorert men ignorert i byte rekkevidde headeren.",
+ "LabelFriendlyName": "Vennlig navn",
+ "LabelManufacturer": "Produsent",
+ "LabelManufacturerUrl": "Produsent url",
+ "LabelModelName": "Modell navn",
+ "LabelModelNumber": "Modell nummer",
+ "LabelModelDescription": "Model beskrivelse",
"LabelModelUrl": "Model url",
- "LabelSerialNumber": "Serial number",
- "LabelDeviceDescription": "Device description",
- "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.",
- "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.",
- "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.",
- "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.",
+ "LabelSerialNumber": "Serienummer",
+ "LabelDeviceDescription": "Enhet beskrivelse",
+ "HeaderIdentificationCriteriaHelp": "Skriv minst ett identifiserings kriterie",
+ "HeaderDirectPlayProfileHelp": "Legg direkte avspill profiler til \u00e5 indikere hvilket format enheten kan st\u00f8tte.",
+ "HeaderTranscodingProfileHelp": "Legg til transcoding profiler for \u00e5 indikere hvilke format som burde bli brukt n\u00e5r transcoding beh\u00f8ves.",
+ "HeaderResponseProfileHelp": "Respons proiler tilbyr en m\u00e5t \u00e5 tilpasse informasjon som er sent til enheten n\u00e5r den spiller en viss type media.",
"LabelXDlnaCap": "X-Dlna cap:",
- "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.",
+ "LabelXDlnaCapHelp": "Bestemmer innholdet i X_DLNACAP element i urn: skjemaer-DLNA-org: enhets 1-0 navnerom.",
"LabelXDlnaDoc": "X-Dlna doc:",
- "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.",
- "LabelSonyAggregationFlags": "Sony aggregation flags:",
- "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.",
- "LabelTranscodingContainer": "Container:",
- "LabelTranscodingVideoCodec": "Video codec:",
- "LabelTranscodingVideoProfile": "Video profile:",
- "LabelTranscodingAudioCodec": "Audio codec:",
- "OptionEnableM2tsMode": "Enable M2ts mode",
- "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.",
- "OptionEstimateContentLength": "Estimate content length when transcoding",
- "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding",
- "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.",
- "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
- "HeaderDownloadSubtitlesFor": "Download subtitles for:",
- "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.",
- "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
- "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "TabSubtitles": "Subtitles",
- "TabChapters": "Chapters",
- "HeaderDownloadChaptersFor": "Download chapter names for:",
- "LabelOpenSubtitlesUsername": "Open Subtitles username:",
- "LabelOpenSubtitlesPassword": "Open Subtitles password:",
- "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.",
- "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
- "LabelSubtitlePlaybackMode": "Subtitle mode:",
- "LabelDownloadLanguages": "Download languages:",
- "ButtonRegister": "Register",
- "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
- "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
- "HeaderSendMessage": "Send Message",
+ "LabelXDlnaDocHelp": "Bestemmer innholdet i X_DLNADOC element i urn: skjemaer-DLNA-org: enhets 1-0 navnerom.",
+ "LabelSonyAggregationFlags": "Sony aggregerigns flagg",
+ "LabelSonyAggregationFlagsHelp": "Bestemmer innholdet i aggregationFlags element i urn: skjemaer-sonycom: av navnerommet.",
+ "LabelTranscodingContainer": "Kontainer:",
+ "LabelTranscodingVideoCodec": "Video kodek:",
+ "LabelTranscodingVideoProfile": "Video profil:",
+ "LabelTranscodingAudioCodec": "lyd kodek:",
+ "OptionEnableM2tsMode": "Sl\u00e5 p\u00e5 M2ts modus",
+ "OptionEnableM2tsModeHelp": "Sl\u00e5 p\u00e5 m2ts modus for enkoding til mpegts.",
+ "OptionEstimateContentLength": "Estimer innholdslengde n\u00e5r transcoding.",
+ "OptionReportByteRangeSeekingWhenTranscoding": "Rapporter at serveren st\u00f8tter byte s\u00f8king n\u00e5r transcoding.",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "Dette kreves for noen enheter som ikke tidss\u00f8ker veldig godt.",
+ "HeaderSubtitleDownloadingHelp": "N\u00e5r Media Browser skanner videofilene, kan den s\u00f8ke etter savnede undertekster, og laste dem ned med en undertittel leverand\u00f8r som OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "Last ned undertekster for:",
+ "MessageNoChapterProviders": "Installer en kapittel tilbyder som eksempelvis ChapterDb for \u00e5 aktivere kapittel muligheter.",
+ "LabelSkipIfGraphicalSubsPresent": "Hopp om videoen inneholder allerede grafiske undertekster",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Ved \u00e5 opprettholde tekst versjoner av undertekster vil medf\u00f8re i mer effektiv levering til mobile enheter.",
+ "TabSubtitles": "Undertekster",
+ "TabChapters": "Kapitler",
+ "HeaderDownloadChaptersFor": "Last ned kapittelnavn for:",
+ "LabelOpenSubtitlesUsername": "Open Subtitles brukernavn:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles passord:",
+ "HeaderChapterDownloadingHelp": "N\u00e5r Media Browser s\u00f8ker igjennom dine video filer s\u00e5 kan den laste ned vennlige kapittelnavn fra internet ved \u00e5 bruke plugins som ChapterDb.",
+ "LabelPlayDefaultAudioTrack": "Spill av lydsporet uavhengig av spr\u00e5k",
+ "LabelSubtitlePlaybackMode": "Undertekst modus:",
+ "LabelDownloadLanguages": "Last ned spr\u00e5k:",
+ "ButtonRegister": "Registrer",
+ "LabelSkipIfAudioTrackPresent": "Hopp hvis standard lydsporet matcher nedlastingen spr\u00e5k",
+ "LabelSkipIfAudioTrackPresentHelp": "Fjern merkingen for \u00e5 sikre at alle videoene har undertekster, uavhengig av lydspr\u00e5k.",
+ "HeaderSendMessage": "Send Melding",
"ButtonSend": "Send",
- "LabelMessageText": "Message text:",
- "MessageNoAvailablePlugins": "No available plugins.",
- "LabelDisplayPluginsFor": "Display plugins for:",
+ "LabelMessageText": "Meldingstekst:",
+ "MessageNoAvailablePlugins": "Ingen tilgjengelige plugins.",
+ "LabelDisplayPluginsFor": "Vis plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
- "ValueSeriesNamePeriod": "Series.name",
- "ValueSeriesNameUnderscore": "Series_name",
- "ValueEpisodeNamePeriod": "Episode.name",
- "ValueEpisodeNameUnderscore": "Episode_name",
- "HeaderTypeText": "Enter Text",
- "LabelTypeText": "Text",
- "HeaderSearchForSubtitles": "Search for Subtitles",
- "MessageNoSubtitleSearchResultsFound": "No search results founds.",
- "TabDisplay": "Display",
- "TabLanguages": "Languages",
- "TabWebClient": "Web Client",
- "LabelEnableThemeSongs": "Enable theme songs",
- "LabelEnableBackdrops": "Enable backdrops",
- "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.",
- "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.",
- "HeaderHomePage": "Home Page",
- "HeaderSettingsForThisDevice": "Settings for This Device",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
+ "ValueSeriesNamePeriod": "Serier.navn",
+ "ValueSeriesNameUnderscore": "Serie_navn",
+ "ValueEpisodeNamePeriod": "Episode.navn",
+ "ValueEpisodeNameUnderscore": "Episode_navn",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
+ "HeaderTypeText": "Skriv Tekst",
+ "LabelTypeText": "Tekst",
+ "HeaderSearchForSubtitles": "S\u00f8k etter undertekster",
+ "MessageNoSubtitleSearchResultsFound": "Ingen s\u00f8k funnet.",
+ "TabDisplay": "Skjerm",
+ "TabLanguages": "Spr\u00e5k",
+ "TabWebClient": "Web Klient",
+ "LabelEnableThemeSongs": "Sl\u00e5 p\u00e5 tema sanger",
+ "LabelEnableBackdrops": "Sl\u00e5 p\u00e5 backdrops",
+ "LabelEnableThemeSongsHelp": "Hvis p\u00e5sl\u00e5tt vil tema sanger bli avspilt i bakgrunnen mens man blar igjennom biblioteket.",
+ "LabelEnableBackdropsHelp": "Hvis p\u00e5sl\u00e5tt vil backdrops bli vist i bakgrunnen p\u00e5 noen sider mens man blar igjennom biblioteket.",
+ "HeaderHomePage": "Hjemmeside",
+ "HeaderSettingsForThisDevice": "Innstillinger for denne enheten",
"OptionAuto": "Auto",
- "OptionYes": "Yes",
- "OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
- "OptionResumablemedia": "Resume",
- "OptionLatestMedia": "Latest media",
- "OptionLatestChannelMedia": "Latest channel items",
- "HeaderLatestChannelItems": "Latest Channel Items",
- "OptionNone": "None",
+ "OptionYes": "Ja",
+ "OptionNo": "Nei",
+ "LabelHomePageSection1": "Hjemme side seksjon 1:",
+ "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)",
+ "OptionResumablemedia": "Fortsett",
+ "OptionLatestMedia": "Siste media",
+ "OptionLatestChannelMedia": "Siste kanal elementer",
+ "HeaderLatestChannelItems": "Siste Kanal Elementer",
+ "OptionNone": "Ingen",
"HeaderLiveTv": "Live TV",
- "HeaderReports": "Reports",
- "HeaderMetadataManager": "Metadata Manager",
- "HeaderPreferences": "Preferences",
- "MessageLoadingChannels": "Loading channel content...",
- "ButtonMarkRead": "Mark Read",
- "OptionDefaultSort": "Default",
- "OptionCommunityMostWatchedSort": "Most Watched",
- "TabNextUp": "Next Up",
- "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 New button to start creating Collections.",
- "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
- "ButtonDismiss": "Dismiss",
- "MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
- "ButtonEditOtherUserPreferences": "Edit this user's personal preferences.",
- "LabelChannelStreamQuality": "Preferred internet stream quality:",
- "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.",
- "OptionBestAvailableStreamQuality": "Best available",
- "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:",
- "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.",
- "LabelChannelDownloadPath": "Channel content download path:",
- "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.",
- "LabelChannelDownloadAge": "Delete content after: (days)",
- "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.",
- "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.",
- "LabelSelectCollection": "Select collection:",
- "ViewTypeMovies": "Movies",
+ "HeaderReports": "Rapporter",
+ "HeaderMetadataManager": "Metadata Behandler",
+ "HeaderPreferences": "Preferanser",
+ "MessageLoadingChannels": "Laster kanal innhold...",
+ "MessageLoadingContent": "Loading content...",
+ "ButtonMarkRead": "Marker Som Lest",
+ "OptionDefaultSort": "Standard",
+ "OptionCommunityMostWatchedSort": "Mest Sett",
+ "TabNextUp": "Neste",
+ "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": "Samlinger tillater at du nyter personlig gruppering av filmer, serier, albumer, b\u00f8ker og spill. Klikk p\u00e5 den nye knappen for \u00e5 starte med \u00e5 lage samlinger.",
+ "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.",
+ "MessageNoPlaylistItemsAvailable": "Denne spillelisten er forel\u00f8pig tom",
+ "HeaderWelcomeToMediaBrowserWebClient": "Velkommen til Media Browser Web Klient",
+ "ButtonDismiss": "Avvis",
+ "MessageLearnHowToCustomize": "L\u00e6r hvordan \u00e5 tilpasse denne siden for din egen personlig smak. Klikk p\u00e5 bruker ikon i p\u00e5 topp h\u00f8yre hj\u00f8rne p\u00e5 skjermen for \u00e5 se og oppdatere dine preferanser.",
+ "ButtonEditOtherUserPreferences": "Rediger denne brukerens personlige preferanser.",
+ "LabelChannelStreamQuality": "Foretrukket internet streaming kvalitet.",
+ "LabelChannelStreamQualityHelp": "P\u00e5 en linje med lav b\u00e5ndbredde, vil begrensing av kvalitet hjelpe med \u00e5 gi en mer behagelig streaming opplevelse.",
+ "OptionBestAvailableStreamQuality": "Beste tilgjengelig",
+ "LabelEnableChannelContentDownloadingFor": "Sl\u00e5 p\u00e5 kanal innhold nedlasting for:",
+ "LabelEnableChannelContentDownloadingForHelp": "Noen kanaler st\u00f8tter nedlasting av innhold f\u00f8r visning. Aktiver dette for en linje med lav b\u00e5ndbredde for \u00e5 laste ned kanalinnholdet n\u00e5r serveren ikke benyttes. Innholdet lastes ned som en del av kanalens planlagte oppgave for nedlasting.",
+ "LabelChannelDownloadPath": "Nedlastingsti for Kanal-innhold:",
+ "LabelChannelDownloadPathHelp": "Spesifiser en tilpasset nedlastingsti hvis \u00f8nsket. La feltet ellers st\u00e5 tomt for \u00e5 bruke den interne program data mappen.",
+ "LabelChannelDownloadAge": "Slett innhold etter: (dager)",
+ "LabelChannelDownloadAgeHelp": "Nedlastet innhold eldre enn dette vil bli slettet. Det vil v\u00e6re avspillbart via internett streaming.",
+ "ChannelSettingsFormHelp": "Installer kanaler som eksempel Trailers og Vimeo i plugin katalogen.",
+ "LabelSelectCollection": "Velg samling:",
+ "ViewTypeMovies": "Filmer",
"ViewTypeTvShows": "TV",
- "ViewTypeGames": "Games",
- "ViewTypeMusic": "Music",
- "ViewTypeBoxSets": "Collections",
- "ViewTypeChannels": "Channels",
+ "ViewTypeGames": "Spill",
+ "ViewTypeMusic": "Musikk",
+ "ViewTypeBoxSets": "Samlinger",
+ "ViewTypeChannels": "Kanaler",
"ViewTypeLiveTV": "Live TV",
- "HeaderOtherDisplaySettings": "Display Settings",
- "HeaderMyViews": "My Views",
- "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",
- "TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "HeaderOtherDisplaySettings": "Visnings Innstillinger",
+ "HeaderMyViews": "Mitt Syn",
+ "LabelSelectFolderGroups": "Automatisk gruppering av innhold fra f\u00f8lgende mapper til oversikter som filmer, musikk og TV:",
+ "LabelSelectFolderGroupsHelp": "Mapper som ikke er valgt vil bli vist for seg selv i deres egen visning.",
+ "OptionDisplayAdultContent": "Vis Voksen materiale",
+ "OptionLibraryFolders": "Media Mapper",
+ "TitleRemoteControl": "Ekstern Kontroll",
+ "OptionLatestTvRecordings": "Siste opptak",
+ "LabelProtocolInfo": "Protokoll info:",
+ "LabelProtocolInfoHelp": "Verdien som blir brukt for \u00e5 gi respons til GetProtocolInfo foresp\u00f8rsler fra enheten.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser inkluderer innebygd st\u00f8tte for Xbmc nfo metadata og bilder. For \u00e5 sl\u00e5 p\u00e5 eller sl\u00e5 av Xbmc metadata, benytt Avansert fanen for \u00e5 konfigurere valg for dine media typer.",
+ "LabelXbmcMetadataUser": "Legg til bruker observering data til nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Sl\u00e5 p\u00e5 dette for \u00e5 observere data i synkronisering mellom Media Browser og Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Utgivelsesdato format",
+ "LabelXbmcMetadataDateFormatHelp": "Alle datoer innen nfo's vil bli lest og skrevet for bruk av dette formatet.",
+ "LabelXbmcMetadataSaveImagePaths": "Lagre bildesti innen nfo's filer",
+ "LabelXbmcMetadataSaveImagePathsHelp": "Dette er anbefalt hvis du har bildenavn som ikke samsvarer med Xbmc sine rettningslinjer.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Sl\u00e5 p\u00e5 sti erstatter",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Sl\u00e5 p\u00e5 sti erstatter for bildestier ved bruk at serverens sti erstatter innstillinger.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "Se sti erstatter.",
+ "LabelGroupChannelsIntoViews": "Via f\u00f8lgende kanaler direkte gjennom Mitt Syn:",
+ "LabelGroupChannelsIntoViewsHelp": "Hvis sl\u00e5tt p\u00e5 vil disse kanalene bli vist direkte sammen med andre visninger. Hvis avsl\u00e5tt, vil de bli vist sammen med separerte Kanaler visning.",
+ "LabelDisplayCollectionsView": "Vis en samling for \u00e5 vise film samlinger",
+ "LabelXbmcMetadataEnableExtraThumbs": "Kopier extrafanart til extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "Ved nedlasting av bildet kan de bli lagret til b\u00e5de extrafanart og extrathumbs for maks Xbmc skin st\u00f8tte.",
+ "TabServices": "Tjenester",
+ "TabLogs": "Logger",
+ "HeaderServerLogFiles": "Server log filer:",
+ "TabBranding": "Merke",
+ "HeaderBrandingHelp": "Tilpass utseende til Media Browser som passer til dine behov for dine grupper eller organiseringer.",
+ "LabelLoginDisclaimer": "Login ansvarsfraskrivelse:",
+ "LabelLoginDisclaimerHelp": "Dette vil bli vist p\u00e5 bunnen av login siden.",
+ "LabelAutomaticallyDonate": "Automatisk doner denne summen hver sjette m\u00e5ned.",
+ "LabelAutomaticallyDonateHelp": "Du kan kansellere n\u00e5r som helst via din PayPal konto.",
+ "OptionList": "Liste",
+ "TabDashboard": "Dashbord",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logger:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Bilder etter navn:",
+ "LabelTranscodingTemporaryFiles": "Transcoding midlertidige filer:",
+ "HeaderLatestMusic": "Siste Musikk",
+ "HeaderBranding": "Merke",
+ "HeaderApiKeys": "Api N\u00f8kkler",
+ "HeaderApiKeysHelp": "Eksterne programmer er p\u00e5lagt \u00e5 ha en API-n\u00f8kkel for \u00e5 kunne kommunisere med Media Browser. N\u00f8kkel f\u00e5es ved \u00e5 logge p\u00e5 med en Media Browser-konto, eller ved \u00e5 manuelt innvilge s\u00f8knaden en n\u00f8kkel.",
+ "HeaderApiKey": "Api N\u00f8kkel",
+ "HeaderApp": "App",
+ "HeaderDevice": "Enhet",
+ "HeaderUser": "Bruker",
+ "HeaderDateIssued": "Dato utstedt",
+ "LabelChapterName": "Kapittel {0}",
+ "HeaderNewApiKey": "Ny Api N\u00f8kkel",
+ "LabelAppName": "Applikasjon navn",
+ "LabelAppNameExample": "Eksempel: Sickbread, NzbDrone",
+ "HeaderNewApiKeyHelp": "Innvilge en applikasjon tillatelser for \u00e5 kommunisere med Media Browser.",
+ "HeaderHttpHeaders": "Http Headere",
+ "HeaderIdentificationHeader": "Identifiserings Header",
+ "LabelValue": "Verdi:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Lik",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "SubString",
+ "TabView": "Se",
+ "TabSort": "Sorter",
+ "TabFilter": "Filter",
+ "ButtonView": "Se",
+ "LabelPageSize": "Element grense:",
+ "LabelPath": "Path:",
+ "LabelView": "Se:",
+ "TabUsers": "Brukere",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Funksjoner",
+ "HeaderAdvanced": "Avansert",
+ "ButtonSync": "Synk",
+ "TabScheduledTasks": "Planlagte Oppgaver",
+ "HeaderChapters": "Kapitler",
+ "HeaderResumeSettings": "Fortsett Innstillinger",
+ "TabSync": "Synk",
+ "TitleUsers": "Brukere",
+ "LabelProtocol": "Protokoll:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Kontekst",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Synk",
+ "ButtonAddToPlaylist": "Legg til spilleliste",
+ "TabPlaylists": "Spliielister",
+ "ButtonClose": "Lukk",
+ "LabelAllLanguages": "Alle spr\u00e5k",
+ "HeaderBrowseOnlineImages": "Bla Igjennom Bilder Online",
+ "LabelSource": "Kilde:",
+ "OptionAll": "Alle",
+ "LabelImage": "Bilde:",
+ "ButtonBrowseImages": "Bla Igjennom Bilder",
+ "HeaderImages": "Bilder",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Legg Til\/Oppdater Bilde",
+ "LabelJpgPngOnly": "JPG\/PNG kun",
+ "LabelImageType": "Bilde type:",
+ "OptionPrimary": "Prim\u00e6re",
+ "OptionArt": "Art",
+ "OptionBox": "Boks",
+ "OptionBoxRear": "Boks bak",
+ "OptionDisc": "Disk",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Meny",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "L\u00e5st",
+ "OptionUnidentified": "uidentifisert",
+ "OptionMissingParentalRating": "Mangler foreldresensur",
+ "OptionStub": "stump",
+ "HeaderEpisodes": "Episoder:",
+ "OptionSeason0": "Sesong 0",
+ "LabelReport": "Rapport:",
+ "OptionReportSongs": "Sanger:",
+ "OptionReportSeries": "Serier",
+ "OptionReportSeasons": "Sesonger",
+ "OptionReportTrailers": "Trailere",
+ "OptionReportMusicVideos": "Musikkvideoer",
+ "OptionReportMovies": "Filmer",
+ "OptionReportHomeVideos": "Hjemme videoer",
+ "OptionReportGames": "Spill",
+ "OptionReportEpisodes": "Episoder",
+ "OptionReportCollections": "Samlinger",
+ "OptionReportBooks": "B\u00f8ker",
+ "OptionReportArtists": "Artisert",
+ "OptionReportAlbums": "Albumer",
+ "OptionReportAdultVideos": "Voksen videoer",
+ "ButtonMore": "Mer",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 31f4a38fe..8eda36b99 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/nl.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/nl.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Meld administratieve gebruikers wanneer:",
- "HeaderEnableNotificationForPlayback": "Meld wanneer gebruikers spelen:",
- "OptionNotifyOnUpdates": "Updates zijn beschikbaar zijn",
- "OptionNotifyOnVideoPlayback": "Video afspelen",
- "OptionNotifyOnAudioPlayback": "Audio afspelen",
- "OptionNotifyOnGamePlayback": "Games afspelen",
- "OptionNotifyOnFailedTasks": "Geplande taken mislukt zijn",
- "OptionNotifyOnNewLibraryContent": "Nieuwe bibliotheek inhoud wordt toegevoegd",
- "OptionNotifyOnServerRestartRequired": "De server moet opnieuw worden gestart",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Updates",
- "HeaderUpdateLevel": "Update Niveau",
- "LabelRequireTextSubtitles": "Ook downloaden als de film al ondertitels bevat",
- "LabelRequireTextSubtitlesHelp": "Als de tekst versies van ondertiteling bewaard wordt zal er effici\u00ebnter naar mobiele apparaten gespeeld worden.",
- "HeaderSubtitleDownloadingMoreHelp": "Ondertiteling wordt als missend gezien als het audio spoor in een buitenlandse taal is en er geen ondertiteling in de voorkeurstaal aanwezig is.",
- "LabelDisplayForcedSubtitlesOnly": "laat alleen geforceerde ondertiteling zien",
- "HeaderCustomizeOptionsPerMediaType": "Pas opties aan per mediatype",
- "LabelAudioLanguagePreferenceHelp": "Indien niet ingevuld zal het standaard audio spoor geselecteerd worden, ongeacht de taal.",
- "TabCustomizations": "Aanpassingen",
- "HeaderAllDevices": "Alle apparaten",
- "HeaderThisDevice": "Dit apparaat",
- "OptionLibraryButtons": "Bibliotheek knoppen",
- "OptionLibraryTiles": "Bibliotheek tegels (groot)",
- "OptionSmallLibraryTiles": "Bibliotheek tegels (klein)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Mislukt",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Vorig nummer",
- "ButtonNextTrack": "Volgend nummer",
- "HeaderMyLibrary": "Mijn Bibliotheek",
- "HeaderLibraryViews": "Bibliotheken overzicht",
+ "HeaderPeople": "Personen",
"LabelExit": "Afsluiten",
+ "HeaderDownloadPeopleMetadataFor": "Download biografie en afbeeldingen voor:",
"LabelVisitCommunity": "Bezoek Gemeenschap",
+ "OptionComposers": "Componisten",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Overigen",
"LabelSwagger": "Swagger",
"LabelStandard": "Standaard",
+ "HeaderDownloadPeopleMetadataForHelp": "Het inschakelen van extra opties zal meer informatie op het scherm bieden, maar resulteert in tragere bibliotheek scan.",
"LabelViewApiDocumentation": "Bekijk Api documentatie",
+ "ViewTypeFolders": "Mappen",
"LabelBrowseLibrary": "Bekijk bibliotheek",
+ "LabelDisplayFoldersView": "Toon een mappenweergave als u gewoon Mediamappen wilt weergeven",
"LabelConfigureMediaBrowser": "Configureer Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Opnamen",
"LabelOpenLibraryViewer": "Open bibliotheek verkenner",
+ "ViewTypeLiveTvChannels": "Kanalen",
"LabelRestartServer": "Server herstarten",
+ "LabelAllowLocalAccessWithoutPassword": "Lokale toegang toestaan zonder wachtwoord",
"LabelShowLogWindow": "Toon log venster",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "Als dit ingeschakled is dan kan er in het thuisnetwerk zonder wachtwoord aangemeld worden.",
"LabelPrevious": "Vorige",
+ "HeaderPassword": "Wachtwoord",
"LabelFinish": "Voltooien",
+ "HeaderLocalAccess": "Lokale toegang",
"LabelNext": "Volgende",
+ "HeaderViewOrder": "Weergave volgorde",
"LabelYoureDone": "Gereed!",
+ "LabelSelectUserViewOrder": "Kies de volgorde van uw weergaven die zullen worden weergegeven in Media Browser applicaties",
"WelcomeToMediaBrowser": "Welkom bij Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata vernieuw mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Afbeelding vernieuw mode:",
"ThisWizardWillGuideYou": "Deze wizard helpt u door het setup-proces.",
+ "OptionDownloadMissingImages": "Ontbrekende afbeeldingen downloaden",
"TellUsAboutYourself": "Vertel ons over u zelf",
+ "OptionReplaceExistingImages": "Bestaande afbeeldingen vervangen",
"LabelYourFirstName": "Uw voornaam:",
+ "OptionRefreshAllData": "Vernieuw alle gegevens",
"MoreUsersCanBeAddedLater": "Meer gebruikers kunnen later via het dashboard worden toegevoegd.",
+ "OptionAddMissingDataOnly": "Alleen ontbrekende gegevens toevoegen",
"UserProfilesIntro": "Media Browser bevat ingebouwde ondersteuning voor gebruikersprofielen, zodat iedere gebruiker zijn eigen display-instellingen, afspeelstatus en ouderlijk toezicht heeft.",
+ "OptionLocalRefreshOnly": "Alleen lokaal vernieuwen",
"LabelWindowsService": "Windows Service",
+ "HeaderRefreshMetadata": "Vernieuw metagegevens",
"AWindowsServiceHasBeenInstalled": "Er is een Windows service ge\u00efnstalleerd.",
+ "HeaderPersonInfo": "Persoon informatie",
"WindowsServiceIntro1": "Media Browser Server werkt normaal als een desktop applicatie met een pictogram in het systeemvak, maar wanneer u het liever op de achtergrond als service laat draaien, dan kan dit worden ingesteld vanuit het Windows services configuratie scherm.",
+ "HeaderIdentifyItem": "Identificeer item",
"WindowsServiceIntro2": "Wanneer u de Windows-service gebruikt, dan dient u er rekening mee te houden dat het niet op hetzelfde moment als de desktop applicatie kan worden uitgevoerd. Het is daarom vereist de desktop applicatie eerst af te sluiten voordat u de service gebruikt. De service moet worden geconfigureerd met beheerdersrechten via het configuratie scherm. Houd er rekening mee dat op dit moment de service niet automatisch kan worden bijgewerkt, zodat nieuwe versies dus handmatige interactie vereisen.",
+ "HeaderIdentifyItemHelp": "Vul \u00e9\u00e9n of meer zoek criteria in. Verwijder criteria om zoekresultaten te vergroten.",
"WizardCompleted": "Dit is alles wat we nodig hebben voor nu. Media Browser is begonnen met het verzamelen van informatie over uw mediabibliotheek. Bekijk enkele van onze apps, en klik vervolgens op <b>Voltooien<\/b> om het <b>Dashboard te bekijken<\/b>.",
+ "HeaderConfirmDeletion": "Bevestigen Verwijdering",
"LabelConfigureSettings": "Configureer instellingen",
+ "LabelFollowingFileWillBeDeleted": "Het volgende bestand wordt verwijderd.",
"LabelEnableVideoImageExtraction": "Videobeeld extractie inschakelen",
+ "LabelIfYouWishToContinueWithDeletion": "Geef om door te gaan het resultaat in:",
"VideoImageExtractionHelp": "Voor video's die nog geen afbeeldingen hebben, en waarvoor geen afbeeldingen op Internet te vinden zijn. Dit voegt extra tijd toe aan de oorspronkelijke bibliotheek scan, maar resulteert in een mooiere weergave.",
+ "ButtonIdentify": "Identificeer",
"LabelEnableChapterImageExtractionForMovies": "Extraheer hoofdstuk afbeeldingen voor Films",
+ "LabelAlbumArtist": "Album artiest:",
"LabelChapterImageExtractionForMoviesHelp": "Extraheren van hoofdstuk afbeeldingen geeft de Cli\u00ebnt de mogelijkheid om grafische scene selectie menu's te tonen. Het proces kan traag en cpu-intensief zijn en kan enkele gigabytes aan ruimte vereisen. Het word uitgevoerd als nachtelijke taak om 4:00, maar dit is instelbaar via de geplande taken. Het wordt niet aanbevolen om deze taak uit te voeren tijdens de piekuren.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Automatische poorttoewijzing inschakelen",
+ "LabelCommunityRating": "Beoordeling gemeenschap:",
"LabelEnableAutomaticPortMappingHelp": "UPnP zorgt voor geautomatiseerde configuratie van de router voor gemakkelijke toegang op afstand. Dit werkt mogelijk niet met sommige routers.",
+ "LabelVoteCount": "Aantal stemmen:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Annuleren",
+ "LabelCriticRating": "Beoordeling critici:",
"ButtonNew": "Nieuw",
+ "LabelCriticRatingSummary": "Samenvatting beoordeling critici:",
"HeaderSetupLibrary": "Stel uw mediabibliotheek in",
+ "LabelAwardSummary": "Samenvatting prijzen:",
"ButtonAddMediaFolder": "Mediamap toevoegen",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Maptype:",
- "MediaFolderHelpPluginRequired": "* Hiervoor is het gebruik van een plug-in vereist, bijvoorbeeld GameBrowser of MB Bookshelf.",
+ "LabelTagline": "Tagline:",
+ "MediaFolderHelpPluginRequired": "* Hiervoor is het gebruik van een Plug-in vereist, bijvoorbeeld GameBrowser of MB Bookshelf.",
+ "LabelOverview": "Overzicht:",
"ReferToMediaLibraryWiki": "Raadpleeg de mediabibliotheek wiki.",
+ "LabelShortOverview": "Kort overzicht:",
"LabelCountry": "Land:",
+ "LabelReleaseDate": "Uitgave datum:",
"LabelLanguage": "Taal:",
- "HeaderPreferredMetadataLanguage": "Gewenste metagegevens taal:",
- "LabelSaveLocalMetadata": "Sla afbeeldingen en metagegevens op in de mediamappen",
- "LabelSaveLocalMetadataHelp": "Door afbeeldingen en metagegevens op te slaan in de mediamappen kunnen ze makkelijker worden gevonden en bewerkt.",
- "LabelDownloadInternetMetadata": "Download afbeeldingen en metagegevens van het internet",
+ "LabelYear": "Jaar:",
+ "HeaderPreferredMetadataLanguage": "Gewenste metadata taal:",
+ "LabelPlaceOfBirth": "Geboorteplaats:",
+ "LabelSaveLocalMetadata": "Sla afbeeldingen en metadata op in de mediamappen",
+ "LabelEndDate": "Eind datum|",
+ "LabelSaveLocalMetadataHelp": "Door afbeeldingen en metadata op te slaan in de mediamappen kunnen ze makkelijker worden gevonden en bewerkt.",
+ "LabelAirDate": "Uitzend dagen:",
+ "LabelDownloadInternetMetadata": "Download afbeeldingen en metadata van het internet",
+ "LabelAirTime:": "Uitzend tijd:",
"LabelDownloadInternetMetadataHelp": "Media Browser kan informatie en afbeeldingen van uw media downloaden, om zo een mooie en uitgebreide weergave mogelijk te maken.",
+ "LabelRuntimeMinutes": "Speelduur (minuten):",
"TabPreferences": "Voorkeuren",
+ "LabelParentalRating": "Kijkwijzer classificatie:",
"TabPassword": "Wachtwoord",
+ "LabelCustomRating": "Aangepaste classificatie:",
"TabLibraryAccess": "Bibliotheek toegang",
+ "LabelBudget": "Budget",
"TabImage": "Afbeelding",
+ "LabelRevenue": "Omzet ($):",
"TabProfile": "Profiel",
+ "LabelOriginalAspectRatio": "Originele aspect ratio:",
"TabMetadata": "Metagegevens",
+ "LabelPlayers": "Spelers:",
"TabImages": "Afbeeldingen",
+ "Label3DFormat": "3D formaat",
"TabNotifications": "Meldingen",
+ "HeaderAlternateEpisodeNumbers": "Afwijkende afleveringsnummers",
"TabCollectionTitles": "Titels",
+ "HeaderSpecialEpisodeInfo": "Speciale afleveringsinformatie",
"LabelDisplayMissingEpisodesWithinSeasons": "Toon ontbrekende afleveringen binnen een seizoen",
+ "HeaderExternalIds": "Externe Id's",
"LabelUnairedMissingEpisodesWithinSeasons": "Toon komende afleveringen binnen een seizoen",
+ "LabelDvdSeasonNumber": "Dvd seizoensnummer:",
"HeaderVideoPlaybackSettings": "Video afspeel instellingen",
+ "LabelDvdEpisodeNumber": "Dvd afleveringsnummer:",
"HeaderPlaybackSettings": "Afspeel instellingen",
+ "LabelAbsoluteEpisodeNumber": "Absoluut afleveringsnummer:",
"LabelAudioLanguagePreference": "Voorkeurs taal geluid:",
+ "LabelAirsBeforeSeason": "Uitgezonden voor seizoen:",
"LabelSubtitleLanguagePreference": "Voorkeurs taal ondertiteling:",
+ "LabelAirsAfterSeason": "Uitgezonden na seizoen:",
"OptionDefaultSubtitles": "Standaard",
+ "LabelAirsBeforeEpisode": "Uitgezonden voor aflevering:",
"OptionOnlyForcedSubtitles": "Alleen 'geforceerde' ondertiteling",
- "OptionAlwaysPlaySubtitles": "Altijd ondertiteling weergeven",
+ "LabelTreatImageAs": "Behandel afbeelding als:",
+ "OptionAlwaysPlaySubtitles": "Ondertiteling altijd weergeven",
+ "LabelDisplayOrder": "Weergave volgorde:",
"OptionNoSubtitles": "Geen ondertitels",
- "OptionDefaultSubtitlesHelp": "Ondertiteling wordt weergegeven in de voorkeurstaal als de audio in een buitenlandse taal is.",
- "OptionOnlyForcedSubtitlesHelp": "Alleen ondertiteling die als 'forced' gemarkeerd zijn worden geladen.",
+ "LabelDisplaySpecialsWithinSeasons": "Voeg specials toe aan het seizoen waarin ze uitgezonden zijn",
+ "OptionDefaultSubtitlesHelp": "Ondertiteling wordt weergegeven in de voorkeurstaal als de audio in een andere taal is.",
+ "HeaderCountries": "Landen",
+ "OptionOnlyForcedSubtitlesHelp": "Alleen ondertitels gemarkeerd als \"gedwongen\" zullen worden geladen.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Ondertiteling wordt weergegeveen in de voorkeurstaal ongeacht de taal van de audio.",
- "OptionNoSubtitlesHelp": "Ondertiteling wordt niet standaard weergegeven.",
+ "HeaderPlotKeywords": "Trefwoorden plot",
+ "OptionNoSubtitlesHelp": "Ondertiteling wordt standaard niet weergegeven.",
+ "HeaderStudios": "Studio's",
"TabProfiles": "Profielen",
+ "HeaderTags": "Labels",
"TabSecurity": "Beveiliging",
+ "HeaderMetadataSettings": "Metagegevens instellingen",
"ButtonAddUser": "Gebruiker toevoegen",
+ "LabelLockItemToPreventChanges": "Blokkeer dit item tegen wijzigingen",
"ButtonSave": "Opslaan",
+ "MessageLeaveEmptyToInherit": "Leeg laten om instellingen van bovenliggend item of de algemene waarde over te nemen.",
"ButtonResetPassword": "Wachtwoord resetten",
+ "TabSupporterClub": "Supporters club",
"LabelNewPassword": "Nieuw wachtwoord:",
+ "HeaderDonationType": "Donatie soort:",
"LabelNewPasswordConfirm": "Bevestig nieuw wachtwoord:",
+ "OptionMakeOneTimeDonation": "Doe een eenmalige donatie",
"HeaderCreatePassword": "Maak wachtwoord",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Huidig wachtwoord",
- "LabelMaxParentalRating": "Leeftijdsgrens",
+ "OptionLifeTimeSupporterClubMembership": "Levenslang supporters club lidmaatschap",
+ "LabelMaxParentalRating": "Maximaal toegestane kijkwijzer classificatie:",
+ "HeaderSupporterBenefit": "Lid worden van de supporters club heeft voordelen als toegang tot premium plugins, internet kanalen en meer.",
"MaxParentalRatingHelp": "Media met een hogere classificatie wordt niet weergegeven",
- "LibraryAccessHelp": "Selecteer de mediamappen om met deze gebruiker te delen. Beheerders kunnen alle mappen bewerken via de metagegevens manager.",
- "ChannelAccessHelp": "Selecteer de kanalen om te delen met deze gebruiker. Beheerders kunnen alle kanalen bewerken met de metagegevens manager.",
+ "OptionNoTrailer": "Geen trailer",
+ "LibraryAccessHelp": "Selecteer de mediamappen om met deze gebruiker te delen. Beheerders kunnen alle mappen bewerken via de metadata manager.",
+ "OptionNoThemeSong": "Geen thema muziek",
+ "ChannelAccessHelp": "Selecteer de kanalen om te delen met deze gebruiker. Beheerders kunnen alle kanalen bewerken met de metadata manager.",
+ "OptionNoThemeVideo": "Geen thema film",
"ButtonDeleteImage": "Verwijder afbeelding",
+ "LabelOneTimeDonationAmount": "Donatie bedrag:",
"LabelSelectUsers": "Selecteer gebruikers:",
+ "OptionActor": "Actor",
"ButtonUpload": "Uploaden",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Nieuwe afbeelding uploaden",
- "LabelDropImageHere": "Hier afbeelding plaatsen",
+ "OptionDirector": "Director",
+ "LabelDropImageHere": "Afbeelding hier neerzetten",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "1:1 beeldverhouding geadviseerd. Alleen JPG\/PNG.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Lijst is leeg.",
- "MessagePleaseEnsureInternetMetadata": "Zorg ervoor dat het downloaden van metagegevens van het internet is ingeschakeld.",
+ "OptionWriter": "Writer",
+ "MessagePleaseEnsureInternetMetadata": "Zorg ervoor dat het downloaden van metadata van het internet is ingeschakeld.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Aanbevolen",
+ "LabelAirTime": "Air time:",
"TabLatest": "Nieuw",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "Binnenkort",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Series",
"TabEpisodes": "Afleveringen",
"TabGenres": "Genres",
@@ -145,7 +207,7 @@
"OptionDirectors": "Regiseurs",
"OptionWriters": "Schrijvers",
"OptionProducers": "Producenten",
- "HeaderResume": "Hervatbaar",
+ "HeaderResume": "Hervatten",
"HeaderNextUp": "Eerstvolgende",
"NoNextUpItemsMessage": "Niets gevonden. Start met kijken!",
"HeaderLatestEpisodes": "Nieuwste Afleveringen",
@@ -163,14 +225,14 @@
"OptionAscending": "Oplopend",
"OptionDescending": "Aflopend",
"OptionRuntime": "Speelduur",
- "OptionReleaseDate": "Release Datum",
+ "OptionReleaseDate": "Uitgave datum",
"OptionPlayCount": "Afspeel telling",
"OptionDatePlayed": "Datum afgespeeld",
"OptionDateAdded": "Datum toegevoegd",
"OptionAlbumArtist": "Albumartiest",
"OptionArtist": "Artiest",
"OptionAlbum": "Album",
- "OptionTrackName": "Track Naam",
+ "OptionTrackName": "Naam van Nummer",
"OptionCommunityRating": "Gemeenschaps Waardering",
"OptionNameSort": "Naam",
"OptionFolderSort": "Mappen",
@@ -195,7 +257,7 @@
"HeaderLatestSongs": "Nieuwste Songs",
"HeaderRecentlyPlayed": "Recent afgespeeld",
"HeaderFrequentlyPlayed": "Vaak afgespeeld",
- "DevBuildWarning": "Development versies zijn voor eigen risico. Ze worden vaak uitgegeven, deze versies zijn niet getest!. De Applicatie kan crashen en sommige functies kunnen mogelijk niet meer werken.",
+ "DevBuildWarning": "Development versies zijn geheel voor eigen risico. Deze versies worden vaak vrijgegeven en zijn niet getest!. De Applicatie kan crashen en sommige functies kunnen mogelijk niet meer werken.",
"LabelVideoType": "Video Type:",
"OptionBluray": "Blu-ray",
"OptionDvd": "Dvd",
@@ -213,6 +275,8 @@
"TabMovies": "Films",
"TabStudios": "Studio's",
"TabTrailers": "Trailers",
+ "LabelArtists": "Artiest:",
+ "LabelArtistsHelp": "Scheidt meerdere met een ;",
"HeaderLatestMovies": "Nieuwste Films",
"HeaderLatestTrailers": "Nieuwste Trailers",
"OptionHasSpecialFeatures": "Extra's",
@@ -224,7 +288,7 @@
"HeaderStatus": "Status",
"OptionContinuing": "Wordt vervolgd...",
"OptionEnded": "Gestopt",
- "HeaderAirDays": "Uitzend dagen:",
+ "HeaderAirDays": "Uitzend Dagen",
"OptionSunday": "Zondag",
"OptionMonday": "Maandag",
"OptionTuesday": "Dinsdag",
@@ -232,11 +296,12 @@
"OptionThursday": "Donderdag",
"OptionFriday": "Vrijdag",
"OptionSaturday": "Zaterdag",
- "HeaderManagement": "Beheer:",
+ "HeaderManagement": "Beheer",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "IMDb Id ontbreekt",
"OptionMissingTvdbId": "TheTVDB Id ontbreekt",
"OptionMissingOverview": "Overzicht ontbreekt",
- "OptionFileMetadataYearMismatch": "Het jaartal in de Bestands\/metagegevens komt niet overeen",
+ "OptionFileMetadataYearMismatch": "Jaartal in Bestands\/metadata komt niet overeen",
"TabGeneral": "Algemeen",
"TitleSupport": "Ondersteuning",
"TabLog": "Logboek",
@@ -266,11 +331,10 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "Selecteer",
- "ButtonSearch": "Zoeken",
"ButtonGroupVersions": "Groepeer Versies",
"ButtonAddToCollection": "Toevoegen aan verzameling",
"PismoMessage": "Pismo File Mount (met een geschonken licentie).",
- "TangibleSoftwareMessage": "Tangible Solution Java\/C# converters worden onder een gedoneerde licentie gebruikt.",
+ "TangibleSoftwareMessage": "Gebruik makend van concrete oplossingen als Java \/ C converters door een geschonken licentie.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "Steun A.U.B. ook de andere gratis producten die wij gebruiken:",
"VersionNumber": "Versie {0}",
@@ -282,21 +346,21 @@
"OptionRelease": "Offici\u00eble Release",
"OptionBeta": "Beta",
"OptionDev": "Dev (Instabiel)",
- "LabelAllowServerAutoRestart": "Sta de server toe automatisch te herstarten om updates toe te passen",
- "LabelAllowServerAutoRestartHelp": "De server zal alleen opnieuw op tijdens inactieve perioden, wanneer er geen gebruikers actief zijn.",
+ "LabelAllowServerAutoRestart": "Automatisch herstarten van de server toestaan om updates toe te passen",
+ "LabelAllowServerAutoRestartHelp": "De server zal alleen opnieuw opstarten tijdens inactieve perioden, wanneer er geen gebruikers actief zijn.",
"LabelEnableDebugLogging": "Foutopsporings logboek inschakelen",
"LabelRunServerAtStartup": "Start server bij het aanmelden",
- "LabelRunServerAtStartupHelp": "Dit zal de applicatie starten als pictogram in het systeemvak tijdens het aanmelden van Windows. Om de Windows-service te starten, schakelt u deze uit en start u de service via het Configuratiescherm van Windows. Houd er rekening mee dat u de service en de applicatie niet tegelijk kunt uitvoeren, u moet dus eerst de applicatie sluiten alvorens u de service start.",
+ "LabelRunServerAtStartupHelp": "Dit start de applicatie als pictogram in het systeemvak tijdens het aanmelden van Windows. Om de Windows-service te starten, schakelt u deze uit en start u de service via het Configuratiescherm van Windows. Houd er rekening mee dat u de service en de applicatie niet tegelijk kunt uitvoeren, u moet dus eerst de applicatie sluiten alvorens u de service start.",
"ButtonSelectDirectory": "Selecteer map",
"LabelCustomPaths": "Geef aangepaste paden op waar gewenst. Laat velden leeg om de standaardinstellingen te gebruiken.",
"LabelCachePath": "Cache pad:",
- "LabelCachePathHelp": "Deze map bevat server cache-bestanden, zoals afbeeldingen.",
+ "LabelCachePathHelp": "Deze locatie bevat server cache-bestanden, zoals afbeeldingen.",
"LabelImagesByNamePath": "Afbeeldingen op naam pad:",
- "LabelImagesByNamePathHelp": "Deze map bevat afbeeldingen van: acteurs, artiesten, genres en studio's.",
- "LabelMetadataPath": "metagegevens pad:",
- "LabelMetadataPathHelp": "Deze locatie bevat gedownloade afbeeldingen en metagegevens die niet zijn geconfigureerd om te worden opgeslagen in mediamappen .",
+ "LabelImagesByNamePathHelp": "Deze locatie bevat afbeeldingen van: acteurs, artiesten, genres en studio's.",
+ "LabelMetadataPath": "metadata pad:",
+ "LabelMetadataPathHelp": "Geef een aangepaste locatie op voor gedownloade afbeeldingen en metadata, indien niet opgeslagen in mediamappen.",
"LabelTranscodingTempPath": "Tijdelijk Transcodeer pad:",
- "LabelTranscodingTempPathHelp": "Deze map bevat werkbestanden die worden gebruikt door de transcoder.",
+ "LabelTranscodingTempPathHelp": "Deze map bevat werkbestanden die worden gebruikt door de transcoder. Geef een eigen locatie op of laat leeg om de standaardlocatie te gebruiken.",
"TabBasics": "Basis",
"TabTV": "TV",
"TabGames": "Games",
@@ -306,19 +370,19 @@
"OptionMovies": "Films",
"OptionEpisodes": "Afleveringen",
"OptionOtherVideos": "Overige Video's",
- "TitleMetadata": "Metagegevens",
+ "TitleMetadata": "Metadata",
"LabelAutomaticUpdatesFanart": "Schakel de automatische update in van FanArt.tv",
"LabelAutomaticUpdatesTmdb": "Schakel de automatische update in van TheMovieDB.org",
"LabelAutomaticUpdatesTvdb": "Schakel de automatische update in van TheTVDB.com",
"LabelAutomaticUpdatesFanartHelp": "Indien ingeschakeld, worden nieuwe afbeeldingen automatisch gedownload wanneer ze zijn toegevoegd aan fanart.tv. Bestaande afbeeldingen zullen niet worden vervangen.",
"LabelAutomaticUpdatesTmdbHelp": "Indien ingeschakeld, worden nieuwe afbeeldingen automatisch gedownload wanneer ze zijn toegevoegd aan TheMovieDB.org. Bestaande afbeeldingen zullen niet worden vervangen.",
"LabelAutomaticUpdatesTvdbHelp": "Indien ingeschakeld, worden nieuwe afbeeldingen automatisch gedownload wanneer ze zijn toegevoegd aan TheTVDB.com. Bestaande afbeeldingen zullen niet worden vervangen.",
- "ExtractChapterImagesHelp": "Extraheren van hoofdstuk afbeeldingen geeft de Cli\u00ebnt de mogelijkheid om grafische scene selectie menu's te tonen. Het proces kan traag en cpu-intensief zijn en kan enkele gigabytes aan ruimte vereisen. Het word uitgevoerd als nachtelijke taak om 4:00, maar dit is instelbaar via de geplande taken. Het wordt niet aanbevolen om deze taak uit te voeren tijdens de piekuren.",
+ "ExtractChapterImagesHelp": "Extraheren van hoofdstuk afbeeldingen geeft de cli\u00ebnt de mogelijkheid om grafische scene selectie menu's te tonen. Het proces kan traag en cpu-intensief zijn en kan enkele gigabytes aan ruimte vereisen. Het word uitgevoerd als nachtelijke taak om 4:00. Deze taak is in te stellen via de geplande taken. Het wordt niet aanbevolen om deze taak uit te voeren tijdens de piekuren.",
"LabelMetadataDownloadLanguage": "Voorkeurs taal:",
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Afbeelding opslag conventie:",
"LabelImageSavingConventionHelp": "Media Browser herkent afbeeldingen van de meeste grote media-applicaties. Het kiezen van uw download conventie is handig als u ook gebruik wilt maken van andere producten.",
- "OptionImageSavingCompatible": "Compatibel - Media Browser \/ Plex \/ XBMC",
+ "OptionImageSavingCompatible": "Compatibel - Media Browser \/ XBMC \/ Plex",
"OptionImageSavingStandard": "Standaard - MB2",
"ButtonSignIn": "Aanmelden",
"TitleSignIn": "Aanmelden",
@@ -329,7 +393,7 @@
"PasswordLocalhostMessage": "Wachtwoorden zijn niet vereist bij het aanmelden van localhost.",
"TabGuide": "Gids",
"TabChannels": "Kanalen",
- "TabCollections": "Verzameling",
+ "TabCollections": "Verzamelingen",
"HeaderChannels": "Kanalen",
"TabRecordings": "Opnamen",
"TabScheduled": "Gepland",
@@ -347,6 +411,8 @@
"TabStatus": "Status",
"TabSettings": "Instellingen",
"ButtonRefreshGuideData": "Gidsgegevens Vernieuwen",
+ "ButtonRefresh": "Vernieuwen",
+ "ButtonAdvancedRefresh": "Geavanceerd vernieuwen",
"OptionPriority": "Prioriteit",
"OptionRecordOnAllChannels": "Programma van alle kanalen opnemen",
"OptionRecordAnytime": "Programma elke keer opnemen",
@@ -366,10 +432,10 @@
"LabelNumberOfGuideDays": "Aantal dagen van de gids om te downloaden:",
"LabelNumberOfGuideDaysHelp": "Het downloaden van meer dagen van de gids gegevens biedt de mogelijkheid verder vooruit te plannen en een beter overzicht geven, maar het zal ook langer duren om te downloaden. Auto kiest op basis van het aantal kanalen.",
"LabelActiveService": "Actieve Service:",
- "LabelActiveServiceHelp": "Er kunnen meerdere tv plug-ins worden ge\u00efnstalleerd, maar er kan er slechts een per keer actief zijn.",
+ "LabelActiveServiceHelp": "Er kunnen meerdere tv Plug-ins worden ge\u00efnstalleerd, maar er kan er slechts een per keer actief zijn.",
"OptionAutomatic": "Automatisch",
- "LiveTvPluginRequired": "Een Live TV service provider plug-in is vereist om door te gaan.",
- "LiveTvPluginRequiredHelp": "Installeer a.u b een van onze beschikbare plug-ins, zoals Next PVR of ServerWmc.",
+ "LiveTvPluginRequired": "Een Live TV service provider Plug-in is vereist om door te gaan.",
+ "LiveTvPluginRequiredHelp": "Installeer a.u b een van onze beschikbare Plug-ins, zoals Next PVR of ServerWmc.",
"LabelCustomizeOptionsPerMediaType": "Aanpassen voor mediatype",
"OptionDownloadThumbImage": "Miniatuur",
"OptionDownloadMenuImage": "Menu",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Cast & Crew",
"HeaderAdditionalParts": "Extra onderdelen",
"ButtonSplitVersionsApart": "Splits Versies Apart",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Ontbreekt",
"LabelOffline": "Offline",
"PathSubstitutionHelp": "Pad vervangen worden gebruikt voor het in kaart brengen van een pad op de server naar een pad dat de Cli\u00ebnt in staat stelt om toegang te krijgen. Doordat de Cli\u00ebnt directe toegang tot de media op de server heeft is deze in staat om ze direct af te spelen via het netwerk. Daardoor wordt het gebruik van server resources om te streamen en te transcoderen vermeden.",
@@ -487,7 +554,7 @@
"HeaderAddToCollection": "Toevoegen aan verzameling",
"ButtonSubmit": "Uitvoeren",
"NewCollectionNameExample": "Voorbeeld: Star Wars Collectie",
- "OptionSearchForInternetMetadata": "Zoeken op het internet voor afbeeldingen en metagegevens",
+ "OptionSearchForInternetMetadata": "Zoeken op het internet voor afbeeldingen en metadata",
"ButtonCreate": "Cre\u00ebren",
"LabelHttpServerPortNumber": "Http server poortnummer:",
"LabelWebSocketPortNumber": "Web socket poortnummer:",
@@ -512,8 +579,10 @@
"HeaderProgram": "Programma",
"HeaderClients": "Clients",
"LabelCompleted": "Compleet",
+ "LabelFailed": "Mislukt",
"LabelSkipped": "Overgeslagen",
"HeaderEpisodeOrganization": "Afleveringen Organisatie",
+ "LabelSeries": "Series:",
"LabelSeasonNumber": "Seizoen:",
"LabelEpisodeNumber": "Aflevering:",
"LabelEndingEpisodeNumber": "Laatste aflevering:",
@@ -553,7 +622,7 @@
"HeaderHelpImproveMediaBrowser": "Help Media Browser te verbeteren",
"HeaderRunningTasks": "Actieve taken",
"HeaderActiveDevices": "Actieve apparaten",
- "HeaderPendingInstallations": "In afwachting van Installaties",
+ "HeaderPendingInstallations": "In afwachting van installaties",
"HeaerServerInformation": "Server Informatie",
"ButtonRestartNow": "Nu opnieuw opstarten",
"ButtonRestart": "Herstart",
@@ -584,7 +653,7 @@
"ErrorMessageInvalidKey": "Voordat U premium content kunt registreren, moet u eerst een MediaBrowser Supporter zijn. Ondersteun en doneer a.u.b. om de continue verdere ontwikkeling van MediaBrowser te waarborgen. Dank u.",
"HeaderDisplaySettings": "Weergave-instellingen",
"TabPlayTo": "Afspelen met",
- "LabelEnableDlnaServer": "Dlna Server inschakelen",
+ "LabelEnableDlnaServer": "DLNA Server inschakelen",
"LabelEnableDlnaServerHelp": "Hiermee kunnen UPnP-apparaten op uw netwerk Media Browser inhoud doorzoeken en afspelen.",
"LabelEnableBlastAliveMessages": "Zend alive berichten",
"LabelEnableBlastAliveMessagesHelp": "Zet dit aan als de server niet betrouwbaar door andere UPnP-apparaten op uw netwerk wordt gedetecteerd.",
@@ -607,9 +676,9 @@
"HeaderNotificationList": "Klik op een melding om de opties voor het versturen ervan te configureren .",
"NotificationOptionApplicationUpdateAvailable": "Programma-update beschikbaar",
"NotificationOptionApplicationUpdateInstalled": "Programma-update ge\u00efnstalleerd",
- "NotificationOptionPluginUpdateInstalled": "Plugin-update ge\u00efnstalleerd",
- "NotificationOptionPluginInstalled": "Plugin ge\u00efnstalleerd",
- "NotificationOptionPluginUninstalled": "Plugin verwijderd",
+ "NotificationOptionPluginUpdateInstalled": "Plug-in-update ge\u00efnstalleerd",
+ "NotificationOptionPluginInstalled": "Plug-in ge\u00efnstalleerd",
+ "NotificationOptionPluginUninstalled": "Plug-in verwijderd",
"NotificationOptionVideoPlayback": "Video afspelen gestart",
"NotificationOptionAudioPlayback": "Audio afspelen gestart",
"NotificationOptionGamePlayback": "Game gestart",
@@ -620,12 +689,11 @@
"NotificationOptionInstallationFailed": "Mislukken van de installatie",
"NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd",
"NotificationOptionNewLibraryContentMultiple": "Nieuwe content toegevoegd (meerdere)",
- "SendNotificationHelp": "Meldingen worden geplaatst in de inbox op het dashboard. Blader door de Plug-ins catalogus om aanvullende opties voor meldingen te installeren.",
+ "SendNotificationHelp": "Meldingen worden geplaatst in de inbox op het dashboard. Blader door de Plug-in catalogus om aanvullende opties voor meldingen te installeren.",
"NotificationOptionServerRestartRequired": "Server herstart nodig",
"LabelNotificationEnabled": "Deze melding inschakelen",
"LabelMonitorUsers": "Monitor activiteit van:",
"LabelSendNotificationToUsers": "Stuur de melding naar:",
- "UsersNotNotifiedAboutSelfActivity": "Gebruikers zullen niet worden ge\u00efnformeerd over hun eigen activiteiten.",
"LabelUseNotificationServices": "Gebruik de volgende diensten:",
"CategoryUser": "Gebruiker",
"CategorySystem": "Systeem",
@@ -633,7 +701,7 @@
"CategoryPlugin": "Plug-in",
"LabelMessageTitle": "Titel van het bericht:",
"LabelAvailableTokens": "Beschikbaar tokens:",
- "AdditionalNotificationServices": "Blader door de plug-in catalogus om aanvullende meldingsdiensten te installeren.",
+ "AdditionalNotificationServices": "Blader door de Plug-in catalogus om aanvullende meldingsdiensten te installeren.",
"OptionAllUsers": "Alle gebruikers",
"OptionAdminUsers": "Beheerders",
"OptionCustomUsers": "Aangepast",
@@ -643,11 +711,12 @@
"ButtonArrowRight": "Rechts",
"ButtonBack": "Terug",
"ButtonInfo": "Info",
- "ButtonOsd": "On Screen Display",
+ "ButtonOsd": "Weergave op het scherm",
"ButtonPageUp": "Page Up",
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
"ButtonHome": "Start",
+ "ButtonSearch": "Zoeken",
"ButtonSettings": "Instellingen",
"ButtonTakeScreenshot": "Vang Schermafbeelding",
"ButtonLetterUp": "Letter omhoog",
@@ -657,10 +726,12 @@
"TabNowPlaying": "Wordt nu afgespeeld",
"TabNavigation": "Navigatie",
"TabControls": "Besturing",
- "ButtonFullscreen": "Volledig scherm in-\/uitschakelen",
+ "ButtonFullscreen": "Schakelen tussen volledig scherm ",
"ButtonScenes": "Scenes",
"ButtonSubtitles": "Ondertitels",
"ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Vorige track",
+ "ButtonNextTrack": "Volgende track",
"ButtonStop": "Stop",
"ButtonPause": "Pauze",
"LabelGroupMoviesIntoCollections": "Groepeer films in verzamelingen",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Gescheiden door een komma. Deze kan leeg gelaten worden om te laten gelden voor alle containers.",
"HeaderResponseProfile": "Antwoord Profiel",
"LabelType": "Type:",
+ "LabelPersonRole": "Rol:",
+ "LabelPersonRoleHelp": "Rol is alleen van toepassing op acteurs.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "Deze waarden bepalen hoe Media Browser zichzelf zal presenteren aan het apparaat.",
"LabelMaxBitrate": "Max. bitrate:",
"LabelMaxBitrateHelp": "Geef een max. bitrate in bandbreedte beperkte omgevingen, of als het apparaat zijn eigen limiet heeft.",
+ "LabelMaxStreamingBitrate": "Maximale streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Geef een maximale bitrate voor streaming op.",
+ "LabelMaxStaticBitrate": "Maximale Synchronisatie bitrate:",
+ "LabelMaxStaticBitrateHelp": "Geef een maximale bitrate op voor synchroniseren in hoge kwaliteit.",
+ "LabelMusicStaticBitrate": "Muzieksynchronisatie bitrate:",
+ "LabelMusicStaticBitrateHelp": "Geef een maximum bitrate op voor het synchroniseren van muziek",
+ "LabelMusicStreamingTranscodingBitrate": "Muziek transcodering bitrate: ",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Geef een maximum bitrate op voor het streamen van muziek",
"OptionIgnoreTranscodeByteRangeRequests": "Transcodeer byte range-aanvragen negeren",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "Indien ingeschakeld, zal deze verzoeken worden gehonoreerd, maar zal de byte bereik header worden genegerd.",
"LabelFriendlyName": "Aangepaste naam",
@@ -751,7 +832,7 @@
"OptionReportByteRangeSeekingWhenTranscodingHelp": "Dit is vereist voor bepaalde apparaten die zo goed op tijd zoeken.",
"HeaderSubtitleDownloadingHelp": "Bij het scannen van uw videobestanden kan Media Browser naar ontbrekende ondertiteling zoeken en deze downloaden bij ondertiteling providers zoals OpenSubtitles.org.",
"HeaderDownloadSubtitlesFor": "Download ondertiteling voor:",
- "MessageNoChapterProviders": "Installeer een hoofdstuk provider plug-in zoals ChapterDb of tagChimp om extra hoofdstuk opties in te schakelen.",
+ "MessageNoChapterProviders": "Installeer een hoofdstuk provider Plug-in zoals ChapterDb om extra hoofdstuk opties in te schakelen.",
"LabelSkipIfGraphicalSubsPresent": "Overslaan als de video al grafische ondertitels bevat",
"LabelSkipIfGraphicalSubsPresentHelp": "Tekstversies houden van ondertitels zal resulteren in meer effici\u00ebnte levering aan mobiele clients.",
"TabSubtitles": "Ondertiteling",
@@ -759,29 +840,31 @@
"HeaderDownloadChaptersFor": "Download hoofdstuk namen voor:",
"LabelOpenSubtitlesUsername": "Gebruikersnaam Open Subtitles:",
"LabelOpenSubtitlesPassword": "Wachtwoord Open Subtitles:",
- "HeaderChapterDownloadingHelp": "Wanneer Media Browser uw videobestanden scant kan het gebruiksvriendelijke namen voor hoofdstukken downloaden van het internet met behulp van hoofdstuk plug-ins zoals ChapterDb en tagChimp.",
+ "HeaderChapterDownloadingHelp": "Wanneer Media Browser uw videobestanden scant kan het gebruiksvriendelijke namen voor hoofdstukken downloaden van het internet met behulp van hoofdstuk Plug-in zoals ChapterDb.",
"LabelPlayDefaultAudioTrack": "Speel standaard audio spoor ongeacht taal",
"LabelSubtitlePlaybackMode": "Ondertitelingsmode:",
"LabelDownloadLanguages": "Download talen:",
"ButtonRegister": "Aanmelden",
- "LabelSkipIfAudioTrackPresent": "Overslaan als de standaard audio track overeenkomt met de taal van de download",
+ "LabelSkipIfAudioTrackPresent": "Overslaan als het standaard audio spoor overeenkomt met de taal van de download",
"LabelSkipIfAudioTrackPresentHelp": "Uitvinken om ervoor te zorgen dat alle video's ondertitels krijgen, ongeacht de gesproken taal.",
"HeaderSendMessage": "Stuur bericht",
"ButtonSend": "Stuur",
"LabelMessageText": "Bericht tekst:",
- "MessageNoAvailablePlugins": "Geen beschikbare plugins.",
- "LabelDisplayPluginsFor": "Toon plugins voor:",
+ "MessageNoAvailablePlugins": "Geen beschikbare Plug-ins.",
+ "LabelDisplayPluginsFor": "Toon Plug-ins voor:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Overig",
- "LabelEpisodeName": "Naam aflevering",
- "LabelSeriesName": "Naam serie",
- "ValueSeriesNamePeriod": "Naam.Serie",
- "ValueSeriesNameUnderscore": "Naam_Serie",
- "ValueEpisodeNamePeriod": "Naam.Aflevering",
- "ValueEpisodeNameUnderscore": "Naam_Aflevering",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
+ "ValueSeriesNamePeriod": "Serie.Naam",
+ "ValueSeriesNameUnderscore": "Serie_naam",
+ "ValueEpisodeNamePeriod": "Aflevering.naam",
+ "ValueEpisodeNameUnderscore": "Aflevering_naam",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Voer tekst in",
- "LabelTypeText": "tekst",
+ "LabelTypeText": "Tekst",
"HeaderSearchForSubtitles": "Zoeken naar Ondertitels",
"MessageNoSubtitleSearchResultsFound": "Geen zoekresultaten gevonden.",
"TabDisplay": "Weergave",
@@ -796,13 +879,13 @@
"OptionAuto": "Auto",
"OptionYes": "Ja",
"OptionNo": "Nee",
- "LabelHomePageSection1": "Startpagina sectie een:",
- "LabelHomePageSection2": "Startpagina sectie twee:",
- "LabelHomePageSection3": "Startpagina sectie drie:",
- "LabelHomePageSection4": "Startpagina sectie vier",
- "OptionMyLibraryButtons": "Mijn bibliotheek (knoppen)",
- "OptionMyLibrary": "Mijn bibliotheek",
- "OptionMyLibrarySmall": "Mijn bibliotheek (klein)",
+ "LabelHomePageSection1": "Startpagina sectie 1:",
+ "LabelHomePageSection2": "Startpagina sectie 2:",
+ "LabelHomePageSection3": "Startpagina sectie 3:",
+ "LabelHomePageSection4": "Startpagina sectie 4:",
+ "OptionMyViewsButtons": "Mijn overzichten (knoppen)",
+ "OptionMyViews": "Mijn overzichten",
+ "OptionMyViewsSmall": "Mijn overzichten (klein)",
"OptionResumablemedia": "Hervatten",
"OptionLatestMedia": "Nieuwste media",
"OptionLatestChannelMedia": "Nieuwste kanaal items",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Voorkeuren",
"MessageLoadingChannels": "Laden kanaal inhoud ...",
+ "MessageLoadingContent": "Inhoud wordt geladen ...",
"ButtonMarkRead": "Markeren als gelezen",
"OptionDefaultSort": "Standaard",
"OptionCommunityMostWatchedSort": "Meest bekeken",
"TabNextUp": "Eerstvolgende",
"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": "Met Verzamelingen kunt u genieten van gepersonaliseerde groeperingen van films, series, Albums, Boeken en games. Klik op de knop Nieuw om te beginnen met het maken van verzamelingen.",
+ "MessageNoPlaylistsAvailable": "Met afspeellijsten kan je een lijst maken waarvan de items achter elkaar afgespeeld worden. Om een item toe te voegen klik je met rechts of tik en hou je het vast om het te selecteren, klik vervolgens op Toevoegen aan afspeellijst.",
+ "MessageNoPlaylistItemsAvailable": "De afspeellijst is momenteel leeg.",
"HeaderWelcomeToMediaBrowserWebClient": "Welkom op de Media Browser Web Client",
"ButtonDismiss": "Afwijzen",
"MessageLearnHowToCustomize": "Leer hoe u deze pagina aan kunt passen aan uw persoonlijke smaak. Klik op uw gebruikersnaam pictogram in de rechterbovenhoek van het scherm om uw voorkeuren te bekijken en bij te werken.",
@@ -829,10 +915,10 @@
"LabelEnableChannelContentDownloadingFor": "Schakel kanaalinhoud downloaden in voor:",
"LabelEnableChannelContentDownloadingForHelp": "Sommige kanalen ondersteunen downloaden en later kijken. Schakel deze optie in als er weinig bandbreedte beschikbaar is. Inhoud zal dan tijdens de kanaal download taak uitgevoerd worden.",
"LabelChannelDownloadPath": "Kanaal inhoud download pad:",
- "LabelChannelDownloadPathHelp": "Geef een eigen download pad op als dit gewenst is, leeglaten voor dowloaden naar de interne program data map.",
+ "LabelChannelDownloadPathHelp": "Geef een eigen download pad op als dit gewenst is, leeglaten voor dowloaden naar de interne programa data map.",
"LabelChannelDownloadAge": "Verwijder inhoud na: (dagen)",
"LabelChannelDownloadAgeHelp": "Gedownloade inhoud die ouder is zal worden verwijderd. Afspelen via internet streaming blijft mogelijk.",
- "ChannelSettingsFormHelp": "Installeer kanalen zoals Trailers en Vimeo in de plug-in catalogus.",
+ "ChannelSettingsFormHelp": "Installeer kanalen zoals Trailers en Vimeo in de Plug-in catalogus.",
"LabelSelectCollection": "Selecteer verzameling:",
"ViewTypeMovies": "Films",
"ViewTypeTvShows": "TV",
@@ -842,11 +928,171 @@
"ViewTypeChannels": "Kanalen",
"ViewTypeLiveTV": "Live TV",
"HeaderOtherDisplaySettings": "Beeld instellingen",
- "HeaderMyViews": "Mijn weergaves",
- "LabelSelectFolderGroups": "De volgende mappen automatisch groeperen in de secties zoals Films, Muziek en TV:",
- "LabelSelectFolderGroupsHelp": "Mappen die niet aangevinkt zijn worden in hun eigen sectie weergegeven.",
+ "HeaderMyViews": "Mijn Overzichten",
+ "LabelSelectFolderGroups": "De inhoud van de volgende mappen automatisch groeperen in de secties zoals Films, Muziek en TV:",
+ "LabelSelectFolderGroupsHelp": "Mappen die niet aangevinkt zijn worden getoond in hun eigen weergave.",
"OptionDisplayAdultContent": "Toon Inhoud voor volwassen",
- "OptionLibraryFolders": "Mapweergave",
+ "OptionLibraryFolders": "Media mappen",
"TitleRemoteControl": "Beheer op afstand",
- "OptionLatestTvRecordings": "Nieuwste opnames"
+ "OptionLatestTvRecordings": "Nieuwste opnames",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "De waarde die wordt gebruikt bij het reageren op GetProtocolInfo verzoeken van het apparaat.",
+ "TabXbmcMetadata": "XBMC",
+ "HeaderXbmcMetadataHelp": "Media Browser heeft ondersteuning voor XBMC NFO metadata en afbeeldingen. Om XBMC metadata aan of uit te zetten gebruikt u het tabblad Geavanceerd om opties voor uw mediatypen configureren.",
+ "LabelXbmcMetadataUser": "Voeg gekeken gegevens toe aan NFO's voor (gebruiker):",
+ "LabelXbmcMetadataUserHelp": "Activeer dit om gekeken gegevens gelijk te houden tussen Media Browser en XBMC.",
+ "LabelXbmcMetadataDateFormat": "Release datum formaat:",
+ "LabelXbmcMetadataDateFormatHelp": "Alle datums binnen NFO's zullen worden gelezen en geschreven en gebruik maken van dit formaat.",
+ "LabelXbmcMetadataSaveImagePaths": "Bewaar afbeeldingspaden in NFO-bestanden",
+ "LabelXbmcMetadataSaveImagePathsHelp": "Dit wordt aanbevolen als je bestandsnamen hebt die niet voldoen aan XBMC richtlijnen.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Pad vervanging inschakelen",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Stelt pad vervanging in voor afbeeldingspaden en maakt gebruik van de Pad Vervangen instellingen van de server",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "Zie Pad Vervanging.",
+ "LabelGroupChannelsIntoViews": "Toon de volgende kanalen binnen mijn overzichten:",
+ "LabelGroupChannelsIntoViewsHelp": "Indien ingeschakeld, zullen deze kanalen direct naast andere overzichten worden weergegeven. Indien uitgeschakeld, zullen ze worden weergegeven in een aparte kanalen overzicht.",
+ "LabelDisplayCollectionsView": "Toon verzamelingen in mijn overzichten om film verzamelingen weer te geven",
+ "LabelXbmcMetadataEnableExtraThumbs": "Kopieer extrafanart naar extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "Als er afbeeldingen gedownload worden kunnen deze zowel in extrafanart als in extrathumbs worden opgeslagen voor maximale compatibiliteit met de XBMC skins",
+ "TabServices": "Meta Diensten",
+ "TabLogs": "Logboeken",
+ "HeaderServerLogFiles": "Server logboek bestanden:",
+ "TabBranding": "Huisstijl",
+ "HeaderBrandingHelp": "Pas het uiterlijk van Media Browser aan, aan de behoeften van uw groep of organisatie.",
+ "LabelLoginDisclaimer": "Aanmeld vrijwaring:",
+ "LabelLoginDisclaimerHelp": "Dit wordt onderaan de login pagina weergegeven.",
+ "LabelAutomaticallyDonate": "Doneer dit bedrag automatisch elke maand",
+ "LabelAutomaticallyDonateHelp": "U kunt dit via uw PayPal account op elk moment annuleren.",
+ "OptionList": "Lijst",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logboeken:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Afbeeldingen op naam:",
+ "LabelTranscodingTemporaryFiles": "Tijdelijke transcodeer bestanden:",
+ "HeaderLatestMusic": "Nieuwste muziek",
+ "HeaderBranding": "Huisstijl",
+ "HeaderApiKeys": "Api Sleutels",
+ "HeaderApiKeysHelp": "Externe applicaties zijn verplicht om een \u200b\u200bAPI-sleutel te hebben om te communiceren met Media Browser. De sleuteloverdracht vindt plaats door in te loggen met een Media Browser account, of door het handmatig invoeren van een sleutel.",
+ "HeaderApiKey": "Api Sleutel",
+ "HeaderApp": "Applicatie",
+ "HeaderDevice": "Apparaat",
+ "HeaderUser": "Gebruiker",
+ "HeaderDateIssued": "Datum uitgegeven",
+ "LabelChapterName": "Hoofdstuk {0}",
+ "HeaderNewApiKey": "Nieuwe API-sleutel",
+ "LabelAppName": "Applicatie Naam",
+ "LabelAppNameExample": "Voorbeeld: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Verleen een applicatie toestemming om te communiceren met Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identificatie Header",
+ "LabelValue": "Waarde:",
+ "LabelMatchType": "Type overeenkomst:",
+ "OptionEquals": "Is gelijk aan",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Subtekenreeks",
+ "TabView": "Weergave",
+ "TabSort": "Sorteren",
+ "TabFilter": "Filter",
+ "ButtonView": "Weergave",
+ "LabelPageSize": "Itemlimiet:",
+ "LabelPath": "Pad:",
+ "LabelView": "Weergave:",
+ "TabUsers": "Gebruikers",
+ "LabelSortName": "Sorteer naam:",
+ "LabelDateAdded": "Datum toegevoegd:",
+ "HeaderFeatures": "Toevoegingen",
+ "HeaderAdvanced": "Geavanceerd",
+ "ButtonSync": "Synchronisatie",
+ "TabScheduledTasks": "Geplande taken",
+ "HeaderChapters": "Hoofdstukken",
+ "HeaderResumeSettings": "Instellingen voor Hervatten",
+ "TabSync": "Synchronisatie",
+ "TitleUsers": "Gebruikers",
+ "LabelProtocol": "Protokol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Synchronisatie",
+ "ButtonAddToPlaylist": "Toevoegen aan afspeellijst",
+ "TabPlaylists": "Afspeellijst",
+ "ButtonClose": "Sluiten",
+ "LabelAllLanguages": "Alle talen",
+ "HeaderBrowseOnlineImages": "Bekijk online afbeeldingen",
+ "LabelSource": "Bron:",
+ "OptionAll": "Alle",
+ "LabelImage": "Afbeedling:",
+ "ButtonBrowseImages": "Bekijk afbeeldingen",
+ "HeaderImages": "Afbeeldingen",
+ "HeaderBackdrops": "Achtergronden",
+ "HeaderScreenshots": "Schermafbeelding",
+ "HeaderAddUpdateImage": "Afbeelding toevoegen\/wijzigen",
+ "LabelJpgPngOnly": "Alleen JPG\/PNG",
+ "LabelImageType": "Afbeeldingstype:",
+ "OptionPrimary": "Primair",
+ "OptionArt": "Art",
+ "OptionBox": "Hoes",
+ "OptionBoxRear": "Achterkant hoes",
+ "OptionDisc": "Schijf",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Schermafbeelding",
+ "OptionLocked": "Vastgezet",
+ "OptionUnidentified": "Onge\u00efdentificeerd",
+ "OptionMissingParentalRating": "Ontbrekende kijkwijzer classificatie",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Seizoen 0",
+ "LabelReport": "Rapport:",
+ "OptionReportSongs": "Nummers",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seizoenen",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Muziek video's",
+ "OptionReportMovies": "Films",
+ "OptionReportHomeVideos": "Home video's",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Verzameling",
+ "OptionReportBooks": "Boeken",
+ "OptionReportArtists": "Artiesten",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult video's",
+ "ButtonMore": "Meer",
+ "HeaderActivity": "Activiteit",
+ "ScheduledTaskStartedWithName": "{0} is gestart",
+ "ScheduledTaskCancelledWithName": "{0} is geannuleerd",
+ "ScheduledTaskCompletedWithName": "{0} is gereed",
+ "ScheduledTaskFailed": "Geplande taak is gereed",
+ "PluginInstalledWithName": "{0} is ge\u00efnstalleerd",
+ "PluginUpdatedWithName": "{0} is bijgewerkt",
+ "PluginUninstalledWithName": "{0} is gede\u00efnstalleerd",
+ "ScheduledTaskFailedWithName": "{0} is mislukt",
+ "ItemAddedWithName": "{0} is toegevoegd aan de bibliotheek",
+ "ItemRemovedWithName": "{0} is verwijderd uit de bibliotheek",
+ "DeviceOnlineWithName": "{0} is verbonden",
+ "UserOnlineFromDevice": "{0} is aangemeld met {1}",
+ "DeviceOfflineWithName": "{0} is losgekoppeld",
+ "UserOfflineFromDevice": "{0} is afgemeld bij {1}",
+ "SubtitlesDownloadedForItem": "Ondertiteling voor {0} is gedownload",
+ "SubtitleDownloadFailureForItem": "Downloaden van ondertiteling voor {0} is mislukt",
+ "LabelRunningTimeValue": "Looptijd: {0}",
+ "LabelIpAddressValue": "IP adres: {0}",
+ "UserConfigurationUpdatedWithName": "Gebruikersinstellingen voor {0} zijn bijgewerkt",
+ "UserCreatedWithName": "Gebruiker {0} is aangemaakt",
+ "UserPasswordChangedWithName": "Wachtwoord voor {0} is gewijzigd",
+ "UserDeletedWithName": "Gebruiker {0} is verwijderd",
+ "MessageServerConfigurationUpdated": "Server configuratie is bijgewerkt",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Sectie {0} van de server configuratie is bijgewerkt",
+ "MessageApplicationUpdated": "Media Browser Server is bijgewerkt",
+ "AuthenticationSucceededWithUserName": "{0} is succesvol geverifieerd",
+ "FailedLoginAttemptWithUserName": "Mislukte aanmeld poging van {0}",
+ "UserStartedPlayingItemWithValues": "{0} heeft afspelen van {1} gestart",
+ "UserStoppedPlayingItemWithValues": "{0} heeft afspelen van {1} gestopt",
+ "AppDeviceValues": "App: {0}, Apparaat: {1}",
+ "ProviderValue": "Aanbieder: {0}",
+ "LabelChannelDownloadSizeLimit": "Downloadlimiet (GB): ",
+ "LabelChannelDownloadSizeLimitHelp": "Beperk de grootte van de kanaal download map",
+ "HeaderRecentActivity": "Recente activiteit"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pl.json b/MediaBrowser.Server.Implementations/Localization/Server/pl.json
new file mode 100644
index 000000000..fcd29a463
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Localization/Server/pl.json
@@ -0,0 +1,1098 @@
+{
+ "HeaderPeople": "People",
+ "LabelExit": "Wyj\u015b\u0107",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
+ "LabelVisitCommunity": "Odwied\u017a spo\u0142eczno\u015b\u0107",
+ "OptionComposers": "Composers",
+ "LabelGithubWiki": "Wiki Github",
+ "OptionOthers": "Others",
+ "LabelSwagger": "Swagger",
+ "LabelStandard": "Standardowy",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
+ "LabelViewApiDocumentation": "Zobacz dokumentacj\u0119 Api",
+ "ViewTypeFolders": "Folders",
+ "LabelBrowseLibrary": "Przejrzyj bibliotek\u0119",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
+ "LabelConfigureMediaBrowser": "Skonfiguruj Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
+ "LabelOpenLibraryViewer": "Otw\u00f3rz przegl\u0105dark\u0119 biblioteki",
+ "ViewTypeLiveTvChannels": "Channels",
+ "LabelRestartServer": "Uruchom serwer ponownie",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
+ "LabelShowLogWindow": "Show Log Window",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
+ "LabelPrevious": "Wstecz",
+ "HeaderPassword": "Password",
+ "LabelFinish": "Koniec",
+ "HeaderLocalAccess": "Local Access",
+ "LabelNext": "Dalej",
+ "HeaderViewOrder": "View Order",
+ "LabelYoureDone": "Sko\u0144czy\u0142e\u015b!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
+ "WelcomeToMediaBrowser": "Witaj w Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
+ "TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
+ "ThisWizardWillGuideYou": "Asystent pomo\u017ce Ci podczas instalacji. Na pocz\u0105tku, wybierz tw\u00f3j preferowany j\u0119zyk.",
+ "OptionDownloadMissingImages": "Download missing images",
+ "TellUsAboutYourself": "Opowiedz nam o sobie",
+ "OptionReplaceExistingImages": "Replace existing images",
+ "LabelYourFirstName": "Twoje imi\u0119:",
+ "OptionRefreshAllData": "Refresh all data",
+ "MoreUsersCanBeAddedLater": "Mo\u017cesz doda\u0107 wi\u0119cej u\u017cytkownik\u00f3w p\u00f3\u017aniej przez tablic\u0119 rozdzielcz\u0105.",
+ "OptionAddMissingDataOnly": "Add missing data only",
+ "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.",
+ "OptionLocalRefreshOnly": "Local refresh only",
+ "LabelWindowsService": "Serwis Windows",
+ "HeaderRefreshMetadata": "Refresh Metadata",
+ "AWindowsServiceHasBeenInstalled": "Serwis Windows zosta\u0142 zainstalowany.",
+ "HeaderPersonInfo": "Person Info",
+ "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.",
+ "HeaderIdentifyItem": "Identify Item",
+ "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.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
+ "WizardCompleted": "To wszystko na teraz. Media Browser zacz\u0105\u0142 zbiera\u0107 informacje o twojej bibliotece. Zapoznaj si\u0119 z aplikacjami po czym kliknij <b>Koniec<\/b> \u017ceby zobaczy\u0107 <b>Tablic\u0119 rozdzielcz\u0105<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
+ "LabelConfigureSettings": "Skonfiguruj ustawienia",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
+ "LabelEnableVideoImageExtraction": "Enable video image extraction",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
+ "VideoImageExtractionHelp": "Dla filmik\u00f3w kt\u00f3re nie maj\u0105 jeszcze obraz\u00f3w i dla kt\u00f3rych nie mo\u017cemy \u017cadnych znale\u017a\u0107 na internecie. Zwi\u0119kszy to czas wst\u0119pnego skanowania biblioteki ale wynikiem b\u0119dzie \u0142adniejsza prezentacja.",
+ "ButtonIdentify": "Identify",
+ "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
+ "LabelAlbumArtist": "Album artist:",
+ "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelAlbum": "Album:",
+ "LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
+ "LabelCommunityRating": "Community rating:",
+ "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "LabelVoteCount": "Vote count:",
+ "ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
+ "ButtonCancel": "Anuluj",
+ "LabelCriticRating": "Critic rating:",
+ "ButtonNew": "New",
+ "LabelCriticRatingSummary": "Critic rating summary:",
+ "HeaderSetupLibrary": "Ustaw swoj\u0105 bibliotek\u0119",
+ "LabelAwardSummary": "Award summary:",
+ "ButtonAddMediaFolder": "Dodaj folder",
+ "LabelWebsite": "Website:",
+ "LabelFolderType": "Typ folderu:",
+ "LabelTagline": "Tagline:",
+ "MediaFolderHelpPluginRequired": "* Wymaga u\u017cycia wtyczki tak jak GameBrowser lub MB Bookshelf.",
+ "LabelOverview": "Overview:",
+ "ReferToMediaLibraryWiki": "Odnie\u015b si\u0119 do wiki biblioteki.",
+ "LabelShortOverview": "Short overview:",
+ "LabelCountry": "Kraj:",
+ "LabelReleaseDate": "Release date:",
+ "LabelLanguage": "J\u0119zyk:",
+ "LabelYear": "Year:",
+ "HeaderPreferredMetadataLanguage": "Preferowany j\u0119zyk metadanych:",
+ "LabelPlaceOfBirth": "Place of birth:",
+ "LabelSaveLocalMetadata": "Save artwork and metadata into media folders",
+ "LabelEndDate": "End date:",
+ "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.",
+ "LabelAirDate": "Air days:",
+ "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet",
+ "LabelAirTime:": "Air time:",
+ "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
+ "TabPreferences": "Preferencje",
+ "LabelParentalRating": "Parental rating:",
+ "TabPassword": "Has\u0142o",
+ "LabelCustomRating": "Custom rating:",
+ "TabLibraryAccess": "Dost\u0119p do biblioteki",
+ "LabelBudget": "Budget",
+ "TabImage": "Obraz",
+ "LabelRevenue": "Revenue ($):",
+ "TabProfile": "Profil",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
+ "TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
+ "TabImages": "Images",
+ "Label3DFormat": "3D format:",
+ "TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
+ "TabCollectionTitles": "Titles",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
+ "LabelDisplayMissingEpisodesWithinSeasons": "Wy\u015bwietl brakuj\u0105ce odcinki w sezonach",
+ "HeaderExternalIds": "External Id's:",
+ "LabelUnairedMissingEpisodesWithinSeasons": "Wy\u015bwietl nie wydanie odcinki w sezonach",
+ "LabelDvdSeasonNumber": "Dvd season number:",
+ "HeaderVideoPlaybackSettings": "Ustawienia odtwarzania wideo",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
+ "HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
+ "LabelAudioLanguagePreference": "Preferencje j\u0119zyka audio:",
+ "LabelAirsBeforeSeason": "Airs before season:",
+ "LabelSubtitleLanguagePreference": "Preferencje j\u0119zyka napis\u00f3w:",
+ "LabelAirsAfterSeason": "Airs after season:",
+ "OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
+ "OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
+ "OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
+ "OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
+ "OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
+ "OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
+ "OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
+ "OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
+ "TabProfiles": "Profile",
+ "HeaderTags": "Tags",
+ "TabSecurity": "Zabezpieczenie",
+ "HeaderMetadataSettings": "Metadata Settings",
+ "ButtonAddUser": "Dodaj u\u017cytkownika",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
+ "ButtonSave": "Zapisz",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
+ "ButtonResetPassword": "Zresetuj has\u0142o",
+ "TabSupporterClub": "Supporter Club",
+ "LabelNewPassword": "Nowe has\u0142o:",
+ "HeaderDonationType": "Donation type:",
+ "LabelNewPasswordConfirm": "Potwierd\u017a nowe has\u0142o:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
+ "HeaderCreatePassword": "Stw\u00f3rz has\u0142o:",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
+ "LabelCurrentPassword": "Bie\u017c\u0105ce has\u0142o:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
+ "LabelMaxParentalRating": "Maksymalna dozwolona ocena rodzicielska:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
+ "MaxParentalRatingHelp": "Zawarto\u015b\u0107 z wy\u017csz\u0105 ocen\u0105 b\u0119dzie schowana dla tego u\u017cytkownika.",
+ "OptionNoTrailer": "No Trailer",
+ "LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.",
+ "OptionNoThemeSong": "No Theme Song",
+ "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
+ "ButtonDeleteImage": "Usu\u0144 obrazek",
+ "LabelOneTimeDonationAmount": "Donation amount:",
+ "LabelSelectUsers": "Select users:",
+ "OptionActor": "Actor",
+ "ButtonUpload": "Wy\u015blij",
+ "OptionComposer": "Composer",
+ "HeaderUploadNewImage": "Wy\u015blij nowy obrazek",
+ "OptionDirector": "Director",
+ "LabelDropImageHere": "Wrzu\u0107 obrazek tutaj",
+ "OptionGuestStar": "Guest star",
+ "ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.",
+ "OptionProducer": "Producer",
+ "MessageNothingHere": "Nic tutaj nie ma.",
+ "OptionWriter": "Writer",
+ "MessagePleaseEnsureInternetMetadata": "Upewnij si\u0119 \u017ce pobieranie metadanych z internetu jest w\u0142\u0105czone.",
+ "LabelAirDays": "Air days:",
+ "TabSuggested": "Sugerowane",
+ "LabelAirTime": "Air time:",
+ "TabLatest": "Ostatnie",
+ "HeaderMediaInfo": "Media Info",
+ "TabUpcoming": "Upcoming",
+ "HeaderPhotoInfo": "Photo Info",
+ "TabShows": "Seriale",
+ "TabEpisodes": "Odcinki",
+ "TabGenres": "Rodzaje",
+ "TabPeople": "Osoby",
+ "TabNetworks": "Sieci",
+ "HeaderUsers": "U\u017cytkownicy",
+ "HeaderFilters": "Filtry:",
+ "ButtonFilter": "Filtr",
+ "OptionFavorite": "Ulubione",
+ "OptionLikes": "Likes",
+ "OptionDislikes": "Dislikes",
+ "OptionActors": "Aktorzy",
+ "OptionGuestStars": "Guest Stars",
+ "OptionDirectors": "Dyrektorzy",
+ "OptionWriters": "Pisarze",
+ "OptionProducers": "Producenci",
+ "HeaderResume": "Wzn\u00f3w",
+ "HeaderNextUp": "Next Up",
+ "NoNextUpItemsMessage": "Nie znaleziono \u017cadnego. Zacznij ogl\u0105da\u0107 Twoje seriale!",
+ "HeaderLatestEpisodes": "Ostanie odcinki",
+ "HeaderPersonTypes": "Person Types:",
+ "TabSongs": "Utwory",
+ "TabAlbums": "Albumy",
+ "TabArtists": "Arty\u015bci",
+ "TabAlbumArtists": "Arty\u015bci albumu",
+ "TabMusicVideos": "Teledyski",
+ "ButtonSort": "Sortuj",
+ "HeaderSortBy": "Sortuj wed\u0142ug:",
+ "HeaderSortOrder": "Kolejno\u015b\u0107 sortowania:",
+ "OptionPlayed": "Played",
+ "OptionUnplayed": "Unplayed",
+ "OptionAscending": "Rosn\u0105co",
+ "OptionDescending": "Malej\u0105co",
+ "OptionRuntime": "D\u0142ugo\u015b\u0107 filmu",
+ "OptionReleaseDate": "Release Date",
+ "OptionPlayCount": "Ilo\u015b\u0107 odtworze\u0144",
+ "OptionDatePlayed": "Data odtworzenia",
+ "OptionDateAdded": "Data dodania",
+ "OptionAlbumArtist": "Artysta albumu",
+ "OptionArtist": "Artysta",
+ "OptionAlbum": "Album",
+ "OptionTrackName": "Nazwa utworu",
+ "OptionCommunityRating": "Ocena spo\u0142eczno\u015bci",
+ "OptionNameSort": "Nazwa",
+ "OptionFolderSort": "Folders",
+ "OptionBudget": "Bud\u017cet",
+ "OptionRevenue": "Doch\u00f3d",
+ "OptionPoster": "Plakat",
+ "OptionBackdrop": "Backdrop",
+ "OptionTimeline": "Timeline",
+ "OptionThumb": "Thumb",
+ "OptionBanner": "Banner",
+ "OptionCriticRating": "Ocena krytyk\u00f3w",
+ "OptionVideoBitrate": "Video Bitrate",
+ "OptionResumable": "Resumable",
+ "ScheduledTasksHelp": "Click a task to adjust its schedule.",
+ "ScheduledTasksTitle": "Zaplanowane zadania",
+ "TabMyPlugins": "Moje wtyczki",
+ "TabCatalog": "Katalog",
+ "PluginsTitle": "Wtyczki",
+ "HeaderAutomaticUpdates": "Automatyczne aktualizacje",
+ "HeaderNowPlaying": "Now Playing",
+ "HeaderLatestAlbums": "Ostatnie albumy",
+ "HeaderLatestSongs": "Ostatnie utwory",
+ "HeaderRecentlyPlayed": "Ostatnio grane",
+ "HeaderFrequentlyPlayed": "Cz\u0119sto grane",
+ "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": "Type widea",
+ "OptionBluray": "Bluray",
+ "OptionDvd": "Dvd",
+ "OptionIso": "Iso",
+ "Option3D": "3D",
+ "LabelFeatures": "W\u0142a\u015bciwo\u015bci",
+ "LabelService": "Service:",
+ "LabelStatus": "Status:",
+ "LabelVersion": "Version:",
+ "LabelLastResult": "Last result:",
+ "OptionHasSubtitles": "Napisy",
+ "OptionHasTrailer": "Zwiastun",
+ "OptionHasThemeSong": "Theme Song",
+ "OptionHasThemeVideo": "Theme Video",
+ "TabMovies": "Filmy",
+ "TabStudios": "Studia",
+ "TabTrailers": "Zwiastuny",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
+ "HeaderLatestMovies": "Ostatnie filmy",
+ "HeaderLatestTrailers": "Ostatnie zwiastuny",
+ "OptionHasSpecialFeatures": "Special Features",
+ "OptionImdbRating": "Ocena IMDb",
+ "OptionParentalRating": "Ocena rodzicielska",
+ "OptionPremiereDate": "Data premiery",
+ "TabBasic": "Podstawowe",
+ "TabAdvanced": "Zaawansowane",
+ "HeaderStatus": "Status",
+ "OptionContinuing": "Continuing",
+ "OptionEnded": "Ended",
+ "HeaderAirDays": "Air Days",
+ "OptionSunday": "Niedziela",
+ "OptionMonday": "Poniedzia\u0142ek",
+ "OptionTuesday": "Wtorek",
+ "OptionWednesday": "\u015aroda",
+ "OptionThursday": "Czwartek",
+ "OptionFriday": "Pi\u0105tek",
+ "OptionSaturday": "Sobota",
+ "HeaderManagement": "Management",
+ "LabelManagement": "Management:",
+ "OptionMissingImdbId": "Brakuje Id IMDb",
+ "OptionMissingTvdbId": "Brakuje Id TheTVDB",
+ "OptionMissingOverview": "Missing Overview",
+ "OptionFileMetadataYearMismatch": "File\/Metadata Years Mismatched",
+ "TabGeneral": "Og\u00f3lne",
+ "TitleSupport": "Wesprzyj",
+ "TabLog": "Log",
+ "TabAbout": "A propos",
+ "TabSupporterKey": "Supporter Key",
+ "TabBecomeSupporter": "Become a Supporter",
+ "MediaBrowserHasCommunity": "Media Browser has a thriving community of users and contributors.",
+ "CheckoutKnowledgeBase": "Check out our knowledge base to help you get the most out of Media Browser.",
+ "SearchKnowledgeBase": "Search the Knowledge Base",
+ "VisitTheCommunity": "Odwied\u017a spo\u0142eczno\u015b\u0107",
+ "VisitMediaBrowserWebsite": "Odwied\u017a stron\u0119 Media Browser",
+ "VisitMediaBrowserWebsiteLong": "Visit the Media Browser Web site to catch the latest news and keep up with the developer blog.",
+ "OptionHideUser": "Hide this user from login screens",
+ "OptionDisableUser": "Disable this user",
+ "OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.",
+ "HeaderAdvancedControl": "Advanced Control",
+ "LabelName": "Name:",
+ "OptionAllowUserToManageServer": "Allow this user to manage the server",
+ "HeaderFeatureAccess": "Feature Access",
+ "OptionAllowMediaPlayback": "Allow media playback",
+ "OptionAllowBrowsingLiveTv": "Allow browsing of live tv",
+ "OptionAllowDeleteLibraryContent": "Allow this user to delete library content",
+ "OptionAllowManageLiveTv": "Allow management of live tv recordings",
+ "OptionAllowRemoteControlOthers": "Allow this user to remote control other users",
+ "OptionMissingTmdbId": "Missing Tmdb Id",
+ "OptionIsHD": "HD",
+ "OptionIsSD": "SD",
+ "OptionMetascore": "Metascore",
+ "ButtonSelect": "Select",
+ "ButtonGroupVersions": "Group Versions",
+ "ButtonAddToCollection": "Add to Collection",
+ "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",
+ "TabTranscoding": "Transcoding",
+ "TitleAdvanced": "Advanced",
+ "LabelAutomaticUpdateLevel": "Automatic update level",
+ "OptionRelease": "Oficjalne wydanie",
+ "OptionBeta": "Beta",
+ "OptionDev": "Dev (Niestabilne)",
+ "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates",
+ "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods, when no users are active.",
+ "LabelEnableDebugLogging": "Enable debug logging",
+ "LabelRunServerAtStartup": "Run server at startup",
+ "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": "Wybierz folder",
+ "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.",
+ "LabelImagesByNamePath": "Images by name path:",
+ "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.",
+ "LabelMetadataPath": "Metadata path:",
+ "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": "Gry",
+ "TabMusic": "Muzyka",
+ "TabOthers": "Inne",
+ "HeaderExtractChapterImagesFor": "Extract chapter images for:",
+ "OptionMovies": "Filmy",
+ "OptionEpisodes": "Odcinki",
+ "OptionOtherVideos": "Inne widea",
+ "TitleMetadata": "Metadata",
+ "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv",
+ "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.",
+ "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
+ "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
+ "ExtractChapterImagesHelp": "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 when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelMetadataDownloadLanguage": "Preferred download language:",
+ "ButtonAutoScroll": "Auto-scroll",
+ "LabelImageSavingConvention": "Image saving convention:",
+ "LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
+ "OptionImageSavingStandard": "Standard - MB2",
+ "ButtonSignIn": "Sign In",
+ "TitleSignIn": "Sign In",
+ "HeaderPleaseSignIn": "Please sign in",
+ "LabelUser": "User:",
+ "LabelPassword": "Password:",
+ "ButtonManualLogin": "Manual Login",
+ "PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
+ "TabGuide": "Guide",
+ "TabChannels": "Channels",
+ "TabCollections": "Collections",
+ "HeaderChannels": "Channels",
+ "TabRecordings": "Recordings",
+ "TabScheduled": "Scheduled",
+ "TabSeries": "Series",
+ "TabFavorites": "Favorites",
+ "TabMyLibrary": "My Library",
+ "ButtonCancelRecording": "Cancel Recording",
+ "HeaderPrePostPadding": "Pre\/Post Padding",
+ "LabelPrePaddingMinutes": "Pre-padding minutes:",
+ "OptionPrePaddingRequired": "Pre-padding is required in order to record.",
+ "LabelPostPaddingMinutes": "Post-padding minutes:",
+ "OptionPostPaddingRequired": "Post-padding is required in order to record.",
+ "HeaderWhatsOnTV": "What's On",
+ "HeaderUpcomingTV": "Upcoming TV",
+ "TabStatus": "Status",
+ "TabSettings": "Settings",
+ "ButtonRefreshGuideData": "Refresh Guide Data",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
+ "OptionPriority": "Priority",
+ "OptionRecordOnAllChannels": "Record program on all channels",
+ "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderDays": "Days",
+ "HeaderActiveRecordings": "Active Recordings",
+ "HeaderLatestRecordings": "Latest Recordings",
+ "HeaderAllRecordings": "All Recordings",
+ "ButtonPlay": "Play",
+ "ButtonEdit": "Edit",
+ "ButtonRecord": "Record",
+ "ButtonDelete": "Delete",
+ "ButtonRemove": "Remove",
+ "OptionRecordSeries": "Record Series",
+ "HeaderDetails": "Details",
+ "TitleLiveTV": "Live TV",
+ "LabelNumberOfGuideDays": "Number of days of guide data to download:",
+ "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.",
+ "LabelActiveService": "Active Service:",
+ "LabelActiveServiceHelp": "Multiple tv plugins can be installed but only one can be active at a time.",
+ "OptionAutomatic": "Auto",
+ "LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
+ "LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
+ "LabelCustomizeOptionsPerMediaType": "Customize for media type:",
+ "OptionDownloadThumbImage": "Thumb",
+ "OptionDownloadMenuImage": "Menu",
+ "OptionDownloadLogoImage": "Logo",
+ "OptionDownloadBoxImage": "Box",
+ "OptionDownloadDiscImage": "Disc",
+ "OptionDownloadBannerImage": "Banner",
+ "OptionDownloadBackImage": "Back",
+ "OptionDownloadArtImage": "Art",
+ "OptionDownloadPrimaryImage": "Primary",
+ "HeaderFetchImages": "Fetch Images:",
+ "HeaderImageSettings": "Image Settings",
+ "TabOther": "Other",
+ "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
+ "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
+ "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
+ "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:",
+ "ButtonAddScheduledTaskTrigger": "Add Task Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Task Trigger",
+ "ButtonAdd": "Add",
+ "LabelTriggerType": "Trigger Type:",
+ "OptionDaily": "Daily",
+ "OptionWeekly": "Weekly",
+ "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:",
+ "HeaderTvTuners": "Tuners",
+ "HeaderGallery": "Gallery",
+ "HeaderLatestGames": "Latest Games",
+ "HeaderRecentlyPlayedGames": "Recently Played Games",
+ "TabGameSystems": "Game Systems",
+ "TitleMediaLibrary": "Media Library",
+ "TabFolders": "Folders",
+ "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",
+ "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",
+ "ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
+ "LabelMissing": "Missing",
+ "LabelOffline": "Offline",
+ "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",
+ "HeaderTo": "To",
+ "LabelFrom": "From:",
+ "LabelFromHelp": "Example: D:\\Movies (on the server)",
+ "LabelTo": "To:",
+ "LabelToHelp": "Example: \\\\MyServer\\Movies (a path clients can access)",
+ "ButtonAddPathSubstitution": "Add Substitution",
+ "OptionSpecialEpisode": "Specials",
+ "OptionMissingEpisode": "Missing Episodes",
+ "OptionUnairedEpisode": "Unaired Episodes",
+ "OptionEpisodeSortName": "Episode Sort Name",
+ "OptionSeriesSortName": "Series Name",
+ "OptionTvdbRating": "Tvdb Rating",
+ "HeaderTranscodingQualityPreference": "Transcoding Quality Preference:",
+ "OptionAutomaticTranscodingHelp": "The server will decide quality and speed",
+ "OptionHighSpeedTranscodingHelp": "Lower quality, but faster encoding",
+ "OptionHighQualityTranscodingHelp": "Higher quality, but slower encoding",
+ "OptionMaxQualityTranscodingHelp": "Best quality with slower encoding and high CPU usage",
+ "OptionHighSpeedTranscoding": "Higher speed",
+ "OptionHighQualityTranscoding": "Higher quality",
+ "OptionMaxQualityTranscoding": "Max quality",
+ "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging",
+ "OptionEnableDebugTranscodingLoggingHelp": "This will create very large log files and is only recommended as needed for troubleshooting purposes.",
+ "OptionUpscaling": "Allow clients to request upscaled video",
+ "OptionUpscalingHelp": "In some cases this will result in improved video quality but will increase CPU usage.",
+ "EditCollectionItemsHelp": "Add or remove any movies, series, albums, books or games you wish to group within this collection.",
+ "HeaderAddTitles": "Add Titles",
+ "LabelEnableDlnaPlayTo": "Enable DLNA Play To",
+ "LabelEnableDlnaPlayToHelp": "Media Browser can detect devices within your network and offer the ability to remote control them.",
+ "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging",
+ "LabelEnableDlnaDebugLoggingHelp": "This will create large log files and should only be used as needed for troubleshooting purposes.",
+ "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)",
+ "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Media Browser.",
+ "HeaderCustomDlnaProfiles": "Custom Profiles",
+ "HeaderSystemDlnaProfiles": "System Profiles",
+ "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.",
+ "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.",
+ "TitleDashboard": "Dashboard",
+ "TabHome": "Home",
+ "TabInfo": "Info",
+ "HeaderLinks": "Links",
+ "HeaderSystemPaths": "System Paths",
+ "LinkCommunity": "Community",
+ "LinkGithub": "Github",
+ "LinkApiDocumentation": "Api Documentation",
+ "LabelFriendlyServerName": "Friendly server name:",
+ "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.",
+ "LabelPreferredDisplayLanguage": "Preferred display language",
+ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.",
+ "LabelReadHowYouCanContribute": "Read about how you can contribute.",
+ "HeaderNewCollection": "New Collection",
+ "HeaderAddToCollection": "Add to Collection",
+ "ButtonSubmit": "Submit",
+ "NewCollectionNameExample": "Example: Star Wars Collection",
+ "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata",
+ "ButtonCreate": "Create",
+ "LabelHttpServerPortNumber": "Http server port number:",
+ "LabelWebSocketPortNumber": "Web socket port number:",
+ "LabelEnableAutomaticPortHelp": "UPnP allows automated router configuration for remote access. This may not work with some router models.",
+ "LabelExternalDDNS": "External DDNS:",
+ "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.",
+ "TabResume": "Resume",
+ "TabWeather": "Weather",
+ "TitleAppSettings": "App Settings",
+ "LabelMinResumePercentage": "Min resume percentage:",
+ "LabelMaxResumePercentage": "Max resume percentage:",
+ "LabelMinResumeDuration": "Min resume duration (seconds):",
+ "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time",
+ "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time",
+ "LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable",
+ "TitleAutoOrganize": "Auto-Organize",
+ "TabActivityLog": "Activity Log",
+ "HeaderName": "Name",
+ "HeaderDate": "Date",
+ "HeaderSource": "Source",
+ "HeaderDestination": "Destination",
+ "HeaderProgram": "Program",
+ "HeaderClients": "Clients",
+ "LabelCompleted": "Completed",
+ "LabelFailed": "Failed",
+ "LabelSkipped": "Skipped",
+ "HeaderEpisodeOrganization": "Episode Organization",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
+ "LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
+ "HeaderSupportTheTeam": "Support the Media Browser Team",
+ "LabelSupportAmount": "Amount (USD)",
+ "HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.",
+ "ButtonEnterSupporterKey": "Enter supporter key",
+ "DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.",
+ "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.",
+ "AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.",
+ "OptionEnableEpisodeOrganization": "Enable new episode organization",
+ "LabelWatchFolder": "Watch folder:",
+ "LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.",
+ "ButtonViewScheduledTasks": "View scheduled tasks",
+ "LabelMinFileSizeForOrganize": "Minimum file size (MB):",
+ "LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.",
+ "LabelSeasonFolderPattern": "Season folder pattern:",
+ "LabelSeasonZeroFolderName": "Season zero folder name:",
+ "HeaderEpisodeFilePattern": "Episode file pattern",
+ "LabelEpisodePattern": "Episode pattern:",
+ "LabelMultiEpisodePattern": "Multi-Episode pattern:",
+ "HeaderSupportedPatterns": "Supported Patterns",
+ "HeaderTerm": "Term",
+ "HeaderPattern": "Pattern",
+ "HeaderResult": "Result",
+ "LabelDeleteEmptyFolders": "Delete empty folders after organizing",
+ "LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.",
+ "LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:",
+ "LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt",
+ "OptionOverwriteExistingEpisodes": "Overwrite existing episodes",
+ "LabelTransferMethod": "Transfer method",
+ "OptionCopy": "Copy",
+ "OptionMove": "Move",
+ "LabelTransferMethodHelp": "Copy or move files from the watch folder",
+ "HeaderLatestNews": "Latest News",
+ "HeaderHelpImproveMediaBrowser": "Help Improve Media Browser",
+ "HeaderRunningTasks": "Running Tasks",
+ "HeaderActiveDevices": "Active Devices",
+ "HeaderPendingInstallations": "Pending Installations",
+ "HeaerServerInformation": "Server Information",
+ "ButtonRestartNow": "Restart Now",
+ "ButtonRestart": "Restart",
+ "ButtonShutdown": "Shutdown",
+ "ButtonUpdateNow": "Update Now",
+ "PleaseUpdateManually": "Please shutdown the server and update manually.",
+ "NewServerVersionAvailable": "A new version of Media Browser Server is available!",
+ "ServerUpToDate": "Media Browser Server is up to date",
+ "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.",
+ "LabelComponentsUpdated": "The following components have been installed or updated:",
+ "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.",
+ "LabelDownMixAudioScale": "Audio boost when downmixing:",
+ "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.",
+ "ButtonLinkKeys": "Link Keys",
+ "LabelOldSupporterKey": "Old supporter key",
+ "LabelNewSupporterKey": "New supporter key",
+ "HeaderMultipleKeyLinking": "Multiple Key Linking",
+ "MultipleKeyLinkingHelp": "If you have more than one supporter key, use this form to link the old key's registrations with your new one.",
+ "LabelCurrentEmailAddress": "Current email address",
+ "LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.",
+ "HeaderForgotKey": "Forgot Key",
+ "LabelEmailAddress": "Email address",
+ "LabelSupporterEmailAddress": "The email address that was used to purchase the key.",
+ "ButtonRetrieveKey": "Retrieve Key",
+ "LabelSupporterKey": "Supporter Key (paste from email)",
+ "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
+ "MessageInvalidKey": "Supporter key is missing or invalid.",
+ "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
+ "HeaderDisplaySettings": "Display Settings",
+ "TabPlayTo": "Play To",
+ "LabelEnableDlnaServer": "Enable Dlna server",
+ "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Media Browser content.",
+ "LabelEnableBlastAliveMessages": "Blast alive messages",
+ "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.",
+ "LabelBlastMessageInterval": "Alive message interval (seconds)",
+ "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.",
+ "LabelDefaultUser": "Default user:",
+ "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.",
+ "TitleDlna": "DLNA",
+ "TitleChannels": "Channels",
+ "HeaderServerSettings": "Server Settings",
+ "LabelWeatherDisplayLocation": "Weather display location:",
+ "LabelWeatherDisplayLocationHelp": "US zip code \/ City, State, Country \/ City, Country",
+ "LabelWeatherDisplayUnit": "Weather display unit:",
+ "OptionCelsius": "Celsius",
+ "OptionFahrenheit": "Fahrenheit",
+ "HeaderRequireManualLogin": "Require manual username entry for:",
+ "HeaderRequireManualLoginHelp": "When disabled clients may present a login screen with a visual selection of users.",
+ "OptionOtherApps": "Other apps",
+ "OptionMobileApps": "Mobile apps",
+ "HeaderNotificationList": "Click on a notification to configure it's sending options.",
+ "NotificationOptionApplicationUpdateAvailable": "Application update available",
+ "NotificationOptionApplicationUpdateInstalled": "Application update installed",
+ "NotificationOptionPluginUpdateInstalled": "Plugin update installed",
+ "NotificationOptionPluginInstalled": "Plugin installed",
+ "NotificationOptionPluginUninstalled": "Plugin uninstalled",
+ "NotificationOptionVideoPlayback": "Video playback started",
+ "NotificationOptionAudioPlayback": "Audio playback started",
+ "NotificationOptionGamePlayback": "Game playback started",
+ "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
+ "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
+ "NotificationOptionGamePlaybackStopped": "Game playback stopped",
+ "NotificationOptionTaskFailed": "Scheduled task failure",
+ "NotificationOptionInstallationFailed": "Installation failure",
+ "NotificationOptionNewLibraryContent": "New content added",
+ "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
+ "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.",
+ "NotificationOptionServerRestartRequired": "Server restart required",
+ "LabelNotificationEnabled": "Enable this notification",
+ "LabelMonitorUsers": "Monitor activity from:",
+ "LabelSendNotificationToUsers": "Send the notification to:",
+ "LabelUseNotificationServices": "Use the following services:",
+ "CategoryUser": "User",
+ "CategorySystem": "System",
+ "CategoryApplication": "Application",
+ "CategoryPlugin": "Plugin",
+ "LabelMessageTitle": "Message title:",
+ "LabelAvailableTokens": "Available tokens:",
+ "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.",
+ "OptionAllUsers": "All users",
+ "OptionAdminUsers": "Administrators",
+ "OptionCustomUsers": "Custom",
+ "ButtonArrowUp": "Up",
+ "ButtonArrowDown": "Down",
+ "ButtonArrowLeft": "Left",
+ "ButtonArrowRight": "Right",
+ "ButtonBack": "Back",
+ "ButtonInfo": "Info",
+ "ButtonOsd": "On screen display",
+ "ButtonPageUp": "Page Up",
+ "ButtonPageDown": "Page Down",
+ "PageAbbreviation": "PG",
+ "ButtonHome": "Home",
+ "ButtonSearch": "Search",
+ "ButtonSettings": "Settings",
+ "ButtonTakeScreenshot": "Capture Screenshot",
+ "ButtonLetterUp": "Letter Up",
+ "ButtonLetterDown": "Letter Down",
+ "PageButtonAbbreviation": "PG",
+ "LetterButtonAbbreviation": "A",
+ "TabNowPlaying": "Now Playing",
+ "TabNavigation": "Navigation",
+ "TabControls": "Controls",
+ "ButtonFullscreen": "Toggle fullscreen",
+ "ButtonScenes": "Scenes",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
+ "ButtonStop": "Stop",
+ "ButtonPause": "Pause",
+ "LabelGroupMoviesIntoCollections": "Group movies into collections",
+ "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.",
+ "NotificationOptionPluginError": "Plugin failure",
+ "ButtonVolumeUp": "Volume up",
+ "ButtonVolumeDown": "Volume down",
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
+ "LabelProfileContainer": "Container:",
+ "LabelProfileVideoCodecs": "Video codecs:",
+ "LabelProfileAudioCodecs": "Audio codecs:",
+ "LabelProfileCodecs": "Codecs:",
+ "HeaderDirectPlayProfile": "Direct Play Profile",
+ "HeaderTranscodingProfile": "Transcoding Profile",
+ "HeaderCodecProfile": "Codec Profile",
+ "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.",
+ "HeaderContainerProfile": "Container Profile",
+ "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.",
+ "OptionProfileVideo": "Video",
+ "OptionProfileAudio": "Audio",
+ "OptionProfileVideoAudio": "Video Audio",
+ "OptionProfilePhoto": "Photo",
+ "LabelUserLibrary": "User library:",
+ "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.",
+ "OptionPlainStorageFolders": "Display all folders as plain storage folders",
+ "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".",
+ "OptionPlainVideoItems": "Display all videos as plain video items",
+ "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".",
+ "LabelSupportedMediaTypes": "Supported Media Types:",
+ "TabIdentification": "Identification",
+ "TabDirectPlay": "Direct Play",
+ "TabContainers": "Containers",
+ "TabCodecs": "Codecs",
+ "TabResponses": "Responses",
+ "HeaderProfileInformation": "Profile Information",
+ "LabelEmbedAlbumArtDidl": "Embed album art in Didl",
+ "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.",
+ "LabelAlbumArtPN": "Album art PN:",
+ "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.",
+ "LabelAlbumArtMaxWidth": "Album art max width:",
+ "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "Album art max height:",
+ "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
+ "LabelIconMaxWidth": "Icon max width:",
+ "LabelIconMaxWidthHelp": "Max resolution of icons exposed via upnp:icon.",
+ "LabelIconMaxHeight": "Icon max height:",
+ "LabelIconMaxHeightHelp": "Max resolution of icons exposed via upnp:icon.",
+ "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.",
+ "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
+ "LabelMaxBitrate": "Max bitrate:",
+ "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
+ "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
+ "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
+ "LabelFriendlyName": "Friendly name",
+ "LabelManufacturer": "Manufacturer",
+ "LabelManufacturerUrl": "Manufacturer url",
+ "LabelModelName": "Model name",
+ "LabelModelNumber": "Model number",
+ "LabelModelDescription": "Model description",
+ "LabelModelUrl": "Model url",
+ "LabelSerialNumber": "Serial number",
+ "LabelDeviceDescription": "Device description",
+ "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.",
+ "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.",
+ "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.",
+ "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.",
+ "LabelXDlnaCap": "X-Dlna cap:",
+ "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.",
+ "LabelXDlnaDoc": "X-Dlna doc:",
+ "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.",
+ "LabelSonyAggregationFlags": "Sony aggregation flags:",
+ "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.",
+ "LabelTranscodingContainer": "Container:",
+ "LabelTranscodingVideoCodec": "Video codec:",
+ "LabelTranscodingVideoProfile": "Video profile:",
+ "LabelTranscodingAudioCodec": "Audio codec:",
+ "OptionEnableM2tsMode": "Enable M2ts mode",
+ "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.",
+ "OptionEstimateContentLength": "Estimate content length when transcoding",
+ "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.",
+ "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "Download subtitles for:",
+ "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "TabChapters": "Chapters",
+ "HeaderDownloadChaptersFor": "Download chapter names for:",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.",
+ "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
+ "LabelSubtitlePlaybackMode": "Subtitle mode:",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:",
+ "MessageNoAvailablePlugins": "No available plugins.",
+ "LabelDisplayPluginsFor": "Display plugins for:",
+ "PluginTabMediaBrowserClassic": "MB Classic",
+ "PluginTabMediaBrowserTheater": "MB Theater",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
+ "ValueSeriesNamePeriod": "Series.name",
+ "ValueSeriesNameUnderscore": "Series_name",
+ "ValueEpisodeNamePeriod": "Episode.name",
+ "ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
+ "HeaderTypeText": "Enter Text",
+ "LabelTypeText": "Text",
+ "HeaderSearchForSubtitles": "Search for Subtitles",
+ "MessageNoSubtitleSearchResultsFound": "No search results founds.",
+ "TabDisplay": "Display",
+ "TabLanguages": "Languages",
+ "TabWebClient": "Web Client",
+ "LabelEnableThemeSongs": "Enable theme songs",
+ "LabelEnableBackdrops": "Enable backdrops",
+ "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.",
+ "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.",
+ "HeaderHomePage": "Home Page",
+ "HeaderSettingsForThisDevice": "Settings for This Device",
+ "OptionAuto": "Auto",
+ "OptionYes": "Yes",
+ "OptionNo": "No",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
+ "OptionResumablemedia": "Resume",
+ "OptionLatestMedia": "Latest media",
+ "OptionLatestChannelMedia": "Latest channel items",
+ "HeaderLatestChannelItems": "Latest Channel Items",
+ "OptionNone": "None",
+ "HeaderLiveTv": "Live TV",
+ "HeaderReports": "Reports",
+ "HeaderMetadataManager": "Metadata Manager",
+ "HeaderPreferences": "Preferences",
+ "MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
+ "ButtonMarkRead": "Mark Read",
+ "OptionDefaultSort": "Default",
+ "OptionCommunityMostWatchedSort": "Most Watched",
+ "TabNextUp": "Next Up",
+ "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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
+ "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
+ "ButtonDismiss": "Dismiss",
+ "MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
+ "ButtonEditOtherUserPreferences": "Edit this user's personal preferences.",
+ "LabelChannelStreamQuality": "Preferred internet stream quality:",
+ "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.",
+ "OptionBestAvailableStreamQuality": "Best available",
+ "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:",
+ "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.",
+ "LabelChannelDownloadPath": "Channel content download path:",
+ "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.",
+ "LabelChannelDownloadAge": "Delete content after: (days)",
+ "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.",
+ "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.",
+ "LabelSelectCollection": "Select collection:",
+ "ViewTypeMovies": "Movies",
+ "ViewTypeTvShows": "TV",
+ "ViewTypeGames": "Games",
+ "ViewTypeMusic": "Music",
+ "ViewTypeBoxSets": "Collections",
+ "ViewTypeChannels": "Channels",
+ "ViewTypeLiveTV": "Live TV",
+ "HeaderOtherDisplaySettings": "Display Settings",
+ "HeaderMyViews": "My Views",
+ "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",
+ "TitleRemoteControl": "Remote Control",
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
+} \ 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 f83c90a75..fa01486a8 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Notificar usu\u00e1rios administradores quando:",
- "HeaderEnableNotificationForPlayback": "Notificar quando os usu\u00e1rios reproduzirem:",
- "OptionNotifyOnUpdates": "Atualiza\u00e7\u00f5es estiverem disponiveis",
- "OptionNotifyOnVideoPlayback": "V\u00eddeo",
- "OptionNotifyOnAudioPlayback": "\u00c1udio",
- "OptionNotifyOnGamePlayback": "Jogos",
- "OptionNotifyOnFailedTasks": "Tarefas agendadas falharem",
- "OptionNotifyOnNewLibraryContent": "Novo conte\u00fado for adicionado \u00e0 biblioteca",
- "OptionNotifyOnServerRestartRequired": "O servidor necessita ser reiniciado",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Atualiza\u00e7\u00f5es",
- "HeaderUpdateLevel": "N\u00edvel de Atualiza\u00e7\u00e3o",
- "LabelRequireTextSubtitles": "Transferir mesmo se o v\u00eddeo possuir legendas gr\u00e1ficas",
- "LabelRequireTextSubtitlesHelp": "Manter vers\u00f5es das legendas em texto resultar\u00e1 em uma entrega mais eficiente para os clientes m\u00f3veis.",
- "HeaderSubtitleDownloadingMoreHelp": "Ser\u00e1 considerado que faltam legendas quando a faixa de \u00e1udio estiver em um idioma estrangeiro e n\u00e3o existirem legendas dispon\u00edveis no idioma preferido.",
- "LabelDisplayForcedSubtitlesOnly": "Exibir apenas legendas for\u00e7adas",
- "HeaderCustomizeOptionsPerMediaType": "Personalize op\u00e7\u00f5es por tipo de m\u00eddia",
- "LabelAudioLanguagePreferenceHelp": "Se estiver em branco, a faixa de \u00e1udio padr\u00e3o ser\u00e1 selecionada, independente do idioma.",
- "TabCustomizations": "Personaliza\u00e7\u00f5es",
- "HeaderAllDevices": "Todos os Dispositivos",
- "HeaderThisDevice": "Este Dispositivo",
- "OptionLibraryButtons": "Bot\u00f5es da biblioteca",
- "OptionLibraryTiles": "Tiles da biblioteca (grandes)",
- "OptionSmallLibraryTiles": "Tiles da biblioteca (pequenas)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Falhou",
- "LabelSeries": "S\u00e9rie:",
- "ButtonPreviousTrack": "Faixa Anterior",
- "ButtonNextTrack": "Pr\u00f3xima Faixa",
- "HeaderMyLibrary": "Minha Biblioteca",
- "HeaderLibraryViews": "Visualiza\u00e7\u00f5es da Biblioteca",
+ "HeaderPeople": "Pessoas",
"LabelExit": "Sair",
+ "HeaderDownloadPeopleMetadataFor": "Fazer download da biografia e imagens para:",
"LabelVisitCommunity": "Visitar a Comunidade",
+ "OptionComposers": "Compositores",
"LabelGithubWiki": "Wiki do Github",
+ "OptionOthers": "Outros",
"LabelSwagger": "Swagger",
"LabelStandard": "Padr\u00e3o",
+ "HeaderDownloadPeopleMetadataForHelp": "Ativar op\u00e7\u00f5es adicionais disponibilizar\u00e1 mais informa\u00e7\u00f5es na tela mas deixar\u00e1 os rastreamentos de biblioteca mais lentos.",
"LabelViewApiDocumentation": "Ver documenta\u00e7\u00e3o da Api",
+ "ViewTypeFolders": "Pastas",
"LabelBrowseLibrary": "Navegar pela Biblioteca",
+ "LabelDisplayFoldersView": "Exibir visualiza\u00e7\u00e3o de pastas para mostrar pastas simples de m\u00eddia",
"LabelConfigureMediaBrowser": "Configurar Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Grava\u00e7\u00f5es",
"LabelOpenLibraryViewer": "Abrir Visualizador da Biblioteca",
+ "ViewTypeLiveTvChannels": "Canais",
"LabelRestartServer": "Reiniciar Servidor",
+ "LabelAllowLocalAccessWithoutPassword": "Permtir acesso local sem senha",
"LabelShowLogWindow": "Exibir Janela de Log",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "Quando ativado, uma senha n\u00e3o ser\u00e1 necess\u00e1ria para entrar atrav\u00e9s de sua rede dom\u00e9stica.",
"LabelPrevious": "Anterior",
- "LabelFinish": "Terminar",
+ "HeaderPassword": "Senha",
+ "LabelFinish": "Finalizar",
+ "HeaderLocalAccess": "Acesso Local",
"LabelNext": "Pr\u00f3ximo",
+ "HeaderViewOrder": "Ordem da Visualiza\u00e7\u00e3o",
"LabelYoureDone": "Pronto!",
+ "LabelSelectUserViewOrder": "Escolha a ordem em que suas visualiza\u00e7\u00f5es ser\u00e3o exibidas dentro das apps do Media Browser",
"WelcomeToMediaBrowser": "Bem Vindo ao Media Browser!",
+ "LabelMetadataRefreshMode": "Modo de atualiza\u00e7\u00e3o dos metadados:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Modo de atualiza\u00e7\u00e3o das imagens:",
"ThisWizardWillGuideYou": "Este assistente ir\u00e1 gui\u00e1-lo pelo processo de instala\u00e7\u00e3o. Para come\u00e7ar, por favor selecione seu idioma preferido.",
+ "OptionDownloadMissingImages": "Fazer download das imagens faltantes",
"TellUsAboutYourself": "Conte-nos sobre voc\u00ea",
+ "OptionReplaceExistingImages": "Substituir imagens existentes",
"LabelYourFirstName": "Seu primeiro nome:",
+ "OptionRefreshAllData": "Atualizar todos os dados",
"MoreUsersCanBeAddedLater": "Mais usu\u00e1rios poder\u00e3o ser adicionados depois dentro do Painel.",
+ "OptionAddMissingDataOnly": "Adicionar apenas dados faltantes",
"UserProfilesIntro": "Media Browser inclui suporte a perfis de usu\u00e1rios, permitindo que cada usu\u00e1rio tenha suas prefer\u00eancias de visualiza\u00e7\u00e3o, status das reprodu\u00e7\u00f5es e controle parental.",
+ "OptionLocalRefreshOnly": "Atualiza\u00e7\u00e3o local apenas",
"LabelWindowsService": "Servi\u00e7o do Windows",
+ "HeaderRefreshMetadata": "Atualizar Metadados",
"AWindowsServiceHasBeenInstalled": "Foi instalado um Servi\u00e7o do Windows.",
+ "HeaderPersonInfo": "Informa\u00e7\u00e3o da Pessoa",
"WindowsServiceIntro1": "O Servidor Media Browser normalmente \u00e9 executado como uma aplica\u00e7\u00e3o de desktop com um \u00edcone na bandeja do sistema, mas se preferir executar como servi\u00e7o pode inici\u00e1-lo no painel de controle de servi\u00e7os do Windows",
+ "HeaderIdentifyItem": "Identificar Item",
"WindowsServiceIntro2": "Se usar o servi\u00e7o do Windows, por favor certifique-se que n\u00e3o esteja sendo executado ao mesmo tempo que o \u00edcone na bandeja, se estiver ter\u00e1 que sair da app antes de executar o servi\u00e7o. O servi\u00e7o necessita ser configurado com privil\u00e9gios de administrador no painel de controle. Neste momento o servi\u00e7o n\u00e3o pode se auto-atualizar, por isso novas vers\u00f5es exigir\u00e3o intera\u00e7\u00e3o manual.",
+ "HeaderIdentifyItemHelp": "Digite um ou mais crit\u00e9rios de busca. Exclua o crit\u00e9rio para aumentar os resultados da busca.",
"WizardCompleted": "Isto \u00e9 todo o necess\u00e1rio. Media Browser iniciou a coleta das informa\u00e7\u00f5es de sua biblioteca de m\u00eddia. Conhe\u00e7a algumas de nossas apps e clique <b>Terminar<\/b> para ver o <b>Painel<\/b>.",
+ "HeaderConfirmDeletion": "Confirmar Exclus\u00e3o",
"LabelConfigureSettings": "Configurar ajustes",
+ "LabelFollowingFileWillBeDeleted": "O seguinte arquivo ser\u00e1 exclu\u00eddo:",
"LabelEnableVideoImageExtraction": "Ativar extra\u00e7\u00e3o de imagens de v\u00eddeo",
+ "LabelIfYouWishToContinueWithDeletion": "Se desejar continuar, por favor confirme digitando o valor de:",
"VideoImageExtractionHelp": "Para v\u00eddeos que n\u00e3o tenham imagens e que n\u00e3o possamos encontrar imagens na internet. Isto aumentar\u00e1 o tempo do rastreamento inicial da biblioteca mas resultar\u00e1 em uma apresenta\u00e7\u00e3o mais bonita.",
+ "ButtonIdentify": "Identificar",
"LabelEnableChapterImageExtractionForMovies": "Extrair imagens de cap\u00edtulos dos Filmes",
+ "LabelAlbumArtist": "Artista do \u00e1lbum:",
"LabelChapterImageExtractionForMoviesHelp": "Extrair imagens de cap\u00edtulos permitir\u00e1 aos clientes exibir menus gr\u00e1ficos de sele\u00e7\u00e3o de cenas. O processo pode ser lento, uso intensivo de cpu e pode exigir bastante espa\u00e7o em disco. Ele ser\u00e1 executado \u00e0s 4:00hs, embora isto possa ser configur\u00e1vel na \u00e1rea de tarefas agendadas. N\u00e3o \u00e9 recomendado executar esta tarefa durante as horas de pico de uso.",
+ "LabelAlbum": "\u00c1lbum:",
"LabelEnableAutomaticPortMapping": "Ativar mapeamento de porta autom\u00e1tico",
+ "LabelCommunityRating": "Avalia\u00e7\u00e3o da comunidade:",
"LabelEnableAutomaticPortMappingHelp": "UPnP permite uma configura\u00e7\u00e3o automatizada do roteador para acesso remoto f\u00e1cil. Isto pode n\u00e3o funcionar em alguns modelos de roteadores.",
+ "LabelVoteCount": "Contagem de votos:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Cancelar",
- "ButtonNew": "Novo",
+ "LabelCriticRating": "Avalia\u00e7\u00e3o da cr\u00edtica:",
+ "ButtonNew": "Nova",
+ "LabelCriticRatingSummary": "Resumo da avalia\u00e7\u00e3o da cr\u00edtica:",
"HeaderSetupLibrary": "Configurar sua biblioteca de m\u00eddias",
+ "LabelAwardSummary": "Resumo da premia\u00e7\u00e3o:",
"ButtonAddMediaFolder": "Adicionar pasta de m\u00eddias",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Tipo de pasta:",
+ "LabelTagline": "Slogan:",
"MediaFolderHelpPluginRequired": "* Requer o uso de um plugin, ex. GameBrowser ou MB Bookshelf.",
+ "LabelOverview": "Sinopse:",
"ReferToMediaLibraryWiki": "Consultar wiki da biblioteca de m\u00eddias",
+ "LabelShortOverview": "Sinopse curta:",
"LabelCountry": "Pa\u00eds:",
+ "LabelReleaseDate": "Data do lan\u00e7amento:",
"LabelLanguage": "Idioma:",
+ "LabelYear": "Ano:",
"HeaderPreferredMetadataLanguage": "Idioma preferido dos metadados:",
+ "LabelPlaceOfBirth": "Local de nascimento:",
"LabelSaveLocalMetadata": "Salvar artwork e metadados dentro das pastas da m\u00eddia",
+ "LabelEndDate": "Data final:",
"LabelSaveLocalMetadataHelp": "Salvar artwork e metadados diretamente nas pastas da m\u00eddia as deixar\u00e1 em um local f\u00e1cil para edit\u00e1-las.",
+ "LabelAirDate": "Dias de exibi\u00e7\u00e3o:",
"LabelDownloadInternetMetadata": "Fazer download das imagens e metadados da internet",
+ "LabelAirTime:": "Hora da exibi\u00e7\u00e3o:",
"LabelDownloadInternetMetadataHelp": "O Media Browser pode fazer download das informa\u00e7\u00f5es de sua m\u00eddia para melhorar a apresenta\u00e7\u00e3o.",
+ "LabelRuntimeMinutes": "Dura\u00e7\u00e3o (minutos):",
"TabPreferences": "Prefer\u00eancias",
+ "LabelParentalRating": "Classifica\u00e7\u00e3o parental:",
"TabPassword": "Senha",
+ "LabelCustomRating": "Classifica\u00e7\u00e3o personalizada:",
"TabLibraryAccess": "Acesso \u00e0 Biblioteca",
+ "LabelBudget": "Or\u00e7amento",
"TabImage": "Imagem",
+ "LabelRevenue": "Receita ($):",
"TabProfile": "Perfil",
+ "LabelOriginalAspectRatio": "Rela\u00e7\u00e3o de aspecto original:",
"TabMetadata": "Metadados",
+ "LabelPlayers": "Reprodutores:",
"TabImages": "Imagens",
+ "Label3DFormat": "Formato 3D:",
"TabNotifications": "Notifica\u00e7\u00f5es",
+ "HeaderAlternateEpisodeNumbers": "N\u00fameros de Epis\u00f3dios Alternativos",
"TabCollectionTitles": "T\u00edtulos",
- "LabelDisplayMissingEpisodesWithinSeasons": "Exibir epis\u00f3dios ausentes dentro das temporadas",
+ "HeaderSpecialEpisodeInfo": "Informa\u00e7\u00e3o do Epis\u00f3dio Especial",
+ "LabelDisplayMissingEpisodesWithinSeasons": "Exibir epis\u00f3dios que faltam dentro das temporadas",
+ "HeaderExternalIds": "Id`s Externos:",
"LabelUnairedMissingEpisodesWithinSeasons": "Exibir epis\u00f3dios por estrear dentro das temporadas",
+ "LabelDvdSeasonNumber": "N\u00famero da temporada do Dvd:",
"HeaderVideoPlaybackSettings": "Ajustes da Reprodu\u00e7\u00e3o de V\u00eddeo",
+ "LabelDvdEpisodeNumber": "N\u00famero do epis\u00f3dio do Dvd:",
"HeaderPlaybackSettings": "Ajustes de Reprodu\u00e7\u00e3o",
+ "LabelAbsoluteEpisodeNumber": "N\u00famero absoluto do epis\u00f3dio:",
"LabelAudioLanguagePreference": "Prefer\u00eancia do idioma do \u00e1udio:",
+ "LabelAirsBeforeSeason": "Exibido antes da temporada:",
"LabelSubtitleLanguagePreference": "Prefer\u00eancia do idioma da legenda:",
+ "LabelAirsAfterSeason": "Exibido depois da temporada:",
"OptionDefaultSubtitles": "Padr\u00e3o",
+ "LabelAirsBeforeEpisode": "Exibido antes do epis\u00f3dio:",
"OptionOnlyForcedSubtitles": "Apenas legendas for\u00e7adas",
+ "LabelTreatImageAs": "Tratar imagem como:",
"OptionAlwaysPlaySubtitles": "Sempre reproduzir legendas",
+ "LabelDisplayOrder": "Ordem de exibi\u00e7\u00e3o:",
"OptionNoSubtitles": "Nenhuma legenda",
+ "LabelDisplaySpecialsWithinSeasons": "Exibir especiais dentro das temporadas em que s\u00e3o exibidos",
"OptionDefaultSubtitlesHelp": "As legendas que forem iguais ao idioma preferido ser\u00e3o carregadas quando o \u00e1udio estiver em um idioma estrangeiro.",
+ "HeaderCountries": "Pa\u00edses",
"OptionOnlyForcedSubtitlesHelp": "Apenas legendas marcadas como for\u00e7adas ser\u00e3o carregadas.",
+ "HeaderGenres": "G\u00eaneros",
"OptionAlwaysPlaySubtitlesHelp": "As legendas que forem iguais ao idioma preferido ser\u00e3o carregadas independente do idioma do \u00e1udio.",
+ "HeaderPlotKeywords": "Palavras-chave da Trama",
"OptionNoSubtitlesHelp": "As legendas n\u00e3o ser\u00e3o carregadas por padr\u00e3o.",
+ "HeaderStudios": "Est\u00fadios",
"TabProfiles": "Perfis",
+ "HeaderTags": "Tags",
"TabSecurity": "Seguran\u00e7a",
+ "HeaderMetadataSettings": "Ajustes dos Metadados",
"ButtonAddUser": "Adicionar Usu\u00e1rio",
+ "LabelLockItemToPreventChanges": "Bloquear este item para evitar altera\u00e7\u00f5es futuras",
"ButtonSave": "Salvar",
+ "MessageLeaveEmptyToInherit": "Deixar em branco para herdar os ajustes de um item superior, ou o valor padr\u00e3o global",
"ButtonResetPassword": "Redefinir Senha",
+ "TabSupporterClub": "Clube do Colaborador",
"LabelNewPassword": "Nova senha:",
+ "HeaderDonationType": "Tipo de doa\u00e7\u00e3o:",
"LabelNewPasswordConfirm": "Confirmar nova senha:",
+ "OptionMakeOneTimeDonation": "Fazer doa\u00e7\u00e3o uma \u00fanica vez",
"HeaderCreatePassword": "Criar Senha",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Senha atual:",
+ "OptionLifeTimeSupporterClubMembership": "Filia\u00e7\u00e3o vital\u00edcia do clube do colaborador",
"LabelMaxParentalRating": "Classifica\u00e7\u00e3o parental m\u00e1xima permitida:",
+ "HeaderSupporterBenefit": "Tornar-se um membro do clube do colaborador oferece benef\u00edcios adicionais como o acesso a plugins premium, conte\u00fado de canais de internet e mais.",
"MaxParentalRatingHelp": "Conte\u00fado com classifica\u00e7\u00e3o maior ser\u00e1 ocultado do usu\u00e1rio.",
+ "OptionNoTrailer": "Nenhum Trailer",
"LibraryAccessHelp": "Selecionar as pastas de m\u00eddia para compartilhar com este usu\u00e1rio. Administradores poder\u00e3o editar todas as pastas usando o gerenciador de metadados.",
+ "OptionNoThemeSong": "Nenhuma M\u00fasica-tema",
"ChannelAccessHelp": "Selecione os canais a compartilhar com este usu\u00e1rio. Administradores poder\u00e3o editar todos os canais usando o gerenciador de metadados.",
+ "OptionNoThemeVideo": "Nenhum V\u00eddeo-tema",
"ButtonDeleteImage": "Apagar Imagem",
+ "LabelOneTimeDonationAmount": "Valor da doa\u00e7\u00e3o:",
"LabelSelectUsers": "Selecionar usu\u00e1rios:",
+ "OptionActor": "Ator",
"ButtonUpload": "Carregar",
+ "OptionComposer": "Compositor",
"HeaderUploadNewImage": "Carregar Nova Imagem",
- "LabelDropImageHere": "Soltar Imagem Aqui",
+ "OptionDirector": "Diretor",
+ "LabelDropImageHere": "Soltar imagem aqui",
+ "OptionGuestStar": "Ator convidado",
"ImageUploadAspectRatioHelp": "Propor\u00e7\u00e3o de Imagem 1:1 Recomendada. Apenas JPG\/PNG",
+ "OptionProducer": "Produtor",
"MessageNothingHere": "Nada aqui.",
+ "OptionWriter": "Escritor",
"MessagePleaseEnsureInternetMetadata": "Por favor, certifique-se que o download de metadados da internet est\u00e1 habilitado.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Sugeridos",
+ "LabelAirTime": "Air time:",
"TabLatest": "Recentes",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "Por Estrear",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "S\u00e9ries",
"TabEpisodes": "Epis\u00f3dios",
"TabGenres": "G\u00eaneros",
@@ -171,7 +233,7 @@
"OptionArtist": "Artista",
"OptionAlbum": "\u00c1lbum",
"OptionTrackName": "Nome da Faixa",
- "OptionCommunityRating": "Classifica\u00e7\u00e3o da Comunidade",
+ "OptionCommunityRating": "Avalia\u00e7\u00e3o da Comunidade",
"OptionNameSort": "Nome",
"OptionFolderSort": "Pastas",
"OptionBudget": "Or\u00e7amento",
@@ -181,7 +243,7 @@
"OptionTimeline": "Linha do tempo",
"OptionThumb": "\u00cdcone",
"OptionBanner": "Banner",
- "OptionCriticRating": "Classifica\u00e7\u00e3o da Cr\u00edtica",
+ "OptionCriticRating": "Avalia\u00e7\u00e3o da Cr\u00edtica",
"OptionVideoBitrate": "Taxa do V\u00eddeo",
"OptionResumable": "Por retomar",
"ScheduledTasksHelp": "Clique em uma tarefa para ajustar quando ser\u00e1 executada.",
@@ -213,10 +275,12 @@
"TabMovies": "Filmes",
"TabStudios": "Est\u00fadios",
"TabTrailers": "Trailers",
+ "LabelArtists": "Artistas:",
+ "LabelArtistsHelp": "Separar m\u00faltiplos usando ;",
"HeaderLatestMovies": "Filmes Recentes",
"HeaderLatestTrailers": "Trailers Recentes",
"OptionHasSpecialFeatures": "Caracter\u00edsticas Especiais",
- "OptionImdbRating": "Classifica\u00e7\u00e3o IMDb",
+ "OptionImdbRating": "Avalia\u00e7\u00e3o IMDb",
"OptionParentalRating": "Classifica\u00e7\u00e3o Parental",
"OptionPremiereDate": "Data da Estr\u00e9ia",
"TabBasic": "B\u00e1sico",
@@ -224,7 +288,7 @@
"HeaderStatus": "Status",
"OptionContinuing": "Em Exibi\u00e7\u00e3o",
"OptionEnded": "Finalizada",
- "HeaderAirDays": "Dias de Exibi\u00e7\u00e3o:",
+ "HeaderAirDays": "Dias de Exibi\u00e7\u00e3o",
"OptionSunday": "Domingo",
"OptionMonday": "Segunda-feira",
"OptionTuesday": "Ter\u00e7a-feira",
@@ -232,7 +296,8 @@
"OptionThursday": "Quinta-feira",
"OptionFriday": "Sexta-feira",
"OptionSaturday": "S\u00e1bado",
- "HeaderManagement": "Gerenciamento:",
+ "HeaderManagement": "Gerenciamento",
+ "LabelManagement": "Administra\u00e7\u00e3o:",
"OptionMissingImdbId": "Faltando Id IMDb",
"OptionMissingTvdbId": "Faltando Id TheTVDB",
"OptionMissingOverview": "Faltando Sinopse",
@@ -249,8 +314,8 @@
"VisitTheCommunity": "Visitar a Comunidade",
"VisitMediaBrowserWebsite": "Visitar o Web Site do Media Browser",
"VisitMediaBrowserWebsiteLong": "Visite o Web Site do Media Browser para obter as \u00faltimas novidades e atualizar-se com o blog de desenvolvedores.",
- "OptionHideUser": "Oculte este usu\u00e1rio das telas de login",
- "OptionDisableUser": "Desative este usu\u00e1rio",
+ "OptionHideUser": "Ocultar este usu\u00e1rio das telas de login",
+ "OptionDisableUser": "Desativar este usu\u00e1rio",
"OptionDisableUserHelp": "Se estiver desativado o servidor n\u00e3o permitir\u00e1 nenhuma conex\u00e3o deste usu\u00e1rio. Conex\u00f5es existentes ser\u00e3o abruptamente terminadas.",
"HeaderAdvancedControl": "Controle Avan\u00e7ado",
"LabelName": "Nome:",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "Selecionar",
- "ButtonSearch": "Busca",
"ButtonGroupVersions": "Agrupar Vers\u00f5es",
"ButtonAddToCollection": "Adicionar \u00e0 Cole\u00e7\u00e3o",
"PismoMessage": "Utilizando Pismo File Mount atrav\u00e9s de uma licen\u00e7a de doa\u00e7\u00e3o",
@@ -286,17 +350,17 @@
"LabelAllowServerAutoRestartHelp": "O servidor s\u00f3 reiniciar\u00e1 durante os per\u00edodos ociosos, quando nenhum usu\u00e1rio estiver ativo.",
"LabelEnableDebugLogging": "Ativar log de depura\u00e7\u00e3o",
"LabelRunServerAtStartup": "Executar servidor na inicializa\u00e7\u00e3o",
- "LabelRunServerAtStartupHelp": "Isto abrir\u00e1 o \u00edcone da bandeja de sistema na inicializa\u00e7\u00e3o do windows. Para iniciar o servi\u00e7o do windows, desmarque esta op\u00e7\u00e3o e inicie o servi\u00e7o no painel de controle do windows. Por favor, saiba que voc\u00ea n\u00e3o pode executar os dois ao mesmo tempo, ent\u00e3o ser\u00e1 necess\u00e1rio sair do \u00edcone na bandeja antes de iniciar o servi\u00e7o.",
+ "LabelRunServerAtStartupHelp": "Esta op\u00e7\u00e3o abrir\u00e1 o \u00edcone da bandeja de sistema na inicializa\u00e7\u00e3o do windows. Para iniciar o servi\u00e7o do windows, desmarque esta op\u00e7\u00e3o e inicie o servi\u00e7o no painel de controle do windows. Por favor, saiba que voc\u00ea n\u00e3o pode executar os dois ao mesmo tempo, ent\u00e3o ser\u00e1 necess\u00e1rio sair do \u00edcone na bandeja antes de iniciar o servi\u00e7o.",
"ButtonSelectDirectory": "Selecionar Diret\u00f3rio",
"LabelCustomPaths": "Defina caminhos personalizados. Deixe os campos em branco para usar o padr\u00e3o.",
"LabelCachePath": "Caminho do cache:",
- "LabelCachePathHelp": "Esta pasta cont\u00e9m arquivos de cache do servidor como, por exemplo, imagens.",
+ "LabelCachePathHelp": "Defina uma localiza\u00e7\u00e3o para os arquivos de cache como, por exemplo, imagens.",
"LabelImagesByNamePath": "Caminho do Images by name:",
- "LabelImagesByNamePathHelp": "Esta pasta cont\u00e9m imagens de ator, artista, g\u00eanero e est\u00fadio.",
+ "LabelImagesByNamePathHelp": "Defina uma localiza\u00e7\u00e3o para imagens baixadas para ator, artista, g\u00eanero e est\u00fadio.",
"LabelMetadataPath": "Caminho dos Metadados:",
- "LabelMetadataPathHelp": "Esta localiza\u00e7\u00e3o cont\u00e9m artwork e metadados transferidos que n\u00e3o foram configurados para serem armazenados nas pastas de m\u00eddia.",
+ "LabelMetadataPathHelp": "Defina uma localiza\u00e7\u00e3o para artwork e metadados baixados, caso n\u00e3o sejam salvos dentro das pastas de m\u00eddia.",
"LabelTranscodingTempPath": "Caminho tempor\u00e1rio para transcodifica\u00e7\u00e3o:",
- "LabelTranscodingTempPathHelp": "Esta pasta cont\u00e9m arquivos ativos usados pelo transcodificador.",
+ "LabelTranscodingTempPathHelp": "Esta pasta cont\u00e9m arquivos ativos usados pelo transcodificador. Especifique um caminho personalizado ou deixe em branco para usar o padr\u00e3o dentro da pasta de dados do servidor.",
"TabBasics": "B\u00e1sico",
"TabTV": "TV",
"TabGames": "Jogos",
@@ -310,15 +374,15 @@
"LabelAutomaticUpdatesFanart": "Ativar atualiza\u00e7\u00f5es autom\u00e1ticas de FanArt.tv",
"LabelAutomaticUpdatesTmdb": "Ativar atualiza\u00e7\u00f5es autom\u00e1ticas de The MovieDB.org",
"LabelAutomaticUpdatesTvdb": "Ativar atualiza\u00e7\u00f5es autom\u00e1ticas de TheTVDB.com",
- "LabelAutomaticUpdatesFanartHelp": "Se ativado, novas imagens ser\u00e3o automaticamente transferidas ao serem adicionadas ao fanart.tv. As Imagens atuais n\u00e3o ser\u00e3o substitu\u00eddas.",
- "LabelAutomaticUpdatesTmdbHelp": "Se ativado, novas imagens ser\u00e3o automaticamente transferidas ao serem adicionadas ao TheMovieDB.org. As Imagens atuais n\u00e3o ser\u00e3o substitu\u00eddas.",
- "LabelAutomaticUpdatesTvdbHelp": "Se ativado, novas imagens ser\u00e3o automaticamente transferidas ao serem adicionadas ao TheTVDB.com. As Imagens atuais n\u00e3o ser\u00e3o substitu\u00eddas.",
- "ExtractChapterImagesHelp": "Extrair imagens de cap\u00edtulos permitir\u00e1 aos clientes exibir menus gr\u00e1ficos de sele\u00e7\u00e3o de cenas. O processo pode ser lento, uso intensivo de cpu e pode exigir bastante espa\u00e7o em disco. Ele ser\u00e1 executado \u00e0s 4:00hs, embora isto possa ser configur\u00e1vel na \u00e1rea de tarefas agendadas. N\u00e3o \u00e9 recomendado executar esta tarefa durante as horas de pico de uso.",
+ "LabelAutomaticUpdatesFanartHelp": "Se ativado, novas imagens ser\u00e3o automaticamente baixadas ao serem adicionadas ao fanart.tv. As Imagens atuais n\u00e3o ser\u00e3o substitu\u00eddas.",
+ "LabelAutomaticUpdatesTmdbHelp": "Se ativado, novas imagens ser\u00e3o automaticamente baixadas ao serem adicionadas ao TheMovieDB.org. As Imagens atuais n\u00e3o ser\u00e3o substitu\u00eddas.",
+ "LabelAutomaticUpdatesTvdbHelp": "Se ativado, novas imagens ser\u00e3o automaticamente baixadas ao serem adicionadas ao TheTVDB.com. As Imagens atuais n\u00e3o ser\u00e3o substitu\u00eddas.",
+ "ExtractChapterImagesHelp": "Extrair imagens de cap\u00edtulos permitir\u00e1 aos clientes exibir menus gr\u00e1ficos de sele\u00e7\u00e3o de cenas. O processo pode ser lento, demandar uso intensivo de cpu e pode exigir bastante espa\u00e7o em disco. Ele ser\u00e1 executado quando os v\u00eddeos forem descobertos e tamb\u00e9m como uma tarefa agendada executada \u00e0s 4 da manh\u00e3. O agendamento pode ser configurado na \u00e1rea de tarefas agendadas. N\u00e3o \u00e9 recomendado executar esta tarefa durante as horas de pico de uso.",
"LabelMetadataDownloadLanguage": "Idioma preferido para download:",
"ButtonAutoScroll": "Auto-rolagem",
"LabelImageSavingConvention": "Conven\u00e7\u00e3o para salvar a imagem:",
"LabelImageSavingConventionHelp": "O Media Browser reconhece imagens da maioria das aplica\u00e7\u00f5es de m\u00eddia. Escolher a conven\u00e7\u00e3o de download \u00e9 \u00fatil se voc\u00ea usa tamb\u00e9m outros produtos.",
- "OptionImageSavingCompatible": "Compat\u00edvel - Media Browser\/Plex\/Xbmc",
+ "OptionImageSavingCompatible": "Compat\u00edvel - Media Browser\/Xbmc\/Plex",
"OptionImageSavingStandard": "Padr\u00e3o - MB2",
"ButtonSignIn": "Iniciar Sess\u00e3o",
"TitleSignIn": "Iniciar Sess\u00e3o",
@@ -347,6 +411,8 @@
"TabStatus": "Status",
"TabSettings": "Ajustes",
"ButtonRefreshGuideData": "Atualizar Dados do Guia",
+ "ButtonRefresh": "Atualizar",
+ "ButtonAdvancedRefresh": "Atualiza\u00e7\u00e3o Avan\u00e7ada",
"OptionPriority": "Prioridade",
"OptionRecordOnAllChannels": "Gravar programa em todos os canais",
"OptionRecordAnytime": "Gravar programa a qualquer hora",
@@ -430,7 +496,8 @@
"HeaderCastCrew": "Elenco & Equipe",
"HeaderAdditionalParts": "Partes Adicionais",
"ButtonSplitVersionsApart": "Separar Vers\u00f5es",
- "LabelMissing": "Ausente",
+ "ButtonPlayTrailer": "Trailer",
+ "LabelMissing": "Faltando",
"LabelOffline": "Desconectado",
"PathSubstitutionHelp": "Substitui\u00e7\u00f5es de caminho s\u00e3o usadas para mapear um caminho no servidor que possa ser acessado pelos clientes. Ao permitir o acesso dos clientes \u00e0 m\u00eddia no servidor, eles podem reproduzir diretamente atrav\u00e9s da rede e evitar o uso de recursos do servidor para fazer stream ou transcodifica\u00e7\u00e3o.",
"HeaderFrom": "De",
@@ -441,11 +508,11 @@
"LabelToHelp": "Exemplo: \\\\MeuServidor\\Filmes (um caminho que os clientes possam acessar)",
"ButtonAddPathSubstitution": "Adicionar Substitui\u00e7\u00e3o",
"OptionSpecialEpisode": "Especiais",
- "OptionMissingEpisode": "Epis\u00f3dios Ausentes",
+ "OptionMissingEpisode": "Epis\u00f3dios Faltantes",
"OptionUnairedEpisode": "Epis\u00f3dios Por Estrear",
"OptionEpisodeSortName": "Nome de Ordena\u00e7\u00e3o do Epis\u00f3dio",
"OptionSeriesSortName": "Nome da S\u00e9rie",
- "OptionTvdbRating": "Classifica\u00e7\u00e3o Tvdb",
+ "OptionTvdbRating": "Avalia\u00e7\u00e3o Tvdb",
"HeaderTranscodingQualityPreference": "Prefer\u00eancia de Qualidade de Transcodifica\u00e7\u00e3o:",
"OptionAutomaticTranscodingHelp": "O servidor decidir\u00e1 a qualidade e a velocidade",
"OptionHighSpeedTranscodingHelp": "Qualidade pior, mas codifica\u00e7\u00e3o mais r\u00e1pida",
@@ -511,12 +578,14 @@
"HeaderDestination": "Destino",
"HeaderProgram": "Programa",
"HeaderClients": "Clientes",
- "LabelCompleted": "Completado",
- "LabelSkipped": "Ignorado",
+ "LabelCompleted": "Completa",
+ "LabelFailed": "Falhou",
+ "LabelSkipped": "Ignorada",
"HeaderEpisodeOrganization": "Organiza\u00e7\u00e3o do Epis\u00f3dio",
- "LabelSeasonNumber": "N\u00famero da temporada",
- "LabelEpisodeNumber": "N\u00famero do epis\u00f3dio",
- "LabelEndingEpisodeNumber": "N\u00famero do epis\u00f3dio final",
+ "LabelSeries": "S\u00e9rie:",
+ "LabelSeasonNumber": "N\u00famero da temporada:",
+ "LabelEpisodeNumber": "N\u00famero do epis\u00f3dio:",
+ "LabelEndingEpisodeNumber": "N\u00famero do epis\u00f3dio final:",
"LabelEndingEpisodeNumberHelp": "Necess\u00e1rio s\u00f3 para arquivos multi-epis\u00f3dios",
"HeaderSupportTheTeam": "Apoie a Equipe do Media Browser",
"LabelSupportAmount": "Valor (USD)",
@@ -541,7 +610,7 @@
"HeaderPattern": "Padr\u00e3o",
"HeaderResult": "Resultado",
"LabelDeleteEmptyFolders": "Apagar pastas vazias depois da organiza\u00e7\u00e3o",
- "LabelDeleteEmptyFoldersHelp": "Ativar isto para manter o diret\u00f3rio de download limpo.",
+ "LabelDeleteEmptyFoldersHelp": "Ativar esta op\u00e7\u00e3o para manter o diret\u00f3rio de download limpo.",
"LabelDeleteLeftOverFiles": "Apagar os arquivos deixados com as seguintes extens\u00f5es:",
"LabelDeleteLeftOverFilesHelp": "Separar com ;. Por exemplo: .nfo;.txt",
"OptionOverwriteExistingEpisodes": "Sobrescrever epis\u00f3dios existentes",
@@ -549,7 +618,7 @@
"OptionCopy": "Copiar",
"OptionMove": "Mover",
"LabelTransferMethodHelp": "Copiar ou mover arquivos da pasta de monitora\u00e7\u00e3o",
- "HeaderLatestNews": "Novidades Recentes",
+ "HeaderLatestNews": "Not\u00edcias Recentes",
"HeaderHelpImproveMediaBrowser": "Ajude a Melhorar o Media Browser",
"HeaderRunningTasks": "Tarefas em Execu\u00e7\u00e3o",
"HeaderActiveDevices": "Dispositivos Ativos",
@@ -557,7 +626,7 @@
"HeaerServerInformation": "Informa\u00e7\u00f5es do Servidor",
"ButtonRestartNow": "Reiniciar Agora",
"ButtonRestart": "Reiniciar",
- "ButtonShutdown": "Terminar",
+ "ButtonShutdown": "Desligar",
"ButtonUpdateNow": "Atualizar Agora",
"PleaseUpdateManually": "Por favor, desligue o servidor e atualize-o manualmente.",
"NewServerVersionAvailable": "Uma nova vers\u00e3o do Servidor Media Browser est\u00e1 dispon\u00edvel!",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Ativar esta notifica\u00e7\u00e3o",
"LabelMonitorUsers": "Monitorar atividade de:",
"LabelSendNotificationToUsers": "Enviar notifica\u00e7\u00e3o para:",
- "UsersNotNotifiedAboutSelfActivity": "Os usu\u00e1rios n\u00e3o ser\u00e3o notificados sobre suas pr\u00f3prias atividades.",
"LabelUseNotificationServices": "Usar os seguintes servi\u00e7os:",
"CategoryUser": "Usu\u00e1rio",
"CategorySystem": "Sistema",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Descer P\u00e1gina",
"PageAbbreviation": "PG",
"ButtonHome": "In\u00edcio",
+ "ButtonSearch": "Busca",
"ButtonSettings": "Ajustes",
"ButtonTakeScreenshot": "Capturar Tela",
"ButtonLetterUp": "Letra Acima",
@@ -657,10 +726,12 @@
"TabNowPlaying": "Reproduzindo Agora",
"TabNavigation": "Navega\u00e7\u00e3o",
"TabControls": "Controles",
- "ButtonFullscreen": "Alternar tela cheia",
+ "ButtonFullscreen": "Alternar para tela cheia",
"ButtonScenes": "Cenas",
"ButtonSubtitles": "Legendas",
"ButtonAudioTracks": "Faixas de \u00e1udio",
+ "ButtonPreviousTrack": "Faixa anterior",
+ "ButtonNextTrack": "Faixa seguinte",
"ButtonStop": "Parar",
"ButtonPause": "Pausar",
"LabelGroupMoviesIntoCollections": "Agrupar filmes nas cole\u00e7\u00f5es",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separados por v\u00edrgula. Pode ser deixado em branco para usar com todos os containers.",
"HeaderResponseProfile": "Perfil de Resposta",
"LabelType": "Tipo:",
+ "LabelPersonRole": "Personagem:",
+ "LabelPersonRoleHelp": "O personagem geralmente s\u00f3 aplica para atores.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Codecs de v\u00eddeo:",
"LabelProfileAudioCodecs": "Codecs de \u00e1udio:",
@@ -719,8 +792,16 @@
"HeaderProfileServerSettingsHelp": "Estes valores controlam como o Media Browser ser\u00e1 exibido no dispositivo.",
"LabelMaxBitrate": "Taxa de bits m\u00e1xima:",
"LabelMaxBitrateHelp": "Especifique uma taxa de bits m\u00e1xima para ambientes com restri\u00e7\u00e3o de tamanho de banda, ou se o dispositivo imp\u00f5e esse limite.",
+ "LabelMaxStreamingBitrate": "Taxa m\u00e1xima para streaming:",
+ "LabelMaxStreamingBitrateHelp": "Defina uma taxa m\u00e1xima para fazer streaming.",
+ "LabelMaxStaticBitrate": "Taxa m\u00e1xima para sincronizar:",
+ "LabelMaxStaticBitrateHelp": "Defina uma taxa m\u00e1xima quando sincronizar conte\u00fado em alta qualidade.",
+ "LabelMusicStaticBitrate": "Taxa de sincroniza\u00e7\u00e3o das m\u00fasicas:",
+ "LabelMusicStaticBitrateHelp": "Defina a taxa m\u00e1xima ao sincronizar m\u00fasicas",
+ "LabelMusicStreamingTranscodingBitrate": "Taxa de transcodifica\u00e7\u00e3o das m\u00fasicas:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Defina a taxa m\u00e1xima ao fazer streaming das m\u00fasicas",
"OptionIgnoreTranscodeByteRangeRequests": "Ignorar requisi\u00e7\u00f5es de extens\u00e3o do byte de transcodifica\u00e7\u00e3o",
- "OptionIgnoreTranscodeByteRangeRequestsHelp": "Se ativado, estas requisi\u00e7\u00f5es ser\u00e3o honradas mas ir\u00e3o ignorar o cabe\u00e7alho da extens\u00e3o do byte.",
+ "OptionIgnoreTranscodeByteRangeRequestsHelp": "Se ativadas, estas requisi\u00e7\u00f5es ser\u00e3o honradas mas ir\u00e3o ignorar o cabe\u00e7alho da extens\u00e3o do byte.",
"LabelFriendlyName": "Nome amig\u00e1vel",
"LabelManufacturer": "Fabricante",
"LabelManufacturerUrl": "Url do fabricante",
@@ -773,18 +854,20 @@
"LabelDisplayPluginsFor": "Exibir plugins para:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Outros",
- "LabelEpisodeName": "Nome do epis\u00f3dio",
- "LabelSeriesName": "Nome da s\u00e9rie",
+ "LabelEpisodeNamePlain": "Nome do epis\u00f3dio",
+ "LabelSeriesNamePlain": "Nome da s\u00e9rie",
"ValueSeriesNamePeriod": "Nome.s\u00e9rie",
"ValueSeriesNameUnderscore": "Nome_s\u00e9rie",
"ValueEpisodeNamePeriod": "Nome.epis\u00f3dio",
"ValueEpisodeNameUnderscore": "Nome_epis\u00f3dio",
+ "LabelSeasonNumberPlain": "N\u00famero da temporada",
+ "LabelEpisodeNumberPlain": "N\u00famero do epis\u00f3dio",
+ "LabelEndingEpisodeNumberPlain": "N\u00famero do epis\u00f3dio final",
"HeaderTypeText": "Digitar texto",
"LabelTypeText": "Texto",
"HeaderSearchForSubtitles": "Buscar Legendas",
"MessageNoSubtitleSearchResultsFound": "N\u00e3o foi encontrado nenhum resultado.",
- "TabDisplay": "Exibir",
+ "TabDisplay": "Exibi\u00e7\u00e3o",
"TabLanguages": "Idiomas",
"TabWebClient": "Cliente Web",
"LabelEnableThemeSongs": "Ativar m\u00fasicas-tema",
@@ -796,29 +879,32 @@
"OptionAuto": "Auto",
"OptionYes": "Sim",
"OptionNo": "N\u00e3o",
- "LabelHomePageSection1": "Se\u00e7\u00e3o um da tela de in\u00edcio:",
- "LabelHomePageSection2": "Se\u00e7\u00e3o dois da tela de in\u00edcio:",
- "LabelHomePageSection3": "Se\u00e7\u00e3o tr\u00eas da tela de in\u00edcio:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "Minha biblioteca (bot\u00f5es)",
- "OptionMyLibrary": "Minha biblioteca",
- "OptionMyLibrarySmall": "Minha biblioteca (pequena)",
+ "LabelHomePageSection1": "Tela de in\u00edcio se\u00e7\u00e3o 1:",
+ "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)",
"OptionResumablemedia": "Retomar",
"OptionLatestMedia": "M\u00eddias recentes",
- "OptionLatestChannelMedia": "Latest channel items",
- "HeaderLatestChannelItems": "Latest Channel Items",
+ "OptionLatestChannelMedia": "Itens recentes de canal",
+ "HeaderLatestChannelItems": "Itens Recentes de Canal",
"OptionNone": "Nenhum",
"HeaderLiveTv": "TV ao Vivo",
"HeaderReports": "Relat\u00f3rios",
"HeaderMetadataManager": "Gerenciador de Metadados",
"HeaderPreferences": "Prefer\u00eancias",
"MessageLoadingChannels": "Carregando conte\u00fado do canal...",
+ "MessageLoadingContent": "Carregando conte\u00fado...",
"ButtonMarkRead": "Marcar com lido",
"OptionDefaultSort": "Padr\u00e3o",
"OptionCommunityMostWatchedSort": "Mais Assistidos",
"TabNextUp": "Pr\u00f3ximos",
- "MessageNoMovieSuggestionsAvailable": "N\u00e3o existem sugest\u00f5es de filmes dispon\u00edveis atualmente. Comece por assistir e classificar seus filmes e, ent\u00e3o, volte para verificar suas recomenda\u00e7\u00f5es.",
+ "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 agrupe os Filmes, S\u00e9ries, Livros e Jogos de forma personalizada. Clique no bot\u00e3o Nova para iniciar a cria\u00e7\u00e3o de 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.",
+ "MessageNoPlaylistItemsAvailable": "Esta lista de reprodu\u00e7\u00e3o est\u00e1 vazia.",
"HeaderWelcomeToMediaBrowserWebClient": "Bem-vindo ao Cliente Web do Media Browser",
"ButtonDismiss": "Descartar",
"MessageLearnHowToCustomize": "Aprenda como personalizar esta p\u00e1gina com seu estilo pessoal. Clique no \u00edcone do usu\u00e1rio no canto superior direito da tela para ver e atualizar suas prefer\u00eancias.",
@@ -842,11 +928,171 @@
"ViewTypeChannels": "Canais",
"ViewTypeLiveTV": "TV ao Vivo",
"HeaderOtherDisplaySettings": "Ajustes de Exibi\u00e7\u00e3o",
- "HeaderMyViews": "My Views",
+ "HeaderMyViews": "Minhas Visualiza\u00e7\u00f5es",
"LabelSelectFolderGroups": "Agrupar automaticamente o conte\u00fado das seguintes pastas dentro das visualiza\u00e7\u00f5es como Filmes, M\u00fasicas e TV:",
"LabelSelectFolderGroupsHelp": "Pastas que n\u00e3o est\u00e3o marcadas ser\u00e3o exibidas em sua pr\u00f3pria visualiza\u00e7\u00e3o.",
"OptionDisplayAdultContent": "Exibir conte\u00fado adulto",
- "OptionLibraryFolders": "Visualiza\u00e7\u00e3o da pasta",
- "TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLibraryFolders": "Pastas de m\u00eddias",
+ "TitleRemoteControl": "Controle Remoto",
+ "OptionLatestTvRecordings": "\u00daltimas grava\u00e7\u00f5es",
+ "LabelProtocolInfo": "Informa\u00e7\u00e3o do protocolo:",
+ "LabelProtocolInfoHelp": "O valor que ser\u00e1 usado ao responder os pedidos GetProtocolInfo do dispositivo.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "O Media Browser inclui suporte nativo aos metadados Nfo e Imagens do Xbmc. Para ativar ou desativar os metadados do Xbmc, use a aba Avan\u00e7ado para configurar as op\u00e7\u00f5es para seus tipos de m\u00eddias.",
+ "LabelXbmcMetadataUser": "Adicionar dados de monitora\u00e7\u00e3o do usu\u00e1rio para nfo`s para:",
+ "LabelXbmcMetadataUserHelp": "Ative esta op\u00e7\u00e3o para manter dados de monitora\u00e7\u00e3o em sincronia entre o Media Browser e o Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Formato da data de lan\u00e7amento:",
+ "LabelXbmcMetadataDateFormatHelp": "Todas as datas dentro dos nfo`s ser\u00e3o lidas e gravadas neste formato.",
+ "LabelXbmcMetadataSaveImagePaths": "Salvar o caminho da imagem dentro dos arquivos nfo.",
+ "LabelXbmcMetadataSaveImagePathsHelp": "Esta op\u00e7\u00e3o \u00e9 recomendada se possuir nomes de arquivos de imagem que n\u00e3o est\u00e3o de acordo com as recomenda\u00e7\u00f5es do Xbmc.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Ativar substitui\u00e7\u00e3o de caminho",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Ativa a substitui\u00e7\u00e3o do caminho da imagem usando as configura\u00e7\u00f5es de substitui\u00e7\u00e3o de caminho do servidor.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "Ver substitui\u00e7\u00e3o de caminho.",
+ "LabelGroupChannelsIntoViews": "Exibir os seguintes canais diretamente dentro de minhas visualiza\u00e7\u00f5es:",
+ "LabelGroupChannelsIntoViewsHelp": "Se ativados, estes canais ser\u00e3o exibidos imediatamente ao lado de outras visualiza\u00e7\u00f5es. Se desativado, eles ser\u00e3o exibidos dentro de uma visualiza\u00e7\u00e3o separada de Canais.",
+ "LabelDisplayCollectionsView": "Exibir uma visualiza\u00e7\u00e3o de cole\u00e7\u00f5es para mostrar colet\u00e2neas de filmes",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copiar extrafanart para dentro de extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "Ao fazer o download de imagens elas podem ser salvas em ambas extrafanart e extrathumbs para uma maior compatibilidade com a skin do Xbmc.",
+ "TabServices": "Servi\u00e7os",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Arquivos de log do servidor:",
+ "TabBranding": "Marca",
+ "HeaderBrandingHelp": "Personalize a apar\u00eancia do Media Browser para as necessidades de seu grupo ou organiza\u00e7\u00e3o.",
+ "LabelLoginDisclaimer": "Aviso legal no login:",
+ "LabelLoginDisclaimerHelp": "Este aviso ser\u00e1 exibido na parte inferior da p\u00e1gina de login.",
+ "LabelAutomaticallyDonate": "Doar automaticamente este valor a cada m\u00eas",
+ "LabelAutomaticallyDonateHelp": "Voc\u00ea pode cancelar a qualquer momento atrav\u00e9s de sua conta do PayPal.",
+ "OptionList": "Lista",
+ "TabDashboard": "Painel",
+ "TitleServer": "Servidor",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadados:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Arquivos tempor\u00e1rios da transcodifica\u00e7\u00e3o:",
+ "HeaderLatestMusic": "M\u00fasicas Recentes",
+ "HeaderBranding": "Marca",
+ "HeaderApiKeys": "Chaves da Api",
+ "HeaderApiKeysHelp": "Aplica\u00e7\u00f5es externas necessitam uma chave da Api para se comunicar com o Media Browser. Chaves s\u00e3o emitidas ao logar com uma conta do Media Browser ou ao conceder manualmente uma chave \u00e0 aplica\u00e7\u00e3o",
+ "HeaderApiKey": "Chave da Api",
+ "HeaderApp": "App",
+ "HeaderDevice": "Dispositivo",
+ "HeaderUser": "Usu\u00e1rio",
+ "HeaderDateIssued": "Data da Emiss\u00e3o",
+ "LabelChapterName": "Cap\u00edtulo {0}",
+ "HeaderNewApiKey": "Nova Chave da Api",
+ "LabelAppName": "Nome da app",
+ "LabelAppNameExample": "Exemplo: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Conceder permiss\u00e3o a uma aplica\u00e7\u00e3o para se comunicar com o Media Browser.",
+ "HeaderHttpHeaders": "Cabe\u00e7alhos de Http",
+ "HeaderIdentificationHeader": "Cabe\u00e7alho de Identifica\u00e7\u00e3o",
+ "LabelValue": "Valor:",
+ "LabelMatchType": "Tipo de correspond\u00eancia",
+ "OptionEquals": "Igual",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "Visualizar",
+ "TabSort": "Ordenar",
+ "TabFilter": "Filtro",
+ "ButtonView": "Visualizar",
+ "LabelPageSize": "Limite de itens:",
+ "LabelPath": "Caminho:",
+ "LabelView": "Visualizar:",
+ "TabUsers": "Usu\u00e1rios",
+ "LabelSortName": "Nome para ordena\u00e7\u00e3o:",
+ "LabelDateAdded": "Data de adi\u00e7\u00e3o:",
+ "HeaderFeatures": "Caracter\u00edsticas",
+ "HeaderAdvanced": "Avan\u00e7ado",
+ "ButtonSync": "Sincronizar",
+ "TabScheduledTasks": "Tarefas Agendadas",
+ "HeaderChapters": "Cap\u00edtulos",
+ "HeaderResumeSettings": "Ajustes para Retomar",
+ "TabSync": "Sincroniza\u00e7\u00e3o",
+ "TitleUsers": "Usu\u00e1rios",
+ "LabelProtocol": "Protocolo:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Contexto:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sinc",
+ "ButtonAddToPlaylist": "Adicionar \u00e0 lista de reprodu\u00e7\u00e3o",
+ "TabPlaylists": "Listas de Reprodu\u00e7\u00e3o",
+ "ButtonClose": "Fechar",
+ "LabelAllLanguages": "Todos os idiomas",
+ "HeaderBrowseOnlineImages": "Procurar Imagens Online",
+ "LabelSource": "Fonte:",
+ "OptionAll": "Todos",
+ "LabelImage": "Imagem:",
+ "ButtonBrowseImages": "Procurar Imagens",
+ "HeaderImages": "Imagens",
+ "HeaderBackdrops": "Imagens de Fundo",
+ "HeaderScreenshots": "Imagens da Tela",
+ "HeaderAddUpdateImage": "Adicionar\/Atualizar Imagem",
+ "LabelJpgPngOnly": "Apenas JPG\/PNG",
+ "LabelImageType": "Tipo de imagem:",
+ "OptionPrimary": "Prim\u00e1ria",
+ "OptionArt": "Arte",
+ "OptionBox": "Caixa",
+ "OptionBoxRear": "Traseira da Caixa",
+ "OptionDisc": "Disco",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Imagem da tela",
+ "OptionLocked": "Bloqueada",
+ "OptionUnidentified": "N\u00e3o identificada",
+ "OptionMissingParentalRating": "Faltando classifica\u00e7\u00e3o parental",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Epis\u00f3dios:",
+ "OptionSeason0": "Temporada 0",
+ "LabelReport": "Relat\u00f3rio:",
+ "OptionReportSongs": "M\u00fasicas",
+ "OptionReportSeries": "S\u00e9ries",
+ "OptionReportSeasons": "Temporadas",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "V\u00eddeos musicais",
+ "OptionReportMovies": "Filmes",
+ "OptionReportHomeVideos": "V\u00eddeos caseiros",
+ "OptionReportGames": "Jogos",
+ "OptionReportEpisodes": "Epis\u00f3dios",
+ "OptionReportCollections": "Cole\u00e7\u00f5es",
+ "OptionReportBooks": "Livros",
+ "OptionReportArtists": "Artistas",
+ "OptionReportAlbums": "\u00c1lbuns",
+ "OptionReportAdultVideos": "V\u00eddeos adultos",
+ "ButtonMore": "Mais",
+ "HeaderActivity": "Atividade",
+ "ScheduledTaskStartedWithName": "{0} iniciado",
+ "ScheduledTaskCancelledWithName": "{0} foi cancelado",
+ "ScheduledTaskCompletedWithName": "{0} completa",
+ "ScheduledTaskFailed": "Tarefa agendada completa",
+ "PluginInstalledWithName": "{0} foi instalado",
+ "PluginUpdatedWithName": "{0} foi atualizado",
+ "PluginUninstalledWithName": "{0} foi desinstalado",
+ "ScheduledTaskFailedWithName": "{0} falhou",
+ "ItemAddedWithName": "{0} foi adicionado \u00e0 biblioteca",
+ "ItemRemovedWithName": "{0} foi removido da biblioteca",
+ "DeviceOnlineWithName": "{0} est\u00e1 conectado",
+ "UserOnlineFromDevice": "{0} est\u00e1 ativo em {1}",
+ "DeviceOfflineWithName": "{0} foi desconectado",
+ "UserOfflineFromDevice": "{0} foi desconectado de {1}",
+ "SubtitlesDownloadedForItem": "Legendas baixadas para {0}",
+ "SubtitleDownloadFailureForItem": "Falha ao baixar legendas para {0}",
+ "LabelRunningTimeValue": "Dura\u00e7\u00e3o: {0}",
+ "LabelIpAddressValue": "Endere\u00e7o Ip: {0}",
+ "UserConfigurationUpdatedWithName": "A configura\u00e7\u00e3o de usu\u00e1rio de {0} foi atualizada",
+ "UserCreatedWithName": "O usu\u00e1rio {0} foi criado",
+ "UserPasswordChangedWithName": "A senha do usu\u00e1rio {0} foi alterada",
+ "UserDeletedWithName": "O usu\u00e1rio {0} foi exclu\u00eddo",
+ "MessageServerConfigurationUpdated": "A configura\u00e7\u00e3o do servidor foi atualizada",
+ "MessageNamedServerConfigurationUpdatedWithValue": "A se\u00e7\u00e3o {0} da configura\u00e7\u00e3o do servidor foi atualizada",
+ "MessageApplicationUpdated": "O Servidor Media Browser foi atualizado",
+ "AuthenticationSucceededWithUserName": "{0} se autenticou com sucesso",
+ "FailedLoginAttemptWithUserName": "Falha em tentativa de login de {0}",
+ "UserStartedPlayingItemWithValues": "{0} come\u00e7ou a reproduzir {1}",
+ "UserStoppedPlayingItemWithValues": "{0} parou de reproduzir {1}",
+ "AppDeviceValues": "App: {0}, Dispositivo: {1}",
+ "ProviderValue": "Provedor: {0}",
+ "LabelChannelDownloadSizeLimit": "Limite do tamanho para download (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limite o tamanho da pasta para download do canal",
+ "HeaderRecentActivity": "Atividade Recente"
} \ 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 457844814..359d838d9 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "Quando utilizadores reproduzem conte\u00fados",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Atualiza\u00e7\u00f5es dispon\u00edveis",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Atualiza\u00e7\u00f5es",
- "HeaderUpdateLevel": "N\u00edvel de atualiza\u00e7\u00e3o",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "Mostrar apenas legendas for\u00e7adas",
- "HeaderCustomizeOptionsPerMediaType": "Personalize as op\u00e7\u00f5es por tipo de conte\u00fado multim\u00e9dia",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Falhou",
- "LabelSeries": "S\u00e9rie:",
- "ButtonPreviousTrack": "Faixa Anterior",
- "ButtonNextTrack": "Pr\u00f3xima Faixa",
- "HeaderMyLibrary": "My Library",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "Sair",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "Visitar a Comunidade",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Wiki do Github",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "Padr\u00e3o",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "Ver Documenta\u00e7\u00e3o da API",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "Navegar pela Biblioteca",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "Configurar o Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "Abrir Visualizador da Biblioteca",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "Reiniciar Servidor",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "Mostrar Janela de Log",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "Anterior",
+ "HeaderPassword": "Password",
"LabelFinish": "Terminar",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "Seguinte",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "Concluiu!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "Bem-vindo ao Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "Este assistente ir\u00e1 ajud\u00e1-lo durante o processo de configura\u00e7\u00e3o. Para come\u00e7ar, selecione o idioma.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "Fale-nos sobre si",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "O seu primeiro nome:",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "\u00c9 poss\u00edvel adicionar utilizadores mais tarde no Painel Principal",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "O Media Browser inclui suporte a perfis de utilizadores, permitindo a cada utilizador ter as suas pr\u00f3prias configura\u00e7\u00f5es da visualiza\u00e7\u00e3o, estado das reprodu\u00e7\u00f5es e controlo parental.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Servi\u00e7o do Windows",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "Foi instalado um Servi\u00e7o do Windows.",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "O Media Browser Server corre, normalmente, como uma aplica\u00e7\u00e3o de Ambiente de trabalho com um \u00edcone na bandeja, mas se preferir corr\u00ea-lo como um servi\u00e7o em segundo plano, pode ser iniciado atrav\u00e9s do Painel de Controlo dos Servi\u00e7os do Windows.",
+ "HeaderIdentifyItem": "Identify Item",
"WindowsServiceIntro2": "Por favor tome aten\u00e7\u00e3o que se estiver a usar o servi\u00e7o, este n\u00e3o pode estar a correr ao mesmo tempo que o \u00edcone na bandeja. Por isso, ter\u00e1 de sair da aplca\u00e7\u00e3o da bandeja para poder correr o servi\u00e7o. Note, ainda, que o servi\u00e7o necessita de privil\u00e9gios administrativos via Painel de Controlo. De momento, n\u00e3o \u00e9 poss\u00edvel utilizar a fun\u00e7\u00e3o de auto-actualiza\u00e7\u00e3o ao mesmo tempo que est\u00e1 em utiliza\u00e7\u00e3o o servi\u00e7o, por isso, novas vers\u00f5es necessitam de interac\u00e7\u00e3o manual.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "\u00c9 tudo o que precisamos de momento. O Media Browser come\u00e7ou a colher informa\u00e7\u00e3o \u00e1cerca da sua biblioteca. D\u00ea uma vista de olhos nas nossas extens\u00f5es e depois clique em <b>Terminar<\/b> para ir para o <b>Painel Principal<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
"LabelConfigureSettings": "Configura\u00e7\u00f5es",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Activar extrac\u00e7\u00e3o de imagens dos v\u00eddeos.",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"VideoImageExtractionHelp": "Para os v\u00eddeos ainda sem imagens e que n\u00e3o se encontram imagens na internet. Esta funcionalidade vai acrescentar mais algum tempo na leitura inicial da biblioteca, mas resultar\u00e1 numa apresenta\u00e7\u00e3o melhorada,",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Extrair imagens dos cap\u00edtulos dos Filmes",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "Extrair imagens dos cap\u00edtulos permite, \u00e0s aplica\u00e7\u00f5es clientes, apresentar menus de selec\u00e7\u00e3o de cap\u00edtulos com cenas. Este processo pode ser lento, intensivo para o CPU e pode requerer v\u00e1rios gigabytes de espa\u00e7o. Corre como um servi\u00e7o nocturno, agendado para as 04h, embora possa ser configurado na \u00e1rea de Tarefas Agendadas. N\u00e3o \u00e9 recomendado correr esta tarefa em horas que haja muita utiliza\u00e7\u00e3o.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Activar mapeamento autom\u00e1tico de portas",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP permite configurar automaticamente o router, para um acesso remoto mais facilitado. Pode n\u00e3o suportar todos os modelos de routers.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Cancelar",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "Novo",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Configurar biblioteca",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "Adicionar pasta de media",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Tipo de pasta",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Requer o uso de uma extens\u00e3o, e.g. GameBrowser ou MB Bookshelf",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Consulte a wiki",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "Pa\u00eds:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "Idioma:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "Idioma preferido para metadados",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "Guardar imagens e metadados nas pastas multim\u00e9dia",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "Guardar imagens e metadados diretamente nas pastas multim\u00e9dia, vai coloc\u00e1-los num local de f\u00e1cil acesso para poderem ser editados facilmente.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "Transferir imagens e metadados da Internet",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "O Media Browser pode transferir informa\u00e7\u00f5es sobre os seus conte\u00fados multim\u00e9dia para possibilitar apresenta\u00e7\u00f5es mais ricas.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "Prefer\u00eancias",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "Senha",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "Aceder \u00e0 Biblioteca",
+ "LabelBudget": "Budget",
"TabImage": "Imagem",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "Perfil",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadados",
+ "LabelPlayers": "Players:",
"TabImages": "Imagens",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifica\u00e7\u00f5es",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "T\u00edtulos",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Mostrar epis\u00f3dios em falta dentro das temporadas",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Mostrar epis\u00f3dios por estrear dentro das temporadas",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "Configura\u00e7\u00f5es de Reprodu\u00e7\u00e3o de V\u00eddeo",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Op\u00e7\u00f5es de Reprodu\u00e7\u00e3o",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "Prefer\u00eancias de Idioma de Audio:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "Prefer\u00eancia de Idioma de Legenda:",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Padr\u00e3o",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Reproduzir sempre legendas",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "As legendas que forem iguais ao idioma preferido ser\u00e3o carregadas quando o \u00e1udio estiver num idioma estrangeiro.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "As legendas que forem iguais ao idioma preferido ser\u00e3o carregadas independente do idioma do \u00e1udio.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "As legendas n\u00e3o ser\u00e3o carregadas por padr\u00e3o.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Perfis",
+ "HeaderTags": "Tags",
"TabSecurity": "Seguran\u00e7a",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "Adicionar Utilizador",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "Guardar",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "Redefinir Senha",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "Nova senha:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "Confirmar nova senha:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "Criar Senha",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Senha actual:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "Controlo Parental m\u00e1ximo permitido:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "Conte\u00fado com classifica\u00e7\u00e3o mais elevada ser\u00e1 escondida deste utilizador.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "Escolha as pastas de media a partilha com este utilizador. Os Administradores poder\u00e3o editar todas as pastas, usando o Gestor de Metadados.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "Apagar imagem",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "Selecionar utilizadores:",
+ "OptionActor": "Actor",
"ButtonUpload": "Carregar",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Carregar Nova Imagem",
+ "OptionDirector": "Director",
"LabelDropImageHere": "Largar imagem aqui",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "1:1 R\u00e1cio de aspecto recomendado. JPG\/ PNG apenas.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Nada aqui.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "Certifique-se que a transfer\u00eancia de metadados da internet est\u00e1 activa.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Sugest\u00f5es",
+ "LabelAirTime": "Air time:",
"TabLatest": "Mais recente",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "Pr\u00f3ximos",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "S\u00e9ries",
"TabEpisodes": "Epis\u00f3dios",
"TabGenres": "G\u00e9neros Art\u00edsticos",
@@ -163,7 +225,7 @@
"OptionAscending": "Ascendente",
"OptionDescending": "Descendente",
"OptionRuntime": "Dura\u00e7\u00e3o",
- "OptionReleaseDate": "Data de lan\u00e7amento",
+ "OptionReleaseDate": "Release Date",
"OptionPlayCount": "N.\u00ba Visualiza\u00e7\u00f5es",
"OptionDatePlayed": "Data de reprodu\u00e7\u00e3o",
"OptionDateAdded": "Data de adi\u00e7\u00e3o",
@@ -213,6 +275,8 @@
"TabMovies": "Filmes",
"TabStudios": "Est\u00fadios",
"TabTrailers": "Trailers",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "\u00daltimos Filmes",
"HeaderLatestTrailers": "\u00daltimos Trailers",
"OptionHasSpecialFeatures": "Extras",
@@ -224,7 +288,7 @@
"HeaderStatus": "Estado",
"OptionContinuing": "A Continuar",
"OptionEnded": "Terminado",
- "HeaderAirDays": "Dias de Exibi\u00e7\u00e3o:",
+ "HeaderAirDays": "Dias de Exibi\u00e7\u00e3o",
"OptionSunday": "Domingo",
"OptionMonday": "Segunda",
"OptionTuesday": "Ter\u00e7a",
@@ -232,7 +296,8 @@
"OptionThursday": "Quinta",
"OptionFriday": "Sexta",
"OptionSaturday": "S\u00e1bado",
- "HeaderManagement": "Gest\u00e3o:",
+ "HeaderManagement": "Gest\u00e3o",
+ "LabelManagement": "Administra\u00e7\u00e3o:",
"OptionMissingImdbId": "Id do IMDb em falta",
"OptionMissingTvdbId": "iD do TheTVDB em falta",
"OptionMissingOverview": "Descri\u00e7\u00e3o em falta",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metascore",
"ButtonSelect": "Selecionar",
- "ButtonSearch": "Procurar",
"ButtonGroupVersions": "Agrupar Vers\u00f5es",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "Usar o Prismo File Mount atrav\u00e9s de uma licen\u00e7a doada.",
@@ -290,11 +354,11 @@
"ButtonSelectDirectory": "Selecione a diretoria",
"LabelCustomPaths": "Defina localiza\u00e7\u00f5es personalizadas. Deixe os campos em branco para usar os valores padr\u00e3o.",
"LabelCachePath": "Localiza\u00e7\u00e3o da cache:",
- "LabelCachePathHelp": "Esta pasta cont\u00e9m ficheiros de cacha do servidor, como por exemplo, imagens.",
+ "LabelCachePathHelp": "Defina uma localiza\u00e7\u00e3o para ficheiros de cache do servidor, como por exemplo, imagens.",
"LabelImagesByNamePath": "Localiza\u00e7\u00e3o das imagens por nome:",
- "LabelImagesByNamePathHelp": "Esta pasta cont\u00e9m imagens de atores, artistas, g\u00e9neros e est\u00fadios.",
+ "LabelImagesByNamePathHelp": "Defina uma localiza\u00e7\u00e3o para imagens de atores, artistas, g\u00e9neros e est\u00fadios.",
"LabelMetadataPath": "Localiza\u00e7\u00e3o dos metadados:",
- "LabelMetadataPathHelp": "Esta localiza\u00e7\u00e3o cont\u00e9m imagens e metadados transferidos que n\u00e3o foram configurados para serem armazenados nas pastas multim\u00e9dia.",
+ "LabelMetadataPathHelp": "Defina uma localiza\u00e7\u00e3o para imagens e metadados transferidos que n\u00e3o foram configurados para serem armazenados nas pastas multim\u00e9dia.",
"LabelTranscodingTempPath": "Localiza\u00e7\u00e3o tempor\u00e1ria das transcodifica\u00e7\u00f5es:",
"LabelTranscodingTempPathHelp": "Esta pasta cont\u00e9m ficheiros de trabalho usados pelo transcodificador.",
"TabBasics": "B\u00e1sico",
@@ -347,6 +411,8 @@
"TabStatus": "Estado",
"TabSettings": "Configura\u00e7\u00f5es",
"ButtonRefreshGuideData": "Atualizar Dados do Guia",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Prioridade",
"OptionRecordOnAllChannels": "Gravar programa em todos os canais",
"OptionRecordAnytime": "Gravar programa em qualquer altura",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Elenco e Equipa",
"HeaderAdditionalParts": "Partes Adicionais",
"ButtonSplitVersionsApart": "Separar Vers\u00f5es",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Em falta",
"LabelOffline": "Desconectado",
"PathSubstitutionHelp": "Substitui\u00e7\u00f5es de localiza\u00e7\u00e3o s\u00e3o usadas para mapear uma localiza\u00e7\u00e3o no servidor que possa ser acedido pelos clientes. Ao permitir o acesso dos clientes ao conte\u00fado multim\u00e9dia no servidor, permite-lhes reproduzir diretamente atrav\u00e9s da rede e evitar o uso de recursos do servidor para fazer stream ou transcodifica\u00e7\u00e3o.",
@@ -512,8 +579,10 @@
"HeaderProgram": "Programa",
"HeaderClients": "Clientes",
"LabelCompleted": "Terminado",
+ "LabelFailed": "Failed",
"LabelSkipped": "Ignorado",
"HeaderEpisodeOrganization": "Organiza\u00e7\u00e3o dos Epis\u00f3dios",
+ "LabelSeries": "Series:",
"LabelSeasonNumber": "N\u00famero da temporada",
"LabelEpisodeNumber": "N\u00famero do epis\u00f3dio",
"LabelEndingEpisodeNumber": "N\u00famero do epis\u00f3dio final",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Ativar esta notifica\u00e7\u00e3o",
"LabelMonitorUsers": "Monitor activity from:",
"LabelSendNotificationToUsers": "Enviar notifica\u00e7\u00e3o para:",
- "UsersNotNotifiedAboutSelfActivity": "Os utilizadores n\u00e3o ser\u00e3o notificados sobre as suas pr\u00f3prias atividades.",
"LabelUseNotificationServices": "Usar os seguintes servi\u00e7os:",
"CategoryUser": "Utilizador",
"CategorySystem": "Sistema",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
"ButtonHome": "In\u00edcio",
+ "ButtonSearch": "Procurar",
"ButtonSettings": "Settings",
"ButtonTakeScreenshot": "Capture Screenshot",
"ButtonLetterUp": "Letter Up",
@@ -661,6 +730,8 @@
"ButtonScenes": "Cenas",
"ButtonSubtitles": "Legendas",
"ButtonAudioTracks": "Faixas de \u00e1udio",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
"ButtonStop": "Parar",
"ButtonPause": "Pausar",
"LabelGroupMoviesIntoCollections": "Group movies into collections",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
"LabelType": "Tipo:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Contentor:",
"LabelProfileVideoCodecs": "Codecs do v\u00eddeo:",
"LabelProfileAudioCodecs": "Codecs do \u00e1udio:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "Estes valores controlam como o Media Browser ser\u00e1 exibido no dispositivo.",
"LabelMaxBitrate": "Taxa de bits m\u00e1xima:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "Nome amig\u00e1vel",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Exibir extens\u00f5es para:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Outros",
- "LabelEpisodeName": "Nome do epis\u00f3dio",
- "LabelSeriesName": "Nome da s\u00e9rie",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Nome.da.s\u00e9rie",
"ValueSeriesNameUnderscore": "Nome_da_s\u00e9rie",
"ValueEpisodeNamePeriod": "Nome.do.epis\u00f3dio",
"ValueEpisodeNameUnderscore": "Nome_do_epis\u00f3dio",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Inserir texto",
"LabelTypeText": "Texto",
"HeaderSearchForSubtitles": "Search for Subtitles",
@@ -796,13 +879,13 @@
"OptionAuto": "Auto",
"OptionYes": "Yes",
"OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferences",
"MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Mark Read",
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
"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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
"ButtonDismiss": "Dismiss",
"MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Display adult content",
"OptionLibraryFolders": "Media folders",
"TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Valor:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Iguais",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Ordenar",
+ "TabFilter": "Filtro",
+ "ButtonView": "Visualizar",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "Visualizar:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Avan\u00e7ado",
+ "ButtonSync": "Sincronizar",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Cap\u00edtulos",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 8dd00090a..2902f716d 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ru.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ru.json
@@ -1,135 +1,197 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435",
- "HeaderEnableNotificationForEvents": "\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u043a\u043e\u0433\u0434\u0430:",
- "HeaderEnableNotificationForPlayback": "\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0438:",
- "OptionNotifyOnUpdates": "\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f",
- "OptionNotifyOnVideoPlayback": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u043e",
- "OptionNotifyOnAudioPlayback": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0430\u0443\u0434\u0438\u043e",
- "OptionNotifyOnGamePlayback": "\u0417\u0430\u043f\u0443\u0441\u043a \u0438\u0433\u0440\u044b",
- "OptionNotifyOnFailedTasks": "\u0421\u0431\u043e\u0439 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f",
- "OptionNotifyOnNewLibraryContent": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0432 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0443",
- "OptionNotifyOnServerRestartRequired": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440",
- "NotificationOptionUpdatesAvailable": "\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f",
- "NotificationOptionFailedTasks": "\u0421\u0431\u043e\u0439 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f",
- "TabUpdates": "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f",
- "HeaderUpdateLevel": "\u0421\u0442\u0435\u043f\u0435\u043d\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u043e\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b",
- "HeaderCustomizeOptionsPerMediaType": "\u0417\u0430\u0434\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043f\u043e \u0442\u0438\u043f\u0443 \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044f",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "\u0412\u0441\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430",
- "HeaderThisDevice": "\u0414\u0430\u043d\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e",
- "OptionLibraryButtons": "\u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 - \u043a\u043d\u043e\u043f\u043a\u0438",
- "OptionLibraryTiles": "\u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 - \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043f\u043b\u0438\u0442\u043a\u0438",
- "OptionSmallLibraryTiles": "\u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 - \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0435 \u043f\u043b\u0438\u0442\u043a\u0438",
- "ButtonPlayTrailer": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440",
- "LabelFailed": "\u041d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e",
- "LabelSeries": "\u0421\u0435\u0440\u0438\u0430\u043b:",
- "ButtonPreviousTrack": "\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430",
- "ButtonNextTrack": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430",
- "HeaderMyLibrary": "\u041c\u043e\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430",
- "HeaderLibraryViews": "\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438",
+ "HeaderPeople": "\u041b\u044e\u0434\u0438",
"LabelExit": "\u0412\u044b\u0445\u043e\u0434",
+ "HeaderDownloadPeopleMetadataFor": "\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0431\u0438\u043e\u0433\u0440\u0430\u0444\u0438\u0439 \u0438 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0434\u043b\u044f:",
"LabelVisitCommunity": "\u041f\u043e\u0441\u0435\u0449\u0435\u043d\u0438\u0435 \u0421\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430",
+ "OptionComposers": "\u041a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u044b",
"LabelGithubWiki": "\u0412\u0438\u043a\u0438 \u043d\u0430 Github",
+ "OptionOthers": "\u0414\u0440\u0443\u0433\u0438\u0435",
"LabelSwagger": "\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Swagger",
"LabelStandard": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442",
+ "HeaderDownloadPeopleMetadataForHelp": "\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043e\u0431\u043e\u0433\u0430\u0449\u0430\u0435\u0442 \u044d\u043a\u0440\u0430\u043d\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u043d\u043e \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435, \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438 \u0437\u0430\u043c\u0435\u0434\u043b\u0438\u0442\u0441\u044f.",
"LabelViewApiDocumentation": "\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e API",
+ "ViewTypeFolders": "\u041f\u0430\u043f\u043a\u0438",
"LabelBrowseLibrary": "\u041e\u0431\u0437\u043e\u0440 \u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438",
+ "LabelDisplayFoldersView": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0430\u0441\u043f\u0435\u043a\u0442 \u041f\u0430\u043f\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438",
"LabelConfigureMediaBrowser": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "\u0417\u0430\u043f\u0438\u0441\u0438",
"LabelOpenLibraryViewer": "\u0421\u0440\u0435\u0434\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438",
+ "ViewTypeLiveTvChannels": "\u041a\u0430\u043d\u0430\u043b\u044b",
"LabelRestartServer": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430",
+ "LabelAllowLocalAccessWithoutPassword": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u0431\u0435\u0437 \u043f\u0430\u0440\u043e\u043b\u044f",
"LabelShowLogWindow": "\u041e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 \u0416\u0443\u0440\u043d\u0430\u043b\u0430 \u0432 \u043e\u043a\u043d\u0435",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "\u0415\u0441\u043b\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e, \u043f\u0430\u0440\u043e\u043b\u044c \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0438 \u0438\u0437\u043d\u0443\u0442\u0440\u0438 \u0432\u0430\u0448\u0435\u0439 \u0434\u043e\u043c\u0430\u0448\u043d\u0435\u0439 \u0441\u0435\u0442\u0438.",
"LabelPrevious": "\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435",
+ "HeaderPassword": "\u041f\u0430\u0440\u043e\u043b\u044c",
"LabelFinish": "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c",
+ "HeaderLocalAccess": "\u041b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f",
"LabelNext": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435",
+ "HeaderViewOrder": "\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0430\u0441\u043f\u0435\u043a\u0442\u043e\u0432",
"LabelYoureDone": "\u0412\u0441\u0451 \u0433\u043e\u0442\u043e\u0432\u043e!",
+ "LabelSelectUserViewOrder": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043f\u043e\u0440\u044f\u0434\u043e\u043a, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u041c\u043e\u0438 \u0430\u0441\u043f\u0435\u043a\u0442\u044b \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 Media Browser",
"WelcomeToMediaBrowser": "\u0412\u0430\u0441 \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 Media Browser!",
+ "LabelMetadataRefreshMode": "\u0420\u0435\u0436\u0438\u043c \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445:",
"TitleMediaBrowser": "Media Browser",
- "ThisWizardWillGuideYou": "\u042d\u0442\u043e\u0442 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u043f\u043e \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u043f\u0440\u043e\u0432\u0435\u0434\u0451\u0442 \u0447\u0435\u0440\u0435\u0437 \u0432\u0441\u0435 \u0444\u0430\u0437\u044b \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430. \u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 \u044f\u0437\u044b\u043a.",
+ "LabelImageRefreshMode": "\u0420\u0435\u0436\u0438\u043c \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0438\u0441\u0443\u043d\u043a\u0430:",
+ "ThisWizardWillGuideYou": "\u042d\u0442\u043e\u0442 \u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u043f\u043e \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \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. \u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0441\u0432\u043e\u0439 \u044f\u0437\u044b\u043a.",
+ "OptionDownloadMissingImages": "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438",
"TellUsAboutYourself": "\u0420\u0430\u0441\u0441\u043a\u0430\u0436\u0438\u0442\u0435 \u043e \u0441\u0435\u0431\u0435",
+ "OptionReplaceExistingImages": "\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438",
"LabelYourFirstName": "\u0412\u0430\u0448\u0435 \u0438\u043c\u044f:",
- "MoreUsersCanBeAddedLater": "\u041f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0449\u0451 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u041f\u0430\u043d\u0435\u043b\u044c \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430.",
- "UserProfilesIntro": "\u0412 Media Browser \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0438\u0437 \u043d\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u0432\u043e\u0438\u043c\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f\u043c\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c.",
+ "OptionRefreshAllData": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435",
+ "MoreUsersCanBeAddedLater": "\u041f\u043e\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0449\u0451 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c.",
+ "OptionAddMissingDataOnly": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0435",
+ "UserProfilesIntro": "\u0412 Media Browser \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0430\u044f \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0438\u0437 \u043d\u0438\u0445 \u0438\u043c\u0435\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c.",
+ "OptionLocalRefreshOnly": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e",
"LabelWindowsService": "\u0421\u043b\u0443\u0436\u0431\u0430 Windows",
+ "HeaderRefreshMetadata": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
"AWindowsServiceHasBeenInstalled": "\u0421\u043b\u0443\u0436\u0431\u0430 Windows \u0431\u044b\u043b\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430.",
+ "HeaderPersonInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u043f\u0435\u0440\u0441\u043e\u043d\u0435",
"WindowsServiceIntro1": "\u041e\u0431\u044b\u0447\u043d\u043e Media Browser Server \u0438\u0441\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e \u0437\u043d\u0430\u0447\u043a\u043e\u043c \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c \u043b\u043e\u0442\u043a\u0435, \u043d\u043e \u043f\u0440\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0432 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435, \u0432\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0435\u0433\u043e \u0438\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043b\u0443\u0436\u0431\u0430\u043c\u0438 Windows.",
+ "HeaderIdentifyItem": "\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430",
"WindowsServiceIntro2": "\u041a\u043e\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u043b\u0443\u0436\u0431\u0430 Windows, \u043f\u0440\u0438\u043c\u0438\u0442\u0435 \u043a \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044e, \u0447\u0442\u043e \u043e\u043d\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0441\u043e \u0437\u043d\u0430\u0447\u043a\u043e\u043c \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c \u043b\u043e\u0442\u043a\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0437\u043d\u0430\u0447\u043e\u043a \u0432 \u043b\u043e\u0442\u043a\u0435, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u043b\u0443\u0436\u0431\u0443. \u0421\u043b\u0443\u0436\u0431\u0443 \u0442\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0443\u0436\u043d\u043e \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u043e\u0431\u043b\u0430\u0434\u0430\u044f \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u043f\u0440\u0430\u0432\u0430\u043c\u0438, \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0432 \u0434\u0430\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u043b\u0443\u0436\u0431\u0435 \u043d\u0435 \u0443\u0434\u0430\u0451\u0442\u0441\u044f \u0441\u0430\u043c\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c\u0441\u044f, \u0442\u0430\u043a \u0447\u0442\u043e \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043d\u043e\u0432\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432\u0430\u0448\u0435 \u0432\u043c\u0435\u0448\u0430\u0442\u0435\u043b\u044c\u0441\u0442\u0432\u043e.",
- "WizardCompleted": "\u042d\u0442\u043e \u0432\u0441\u0451, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. Media Browser \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0441\u0431\u043e\u0440 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \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 \u0438\u0437 \u043d\u0430\u0448\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0438 \u0442\u043e\u0433\u0434\u0430 \u0449\u0451\u043b\u043a\u043d\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 <b>\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c<\/b>, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 <b>\u041f\u0430\u043d\u0435\u043b\u044c \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430<\/b>.",
+ "HeaderIdentifyItemHelp": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u0431\u043e\u043b\u0435\u0435 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0435\u0432 \u043f\u043e\u0438\u0441\u043a\u0430. \u0414\u043b\u044f \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044f \u0447\u0438\u0441\u043b\u0430 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 \u0443\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0439.",
+ "WizardCompleted": "\u042d\u0442\u043e \u0432\u0441\u0451, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442. Media Browser \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0441\u0431\u043e\u0440 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \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 \u0438\u0437 \u043d\u0430\u0448\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0438 \u0442\u043e\u0433\u0434\u0430 \u0449\u0451\u043b\u043a\u043d\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 <b>\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c<\/b>, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0432 <b>\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c<\/b>.",
+ "HeaderConfirmDeletion": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f",
"LabelConfigureSettings": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432",
+ "LabelFollowingFileWillBeDeleted": "\u0411\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043b\u0451\u043d \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0444\u0430\u0439\u043b:",
"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",
+ "LabelIfYouWishToContinueWithDeletion": "\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c, \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u0435 \u044d\u0442\u043e, \u0432\u0432\u0435\u0434\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f:",
"VideoImageExtractionHelp": "\u0414\u043b\u044f \u0432\u0438\u0434\u0435\u043e, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0449\u0451 \u200b\u200b\u043d\u0435 \u0438\u043c\u0435\u044e\u0442 \u043e\u0431\u043b\u043e\u0436\u043a\u0438, \u0438 \u0434\u043b\u044f \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 \u0442\u0430\u043a\u043e\u0432\u044b\u0445. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438 \u043f\u0440\u043e\u0434\u043b\u0438\u0442\u0441\u044f \u0435\u0449\u0451 \u043d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u043d\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u0441\u0442\u0430\u043d\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u044f\u0442\u043d\u043e\u0435 \u0434\u043b\u044f \u0433\u043b\u0430\u0437 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.",
+ "ButtonIdentify": "\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c",
"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 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \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. \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u043d\u0430 4:00 \u0443\u0442\u0440\u0430, \u043e\u0434\u043d\u0430\u043a\u043e, \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043d\u0430\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\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u044f. \u041d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u043e\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u0432 \u0447\u0430\u0441\u044b \u043f\u0438\u043a.",
+ "LabelAlbumArtist": "\u0410\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c:",
+ "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 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \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. \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u043d\u0430 4:00 \u0443\u0442\u0440\u0430, \u043e\u0434\u043d\u0430\u043a\u043e, \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430. \u041d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u043e\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u0432 \u0447\u0430\u0441\u044b \u043f\u0438\u043a.",
+ "LabelAlbum": "\u0410\u043b\u044c\u0431\u043e\u043c",
"LabelEnableAutomaticPortMapping": "\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",
- "LabelEnableAutomaticPortMappingHelp": "UPnP \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u044d\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \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.",
+ "LabelCommunityRating": "\u041e\u0431\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u043e\u0446\u0435\u043d\u043a\u0430:",
+ "LabelEnableAutomaticPortMappingHelp": "UPnP \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u044f \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u044d\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \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.",
+ "LabelVoteCount": "\u0427\u0438\u0441\u043b\u043e \u0433\u043e\u043b\u043e\u0441\u043e\u0432:",
"ButtonOk": "\u041e\u041a",
+ "LabelMetascore": "\u041e\u0446\u0435\u043d\u043a\u0430 Metascore:",
"ButtonCancel": "\u041e\u0442\u043c\u0435\u043d\u0430",
+ "LabelCriticRating": "\u041e\u0446\u0435\u043d\u043a\u0430 \u043a\u0440\u0438\u0442\u0438\u043a\u043e\u0432:",
"ButtonNew": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c",
- "HeaderSetupLibrary": "\u041f\u0435\u0440\u0432\u043e\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438",
+ "LabelCriticRatingSummary": "\u0421\u0432\u043e\u0434\u043a\u0430 \u043e\u0446\u0435\u043d\u043a\u0438 \u043a\u0440\u0438\u0442\u0438\u043a\u043e\u0432:",
+ "HeaderSetupLibrary": "\u0421\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0443",
+ "LabelAwardSummary": "\u0421\u0432\u043e\u0434\u043a\u0430 \u043d\u0430\u0433\u0440\u0430\u0434:",
"ButtonAddMediaFolder": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0443",
+ "LabelWebsite": "\u0412\u0435\u0431\u0441\u0430\u0439\u0442:",
"LabelFolderType": "\u0422\u0438\u043f \u043f\u0430\u043f\u043a\u0438:",
- "MediaFolderHelpPluginRequired": "* \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d, \u043d\u043f\u0440. GameBrowser \u0438\u043b\u0438 MB Bookshelf.",
+ "LabelTagline": "\u041a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u0444\u0440\u0430\u0437\u0430:",
+ "MediaFolderHelpPluginRequired": "* \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d, \u043d\u043f\u0440., GameBrowser \u0438\u043b\u0438 MB Bookshelf.",
+ "LabelOverview": "\u041e\u0431\u043e\u0437\u0440\u0435\u043d\u0438\u0435:",
"ReferToMediaLibraryWiki": "C\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043f\u043e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435 \u0441\u043c. \u0432 \u0432\u0438\u043a\u0438.",
+ "LabelShortOverview": "\u041a\u0440\u0430\u0442\u043a\u043e\u0435 \u043e\u0431\u043e\u0437\u0440\u0435\u043d\u0438\u0435:",
"LabelCountry": "\u0421\u0442\u0440\u0430\u043d\u0430:",
+ "LabelReleaseDate": "\u0414\u0430\u0442\u0430 \u0432\u044b\u043f\u0443\u0441\u043a\u0430:",
"LabelLanguage": "\u042f\u0437\u044b\u043a:",
- "HeaderPreferredMetadataLanguage": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u044f\u0437\u044b\u043a\u0430 \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\u0438 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043e\u043a",
- "LabelSaveLocalMetadataHelp": "\u0418\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043e\u043a, \u043f\u0440\u0438 \u0442\u0430\u043a\u043e\u043c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u0430\u0432\u0438\u0442\u044c.",
+ "LabelYear": "\u0413\u043e\u0434:",
+ "HeaderPreferredMetadataLanguage": "\u0412\u044b\u0431\u043e\u0440 \u044f\u0437\u044b\u043a\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445:",
+ "LabelPlaceOfBirth": "\u041c\u0435\u0441\u0442\u043e \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f:",
+ "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",
+ "LabelEndDate": "\u041a\u043e\u043d\u0435\u0447\u043d\u0430\u044f \u0434\u0430\u0442\u0430:",
+ "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\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \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.",
+ "LabelAirDate": "\u0414\u043d\u0438 \u044d\u0444\u0438\u0440\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 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0430",
- "LabelDownloadInternetMetadataHelp": "\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u0435 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f Media Browser, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445.",
+ "LabelAirTime:": "\u0412\u0440\u0435\u043c\u044f \u044d\u0444\u0438\u0440\u0430:",
+ "LabelDownloadInternetMetadataHelp": "\u0414\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0432 Media Browser.",
+ "LabelRuntimeMinutes": "\u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u0435\u043d\u0438\u044f, \u043c\u0438\u043d:",
"TabPreferences": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438",
+ "LabelParentalRating": "\u0412\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f:",
"TabPassword": "\u041f\u0430\u0440\u043e\u043b\u044c",
+ "LabelCustomRating": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f:",
"TabLibraryAccess": "\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435",
+ "LabelBudget": "\u0411\u044e\u0434\u0436\u0435\u0442",
"TabImage": "\u0420\u0438\u0441\u0443\u043d\u043e\u043a",
+ "LabelRevenue": "\u0412\u044b\u0440\u0443\u0447\u043a\u0430, $:",
"TabProfile": "\u041f\u0440\u043e\u0444\u0438\u043b\u044c",
+ "LabelOriginalAspectRatio": "\u041e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0441\u0442\u043e\u0440\u043e\u043d:",
"TabMetadata": "\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435",
+ "LabelPlayers": "\u0418\u0433\u0440\u043e\u043a\u0438:",
"TabImages": "\u0420\u0438\u0441\u0443\u043d\u043a\u0438",
+ "Label3DFormat": "3D \u0444\u043e\u0440\u043c\u0430\u0442",
"TabNotifications": "\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f",
- "TabCollectionTitles": "\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f",
- "LabelDisplayMissingEpisodesWithinSeasons": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0432 \u0441\u0435\u0437\u043e\u043d\u0430\u0445",
- "LabelUnairedMissingEpisodesWithinSeasons": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0432 \u0441\u0435\u0437\u043e\u043d\u0430\u0445",
+ "HeaderAlternateEpisodeNumbers": "\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u043d\u043e\u043c\u0435\u0440\u0430 \u044d\u043f\u0438\u0437\u043e\u0434\u043e\u0432",
+ "TabCollectionTitles": "\u041f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
+ "HeaderSpecialEpisodeInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c \u044d\u043f\u0438\u0437\u043e\u0434\u0435",
+ "LabelDisplayMissingEpisodesWithinSeasons": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0437\u043e\u043d\u043e\u0432",
+ "HeaderExternalIds": "\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b:",
+ "LabelUnairedMissingEpisodesWithinSeasons": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0437\u043e\u043d\u043e\u0432",
+ "LabelDvdSeasonNumber": "\u041d\u043e\u043c\u0435\u0440 \u0441\u0435\u0437\u043e\u043d\u0430 DVD",
"HeaderVideoPlaybackSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0432\u0438\u0434\u0435\u043e",
+ "LabelDvdEpisodeNumber": "\u041d\u043e\u043c\u0435\u0440 \u044d\u043f\u0438\u0437\u043e\u0434\u0430 DVD",
"HeaderPlaybackSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
+ "LabelAbsoluteEpisodeNumber": "\u0410\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u044d\u043f\u0438\u0437\u043e\u0434\u0430",
"LabelAudioLanguagePreference": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u044f\u0437\u044b\u043a\u0430 \u0430\u0443\u0434\u0438\u043e:",
+ "LabelAirsBeforeSeason": "\u0421\u0435\u0437\u043e\u043d \"airs before\":",
"LabelSubtitleLanguagePreference": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u044f\u0437\u044b\u043a\u0430 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432:",
- "OptionDefaultSubtitles": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e",
+ "LabelAirsAfterSeason": "\u0421\u0435\u0437\u043e\u043d \"airs after\":",
+ "OptionDefaultSubtitles": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435",
+ "LabelAirsBeforeEpisode": "\u042d\u043f\u0438\u0437\u043e\u0434 \"airs before\":",
"OptionOnlyForcedSubtitles": "\u0422\u043e\u043b\u044c\u043a\u043e \u0444\u043e\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b",
+ "LabelTreatImageAs": "\u0421\u0447\u0438\u0442\u0430\u0442\u044c \u0440\u0438\u0441\u0443\u043d\u043e\u043a \u043a\u0430\u043a:",
"OptionAlwaysPlaySubtitles": "\u0412\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b",
- "OptionNoSubtitles": "\u0411\u0435\u0437 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432",
- "OptionDefaultSubtitlesHelp": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u044f\u0437\u044b\u043a\u0430, \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0430\u0443\u0434\u0438\u043e \u043d\u0430 \u0438\u043d\u043e\u0441\u0442\u0440\u0430\u043d\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435.",
+ "LabelDisplayOrder": "\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f:",
+ "OptionNoSubtitles": "\u041d\u0435\u0442 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432",
+ "LabelDisplaySpecialsWithinSeasons": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0437\u043e\u043d\u043e\u0432, \u0433\u0434\u0435 \u043e\u043d\u0438 \u0432\u044b\u0445\u043e\u0434\u0438\u043b\u0438 \u0432 \u044d\u0444\u0438\u0440",
+ "OptionDefaultSubtitlesHelp": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u044f\u0437\u044b\u043a\u0430, \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f, \u0435\u0441\u043b\u0438 \u0430\u0443\u0434\u0438\u043e \u043d\u0430 \u0438\u043d\u043e\u0441\u0442\u0440\u0430\u043d\u043d\u043e\u043c \u044f\u0437\u044b\u043a\u0435.",
+ "HeaderCountries": "\u0421\u0442\u0440\u0430\u043d\u044b",
"OptionOnlyForcedSubtitlesHelp": "\u0411\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b, \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u043a\u0430\u043a \u0444\u043e\u0440\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435.",
+ "HeaderGenres": "\u0416\u0430\u043d\u0440\u044b",
"OptionAlwaysPlaySubtitlesHelp": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 \u044f\u0437\u044b\u043a\u0430, \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u044f\u0437\u044b\u043a\u0430 \u0430\u0443\u0434\u0438\u043e.",
- "OptionNoSubtitlesHelp": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f.",
+ "HeaderPlotKeywords": "\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u0441\u044e\u0436\u0435\u0442\u0430",
+ "OptionNoSubtitlesHelp": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.",
+ "HeaderStudios": "\u0421\u0442\u0443\u0434\u0438\u0438",
"TabProfiles": "\u041f\u0440\u043e\u0444\u0438\u043b\u0438",
+ "HeaderTags": "\u0422\u0435\u0433\u0438",
"TabSecurity": "\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c",
+ "HeaderMetadataSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
"ButtonAddUser": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f",
+ "LabelLockItemToPreventChanges": "\u0417\u0430\u0431\u043b\u043e\u043a\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 \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u0431\u0443\u0434\u0443\u0449\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f",
"ButtonSave": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c",
+ "MessageLeaveEmptyToInherit": "\u041e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u0443\u0441\u0442\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.",
"ButtonResetPassword": "\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c",
+ "TabSupporterClub": "\u041a\u043b\u0443\u0431 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043e\u0432",
"LabelNewPassword": "\u041d\u043e\u0432\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c",
+ "HeaderDonationType": "\u0422\u0438\u043f \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f:",
"LabelNewPasswordConfirm": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f",
+ "OptionMakeOneTimeDonation": "\u041e\u0434\u043d\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0435 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0435",
"HeaderCreatePassword": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0430\u0440\u043e\u043b\u044c",
+ "OptionLifeTimeSupporterClubMembership": "\u041f\u043e\u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e\u0435 \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u043e \u0432 \u043a\u043b\u0443\u0431\u0435 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043e\u0432",
"LabelMaxParentalRating": "\u041c\u0430\u043a\u0441. \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u0430\u044f \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f:",
- "MaxParentalRatingHelp": "\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0441 \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u0440\u044b\u0442\u043e \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f",
+ "HeaderSupporterBenefit": "\u0427\u043b\u0435\u043d\u0441\u0442\u0432\u043e \u0432\u043e \u043a\u043b\u0443\u0431\u0435 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043e\u0432 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u0440\u0435\u043c\u0438\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043b\u0430\u0433\u0438\u043d\u0430\u043c, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044e \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043a\u0430\u043d\u0430\u043b\u043e\u0432 \u0438 \u043c\u043d\u043e\u0433\u043e\u043c\u0443 \u0434\u0440\u0443\u0433\u043e\u043c\u0443.",
+ "MaxParentalRatingHelp": "\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0441 \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u043e\u0439 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u0440\u044b\u0442\u043e \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f",
+ "OptionNoTrailer": "\u0411\u0435\u0437 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u0430",
"LibraryAccessHelp": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438 \u0434\u043b\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441 \u044d\u0442\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c. \u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u044b \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432\u0441\u0435 \u043f\u0430\u043f\u043a\u0438 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 \u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445.",
+ "OptionNoThemeSong": "\u0411\u0435\u0437 \u043c\u0435\u043b\u043e\u0434\u0438\u0438 \u0442\u0435\u043c\u044b",
"ChannelAccessHelp": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u043a\u0430\u043d\u0430\u043b\u044b \u0434\u043b\u044f \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441 \u044d\u0442\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c. \u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u044b \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432\u0441\u0435 \u043a\u0430\u043d\u0430\u043b\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445.",
+ "OptionNoThemeVideo": "\u0411\u0435\u0437 \u0432\u0438\u0434\u0435\u043e \u0442\u0435\u043c\u044b",
"ButtonDeleteImage": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0440\u0438\u0441\u0443\u043d\u043e\u043a",
+ "LabelOneTimeDonationAmount": "\u0421\u0443\u043c\u043c\u0430 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f",
"LabelSelectUsers": "\u0412\u044b\u0431\u043e\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439:",
+ "OptionActor": "\u0410\u043a\u0442\u0451\u0440",
"ButtonUpload": "\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c",
+ "OptionComposer": "\u041a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u043e\u0440",
"HeaderUploadNewImage": "\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043d\u043e\u0432\u043e\u0433\u043e \u0440\u0438\u0441\u0443\u043d\u043a\u0430",
+ "OptionDirector": "\u0420\u0435\u0436\u0438\u0441\u0441\u0451\u0440",
"LabelDropImageHere": "\u041f\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435 \u0440\u0438\u0441\u0443\u043d\u043e\u043a \u0441\u044e\u0434\u0430",
+ "OptionGuestStar": "\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0451\u043d\u043d\u044b\u0439 \u0430\u043a\u0442\u0451\u0440",
"ImageUploadAspectRatioHelp": "\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u043c\u044b\u0435 \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u0438 - 1:1. \u0422\u043e\u043b\u044c\u043a\u043e JPG\/PNG.",
+ "OptionProducer": "\u041f\u0440\u043e\u0434\u044e\u0441\u0435\u0440",
"MessageNothingHere": "\u0417\u0434\u0435\u0441\u044c \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e.",
+ "OptionWriter": "\u0421\u0446\u0435\u043d\u0430\u0440\u0438\u0441\u0442",
"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\u043e\u0436\u0435\u043d\u0438\u044f",
+ "LabelAirDays": "Air days:",
+ "TabSuggested": "\u041f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u044b\u0435",
+ "LabelAirTime": "Air time:",
"TabLatest": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435",
- "TabShows": "\u0421\u0435\u0440\u0438\u0430\u043b\u044b",
+ "HeaderPhotoInfo": "Photo Info",
+ "TabShows": "\u0426\u0438\u043a\u043b\u044b",
"TabEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u044b",
"TabGenres": "\u0416\u0430\u043d\u0440\u044b",
"TabPeople": "\u041b\u044e\u0434\u0438",
@@ -138,36 +200,36 @@
"HeaderFilters": "\u0424\u0438\u043b\u044c\u0442\u0440\u044b:",
"ButtonFilter": "\u0424\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c",
"OptionFavorite": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u044b\u0435",
- "OptionLikes": "\u041d\u0440\u0430\u0432\u044f\u0449\u0438\u0435\u0441\u044f",
- "OptionDislikes": "\u041d\u0435 \u043d\u0440\u0430\u0432\u044f\u0449\u0438\u0435\u0441\u044f",
+ "OptionLikes": "\u041d\u0440\u0430\u0432\u0438\u0442\u0441\u044f",
+ "OptionDislikes": "\u041d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f",
"OptionActors": "\u0410\u043a\u0442\u0451\u0440\u044b",
- "OptionGuestStars": "\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0451\u043d\u043d\u044b\u0435 \u0437\u0432\u0451\u0437\u0434\u044b",
+ "OptionGuestStars": "\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0451\u043d\u043d\u044b\u0435 \u0430\u043a\u0442\u0451\u0440\u044b",
"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": "\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f",
- "NoNextUpItemsMessage": "\u041d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e. \u0421\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u0441\u0432\u043e\u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u044b \u0441 \u043d\u0430\u0447\u0430\u043b\u0430!",
+ "HeaderNextUp": "\u041e\u0447\u0435\u0440\u0435\u0434\u043d\u044b\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 \u0442\u0432 \u0446\u0438\u043a\u043b\u044b!",
"HeaderLatestEpisodes": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u044d\u043f\u0438\u0437\u043e\u0434\u043e\u0432",
- "HeaderPersonTypes": "\u0422\u0438\u043f\u044b \u043b\u044e\u0434\u0435\u0439:",
+ "HeaderPersonTypes": "\u0422\u0438\u043f\u044b \u043f\u0435\u0440\u0441\u043e\u043d:",
"TabSongs": "\u041c\u0435\u043b\u043e\u0434\u0438\u0438",
"TabAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u044b",
"TabArtists": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438",
"TabAlbumArtists": "\u0410\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438",
"TabMusicVideos": "\u041a\u043b\u0438\u043f\u044b",
"ButtonSort": "\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c",
- "HeaderSortBy": "\u041f\u043e \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044e:",
- "HeaderSortOrder": "\u041f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443:",
- "OptionPlayed": "\u0412\u043e\u0441\u043f\u0440-\u043d\u043d\u044b\u0435",
- "OptionUnplayed": "\u041d\u0435 \u0432\u043e\u0441\u043f\u0440-\u043d\u043d\u044b\u0435",
+ "HeaderSortBy": "\u041a\u0440\u0438\u0442\u0435\u0440\u0438\u0439:",
+ "HeaderSortOrder": "\u041d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435:",
+ "OptionPlayed": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043b\u0438\u0441\u044c",
+ "OptionUnplayed": "\u041d\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043b\u0438\u0441\u044c",
"OptionAscending": "\u0412\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u043d\u0438\u0435",
"OptionDescending": "\u0423\u0431\u044b\u0432\u0430\u043d\u0438\u0435",
"OptionRuntime": "\u0414\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c",
"OptionReleaseDate": "\u0414\u0430\u0442\u0430 \u0432\u044b\u043f\u0443\u0441\u043a\u0430",
- "OptionPlayCount": "\u0427\u0438\u0441\u043b\u043e \u0432\u043e\u0441\u043f\u0440-\u0438\u0439",
- "OptionDatePlayed": "\u0414\u0430\u0442\u0430 \u0432\u043e\u0441\u043f\u0440-\u0438\u044f",
- "OptionDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432-\u043d\u0438\u044f",
- "OptionAlbumArtist": "\u0410\u043b\u044c\u0431-\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c",
+ "OptionPlayCount": "\u0427\u0438\u0441\u043b\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0439",
+ "OptionDatePlayed": "\u0414\u0430\u0442\u0430 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
+ "OptionDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f",
+ "OptionAlbumArtist": "\u0410\u043b\u044c\u0431\u043e\u043c. \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c",
"OptionArtist": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c",
"OptionAlbum": "\u0410\u043b\u044c\u0431\u043e\u043c",
"OptionTrackName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0434\u043e\u0440\u043e\u0436\u043a\u0438",
@@ -185,7 +247,7 @@
"OptionVideoBitrate": "\u0421\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",
"ScheduledTasksHelp": "\u0429\u0451\u043b\u043a\u043d\u0438\u0442\u0435 \u043f\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044e, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0435\u0433\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435.",
- "ScheduledTasksTitle": "\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u044f",
+ "ScheduledTasksTitle": "\u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a",
"TabMyPlugins": "\u041c\u043e\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u044b",
"TabCatalog": "\u041a\u0430\u0442\u0430\u043b\u043e\u0433",
"PluginsTitle": "\u041f\u043b\u0430\u0433\u0438\u043d\u044b",
@@ -201,7 +263,7 @@
"OptionDvd": "DVD",
"OptionIso": "ISO",
"Option3D": "3D",
- "LabelFeatures": "\u0414\u043b\u044f \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432:",
+ "LabelFeatures": "\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b:",
"LabelService": "\u0421\u043b\u0443\u0436\u0431\u0430:",
"LabelStatus": "\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435:",
"LabelVersion": "\u0412\u0435\u0440\u0441\u0438\u044f:",
@@ -213,18 +275,20 @@
"TabMovies": "\u0424\u0438\u043b\u044c\u043c\u044b",
"TabStudios": "\u0421\u0442\u0443\u0434\u0438\u0438",
"TabTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b",
+ "LabelArtists": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438:",
+ "LabelArtistsHelp": "\u0420\u0430\u0437\u0434\u0435\u043b\u044f\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ;",
"HeaderLatestMovies": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u0444\u0438\u043b\u044c\u043c\u043e\u0432",
"HeaderLatestTrailers": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432",
"OptionHasSpecialFeatures": "\u0414\u043e\u043f. \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b",
"OptionImdbRating": "\u041e\u0446\u0435\u043d\u043a\u0430 IMDb",
"OptionParentalRating": "\u0412\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u0430\u044f \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f",
"OptionPremiereDate": "\u0414\u0430\u0442\u0430 \u043f\u0440\u0435\u043c\u044c\u0435\u0440\u044b",
- "TabBasic": "\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435",
- "TabAdvanced": "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435",
+ "TabBasic": "\u041e\u0441\u043d\u043e\u0432\u044b",
+ "TabAdvanced": "\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e",
"HeaderStatus": "\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435",
- "OptionContinuing": "\u041f\u0440\u043e\u0434\u043b\u0435\u043d\u043e",
- "OptionEnded": "\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e",
- "HeaderAirDays": "\u0414\u043d\u0438 \u044d\u0444\u0438\u0440\u0430:",
+ "OptionContinuing": "\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442\u0441\u044f",
+ "OptionEnded": "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0441\u044f",
+ "HeaderAirDays": "\u0414\u043d\u0438 \u044d\u0444\u0438\u0440\u0430",
"OptionSunday": "\u0432\u043e\u0441\u043a\u0440\u0435\u0441\u0435\u043d\u044c\u0435",
"OptionMonday": "\u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a",
"OptionTuesday": "\u0432\u0442\u043e\u0440\u043d\u0438\u043a",
@@ -232,10 +296,11 @@
"OptionThursday": "\u0447\u0435\u0442\u0432\u0435\u0440\u0433",
"OptionFriday": "\u043f\u044f\u0442\u043d\u0438\u0446\u0430",
"OptionSaturday": "\u0441\u0443\u0431\u0431\u043e\u0442\u0430",
- "HeaderManagement": "\u0414\u043b\u044f \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445:",
- "OptionMissingImdbId": "\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d IMDb Id",
- "OptionMissingTvdbId": "\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d TheTVDB Id",
- "OptionMissingOverview": "\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043e \u043e\u0431\u043e\u0437\u0440\u0435\u043d\u0438\u0435",
+ "HeaderManagement": "\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435",
+ "LabelManagement": "\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435",
+ "OptionMissingImdbId": "\u041d\u0435\u0442 IMDb Id",
+ "OptionMissingTvdbId": "\u041d\u0435\u0442 TheTVDB Id",
+ "OptionMissingOverview": "\u041d\u0435\u0442 \u043e\u0431\u043e\u0437\u0440\u0435\u043d\u0438\u044f",
"OptionFileMetadataYearMismatch": "\u0420\u0430\u0437\u043d\u044b\u0435 \u0433\u043e\u0434\u044b \u0432 \u0444\u0430\u0439\u043b\u0435\/\u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
"TabGeneral": "\u041e\u0431\u0449\u0438\u0435",
"TitleSupport": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430",
@@ -243,41 +308,40 @@
"TabAbout": "\u041e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435",
"TabSupporterKey": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430",
"TabBecomeSupporter": "\u0421\u0442\u0430\u0442\u044c \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043e\u043c",
- "MediaBrowserHasCommunity": "Media Browser \u0438\u043c\u0435\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u044e\u0449\u0435\u0435\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.",
- "CheckoutKnowledgeBase": "\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u0411\u0430\u0437\u043e\u0439 \u0437\u043d\u0430\u043d\u0438\u0439 \u0434\u043b\u044f \u043f\u043e\u043c\u043e\u0449\u0438 \u043f\u043e \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u0442\u0434\u0430\u0447\u0438 \u043e\u0442 Media Browser.",
+ "MediaBrowserHasCommunity": "\u0423 Media Browser - \u0440\u0430\u0441\u0442\u0443\u0449\u0435\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432.",
+ "CheckoutKnowledgeBase": "\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u0411\u0430\u0437\u043e\u0439 \u0437\u043d\u0430\u043d\u0438\u0439 \u0434\u043b\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u043e \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u0442\u0434\u0430\u0447\u0438 \u043e\u0442 Media Browser.",
"SearchKnowledgeBase": "\u0418\u0441\u043a\u0430\u0442\u044c \u0432 \u0411\u0430\u0437\u0435 \u0437\u043d\u0430\u043d\u0438\u0439",
"VisitTheCommunity": "\u041f\u043e\u0441\u0435\u0442\u0438\u0442\u044c \u0421\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e",
"VisitMediaBrowserWebsite": "\u041f\u043e\u0441\u0435\u0442\u0438\u0442\u044c \u0441\u0430\u0439\u0442 Media Browser",
- "VisitMediaBrowserWebsiteLong": "\u041f\u043e\u0441\u0435\u0449\u0430\u0439\u0442\u0435 \u0441\u0430\u0439\u0442 Media Browser, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043f\u0435\u0432\u0430\u0442\u044c \u0437\u0430 \u043d\u043e\u0432\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0447\u0438\u0442\u0430\u0442\u044c \u0431\u043b\u043e\u0433 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.",
+ "VisitMediaBrowserWebsiteLong": "\u041f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 \u0441\u0430\u0439\u0442 Media Browser, \u0447\u0442\u043e\u0431\u044b \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u043d\u043e\u0432\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0447\u0438\u0442\u0430\u0442\u044c \u0431\u043b\u043e\u0433\u0438 \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",
"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\u0438\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \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 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u043e\u0431\u043e\u0440\u0432\u0430\u043d\u044b.",
+ "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\u0438\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \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:",
+ "LabelName": "\u0418\u043c\u044f (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435):",
"OptionAllowUserToManageServer": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \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\u0444\u0430\u0439\u043b\u043e\u0432",
+ "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",
"OptionAllowBrowsingLiveTv": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043e\u0431\u0437\u043e\u0440 \u044d\u0444\u0438\u0440\u043d\u043e\u0433\u043e \u0442\u0432",
"OptionAllowDeleteLibraryContent": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438",
"OptionAllowManageLiveTv": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u044d\u0444\u0438\u0440\u043d\u043e\u0433\u043e \u0442\u0432",
"OptionAllowRemoteControlOthers": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438",
- "OptionMissingTmdbId": "\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d TMDb Id",
+ "OptionMissingTmdbId": "\u041d\u0435\u0442 TMDb Id",
"OptionIsHD": "HD",
"OptionIsSD": "SD",
"OptionMetascore": "\u041e\u0446\u0435\u043d\u043a\u0430 Metascore",
"ButtonSelect": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c",
- "ButtonSearch": "\u041f\u043e\u0438\u0441\u043a",
"ButtonGroupVersions": "\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u0438",
"ButtonAddToCollection": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043a \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438",
"PismoMessage": "Pismo File Mount \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u0434\u0430\u0440\u0435\u043d\u043d\u043e\u0439 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438.",
- "TangibleSoftwareMessage": "Tangible Solutions Java\/C# \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u0434\u0430\u0440\u0435\u043d\u043d\u043e\u0439 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438.",
- "HeaderCredits": "\u0412\u043d\u0451\u0441\u0448\u0438\u0435 \u0432\u043a\u043b\u0430\u0434",
- "PleaseSupportOtherProduces": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u0442\u0430\u043a\u0436\u0435 \u0434\u0440\u0443\u0433\u043e\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c:",
+ "TangibleSoftwareMessage": "\u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0435\u0440\u044b Java\/C# \u043e\u0442 Tangible Solutions \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043f\u043e \u043f\u043e\u0434\u0430\u0440\u0435\u043d\u043d\u043e\u0439 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0438.",
+ "HeaderCredits": "\u0423\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0438",
+ "PleaseSupportOtherProduces": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0442\u0435 \u0438 \u0438\u043d\u043e\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f:",
"VersionNumber": "\u0412\u0435\u0440\u0441\u0438\u044f {0}",
"TabPaths": "\u041f\u0443\u0442\u0438",
"TabServer": "\u0421\u0435\u0440\u0432\u0435\u0440",
"TabTranscoding": "\u041f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430",
- "TitleAdvanced": "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b",
+ "TitleAdvanced": "\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e",
"LabelAutomaticUpdateLevel": "\u0421\u0442\u0435\u043f\u0435\u043d\u044c \u0430\u0432\u0442\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f",
"OptionRelease": "\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u044b\u043f\u0443\u0441\u043a",
"OptionBeta": "\u0411\u0435\u0442\u0430-\u0432\u0435\u0440\u0441\u0438\u044f",
@@ -288,15 +352,15 @@
"LabelRunServerAtStartup": "\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b",
"LabelRunServerAtStartupHelp": "\u0417\u043d\u0430\u0447\u043e\u043a \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c \u043b\u043e\u0442\u043a\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u0442\u0430\u0440\u0442\u0430 Windows. \u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u043b\u0443\u0436\u0431\u0443 Windows, \u0443\u0431\u0435\u0440\u0438\u0442\u0435 \u0433\u0430\u043b\u043e\u0447\u043a\u0443 \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u0441\u043b\u0443\u0436\u0431\u0443 \u0438\u0437 \u043a\u043e\u043d\u0441\u043e\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f Windows. \u041f\u0440\u0438\u043c\u0438\u0442\u0435 \u043a \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044e, \u0447\u0442\u043e \u043e\u043d\u0438 \u043e\u0431\u0430 \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u043e\u043a \u0432 \u043b\u043e\u0442\u043a\u0435 \u0434\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u043b\u0443\u0436\u0431\u044b.",
"ButtonSelectDirectory": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043a\u0430\u0442\u0430\u043b\u043e\u0433",
- "LabelCustomPaths": "\u041d\u0430\u0437\u043d\u0430\u0447\u044c\u0442\u0435 \u043f\u0443\u0442\u0438 \u0442\u0443\u0434\u0430, \u043a\u0443\u0434\u0430 \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e. \u041e\u0441\u0442\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u043f\u043e\u043b\u044f \u043f\u0443\u0441\u0442\u044b\u043c\u0438 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.",
+ "LabelCustomPaths": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u043f\u043e \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u043c. \u041e\u0441\u0442\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u043f\u043e\u043b\u044f \u043f\u0443\u0441\u0442\u044b\u043c\u0438 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445.",
"LabelCachePath": "\u041f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 Cache:",
- "LabelCachePathHelp": "\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0444\u0430\u0439\u043b\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u043a\u044d\u0448\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0438\u0441\u0443\u043d\u043a\u0438.",
+ "LabelCachePathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u043a\u044d\u0448\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432.",
"LabelImagesByNamePath": "\u041f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 Images by name:",
- "LabelImagesByNamePathHelp": "\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0430\u043a\u0442\u0451\u0440\u043e\u0432. \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0435\u0439 \u0438 \u0441\u0442\u0443\u0434\u0438\u0439.",
+ "LabelImagesByNamePathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\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 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0430\u043a\u0442\u0451\u0440\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0435\u0439, \u0436\u0430\u043d\u0440\u043e\u0432 \u0438 \u0441\u0442\u0443\u0434\u0438\u0439.",
"LabelMetadataPath": "\u041f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 Metadata:",
- "LabelMetadataPathHelp": "\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0435 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435, \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0430\u0445.",
+ "LabelMetadataPathHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\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, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043d\u0435 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043e\u043a.",
"LabelTranscodingTempPath": "\u041f\u0443\u0442\u044c \u043a \u043f\u0430\u043f\u043a\u0435 Transcoding temporary:",
- "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.",
+ "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 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c, \u0438\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u0443\u0441\u0442\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.",
"TabBasics": "\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435",
"TabTV": "\u0422\u0412",
"TabGames": "\u0418\u0433\u0440\u044b",
@@ -304,21 +368,21 @@
"TabOthers": "\u0414\u0440\u0443\u0433\u0438\u0435",
"HeaderExtractChapterImagesFor": "\u0418\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0441\u0446\u0435\u043d \u0434\u043b\u044f:",
"OptionMovies": "\u0424\u0438\u043b\u044c\u043c\u044b",
- "OptionEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u044b",
+ "OptionEpisodes": "\u0422\u0412 \u044d\u043f\u0438\u0437\u043e\u0434\u044b",
"OptionOtherVideos": "\u0414\u0440\u0443\u0433\u0438\u0435 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u044b",
"TitleMetadata": "\u041c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435",
"LabelAutomaticUpdatesFanart": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441 FanArt.tv",
"LabelAutomaticUpdatesTmdb": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441 TheMovieDB.org",
"LabelAutomaticUpdatesTvdb": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441 TheTVDB.com",
- "LabelAutomaticUpdatesFanartHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043d\u043e\u0432\u044b\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430 fanart.tv. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f.",
- "LabelAutomaticUpdatesTmdbHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043d\u043e\u0432\u044b\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430 TheMovieDB.org. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f.",
- "LabelAutomaticUpdatesTvdbHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043d\u043e\u0432\u044b\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430 TheTVDB.com. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f.",
- "ExtractChapterImagesHelp": "\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 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \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\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\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. \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u043d\u0430 4:00 \u0443\u0442\u0440\u0430, \u043e\u0434\u043d\u0430\u043a\u043e, \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043d\u0430\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\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u044f. \u041d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u043e\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u0432 \u0447\u0430\u0441\u044b \u043f\u0438\u043a.",
- "LabelMetadataDownloadLanguage": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u044f\u0437\u044b\u043a\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445:",
+ "LabelAutomaticUpdatesFanartHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043d\u043e\u0432\u044b\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430 fanart.tv. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f.",
+ "LabelAutomaticUpdatesTmdbHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043d\u043e\u0432\u044b\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430 TheMovieDB.org. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f.",
+ "LabelAutomaticUpdatesTvdbHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043d\u043e\u0432\u044b\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430 TheTVDB.com. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043c\u0435\u0449\u0430\u0442\u044c\u0441\u044f.",
+ "ExtractChapterImagesHelp": "\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 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \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\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\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 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043a\u0430\u043a \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0435 \u043d\u0430 4:00 \u0443\u0442\u0440\u0430, \u0420\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430. \u041d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u043e\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u0432 \u0447\u0430\u0441\u044b \u043f\u0438\u043a.",
+ "LabelMetadataDownloadLanguage": "\u0412\u044b\u0431\u043e\u0440 \u044f\u0437\u044b\u043a\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438:",
"ButtonAutoScroll": "\u0410\u0432\u0442\u043e\u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0430",
"LabelImageSavingConvention": "\u0424\u043e\u0440\u043c\u0430\u0442 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432:",
- "LabelImageSavingConventionHelp": "\u0412 Media Browser \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u044e\u0442\u0441\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0438\u043c\u0435\u044e\u0449\u0438\u0435\u0441\u044f \u0432 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445 \u043c\u0435\u0434\u0438\u0430\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445. \u0412\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432.",
- "OptionImageSavingCompatible": "\u0421\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 - Media Browser\/Plex\/XBMC",
+ "LabelImageSavingConventionHelp": "\u0412 Media Browser \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u044e\u0442\u0441\u044f \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0438\u043c\u0435\u044e\u0449\u0438\u0435\u0441\u044f \u0432 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445 \u043c\u0443\u043b\u044c\u0442\u0438\u043c\u0435\u0434\u0438\u0439\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445. \u0412\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432.",
+ "OptionImageSavingCompatible": "\u0421\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 - Media Browser\/XBMC\/Plex",
"OptionImageSavingStandard": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 - MB2",
"ButtonSignIn": "\u0412\u043e\u0439\u0442\u0438",
"TitleSignIn": "\u0412\u0445\u043e\u0434",
@@ -333,20 +397,22 @@
"HeaderChannels": "\u041a\u0430\u043d\u0430\u043b\u044b",
"TabRecordings": "\u0417\u0430\u043f\u0438\u0441\u0438",
"TabScheduled": "\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435",
- "TabSeries": "\u0421\u0435\u0440\u0438\u0438",
+ "TabSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u044b",
"TabFavorites": "\u0418\u0437\u0431\u0440\u0430\u043d\u043d\u043e\u0435",
"TabMyLibrary": "\u041c\u043e\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430",
"ButtonCancelRecording": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c",
- "HeaderPrePostPadding": "\u041e\u0442\u0431\u0438\u0432\u043a\u0438 \u0434\u043e\/\u043f\u043e\u0441\u043b\u0435",
- "LabelPrePaddingMinutes": "\u041e\u0442\u0431\u0438\u0432\u043a\u0430 \u0434\u043e, \u043c\u0438\u043d:",
- "OptionPrePaddingRequired": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u0431\u0438\u0432\u043a\u0430 \u0434\u043e \u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u043b\u044f \u0435\u0451 \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u0438.",
- "LabelPostPaddingMinutes": "\u041e\u0442\u0431\u0438\u0432\u043a\u0430 \u043f\u043e\u0441\u043b\u0435, \u043c\u0438\u043d:",
- "OptionPostPaddingRequired": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u0442\u0431\u0438\u0432\u043a\u0430 \u043f\u043e\u0441\u043b\u0435 \u043a\u043e\u043d\u0446\u0430 \u0437\u0430\u043f\u0438\u0441\u0438 \u0434\u043b\u044f \u0435\u0451 \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u0438.",
+ "HeaderPrePostPadding": "\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f\/\u043a\u043e\u043d\u0435\u0447\u043d\u0430\u044f \u043e\u0442\u0431\u0438\u0432\u043a\u0438",
+ "LabelPrePaddingMinutes": "\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u043e\u0442\u0431\u0438\u0432\u043a\u0430, \u043c\u0438\u043d:",
+ "OptionPrePaddingRequired": "\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u043e\u0442\u0431\u0438\u0432\u043a\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f.",
+ "LabelPostPaddingMinutes": "\u041a\u043e\u043d\u0435\u0447\u043d\u0430\u044f \u043e\u0442\u0431\u0438\u0432\u043a\u0430, \u043c\u0438\u043d:",
+ "OptionPostPaddingRequired": "\u041a\u043e\u043d\u0435\u0447\u043d\u0430\u044f \u043e\u0442\u0431\u0438\u0432\u043a\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f.",
"HeaderWhatsOnTV": "\u0412 \u044d\u0444\u0438\u0440\u0435",
"HeaderUpcomingTV": "\u0421\u043a\u043e\u0440\u043e",
"TabStatus": "\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435",
"TabSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b",
- "ButtonRefreshGuideData": "\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0433\u0438\u0434",
+ "ButtonRefreshGuideData": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0433\u0438\u0434",
+ "ButtonRefresh": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c",
+ "ButtonAdvancedRefresh": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\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",
@@ -355,22 +421,22 @@
"HeaderActiveRecordings": "\u0410\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438",
"HeaderLatestRecordings": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439",
"HeaderAllRecordings": "\u0412\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438",
- "ButtonPlay": "\u0412\u043e\u0441\u043f\u0440",
+ "ButtonPlay": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438",
"ButtonEdit": "\u041f\u0440\u0430\u0432\u0438\u0442\u044c",
"ButtonRecord": "\u0417\u0430\u043f\u0438\u0441\u0430\u0442\u044c",
"ButtonDelete": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c",
- "ButtonRemove": "\u0423\u0431\u0440\u0430\u0442\u044c",
- "OptionRecordSeries": "\u0417\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0435\u0440\u0438\u0438",
+ "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",
"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": "\u0411\u043e\u043b\u044c\u0448\u0435\u0435 \u0447\u0438\u0441\u043b\u043e \u0434\u043d\u0435\u0439 \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0433\u0438\u0434\u0430 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u0447\u0438\u0441\u043b\u0430 \u043f\u0443\u043d\u043a\u0442\u043e\u0432 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u044f, \u043d\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u041f\u0440\u0438 \u0440\u0435\u0436\u0438\u043c\u0435 \u0410\u0432\u0442\u043e \u0432\u044b\u0431\u043e\u0440 \u0431\u0443\u0434\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u043d \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043a\u0430\u043d\u0430\u043b\u043e\u0432.",
"LabelActiveService": "\u0410\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0441\u043b\u0443\u0436\u0431\u0430:",
- "LabelActiveServiceHelp": "\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u044d\u0444\u0438\u0440\u043d\u043e\u0433\u043e \u0442\u0432, \u043d\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0432 \u0442\u043e\u0442 \u0436\u0435 \u0441\u0430\u043c\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0443 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u043d\u0438\u0445.",
+ "LabelActiveServiceHelp": "\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u044d\u0444\u0438\u0440\u043d\u043e\u0433\u043e \u0442\u0432, \u043d\u043e \u0432 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d.",
"OptionAutomatic": "\u0410\u0432\u0442\u043e",
- "LiveTvPluginRequired": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u043b\u0430\u0433\u0438\u043d-\u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a \u0443\u0441\u043b\u0443\u0433 \u044d\u0444\u0438\u0440\u043d\u043e\u0433\u043e \u0422\u0412 \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f.",
+ "LiveTvPluginRequired": "\u0427\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c, \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u043b\u0430\u0433\u0438\u043d-\u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a \u0443\u0441\u043b\u0443\u0433 \u044d\u0444\u0438\u0440\u043d\u043e\u0433\u043e \u0422\u0412.",
"LiveTvPluginRequiredHelp": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043e\u0434\u0438\u043d \u0438\u0437 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, NextPVR \u0438\u043b\u0438 ServerWMC.",
- "LabelCustomizeOptionsPerMediaType": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u043e \u0442\u0438\u043f\u0443 \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044f:",
+ "LabelCustomizeOptionsPerMediaType": "\u0410\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u043b\u044f \u0442\u0438\u043f\u0430 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445:",
"OptionDownloadThumbImage": "\u0411\u0435\u0433\u0443\u043d\u043e\u043a",
"OptionDownloadMenuImage": "\u041c\u0435\u043d\u044e",
"OptionDownloadLogoImage": "\u041b\u043e\u0433\u043e\u0442\u0438\u043f",
@@ -380,7 +446,7 @@
"OptionDownloadBackImage": "\u0421\u043f\u0438\u043d\u043a\u0430",
"OptionDownloadArtImage": "\u0412\u0438\u043d\u044c\u0435\u0442\u043a\u0430",
"OptionDownloadPrimaryImage": "\u041f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439",
- "HeaderFetchImages": "\u0412\u044b\u0431\u043e\u0440\u043a\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432:",
+ "HeaderFetchImages": "\u041e\u0442\u0431\u043e\u0440\u043a\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432:",
"HeaderImageSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432",
"TabOther": "\u0414\u0440\u0443\u0433\u0438\u0435",
"LabelMaxBackdropsPerItem": "\u041c\u0430\u043a\u0441. \u0447\u0438\u0441\u043b\u043e \u0437\u0430\u0434\u043d\u0438\u043a\u043e\u0432 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442:",
@@ -411,7 +477,7 @@
"TabPathSubstitution": "\u041f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0443\u0442\u0435\u0439",
"LabelSeasonZeroDisplayName": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0435\u0437\u043e\u043d\u0430 0:",
"LabelEnableRealtimeMonitor": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438",
- "LabelEnableRealtimeMonitorHelp": "\u0412 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u0436\u0435.",
+ "LabelEnableRealtimeMonitorHelp": "\u0412 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e.",
"ButtonScanLibrary": "\u0421\u043a\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0443",
"HeaderNumberOfPlayers": "\u0418\u0433\u0440\u043e\u043a\u0438:",
"OptionAnyNumberOfPlayers": "\u041b\u044e\u0431\u043e\u0435",
@@ -421,7 +487,7 @@
"Option4Player": "4+",
"HeaderMediaFolders": "\u041c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438",
"HeaderThemeVideos": "\u0412\u0438\u0434\u0435\u043e \u0442\u0435\u043c\u044b",
- "HeaderThemeSongs": "\u041c\u0435\u043b\u043e\u0434\u0438\u0438 \u0442\u0435\u043c",
+ "HeaderThemeSongs": "\u041c\u0435\u043b\u043e\u0434\u0438\u0438 \u0442\u0435\u043c\u044b",
"HeaderScenes": "\u0421\u0446\u0435\u043d\u044b",
"HeaderAwardsAndReviews": "\u041d\u0430\u0433\u0440\u0430\u0434\u044b \u0438 \u043e\u0442\u0437\u044b\u0432\u044b",
"HeaderSoundtracks": "\u0421\u0430\u0443\u043d\u0434\u0442\u0440\u0435\u043a\u0438",
@@ -429,10 +495,11 @@
"HeaderSpecialFeatures": "\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b",
"HeaderCastCrew": "\u0423\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0438 \u0441\u044a\u0451\u043c\u043e\u043a",
"HeaderAdditionalParts": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u0438",
- "ButtonSplitVersionsApart": "\u0420\u0430\u0441\u0449\u0435\u043f\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438",
- "LabelMissing": "\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043e",
+ "ButtonSplitVersionsApart": "\u0420\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u0432\u0435\u0440\u0441\u0438\u0438 \u043f\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438",
+ "ButtonPlayTrailer": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440",
+ "LabelMissing": "\u041d\u0435\u0442",
"LabelOffline": "\u0410\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e",
- "PathSubstitutionHelp": "\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430\u043c \u043f\u0443\u0442\u0435\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u043f\u0443\u0442\u044c, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c. \u041f\u0440\u0438 \u043f\u0440\u044f\u043c\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043a \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044f\u043c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0442\u0435 \u0441\u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u0445 \u043f\u0440\u044f\u043c\u043e \u043f\u043e \u0441\u0435\u0442\u0438, \u043d\u0435 \u0442\u0440\u0430\u0442\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0434\u043b\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438.",
+ "PathSubstitutionHelp": "\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430\u043c \u043f\u0443\u0442\u0435\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u043f\u0443\u0442\u044c, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c. \u041f\u0440\u0438 \u043f\u0440\u044f\u043c\u043e\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043a \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u0442\u0435 \u0441\u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0438\u0445 \u043f\u0440\u044f\u043c\u043e \u043f\u043e \u0441\u0435\u0442\u0438, \u043d\u0435 \u0442\u0440\u0430\u0442\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0434\u043b\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438.",
"HeaderFrom": "\u041e\u0442\u043a\u0443\u0434\u0430",
"HeaderTo": "\u041a\u0443\u0434\u0430",
"LabelFrom": "\u041e\u0442\u043a\u0443\u0434\u0430:",
@@ -441,16 +508,16 @@
"LabelToHelp": "\u041f\u0440\u0438\u043c\u0435\u0440: \\\\MyServer\\Movies (\u043f\u0443\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c)",
"ButtonAddPathSubstitution": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438",
"OptionSpecialEpisode": "\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435",
- "OptionMissingEpisode": "\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d. \u044d\u043f\u0438\u0437\u043e\u0434\u044b",
+ "OptionMissingEpisode": "\u041d\u0435\u0442 \u044d\u043f\u0438\u0437\u043e\u0434\u043e\u0432",
"OptionUnairedEpisode": "\u041e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b",
- "OptionEpisodeSortName": "\u0418\u043c\u044f \u0441\u043e\u0440\u0442-\u043a\u0438 \u044d\u043f\u0438\u0437\u043e\u0434\u0430",
+ "OptionEpisodeSortName": "\u0421\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u0430",
"OptionSeriesSortName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0438\u0430\u043b\u0430",
"OptionTvdbRating": "\u041e\u0446\u0435\u043d\u043a\u0430 TVDb",
"HeaderTranscodingQualityPreference": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438:",
"OptionAutomaticTranscodingHelp": "\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c\u0441\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c",
"OptionHighSpeedTranscodingHelp": "\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u043d\u0438\u0436\u0435, \u043d\u043e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u044b\u0441\u0442\u0440\u0435\u0435",
"OptionHighQualityTranscodingHelp": "\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0432\u044b\u0448\u0435, \u043d\u043e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435",
- "OptionMaxQualityTranscodingHelp": "\u041b\u0443\u0447\u0448\u0435\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e, \u043f\u0440\u0438 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u043c \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440",
+ "OptionMaxQualityTranscodingHelp": "\u041b\u0443\u0447\u0448\u0435\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e, \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u0435\u0435, \u0430 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0432\u044b\u0448\u0435",
"OptionHighSpeedTranscoding": "\u0411\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c",
"OptionHighQualityTranscoding": "\u0411\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e",
"OptionMaxQualityTranscoding": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e",
@@ -458,21 +525,21 @@
"OptionEnableDebugTranscodingLoggingHelp": "\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0444\u0430\u0439\u043b\u044b \u0416\u0443\u0440\u043d\u0430\u043b\u0430 \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043e\u0431\u044a\u0451\u043c\u0430, \u0430 \u044d\u0442\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u0438\u043b\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0435\u043f\u043e\u043b\u0430\u0434\u043e\u043a.",
"OptionUpscaling": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0442\u044c \u0432\u0438\u0434\u0435\u043e \u0441 \u043f\u043e\u0432\u044b\u0448\u0430\u044e\u0448\u0438\u043c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c",
"OptionUpscalingHelp": "\u0412 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u0438\u0434\u0435\u043e, \u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u0441\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043d\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440.",
- "EditCollectionItemsHelp": "\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u0438\u043b\u0438 \u0443\u0431\u0438\u0440\u0430\u0439\u0442\u0435 \u043b\u044e\u0431\u044b\u0435 \u0444\u0438\u043b\u044c\u043c\u044b, \u0441\u0435\u0440\u0438\u0430\u043b\u044b, \u0430\u043b\u044c\u0431\u043e\u043c\u044b, \u043a\u043d\u0438\u0433\u0438 \u0438\u043b\u0438 \u0438\u0433\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0434\u0430\u043d\u043d\u0443\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e.",
- "HeaderAddTitles": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f",
- "LabelEnableDlnaPlayTo": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435 DLNA",
- "LabelEnableDlnaPlayToHelp": "Media Browser \u0438\u043c\u0435\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0432 \u0441\u0435\u0442\u0438 \u0438 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043c\u0438.",
+ "EditCollectionItemsHelp": "\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0438\u043b\u0438 \u0438\u0437\u044b\u043c\u0438\u0442\u0435 \u043b\u044e\u0431\u044b\u0435 \u0444\u0438\u043b\u044c\u043c\u044b, \u0441\u0435\u0440\u0438\u0430\u043b\u044b, \u0430\u043b\u044c\u0431\u043e\u043c\u044b, \u043a\u043d\u0438\u0433\u0438 \u0438\u043b\u0438 \u0438\u0433\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0434\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438.",
+ "HeaderAddTitles": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0439",
+ "LabelEnableDlnaPlayTo": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e DLNA \u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u041d\u0430",
+ "LabelEnableDlnaPlayToHelp": "\u0412 Media Browser \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0442\u0438 \u0438 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043c\u0438.",
"LabelEnableDlnaDebugLogging": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 DLNA \u0432 \u0416\u0443\u0440\u043d\u0430\u043b\u0435",
"LabelEnableDlnaDebugLoggingHelp": "\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0444\u0430\u0439\u043b\u044b \u0416\u0443\u0440\u043d\u0430\u043b\u0430 \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043e\u0431\u044a\u0451\u043c\u0430, \u0430 \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u0438\u043b\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0435\u043f\u043e\u043b\u0430\u0434\u043e\u043a.",
"LabelEnableDlnaClientDiscoveryInterval": "\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432, \u0441",
"LabelEnableDlnaClientDiscoveryIntervalHelp": "\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445 \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u043c\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 SSDP \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u044b\u043c\u0438 Media Browser.",
- "HeaderCustomDlnaProfiles": "\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438",
+ "HeaderCustomDlnaProfiles": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438",
"HeaderSystemDlnaProfiles": "\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438",
- "CustomDlnaProfilesHelp": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c.",
- "SystemDlnaProfilesHelp": "\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f. \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b \u0432 \u043d\u043e\u0432\u043e\u043c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0435.",
- "TitleDashboard": "\u041f\u0430\u043d\u0435\u043b\u044c \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430",
+ "CustomDlnaProfilesHelp": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c.",
+ "SystemDlnaProfilesHelp": "\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f. \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u044b \u0432 \u043d\u043e\u0432\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0435.",
+ "TitleDashboard": "\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c",
"TabHome": "\u0413\u043b\u0430\u0432\u043d\u0430\u044f",
- "TabInfo": "\u0418\u043d\u0444\u043e",
+ "TabInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
"HeaderLinks": "\u0421\u0441\u044b\u043b\u043a\u0438",
"HeaderSystemPaths": "\u0421\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043f\u0443\u0442\u0438",
"LinkCommunity": "\u0421\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e",
@@ -480,29 +547,29 @@
"LinkApiDocumentation": "\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e API",
"LabelFriendlyServerName": "\u041f\u043e\u043d\u044f\u0442\u043d\u043e\u0435 \u0438\u043c\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430:",
"LabelFriendlyServerNameHelp": "\u042d\u0442\u043e \u0438\u043c\u044f \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0415\u0441\u043b\u0438 \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u043b\u0435 \u043f\u0443\u0441\u0442\u044b\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u043c\u044f \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0430.",
- "LabelPreferredDisplayLanguage": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430",
- "LabelPreferredDisplayLanguageHelp": "\u041f\u0440\u043e\u0435\u043a\u0442 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 Media Browser \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0438 \u0438 \u0432\u0441\u0451 \u0435\u0449\u0451 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d.",
+ "LabelPreferredDisplayLanguage": "\u0412\u044b\u0431\u043e\u0440 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430",
+ "LabelPreferredDisplayLanguageHelp": "\u041f\u0435\u0440\u0435\u0432\u043e\u0434 Media Browser \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u044e\u0449\u0438\u043c\u0441\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0438 \u0432\u0441\u0451 \u0435\u0449\u0451 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043d.",
"LabelReadHowYouCanContribute": "\u0427\u0438\u0442\u0430\u0439\u0442\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0432\u043d\u0435\u0441\u0442\u0438 \u0441\u0432\u043e\u0439 \u0432\u043a\u043b\u0430\u0434.",
"HeaderNewCollection": "\u041d\u043e\u0432\u0430\u044f \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f",
- "HeaderAddToCollection": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438",
+ "HeaderAddToCollection": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e",
"ButtonSubmit": "\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c",
"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 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435",
"ButtonCreate": "\u0413\u043e\u0442\u043e\u0432\u043e",
"LabelHttpServerPortNumber": "\u041d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0430 HTTP \u0441\u0435\u0440\u0432\u0435\u0440\u0430:",
"LabelWebSocketPortNumber": "\u041d\u043e\u043c\u0435\u0440 \u043f\u043e\u0440\u0442\u0430 \u0432\u0435\u0431-\u0441\u043e\u043a\u0435\u0442\u0430:",
- "LabelEnableAutomaticPortHelp": "UPnP \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u044d\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \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.",
+ "LabelEnableAutomaticPortHelp": "UPnP \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0443\u043f\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u044d\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \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 DDNS \u0434\u043e\u043c\u0435\u043d:",
- "LabelExternalDDNSHelp": "\u0415\u0441\u043b\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0434\u043e\u043c\u0435\u043d, \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 DynDNS, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0435\u0433\u043e \u0437\u0434\u0435\u0441\u044c. \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Media Browser \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438.",
+ "LabelExternalDDNSHelp": "\u0415\u0441\u043b\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0434\u043e\u043c\u0435\u043d, \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 DynDNS, \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u0435\u0433\u043e \u0437\u0434\u0435\u0441\u044c. \u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f Media Browser \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u0440\u0438 \u0432\u043d\u0435\u0448\u043d\u0435\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438.",
"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",
"LabelMinResumePercentage": "\u041c\u0438\u043d. \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f, %:",
"LabelMaxResumePercentage": "\u041c\u0430\u043a\u0441. \u0441\u043e\u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f, %:",
"LabelMinResumeDuration": "\u041c\u0438\u043d. \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f, \u0441:",
- "LabelMinResumePercentageHelp": "\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0447\u0438\u0442\u0430\u044e\u0442\u0441\u044f \u043d\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u043c\u0438, \u043f\u0440\u0438 \u0441\u0442\u043e\u043f\u0435 \u0434\u043e \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430",
- "LabelMaxResumePercentageHelp": "\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0447\u0438\u0442\u0430\u044e\u0442\u0441\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e, \u043f\u0440\u0438 \u0441\u0442\u043e\u043f\u0435 \u043f\u043e\u0441\u043b\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430",
- "LabelMinResumeDurationHelp": "\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u044b \u043f\u0440\u0438 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043c\u0435\u043d\u0435\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e",
+ "LabelMinResumePercentageHelp": "\u041f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0441\u0447\u0438\u0442\u0430\u044e\u0442\u0441\u044f \u043d\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u043c\u0438, \u043f\u0440\u0438 \u0441\u0442\u043e\u043f\u0435 \u0434\u043e \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430",
+ "LabelMaxResumePercentageHelp": "\u041f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0441\u0447\u0438\u0442\u0430\u044e\u0442\u0441\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e, \u043f\u0440\u0438 \u0441\u0442\u043e\u043f\u0435 \u043f\u043e\u0441\u043b\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043c\u043e\u043c\u0435\u043d\u0442\u0430",
+ "LabelMinResumeDurationHelp": "\u041f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u043c\u044b \u043f\u0440\u0438 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043c\u0435\u043d\u0435\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e",
"TitleAutoOrganize": "\u0410\u0432\u0442\u043e\u0440\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f",
"TabActivityLog": "\u0416\u0443\u0440\u043d\u0430\u043b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439",
"HeaderName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435",
@@ -512,24 +579,26 @@
"HeaderProgram": "\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430",
"HeaderClients": "\u041a\u043b\u0438\u0435\u043d\u0442\u044b",
"LabelCompleted": "\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e",
+ "LabelFailed": "\u041d\u0435\u0443\u0434\u0430\u0447\u043d\u043e",
"LabelSkipped": "\u041e\u0442\u043b\u043e\u0436\u0435\u043d\u043e",
"HeaderEpisodeOrganization": "\u0420\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u043f\u0438\u0437\u043e\u0434\u0430",
- "LabelSeasonNumber": "\u041d\u043e\u043c\u0435\u0440 \u0441\u0435\u0437\u043e\u043d\u0430",
- "LabelEpisodeNumber": "\u041d\u043e\u043c\u0435\u0440 \u044d\u043f\u0438\u0437\u043e\u0434\u0430",
- "LabelEndingEpisodeNumber": "\u041d\u043e\u043c\u0435\u0440 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u044d\u043f\u0438\u0437\u043e\u0434\u0430",
+ "LabelSeries": "\u0421\u0435\u0440\u0438\u0430\u043b:",
+ "LabelSeasonNumber": "\u041d\u043e\u043c\u0435\u0440 \u0441\u0435\u0437\u043e\u043d\u0430:",
+ "LabelEpisodeNumber": "\u041d\u043e\u043c\u0435\u0440 \u044d\u043f\u0438\u0437\u043e\u0434\u0430:",
+ "LabelEndingEpisodeNumber": "\u041d\u043e\u043c\u0435\u0440 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u044d\u043f\u0438\u0437\u043e\u0434\u0430:",
"LabelEndingEpisodeNumberHelp": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u044d\u043f\u0438\u0437\u043e\u0434\u0430\u043c\u0438",
"HeaderSupportTheTeam": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u044b Media Browser",
"LabelSupportAmount": "\u0421\u0443\u043c\u043c\u0430 (USD)",
- "HeaderSupportTheTeamHelp": "\u041f\u043e\u043c\u043e\u0433\u0438\u0442\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0435 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043f\u0443\u0442\u0451\u043c \u0434\u0430\u0440\u0435\u043d\u0438\u044f. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0432\u0441\u0435\u0445 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043b\u043e\u0436\u0435\u043d\u0430 \u0432 \u0434\u0440\u0443\u0433\u043e\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e.",
+ "HeaderSupportTheTeamHelp": "\u041f\u043e\u043c\u043e\u0433\u0438\u0442\u0435 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u044f\u043c\u0438 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0435 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u0427\u0430\u0441\u0442\u044c \u0432\u0441\u0435\u0445 \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u043b\u043e\u0436\u0435\u043d\u0430 \u0432 \u0438\u043d\u043e\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u0435, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c.",
"ButtonEnterSupporterKey": "\u0412\u0432\u0435\u0441\u0442\u0438 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430",
- "DonationNextStep": "\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u043d\u0438\u0442\u0435\u0441\u044c, \u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043f\u043e \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u0435.",
+ "DonationNextStep": "\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u043d\u0438\u0442\u0435\u0441\u044c, \u0438 \u0432\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 \u043f\u043e \u042d-\u043f\u043e\u0447\u0442\u0435.",
"AutoOrganizeHelp": "\u041f\u0440\u0438 \u0430\u0432\u0442\u043e\u0440\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0430\u043f\u043a\u0430, \u043a\u0443\u0434\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b, \u0430 \u0437\u0430\u0442\u0435\u043c \u0442\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0435\u043d\u044b \u0432 \u0432\u0430\u0448\u0438 \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438.",
"AutoOrganizeTvHelp": "\u041f\u0440\u0438 \u0440\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0422\u0412 \u0444\u0430\u0439\u043b\u043e\u0432 \u044d\u043f\u0438\u0437\u043e\u0434\u044b \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0441\u0435\u0440\u0438\u0430\u043b\u044b. \u041d\u043e\u0432\u044b\u0435 \u043f\u0430\u043f\u043a\u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u043e\u0432 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u044b.",
"OptionEnableEpisodeOrganization": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u043e\u0432\u044b\u0445 \u044d\u043f\u0438\u0437\u043e\u0434\u043e\u0432",
- "LabelWatchFolder": "\u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u043c\u0430\u044f \u043f\u0430\u043f\u043a\u0430:",
+ "LabelWatchFolder": "\u041f\u0430\u043f\u043a\u0430 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f:",
"LabelWatchFolderHelp": "\u0421\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043e\u043f\u0440\u043e\u0441 \u0434\u0430\u043d\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0438 \u0432 \u0445\u043e\u0434\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f \"\u0420\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u043e\u0432\u044b\u0445 \u043c\u0435\u0434\u0438\u0430\u0444\u0430\u0439\u043b\u043e\u0432\".",
"ButtonViewScheduledTasks": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u044f",
- "LabelMinFileSizeForOrganize": "\u041c\u0438\u043d. \u0440\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430 (\u041c\u0411):",
+ "LabelMinFileSizeForOrganize": "\u041c\u0438\u043d. \u0440\u0430\u0437\u043c\u0435\u0440 \u0444\u0430\u0439\u043b\u0430, \u041c\u0411:",
"LabelMinFileSizeForOrganizeHelp": "\u0411\u0443\u0434\u0443\u0442 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0444\u0430\u0439\u043b\u044b \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u043c\u0435\u043d\u0435\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e.",
"LabelSeasonFolderPattern": "\u0428\u0430\u0431\u043b\u043e\u043d \u043f\u0430\u043f\u043a\u0438 \u0441\u0435\u0437\u043e\u043d\u0430:",
"LabelSeasonZeroFolderName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u043f\u043a\u0438 \u043d\u0443\u043b\u0435\u0432\u043e\u0433\u043e \u0441\u0435\u0437\u043e\u043d\u0430:",
@@ -537,7 +606,7 @@
"LabelEpisodePattern": "\u0428\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f \u044d\u043f\u0438\u0437\u043e\u0434\u0430:",
"LabelMultiEpisodePattern": "\u0428\u0430\u0431\u043b\u043e\u043d \u0434\u043b\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u044d\u043f\u0438\u0437\u043e\u0434\u043e\u0432:",
"HeaderSupportedPatterns": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u044b",
- "HeaderTerm": "\u041e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435",
+ "HeaderTerm": "\u041f\u043e\u043d\u044f\u0442\u0438\u0435",
"HeaderPattern": "\u0428\u0430\u0431\u043b\u043e\u043d",
"HeaderResult": "\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442",
"LabelDeleteEmptyFolders": "\u0423\u0434\u0430\u043b\u044f\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u0435 \u043f\u0430\u043f\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u0440\u0435\u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438",
@@ -548,22 +617,22 @@
"LabelTransferMethod": "\u041c\u0435\u0442\u043e\u0434 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0430",
"OptionCopy": "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435",
"OptionMove": "\u041f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435",
- "LabelTransferMethodHelp": "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u0437 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u0439 \u043f\u0430\u043f\u043a\u0438",
+ "LabelTransferMethodHelp": "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u0437 \u043f\u0430\u043f\u043a\u0438 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f",
"HeaderLatestNews": "\u041d\u043e\u0432\u043e\u0441\u0442\u0438",
"HeaderHelpImproveMediaBrowser": "\u041f\u043e\u043c\u043e\u0449\u044c \u0432 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u0438\u0438 Media Browser",
"HeaderRunningTasks": "\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0437\u0430\u0434\u0430\u043d\u0438\u044f",
"HeaderActiveDevices": "\u0410\u043a\u0442\u0438\u0432\u043d\u044b\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430",
"HeaderPendingInstallations": "\u041e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438",
"HeaerServerInformation": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0435",
- "ButtonRestartNow": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441",
+ "ButtonRestartNow": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e",
"ButtonRestart": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c",
"ButtonShutdown": "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443",
- "ButtonUpdateNow": "\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0435\u0439\u0447\u0430\u0441",
+ "ButtonUpdateNow": "\u041e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e",
"PleaseUpdateManually": "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0435 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0432\u0440\u0443\u0447\u043d\u0443\u044e.",
"NewServerVersionAvailable": "\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f Media Browser Server!",
"ServerUpToDate": "Media Browser Server - \u043e\u0431\u043d\u043e\u0432\u043b\u0451\u043d",
"ErrorConnectingToMediaBrowserRepository": "\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u043c\u0443 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044e Media Browser.",
- "LabelComponentsUpdated": "\u0411\u044b\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b :",
+ "LabelComponentsUpdated": "\u0411\u044b\u043b\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b:",
"MessagePleaseRestartServerToFinishUpdating": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u0441\u0435\u0440\u0432\u0435\u0440, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439.",
"LabelDownMixAudioScale": "\u0423\u0441\u0438\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043f\u043e\u043d\u0438\u0436\u0430\u044e\u0449\u0435\u043c \u043c\u0438\u043a\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438:",
"LabelDownMixAudioScaleHelp": "\u0423\u0441\u0438\u043b\u0435\u043d\u0438\u0435 \u0437\u0432\u0443\u043a\u0430 \u043f\u0440\u0438 \u043f\u043e\u043d\u0438\u0436\u0430\u044e\u0449\u0435\u043c \u043c\u0438\u043a\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438. \u0412\u0432\u0435\u0434\u0438\u0442\u0435 1, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f.",
@@ -572,27 +641,27 @@
"LabelNewSupporterKey": "\u041d\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430",
"HeaderMultipleKeyLinking": "\u0421\u0432\u044f\u0437\u044b\u0432\u0430\u043d\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043b\u044e\u0447\u0435\u0439",
"MultipleKeyLinkingHelp": "\u0415\u0441\u043b\u0438 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u0435\u0435 \u0447\u0435\u043c \u043e\u0434\u0438\u043d \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u044d\u0442\u043e\u0439 \u0444\u043e\u0440\u043c\u043e\u0439, \u0447\u0442\u043e\u0431\u044b \u0441\u0432\u044f\u0437\u0430\u0442\u044c \u0441\u0442\u0430\u0440\u044b\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u043a\u043b\u044e\u0447\u0435\u0439 \u0441 \u043d\u043e\u0432\u043e\u0439.",
- "LabelCurrentEmailAddress": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0430\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b",
- "LabelCurrentEmailAddressHelp": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0430\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u0447.",
+ "LabelCurrentEmailAddress": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0430\u0434\u0440\u0435\u0441 \u042d-\u043f\u043e\u0447\u0442\u044b",
+ "LabelCurrentEmailAddressHelp": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0430\u0434\u0440\u0435\u0441 \u042d-\u043f\u043e\u0447\u0442\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043d\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u0447.",
"HeaderForgotKey": "\u041a\u043b\u044e\u0447 \u0431\u044b\u043b \u0437\u0430\u0431\u044b\u0442",
- "LabelEmailAddress": "\u0410\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b",
- "LabelSupporterEmailAddress": "\u0410\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0435\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0430.",
+ "LabelEmailAddress": "\u0410\u0434\u0440\u0435\u0441 \u042d-\u043f\u043e\u0447\u0442\u044b",
+ "LabelSupporterEmailAddress": "\u0410\u0434\u0440\u0435\u0441 \u042d-\u043f\u043e\u0447\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043f\u0440\u0438\u043e\u0431\u0440\u0435\u0442\u0435\u043d\u0438\u044f \u043a\u043b\u044e\u0447\u0430.",
"ButtonRetrieveKey": "\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043a\u043b\u044e\u0447",
- "LabelSupporterKey": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 (\u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u0437 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b)",
+ "LabelSupporterKey": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 (\u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u0437 \u043f\u0438\u0441\u044c\u043c\u0430 \u043f\u043e \u042d-\u043f\u043e\u0447\u0442\u0435)",
"LabelSupporterKeyHelp": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u043d\u0430\u0441\u043b\u0430\u0436\u0434\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b\u043b\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e\u043c \u0434\u043b\u044f Media Browser.",
"MessageInvalidKey": "\u041a\u043b\u044e\u0447 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0438\u043b\u0438 \u043d\u0435\u0432\u0435\u0440\u0435\u043d",
- "ErrorMessageInvalidKey": "\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0435 \u043f\u0440\u0435\u043c\u0438\u0443\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435, \u0432\u044b \u0442\u0430\u043a\u0436\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043e\u043c Media Browser. \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0430\u0440\u0441\u0442\u0432\u0443\u0439\u0442\u0435 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044e\u0449\u0435\u0435\u0441\u044f \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u043e\u0441\u043d\u043e\u0432\u043e\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u0438\u043c \u0432\u0430\u0441.",
+ "ErrorMessageInvalidKey": "\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0435 \u043f\u0440\u0435\u043c\u0438\u0443\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435, \u0432\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0442\u0430\u043a\u0436\u0435 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u043e\u043c Media Browser. \u0416\u0435\u0440\u0442\u0432\u0443\u0439\u0442\u0435 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0441\u043d\u043e\u0432\u043e\u043f\u043e\u043b\u0430\u0433\u0430\u044e\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430.",
"HeaderDisplaySettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f",
- "TabPlayTo": " \u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435",
- "LabelEnableDlnaServer": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c DLNA \u0441\u0435\u0440\u0432\u0435\u0440",
- "LabelEnableDlnaServerHelp": "\u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 UPnP \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c \u0432 \u0441\u0435\u0442\u0438 \u043e\u0431\u0437\u043e\u0440 \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f Media Browser.",
+ "TabPlayTo": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u041d\u0430",
+ "LabelEnableDlnaServer": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c DLNA-\u0441\u0435\u0440\u0432\u0435\u0440",
+ "LabelEnableDlnaServerHelp": "\u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 UPnP-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c \u0432 \u0441\u0435\u0442\u0438 \u043f\u0440\u043e\u043b\u0438\u0441\u0442\u044b\u0432\u0430\u0442\u044c \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 Media Browser.",
"LabelEnableBlastAliveMessages": "\u0423\u0447\u0430\u0449\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438",
"LabelEnableBlastAliveMessagesHelp": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0434\u0451\u0436\u043d\u043e \u0434\u0440\u0443\u0433\u0438\u043c\u0438 UPnP \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0432 \u0441\u0435\u0442\u0438.",
"LabelBlastMessageInterval": "\u0418\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438, \u0441",
"LabelBlastMessageIntervalHelp": "\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u043c\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.",
- "LabelDefaultUser": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e",
+ "LabelDefaultUser": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c:",
"LabelDefaultUserHelp": "\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c, \u0447\u044c\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445. \u041f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u0439.",
- "TitleDlna": "DLNA \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430",
+ "TitleDlna": "DLNA",
"TitleChannels": "\u041a\u0430\u043d\u0430\u043b\u044b",
"HeaderServerSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0430",
"LabelWeatherDisplayLocation": "\u041f\u043e\u0433\u043e\u0434\u0430 \u0434\u043b\u044f \u043c\u0435\u0441\u0442\u043d\u043e\u0441\u0442\u0438:",
@@ -619,13 +688,12 @@
"NotificationOptionTaskFailed": "\u0421\u0431\u043e\u0439 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f",
"NotificationOptionInstallationFailed": "\u0421\u0431\u043e\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438",
"NotificationOptionNewLibraryContent": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e",
- "NotificationOptionNewLibraryContentMultiple": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e (\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e)",
- "SendNotificationHelp": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u044f\u0449\u0438\u043a \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u043f\u0430\u043d\u0435\u043b\u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430. \u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f.",
+ "NotificationOptionNewLibraryContentMultiple": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e (\u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e)",
+ "SendNotificationHelp": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u044f\u0449\u0438\u043a \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0432 \u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u0438. \u041f\u0440\u043e\u043b\u0438\u0441\u0442\u0430\u0439\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.",
"NotificationOptionServerRestartRequired": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430",
"LabelNotificationEnabled": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u043e\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435",
"LabelMonitorUsers": "\u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0434\u0435\u044f\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043e\u0442:",
"LabelSendNotificationToUsers": "\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043b\u044f:",
- "UsersNotNotifiedAboutSelfActivity": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c\u0441\u044f \u043e \u0441\u0432\u043e\u0438\u0445 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u0445.",
"LabelUseNotificationServices": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0441\u043b\u0443\u0436\u0431:",
"CategoryUser": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c",
"CategorySystem": "\u0421\u0438\u0441\u0442\u0435\u043c\u0430",
@@ -633,10 +701,10 @@
"CategoryPlugin": "\u041f\u043b\u0430\u0433\u0438\u043d",
"LabelMessageTitle": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f:",
"LabelAvailableTokens": "\u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043c\u0430\u0440\u043a\u0435\u0440\u044b:",
- "AdditionalNotificationServices": "\u041f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043b\u0443\u0436\u0431\u044b \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.",
+ "AdditionalNotificationServices": "\u041f\u0440\u043e\u043b\u0438\u0441\u0442\u0430\u0439\u0442\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043b\u0443\u0436\u0431\u044b \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.",
"OptionAllUsers": "\u0412\u0441\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438",
"OptionAdminUsers": "\u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u044b",
- "OptionCustomUsers": "\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435",
+ "OptionCustomUsers": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435",
"ButtonArrowUp": "\u0412\u0432\u0435\u0440\u0445",
"ButtonArrowDown": "\u0412\u043d\u0438\u0437",
"ButtonArrowLeft": "\u0412\u043b\u0435\u0432\u043e",
@@ -648,8 +716,9 @@
"ButtonPageDown": "\u041d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0432\u043d\u0438\u0437",
"PageAbbreviation": "\u0421\u0422\u0420",
"ButtonHome": "\u0413\u043b\u0430\u0432\u043d\u0430\u044f",
+ "ButtonSearch": "\u041f\u043e\u0438\u0441\u043a",
"ButtonSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b",
- "ButtonTakeScreenshot": "\u0421\u043d\u0438\u043c\u043e\u043a \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b",
+ "ButtonTakeScreenshot": "\u0421\u043d\u044f\u0442\u044c \u044d\u043a\u0440\u0430\u043d",
"ButtonLetterUp": "\u041d\u0430 \u0431\u0443\u043a\u0432\u0443 \u0432\u0432\u0435\u0440\u0445",
"ButtonLetterDown": "\u041d\u0430 \u0431\u0443\u043a\u0432\u0443 \u0432\u043d\u0438\u0437",
"PageButtonAbbreviation": "\u0421\u0422\u0420",
@@ -661,21 +730,25 @@
"ButtonScenes": "\u0421\u0446\u0435\u043d\u044b",
"ButtonSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b",
"ButtonAudioTracks": "\u0410\u0443\u0434\u0438\u043e \u0434\u043e\u0440\u043e\u0436\u043a\u0438",
- "ButtonStop": "\u0421\u0442\u043e\u043f",
+ "ButtonPreviousTrack": "\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430",
+ "ButtonNextTrack": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0434\u043e\u0440\u043e\u0436\u043a\u0430",
+ "ButtonStop": "\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c",
"ButtonPause": "\u041f\u0430\u0443\u0437\u0430",
- "LabelGroupMoviesIntoCollections": "\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0438\u043b\u044c\u043c\u044b \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0439",
+ "LabelGroupMoviesIntoCollections": "\u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0438\u043b\u044c\u043c\u044b \u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438",
"LabelGroupMoviesIntoCollectionsHelp": "\u041f\u0440\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u0441\u043f\u0438\u0441\u043a\u043e\u0432 \u0444\u0438\u043b\u044c\u043c\u043e\u0432, \u0444\u0438\u043b\u044c\u043c\u044b \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u043a\u0430\u043a \u0435\u0434\u0438\u043d\u044b\u0439 \u0441\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442.",
"NotificationOptionPluginError": "\u0421\u0431\u043e\u0439 \u043f\u043b\u0430\u0433\u0438\u043d\u0430",
"ButtonVolumeUp": "\u0413\u0440\u043e\u043c\u043a\u043e\u0441\u0442\u044c \u0432\u044b\u0448\u0435",
"ButtonVolumeDown": "\u0413\u0440\u043e\u043c\u043a\u043e\u0441\u0442\u044c \u043d\u0438\u0436\u0435",
"ButtonMute": "\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u0432\u0443\u043a",
- "HeaderLatestMedia": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043c\u0435\u0434\u0438\u0430\u0444\u0430\u0439\u043b\u043e\u0432",
+ "HeaderLatestMedia": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
"OptionSpecialFeatures": "\u0414\u043e\u043f. \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b",
"HeaderCollections": "\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438",
"LabelProfileCodecsHelp": "\u041e\u0442\u0434\u0435\u043b\u044f\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0437\u0430\u043f\u044f\u0442\u043e\u0439. \u041c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043a\u043e\u0434\u0435\u043a\u043e\u0432.",
"LabelProfileContainersHelp": "\u041e\u0442\u0434\u0435\u043b\u044f\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0437\u0430\u043f\u044f\u0442\u043e\u0439. \u041c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432.",
"HeaderResponseProfile": "\u041f\u0440\u043e\u0444\u0438\u043b\u044c \u043e\u0442\u043a\u043b\u0438\u043a\u0430",
"LabelType": "\u0422\u0438\u043f:",
+ "LabelPersonRole": "\u0420\u043e\u043b\u044c:",
+ "LabelPersonRoleHelp": "\u0420\u043e\u043b\u0438, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043a \u0430\u043a\u0442\u0451\u0440\u0430\u043c.",
"LabelProfileContainer": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440:",
"LabelProfileVideoCodecs": "\u0412\u0438\u0434\u0435\u043e \u043a\u043e\u0434\u0435\u043a\u0438:",
"LabelProfileAudioCodecs": "\u0410\u0443\u0434\u0438\u043e \u043a\u043e\u0434\u0435\u043a\u0438:",
@@ -683,42 +756,50 @@
"HeaderDirectPlayProfile": "\u041f\u0440\u043e\u0444\u0438\u043b\u044c \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
"HeaderTranscodingProfile": "\u041f\u0440\u043e\u0444\u0438\u043b\u044c \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438",
"HeaderCodecProfile": "\u041f\u0440\u043e\u0444\u0438\u043b\u044c \u043a\u043e\u0434\u0435\u043a\u043e\u0432",
- "HeaderCodecProfileHelp": "\u041f\u0440\u043e\u0444\u0438\u043b\u0438 \u043a\u043e\u0434\u0435\u043a\u043e\u0432 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u043a\u043e\u0434\u0435\u043a\u043e\u0432. \u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435, \u0442\u043e \u043c\u0435\u0434\u0438\u0430\u0444\u0430\u0439\u043b \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043a\u043e\u0434\u0435\u043a \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f.",
+ "HeaderCodecProfileHelp": "\u041f\u0440\u043e\u0444\u0438\u043b\u0438 \u043a\u043e\u0434\u0435\u043a\u043e\u0432 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u043a\u043e\u0434\u0435\u043a\u043e\u0432. \u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435, \u0442\u043e \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u044e\u0442\u0441\u044f, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043a\u043e\u0434\u0435\u043a \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f.",
"HeaderContainerProfile": "\u041f\u0440\u043e\u0444\u0438\u043b\u044c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430",
- "HeaderContainerProfileHelp": "\u041f\u0440\u043e\u0444\u0438\u043b\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432. \u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435, \u0442\u043e \u043c\u0435\u0434\u0438\u0430\u0444\u0430\u0439\u043b \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0444\u043e\u0440\u043c\u0430\u0442 \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f.",
+ "HeaderContainerProfileHelp": "\u041f\u0440\u043e\u0444\u0438\u043b\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043d\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432. \u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435, \u0442\u043e \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u0443\u044e\u0442\u0441\u044f, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0444\u043e\u0440\u043c\u0430\u0442 \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f.",
"OptionProfileVideo": "\u0412\u0438\u0434\u0435\u043e",
"OptionProfileAudio": "\u0410\u0443\u0434\u0438\u043e",
"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\u0443\u0441\u0442\u044b\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \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 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u043f\u0430\u043f\u043a\u0438 \u0445\u0440\u0430\u043d\u0438\u0435\u043d\u0438\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\u0443\u0441\u0442\u044b\u043c \u0434\u043b\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430.",
+ "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 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432 DIDL \u043a\u0430\u043a \"object.container.storageFolder\", \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, \"object.container.person.musicArtist\".",
- "OptionPlainVideoItems": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0432\u0441\u0435 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u044b, \u043a\u0430\u043a \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0432\u0438\u0434\u0435\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b",
+ "OptionPlainVideoItems": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0432\u0441\u0435 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u044b, \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b",
"OptionPlainVideoItemsHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0432\u0441\u0435 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0432 DIDL \u043a\u0430\u043a \"object.item.videoItem\", \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, \"object.item.videoItem.movie\".",
- "LabelSupportedMediaTypes": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u0435\u0439:",
+ "LabelSupportedMediaTypes": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445:",
"TabIdentification": "\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f",
"TabDirectPlay": "\u041f\u0440\u044f\u043c\u043e\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435",
"TabContainers": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b",
"TabCodecs": "\u041a\u043e\u0434\u0435\u043a\u0438",
"TabResponses": "\u041e\u0442\u043a\u043b\u0438\u043a\u0438",
- "HeaderProfileInformation": "\u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043f\u0440\u043e\u0444\u0438\u043b\u0435",
- "LabelEmbedAlbumArtDidl": "\u0412\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u044e \u0430\u043b\u044c\u0431\u043e\u043c\u0430 \u0432 DIDL",
- "LabelEmbedAlbumArtDidlHelp": "\u0414\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0439 \u0430\u043b\u044c\u0431\u043e\u043c\u043e\u0432 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c. \u0414\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0436\u0435, \u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430, \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0443\u0434\u0430\u0441\u0442\u0441\u044f.",
- "LabelAlbumArtPN": "PN \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0430\u043b\u044c\u0431\u043e\u043c\u0430",
- "LabelAlbumArtHelp": "PN \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0435 \u0434\u043b\u044f \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0430\u043b\u044c\u0431\u043e\u043c\u0430, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c dlna:profileID \u043d\u0430 upnp:albumArtURI. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u0430.",
- "LabelAlbumArtMaxWidth": "\u041c\u0430\u043a\u0441. \u0448\u0438\u0440\u0438\u043d\u0430 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0430\u043b\u044c\u0431\u043e\u043c\u0430:",
- "LabelAlbumArtMaxWidthHelp": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0439 \u0430\u043b\u044c\u0431\u043e\u043c\u043e\u0432 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 upnp:albumArtURI.",
- "LabelAlbumArtMaxHeight": "\u041c\u0430\u043a\u0441. \u0432\u044b\u0441\u043e\u0442\u0430 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0430\u043b\u044c\u0431\u043e\u043c\u0430:",
- "LabelAlbumArtMaxHeightHelp": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0439 \u0430\u043b\u044c\u0431\u043e\u043c\u043e\u0432 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 upnp:albumArtURI.",
+ "HeaderProfileInformation": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u043f\u0440\u043e\u0444\u0438\u043b\u0435",
+ "LabelEmbedAlbumArtDidl": "\u0412\u043d\u0435\u0434\u0440\u044f\u0442\u044c \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0435 \u043e\u0431\u043b\u043e\u0436\u043a\u0438 \u0432 DIDL",
+ "LabelEmbedAlbumArtDidlHelp": "\u0414\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0445 \u043e\u0431\u043b\u043e\u0436\u0435\u043a \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c. \u0414\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0436\u0435, \u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430, \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0443\u0434\u0430\u0441\u0442\u0441\u044f.",
+ "LabelAlbumArtPN": "PN \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u043e\u0439 \u043e\u0431\u043b\u043e\u0436\u043a\u0438:",
+ "LabelAlbumArtHelp": "PN \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0435 \u0434\u043b\u044f \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0445 \u043e\u0431\u043b\u043e\u0436\u0435\u043a, \u0432\u043d\u0443\u0442\u0440\u0438 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 dlna:profileID \u043f\u0440\u0438 upnp:albumArtURI. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u0430.",
+ "LabelAlbumArtMaxWidth": "\u041c\u0430\u043a\u0441. \u0448\u0438\u0440\u0438\u043d\u0430 \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u043e\u0439 \u043e\u0431\u043b\u043e\u0436\u043a\u0438:",
+ "LabelAlbumArtMaxWidthHelp": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0445 \u043e\u0431\u043b\u043e\u0436\u0435\u043a \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 upnp:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "\u041c\u0430\u043a\u0441. \u0432\u044b\u0441\u043e\u0442\u0430 \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u043e\u0439 \u043e\u0431\u043b\u043e\u0436\u043a\u0438:",
+ "LabelAlbumArtMaxHeightHelp": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0430\u043b\u044c\u0431\u043e\u043c\u043d\u044b\u0445 \u043e\u0431\u043b\u043e\u0436\u0435\u043a \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 upnp:albumArtURI.",
"LabelIconMaxWidth": "\u041c\u0430\u043a\u0441. \u0448\u0438\u0440\u0438\u043d\u0430 \u0437\u043d\u0430\u0447\u043a\u0430:",
"LabelIconMaxWidthHelp": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u043a\u043e\u0432 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 upnp:icon.",
"LabelIconMaxHeight": "\u041c\u0430\u043a\u0441. \u0432\u044b\u0441\u043e\u0442\u0430 \u0437\u043d\u0430\u0447\u043a\u0430:",
"LabelIconMaxHeightHelp": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u043a\u043e\u0432 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 upnp:icon.",
"LabelIdentificationFieldHelp": "\u041f\u043e\u0434\u0441\u0442\u0440\u043e\u043a\u0430 \u0431\u0435\u0437 \u0443\u0447\u0451\u0442\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430, \u043b\u0438\u0431\u043e \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435.",
- "HeaderProfileServerSettingsHelp": "\u042d\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442, \u043a\u0430\u043a Media Browser \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0435\u0431\u044f \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435.",
+ "HeaderProfileServerSettingsHelp": "\u042d\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442, \u043a\u0430\u043a Media Browser \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435.",
"LabelMaxBitrate": "\u041c\u0430\u043a\u0441. \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c:",
- "LabelMaxBitrateHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0443\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432 \u0441\u0440\u0435\u0434\u0430\u0445 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0439 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e, \u043b\u0438\u0431\u043e \u0435\u0441\u043b\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u0441\u0432\u043e\u0451 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435.",
+ "LabelMaxBitrateHelp": "\u0423\u043a\u0430\u0436\u0438\u0442\u0435 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0443\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0432 \u0441\u0440\u0435\u0434\u0430\u0445 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0439 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e, \u043b\u0438\u0431\u043e, \u0435\u0441\u043b\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0443 - \u0435\u0433\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435.",
+ "LabelMaxStreamingBitrate": "\u041c\u0430\u043a\u0441. \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c:",
+ "LabelMaxStreamingBitrateHelp": "\u0423\u043a\u0430\u0437\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435.",
+ "LabelMaxStaticBitrate": "\u041c\u0430\u043a\u0441. \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438:",
+ "LabelMaxStaticBitrateHelp": "\u0423\u043a\u0430\u0437\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0443\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0432\u043e \u0432\u044b\u0441\u043e\u043a\u043e\u043c \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435.",
+ "LabelMusicStaticBitrate": "\u041f\u043e\u0442\u043e\u043a\u043e\u0432\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0441\u0438\u043d\u0445\u0440-\u0438\u0438 \u043c\u0443\u0437\u044b\u043a\u0438:",
+ "LabelMusicStaticBitrateHelp": "\u0423\u043a\u0430\u0437\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u0443\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0443\u0437\u044b\u043a\u0438",
+ "LabelMusicStreamingTranscodingBitrate": "\u041f\u043e\u0442\u043e\u043a\u043e\u0432\u0430\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438 \u043c\u0443\u0437\u044b\u043a\u0438:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "\u0423\u043a\u0430\u0437\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u043f\u0440\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435 \u043c\u0443\u0437\u044b\u043a\u0438",
"OptionIgnoreTranscodeByteRangeRequests": "\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430 \u0431\u0430\u0439\u0442\u043e\u0432 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u044d\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0431\u0443\u0434\u0443\u0442 \u0443\u0447\u0442\u0435\u043d\u044b, \u043d\u043e \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430 \u0431\u0430\u0439\u0442\u043e\u0432 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u043d.",
"LabelFriendlyName": "\u041f\u043e\u043d\u044f\u0442\u043d\u043e\u0435 \u0438\u043c\u044f",
@@ -730,10 +811,10 @@
"LabelModelUrl": "URL \u043c\u043e\u0434\u0435\u043b\u0438",
"LabelSerialNumber": "\u0421\u0435\u0440\u0438\u0439\u043d\u044b\u0439 \u043d\u043e\u043c\u0435\u0440",
"LabelDeviceDescription": "\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430",
- "HeaderIdentificationCriteriaHelp": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435, \u043f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435, \u043e\u0434\u0438\u043d \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0439.",
+ "HeaderIdentificationCriteriaHelp": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435, \u043f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435, \u043e\u0434\u0438\u043d \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u0439 \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.",
"HeaderDirectPlayProfileHelp": "\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e.",
"HeaderTranscodingProfileHelp": "\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a\u0438\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430.",
- "HeaderResponseProfileHelp": "\u041f\u0440\u043e\u0444\u0438\u043b\u0438 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u043c\u043e\u0439 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u0440\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u0438\u0434\u043e\u0432 \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u0435\u0439.",
+ "HeaderResponseProfileHelp": "\u041f\u0440\u043e\u0444\u0438\u043b\u0438 \u043e\u0442\u043a\u043b\u0438\u043a\u043e\u0432 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u043f\u043e\u0441\u044b\u043b\u0430\u0435\u043c\u043e\u0439 \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u0440\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u0438\u0434\u043e\u0432 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445.",
"LabelXDlnaCap": "\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 X-Dlna:",
"LabelXDlnaCapHelp": "\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 X_DLNACAP \u0432 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435 \u0438\u043c\u0451\u043d urn:schemas-dlna-org:device-1-0",
"LabelXDlnaDoc": "\u0421\u0445\u0435\u043c\u0430 X-Dlna:",
@@ -746,12 +827,12 @@
"LabelTranscodingAudioCodec": "\u0410\u0443\u0434\u0438\u043e \u043f\u0440\u043e\u0444\u0438\u043b\u044c:",
"OptionEnableM2tsMode": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c M2ts",
"OptionEnableM2tsModeHelp": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c M2ts, \u043f\u0440\u0438 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0434\u043b\u044f mpegts.",
- "OptionEstimateContentLength": "\u0420\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0434\u043b\u0438\u043d\u0443 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435",
+ "OptionEstimateContentLength": "\u0420\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0434\u043b\u0438\u043d\u0443 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435",
"OptionReportByteRangeSeekingWhenTranscoding": "\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u044f\u0442\u044c \u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u043f\u043e\u0431\u0430\u0439\u0442\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u043c\u043e\u0442\u043a\u0438 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0435",
- "OptionReportByteRangeSeekingWhenTranscodingHelp": "\u042d\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0434\u0435\u043b\u0430\u044e\u0442 \u043f\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u043e\u0442\u043a\u0443 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0445\u043e\u0440\u043e\u0448\u043e.",
- "HeaderSubtitleDownloadingHelp": "\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, Media Browser \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043a\u0430\u0442\u044c \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u044e\u0449\u0438\u0435 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u0445 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0430 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, OpenSubtitles.org.",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0435\u043b\u0430\u044e\u0442 \u043f\u043e\u0432\u0440\u0435\u043c\u0451\u043d\u043d\u0443\u044e \u043f\u0435\u0440\u0435\u043c\u043e\u0442\u043a\u0443 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e.",
+ "HeaderSubtitleDownloadingHelp": "\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 Media Browser, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043a\u0430\u0442\u044c \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u044e\u0449\u0438\u0435 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u0445 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a\u0430 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, OpenSubtitles.org.",
"HeaderDownloadSubtitlesFor": "\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432 \u0434\u043b\u044f:",
- "MessageNoChapterProviders": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u043b\u0430\u0433\u0438\u043d-\u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a \u0441\u0446\u0435\u043d (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, ChapterDb) \u0434\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0441\u0446\u0435\u043d.",
+ "MessageNoChapterProviders": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u043b\u0430\u0433\u0438\u043d-\u043f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a \u0441\u0446\u0435\u043d (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: ChapterDb) \u0434\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0441\u0446\u0435\u043d.",
"LabelSkipIfGraphicalSubsPresent": "\u041e\u043f\u0443\u0441\u0442\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u0432 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u0435 \u0443\u0436\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b",
"LabelSkipIfGraphicalSubsPresentHelp": "\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0442 \u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u0443\u044e \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0443 \u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432.",
"TabSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b",
@@ -760,26 +841,28 @@
"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, Media Browser \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0441\u0446\u0435\u043d \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \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 \u0430\u0443\u0434\u0438\u043e\u0434\u043e\u0440\u043e\u0436\u043a\u0443 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u044f\u0437\u044b\u043a\u0430",
+ "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:",
"ButtonRegister": "\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f",
- "LabelSkipIfAudioTrackPresent": "\u041e\u043f\u0443\u0441\u0442\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0439 \u044f\u0437\u044b\u043a \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u0441 \u044f\u0437\u044b\u043a\u043e\u043c \u0430\u0443\u0434\u0438\u043e\u0434\u043e\u0440\u043e\u0436\u043a\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e",
+ "LabelSkipIfAudioTrackPresent": "\u041e\u043f\u0443\u0441\u0442\u0438\u0442\u044c, \u0435\u0441\u043b\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u0430\u0443\u0434\u0438\u043e\u0434\u043e\u0440\u043e\u0436\u043a\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u043c\u0443 \u044f\u0437\u044b\u043a\u0443",
"LabelSkipIfAudioTrackPresentHelp": "\u0421\u043d\u044f\u0442\u044c \u0444\u043b\u0430\u0436\u043e\u043a, \u0447\u0442\u043e\u0431\u044b \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u0432\u0438\u0434\u0435\u043e \u0438\u043c\u0435\u043b\u0438\u0441\u044c \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u044b, \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u044f\u0437\u044b\u043a\u0430 \u0430\u0443\u0434\u0438\u043e.",
- "HeaderSendMessage": "\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435",
+ "HeaderSendMessage": "\u041e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f",
"ButtonSend": "\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c",
"LabelMessageText": "\u0422\u0435\u043a\u0441\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f:",
"MessageNoAvailablePlugins": "\u041d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432.",
"LabelDisplayPluginsFor": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u0434\u043b\u044f:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "\u0414\u0440\u0443\u0433\u0438\u0435",
- "LabelEpisodeName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u0430",
- "LabelSeriesName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0438\u0430\u043b\u0430",
+ "LabelEpisodeNamePlain": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u0430",
+ "LabelSeriesNamePlain": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0435\u0440\u0438\u0430\u043b\u0430",
"ValueSeriesNamePeriod": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435.\u0441\u0435\u0440\u0438\u0430\u043b\u0430",
"ValueSeriesNameUnderscore": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435_\u0441\u0435\u0440\u0438\u0430\u043b\u0430",
"ValueEpisodeNamePeriod": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435.\u044d\u043f\u0438\u0437\u043e\u0434\u0430",
"ValueEpisodeNameUnderscore": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435_\u044d\u043f\u0438\u0437\u043e\u0434\u0430",
+ "LabelSeasonNumberPlain": "\u041d\u043e\u043c\u0435\u0440 \u0441\u0435\u0437\u043e\u043d\u0430",
+ "LabelEpisodeNumberPlain": "\u041d\u043e\u043c\u0435\u0440 \u044d\u043f\u0438\u0437\u043e\u0434\u0430",
+ "LabelEndingEpisodeNumberPlain": "\u041d\u043e\u043c\u0435\u0440 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u044d\u043f\u0438\u0437\u043e\u0434\u0430",
"HeaderTypeText": "\u0412\u0432\u043e\u0434 \u0442\u0435\u043a\u0441\u0442\u0430",
"LabelTypeText": "\u0422\u0435\u043a\u0441\u0442",
"HeaderSearchForSubtitles": "\u041f\u043e\u0438\u0441\u043a \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432",
@@ -787,12 +870,12 @@
"TabDisplay": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435",
"TabLanguages": "\u042f\u0437\u044b\u043a\u0438",
"TabWebClient": "\u0412\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442",
- "LabelEnableThemeSongs": "\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u043b\u043e\u0434\u0438\u0438 \u0442\u0435\u043c",
+ "LabelEnableThemeSongs": "\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043c\u0435\u043b\u043e\u0434\u0438\u0439 \u0442\u0435\u043c\u044b",
"LabelEnableBackdrops": "\u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u043d\u0438\u043a\u043e\u0432",
- "LabelEnableThemeSongsHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043c\u0435\u043b\u043e\u0434\u0438\u0438 \u0442\u0435\u043c \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u043f\u0440\u0438 \u043e\u0431\u0437\u043e\u0440\u0435 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438.",
+ "LabelEnableThemeSongsHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043c\u0435\u043b\u043e\u0434\u0438\u0438 \u0442\u0435\u043c\u044b \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0432 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u043f\u0440\u0438 \u043e\u0431\u0437\u043e\u0440\u0435 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438.",
"LabelEnableBackdropsHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0437\u0430\u0434\u043d\u0438\u043a\u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u0444\u043e\u043d \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446 \u043f\u0440\u0438 \u043e\u0431\u0437\u043e\u0440\u0435 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438.",
"HeaderHomePage": "\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430",
- "HeaderSettingsForThisDevice": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430",
+ "HeaderSettingsForThisDevice": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430",
"OptionAuto": "\u0410\u0432\u0442\u043e",
"OptionYes": "\u0414\u0430",
"OptionNo": "\u041d\u0435\u0442",
@@ -800,39 +883,42 @@
"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:",
- "OptionMyLibraryButtons": "\u041c\u043e\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 (\u043a\u043d\u043e\u043f\u043a\u0438)",
- "OptionMyLibrary": "\u041c\u043e\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430",
- "OptionMyLibrarySmall": "\u041c\u043e\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0430 (\u043c\u0430\u043b\u044b\u0435)",
+ "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",
- "OptionLatestMedia": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u0435\u0439",
+ "OptionLatestMedia": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
"OptionLatestChannelMedia": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u043e\u0432",
"HeaderLatestChannelItems": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u043e\u0432",
- "OptionNone": "\u041d\u0438\u043a\u0430\u043a\u043e\u0435",
+ "OptionNone": "\u041d\u0438\u0447\u0435\u0433\u043e",
"HeaderLiveTv": "\u0422\u0412 \u044d\u0444\u0438\u0440",
"HeaderReports": "\u041e\u0442\u0447\u0451\u0442\u044b",
"HeaderMetadataManager": "\u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
"HeaderPreferences": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438",
"MessageLoadingChannels": "\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u043a\u0430\u043d\u0430\u043b\u0430...",
+ "MessageLoadingContent": "\u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435...",
"ButtonMarkRead": "\u041e\u0442\u043c\u0435\u0442\u0438\u0442\u044c \u043a\u0430\u043a \u043f\u0440\u043e\u0447\u0442\u0451\u043d\u043d\u043e\u0435",
- "OptionDefaultSort": "\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e",
+ "OptionDefaultSort": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f",
"OptionCommunityMostWatchedSort": "\u041d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c\u044b\u0435",
- "TabNextUp": "\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f",
- "MessageNoMovieSuggestionsAvailable": "\u0421\u0435\u0439\u0447\u0430\u0441 \u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \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 \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 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0432\u0430\u0448\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438.",
+ "TabNextUp": "\u041e\u0447\u0435\u0440\u0435\u0434\u043d\u044b\u0435",
+ "MessageNoMovieSuggestionsAvailable": "\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \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 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u043c \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0438\u0437 \u0444\u0438\u043b\u044c\u043c\u043e\u0432, \u0441\u0435\u0440\u0438\u0430\u043b\u043e\u0432, \u0430\u043b\u044c\u0431\u043e\u043c\u043e\u0432 \u0438 \u0438\u0433\u0440. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043a\u043d\u043e\u043f\u043a\u0443 \"\u0421\u043e\u0437\u0434\u0430\u0442\u044c\", \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e.",
+ "MessageNoPlaylistsAvailable": "\u0421\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043f\u0438\u0441\u043a\u0438 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0437\u0430 \u0440\u0430\u0437. \u0427\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0432 \u0441\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f, \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 \u0434\u0435\u0440\u0436\u0438\u0442\u0435, \u0437\u0430\u0442\u0435\u043c \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f.",
+ "MessageNoPlaylistItemsAvailable": "\u0414\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u0443\u0441\u0442.",
"HeaderWelcomeToMediaBrowserWebClient": "\u0412\u0435\u0431-\u043a\u043b\u0438\u0435\u043d\u0442 Media Browser \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u0430\u0441!",
"ButtonDismiss": "\u0421\u043a\u0440\u044b\u0442\u044c",
- "MessageLearnHowToCustomize": "\u0423\u0437\u043d\u0430\u0439\u0442\u0435, \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u044d\u0442\u0443 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c\u0443 \u0432\u043a\u0443\u0441\u0443. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0432\u0430\u0448\u0443 \u0430\u0432\u0430\u0442\u0430\u0440\u0443 \u0432 \u043f\u0440\u0430\u0432\u043e\u043c \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0433\u043b\u0443 \u044d\u043a\u0440\u0430\u043d\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438.",
+ "MessageLearnHowToCustomize": "\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c, \u043a\u0430\u043a \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u043e \u0441\u0432\u043e\u0435\u043c\u0443 \u043b\u0438\u0447\u043d\u043e\u043c\u0443 \u0432\u043a\u0443\u0441\u0443. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0430\u0432\u0430\u0442\u0430\u0440\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0432 \u043f\u0440\u0430\u0432\u043e\u043c \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0433\u043b\u0443 \u044d\u043a\u0440\u0430\u043d\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438.",
"ButtonEditOtherUserPreferences": "\u041f\u0440\u0430\u0432\u0438\u0442\u044c \u043b\u0438\u0447\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.",
- "LabelChannelStreamQuality": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u043f\u043e\u0442\u043e\u043a\u0430:",
- "LabelChannelStreamQualityHelp": "\u0412 \u0441\u0440\u0435\u0434\u0435 \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, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043f\u043b\u0430\u0432\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f.",
+ "LabelChannelStreamQuality": "\u0412\u044b\u0431\u043e\u0440 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435:",
+ "LabelChannelStreamQualityHelp": "\u0412 \u0441\u0440\u0435\u0434\u0435 \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, \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u043e\u0447\u044c \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0432\u043f\u0435\u0447\u0430\u0442\u043b\u0435\u043d\u0438\u0435 \u0431\u043e\u043b\u0435\u0435 \u043f\u043b\u0430\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438.",
"OptionBestAvailableStreamQuality": "\u041d\u0430\u0438\u043b\u0443\u0447\u0448\u0435\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0435",
"LabelEnableChannelContentDownloadingFor": "\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043a\u0430\u043d\u0430\u043b\u0430 \u0434\u043b\u044f:",
- "LabelEnableChannelContentDownloadingForHelp": "\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043a\u0430\u043d\u0430\u043b\u0430\u043c\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043f\u0440\u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435. \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 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043e \u043a\u0430\u043a \u0447\u0430\u0441\u0442\u044c \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u043e\u0432.",
+ "LabelEnableChannelContentDownloadingForHelp": "\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043a\u0430\u043d\u0430\u043b\u0430\u043c\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0434\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430. \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\u0433\u043e \u0437\u0430\u0434\u0430\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u043e\u0432.",
"LabelChannelDownloadPath": "\u041f\u0443\u0442\u044c \u0434\u043b\u044f \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\u043e\u0432:",
- "LabelChannelDownloadPathHelp": "\u041d\u0430\u0437\u043d\u0430\u0447\u044c\u0442\u0435 \u0436\u0435\u043b\u0430\u0435\u043c\u044b\u0439 \u043f\u0443\u0442\u044c \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u041e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u0443\u0441\u0442\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, \u043f\u043e \u0436\u0435\u043b\u0430\u043d\u0438\u044e, \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u043a. \u041e\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u043f\u0443\u0441\u0442\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.",
"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": "\u0411\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0440\u0435\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\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\u0440\u0438 \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442.",
- "ChannelSettingsFormHelp": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043a\u0430\u043d\u0430\u043b\u044b \u0438\u0437 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Trailers \u0438 Vimeo.",
+ "LabelChannelDownloadAgeHelp": "\u0411\u0443\u0434\u0435\u0442 \u0443\u0434\u0430\u043b\u0435\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \u0441\u0442\u0430\u0440\u0435\u0435, \u0447\u0435\u043c \u0434\u0430\u043d\u043d\u043e\u0435. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0435\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f.",
+ "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.",
"LabelSelectCollection": "\u0412\u044b\u0431\u043e\u0440 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438:",
"ViewTypeMovies": "\u041a\u0438\u043d\u043e",
"ViewTypeTvShows": "\u0422\u0412",
@@ -842,11 +928,171 @@
"ViewTypeChannels": "\u041a\u0430\u043d\u0430\u043b\u044b",
"ViewTypeLiveTV": "\u0422\u0412 \u044d\u0444\u0438\u0440",
"HeaderOtherDisplaySettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f",
- "HeaderMyViews": "\u041c\u043e\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f",
- "LabelSelectFolderGroups": "\u0410\u0432\u0442\u043e\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u041a\u0438\u043d\u043e, \u041c\u0443\u0437\u044b\u043a\u0430 \u0438 \u0422\u0412) \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043f\u0430\u043f\u043e\u043a:",
- "LabelSelectFolderGroupsHelp": "\u041f\u0430\u043f\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u044b, \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e \u043f\u0440\u0438\u0441\u0443\u0449\u0438\u043c \u0438\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u043c.",
- "OptionDisplayAdultContent": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \"\u0434\u043b\u044f \u0432\u0437\u0440\u043e\u0441\u043b\u044b\u0445\"",
+ "HeaderMyViews": "\u041c\u043e\u0438 \u0430\u0441\u043f\u0435\u043a\u0442\u044b",
+ "LabelSelectFolderGroups": "\u0410\u0432\u0442\u043e\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u043d\u0443\u0442\u0440\u044c \u0430\u0441\u043f\u0435\u043a\u0442\u043e\u0432 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: \u041a\u0438\u043d\u043e, \u041c\u0443\u0437\u044b\u043a\u0430 \u0438\u043b\u0438 \u0422\u0412) \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043f\u0430\u043f\u043e\u043a:",
+ "LabelSelectFolderGroupsHelp": "\u041f\u0430\u043f\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043e\u0442\u043c\u0435\u0447\u0435\u043d\u044b, \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u0440\u0438\u0441\u0443\u0449\u0438\u043c \u0438\u043c \u0430\u0441\u043f\u0435\u043a\u0442\u0430\u043c.",
+ "OptionDisplayAdultContent": "\u041e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \"\u0432\u0437\u0440\u043e\u0441\u043b\u043e\u0435\" \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435",
"OptionLibraryFolders": "\u041c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0438",
"TitleRemoteControl": "\u0423\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435",
- "OptionLatestTvRecordings": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439"
+ "OptionLatestTvRecordings": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439",
+ "LabelProtocolInfo": "\u0421\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0435:",
+ "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.",
+ "TabXbmcMetadata": "XBMC",
+ "HeaderXbmcMetadataHelp": "Media Browser \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0434\u043b\u044f NFO-\u0444\u0430\u0439\u043b\u043e\u0432 XBMC. \u0414\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 XBMC, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0421\u043b\u0443\u0436\u0431\u044b, \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e \u0442\u0438\u043f\u0430\u043c \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445.",
+ "LabelXbmcMetadataUser": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435 \u0432 NFO-\u0444\u0430\u0439\u043b\u044b \u0434\u043b\u044f:",
+ "LabelXbmcMetadataUserHelp": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435 \u043c\u0435\u0436\u0434\u0443 Media Browser \u0438 XBMC.",
+ "LabelXbmcMetadataDateFormat": "\u0424\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u0442\u044b \u0432\u044b\u043f\u0443\u0441\u043a\u0430:",
+ "LabelXbmcMetadataDateFormatHelp": "\u0412\u0441\u0435 \u0434\u0430\u0442\u044b \u0432\u043d\u0443\u0442\u0440\u0438 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.",
+ "LabelXbmcMetadataSaveImagePaths": "\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043f\u0443\u0442\u0438 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0432\u043d\u0443\u0442\u0440\u0438 NFO-\u0444\u0430\u0439\u043b\u043e\u0432",
+ "LabelXbmcMetadataSaveImagePathsHelp": "\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 \u0438\u043c\u0435\u043d\u0430 \u0444\u0430\u0439\u043b\u043e\u0432 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u043d\u0435 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u044f\u0449\u0438\u043c \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u043c XBMC.",
+ "LabelXbmcMetadataEnablePathSubstitution": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0443\u0442\u0435\u0439",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "\u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0443\u0442\u0435\u0439 \u043a \u0440\u0438\u0441\u0443\u043d\u043a\u0430\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043e\u043a \u043f\u0443\u0442\u0435\u0439 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u0443\u0442\u0435\u0439.",
+ "LabelGroupChannelsIntoViews": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0440\u0435\u0434\u0438 \u043c\u043e\u0438\u0445 \u0430\u0441\u043f\u0435\u043a\u0442\u043e\u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u0430\u043d\u0430\u043b\u044b:",
+ "LabelGroupChannelsIntoViewsHelp": "\u041f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u0430\u043d\u0430\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0441\u0440\u0435\u0434\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0430\u0441\u043f\u0435\u043a\u0442\u043e\u0432. \u041f\u0440\u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438, \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0430\u0441\u043f\u0435\u043a\u0442\u0430 \u041a\u0430\u043d\u0430\u043b\u044b.",
+ "LabelDisplayCollectionsView": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0430\u0441\u043f\u0435\u043a\u0442 \u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0444\u0438\u043b\u044c\u043c\u043e\u0432",
+ "LabelXbmcMetadataEnableExtraThumbs": "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c extrafanart \u0432\u043d\u0443\u0442\u0440\u044c extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "\u041f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432, \u0438\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u044c extrafanart \u0438 extrathumbs \u0434\u043b\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0441 \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u043e\u0439 Xbmc.",
+ "TabServices": "\u0421\u043b\u0443\u0436\u0431\u044b",
+ "TabLogs": "\u0416\u0443\u0440\u043d\u0430\u043b\u044b",
+ "HeaderServerLogFiles": "\u0424\u0430\u0439\u043b\u044b \u0436\u0443\u0440\u043d\u0430\u043b\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:",
+ "TabBranding": "\u0411\u0440\u0435\u043d\u0434\u0438\u043d\u0433",
+ "HeaderBrandingHelp": "\u0410\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u0439\u0442\u0435 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0432\u0438\u0434 Media Browser \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0432\u0430\u0448\u0435\u0439 \u0433\u0440\u0443\u043f\u043f\u044b \u0438\u043b\u0438 \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438.",
+ "LabelLoginDisclaimer": "\u041e\u0433\u043e\u0432\u043e\u0440\u043a\u0430 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 \u0432\u0445\u043e\u0434\u0430:",
+ "LabelLoginDisclaimerHelp": "\u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u043d\u0438\u0436\u043d\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432\u0445\u043e\u0434\u0430 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443.",
+ "LabelAutomaticallyDonate": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0441\u0443\u043c\u043c\u0443 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u0435\u0441\u044f\u0446",
+ "LabelAutomaticallyDonateHelp": "\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432 \u043b\u044e\u0431\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u0442\u043e \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u044e \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c PayPal.",
+ "OptionList": "\u0421\u043f\u0438\u0441\u043e\u043a",
+ "TabDashboard": "\u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c",
+ "TitleServer": "\u0421\u0435\u0440\u0432\u0435\u0440",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "\u041d\u043e\u0432\u0438\u043d\u043a\u0438 \u043c\u0443\u0437\u044b\u043a\u0438",
+ "HeaderBranding": "\u0411\u0440\u0435\u043d\u0434\u0438\u043d\u0433",
+ "HeaderApiKeys": "\u041a\u043b\u044e\u0447\u0438 API",
+ "HeaderApiKeysHelp": "\u0412\u043d\u0435\u0448\u043d\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043a\u043b\u044e\u0447 API, \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a Media Browser. \u041a\u043b\u044e\u0447\u0438 \u0432\u044b\u0434\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u0432\u0445\u043e\u0434\u0435 \u0441 \u0443\u0447\u0451\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u044c\u044e Media Browser, \u0438\u043b\u0438 \u043a\u043b\u044e\u0447 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0432\u0440\u0443\u0447\u043d\u0443\u044e.",
+ "HeaderApiKey": "\u041a\u043b\u044e\u0447 API",
+ "HeaderApp": "\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435",
+ "HeaderDevice": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e",
+ "HeaderUser": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c",
+ "HeaderDateIssued": "\u0414\u0430\u0442\u0430 \u0432\u044b\u0434\u0430\u0447\u0438",
+ "LabelChapterName": "\u0421\u0446\u0435\u043d\u0430 {0}",
+ "HeaderNewApiKey": "\u041d\u043e\u0432\u044b\u0439 \u043a\u043b\u044e\u0447 API",
+ "LabelAppName": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f",
+ "LabelAppNameExample": "\u041f\u0440\u0438\u043c\u0435\u0440: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u043f\u0440\u0430\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0441\u0432\u044f\u0437\u0438 \u0441 Media Browser.",
+ "HeaderHttpHeaders": "HTTP-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438",
+ "HeaderIdentificationHeader": "\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a",
+ "LabelValue": "\u0417\u043d\u0430\u0447\u0435\u043d\u0438\u0435:",
+ "LabelMatchType": "\u0422\u0438\u043f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f:",
+ "OptionEquals": "\u0420\u0430\u0432\u043d\u043e",
+ "OptionRegex": "\u0420\u0435\u0433. \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435",
+ "OptionSubstring": "\u041f\u043e\u0434\u0441\u0442\u0440\u043e\u043a\u0430",
+ "TabView": "\u0412\u0438\u0434",
+ "TabSort": "\u041f\u043e\u0440\u044f\u0434\u043e\u043a",
+ "TabFilter": "\u0424\u0438\u043b\u044c\u0442\u0440\u044b",
+ "ButtonView": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c",
+ "LabelPageSize": "\u041c\u0430\u043a\u0441. \u0447\u0438\u0441\u043b\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432:",
+ "LabelPath": "\u041f\u0443\u0442\u044c:",
+ "LabelView": "\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435:",
+ "TabUsers": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438",
+ "LabelSortName": "\u0421\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435:",
+ "LabelDateAdded": "\u0414\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f:",
+ "HeaderFeatures": "\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b",
+ "HeaderAdvanced": "\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e",
+ "ButtonSync": "\u0421\u0438\u043d\u0445\u0440\u043e",
+ "TabScheduledTasks": "\u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a",
+ "HeaderChapters": "\u0421\u0446\u0435\u043d\u044b",
+ "HeaderResumeSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f",
+ "TabSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f",
+ "TitleUsers": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438",
+ "LabelProtocol": "\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http \u041f\u0440\u044f\u043c\u043e\u0439 \u041f\u043e\u0442\u043e\u043a (HLS)",
+ "LabelContext": "\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442",
+ "OptionContextStreaming": "\u041f\u043e\u0442\u043e\u043a\u043e\u0432\u0430\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430",
+ "OptionContextStatic": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f",
+ "ButtonAddToPlaylist": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440-\u0438\u044f",
+ "TabPlaylists": "\u0421\u043f\u0438\u0441\u043a\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f",
+ "ButtonClose": "\u0417\u0430\u043a\u0440\u044b\u0442\u044c",
+ "LabelAllLanguages": "\u0412\u0441\u0435 \u044f\u0437\u044b\u043a\u0438",
+ "HeaderBrowseOnlineImages": "\u041e\u0431\u0437\u043e\u0440 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0432 \u0441\u0435\u0442\u0438",
+ "LabelSource": "\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a:",
+ "OptionAll": "\u0412\u0441\u0435",
+ "LabelImage": "\u0420\u0438\u0441\u0443\u043d\u043e\u043a:",
+ "ButtonBrowseImages": "\u041f\u0440\u043e\u043b\u0438\u0441\u0442\u0430\u0442\u044c \u0440\u0438\u0441\u0443\u043d\u043a\u0438",
+ "HeaderImages": "\u0420\u0438\u0441\u0443\u043d\u043a\u0438",
+ "HeaderBackdrops": "\u0417\u0430\u0434\u043d\u0438\u043a\u0438",
+ "HeaderScreenshots": "\u0421\u043d\u0438\u043c\u043a\u0438 \u044d\u043a\u0440\u0430\u043d\u0430",
+ "HeaderAddUpdateImage": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\/\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0430",
+ "LabelJpgPngOnly": "\u0422\u043e\u043b\u044c\u043a\u043e JPG\/PNG",
+ "LabelImageType": "\u0422\u0438\u043f \u0440\u0438\u0441\u0443\u043d\u043a\u0430:",
+ "OptionPrimary": "\u041f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0439",
+ "OptionArt": "\u0412\u0438\u043d\u044c\u0435\u0442\u043a\u0430",
+ "OptionBox": "\u041a\u043e\u0440\u043e\u0431\u043a\u0430",
+ "OptionBoxRear": "\u041a\u043e\u0440\u043e\u0431\u043a\u0430 \u0441\u0437\u0430\u0434\u0438",
+ "OptionDisc": "\u0414\u0438\u0441\u043a",
+ "OptionLogo": "\u041b\u043e\u0433\u043e\u0442\u0438\u043f",
+ "OptionMenu": "\u041c\u0435\u043d\u044e",
+ "OptionScreenshot": "\u0421\u043d\u0438\u043c\u043e\u043a \u044d\u043a\u0440\u0430\u043d\u0430",
+ "OptionLocked": "\u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435",
+ "OptionUnidentified": "\u041d\u0435\u043e\u043f\u043e\u0437\u043d\u0430\u043d\u043d\u044b\u0435",
+ "OptionMissingParentalRating": "\u041d\u0435\u0442 \u0432\u043e\u0437\u0440\u0430\u0441\u0442. \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0438",
+ "OptionStub": "\u0428\u043b\u0435\u0439\u0444",
+ "HeaderEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u044b:",
+ "OptionSeason0": "\u0421\u0435\u0437\u043e\u043d 0",
+ "LabelReport": "\u041e\u0442\u0447\u0451\u0442:",
+ "OptionReportSongs": "\u041c\u0435\u043b\u043e\u0434\u0438\u0438",
+ "OptionReportSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u044b",
+ "OptionReportSeasons": "\u0421\u0435\u0437\u043e\u043d\u044b",
+ "OptionReportTrailers": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b",
+ "OptionReportMusicVideos": "\u041a\u043b\u0438\u043f\u044b",
+ "OptionReportMovies": "\u0424\u0438\u043b\u044c\u043c\u044b",
+ "OptionReportHomeVideos": "\u0414\u043e\u043c\u0430\u0448\u043d\u0435\u0435 \u0432\u0438\u0434\u0435\u043e",
+ "OptionReportGames": "\u0418\u0433\u0440\u044b",
+ "OptionReportEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u044b",
+ "OptionReportCollections": "\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438",
+ "OptionReportBooks": "\u041a\u043d\u0438\u0433\u0438",
+ "OptionReportArtists": "\u0418\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438",
+ "OptionReportAlbums": "\u0410\u043b\u044c\u0431\u043e\u043c\u044b",
+ "OptionReportAdultVideos": "\u0412\u0437\u0440\u043e\u0441\u043b\u043e\u0435 \u0432\u0438\u0434\u0435\u043e",
+ "ButtonMore": "\u0415\u0449\u0451",
+ "HeaderActivity": "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f",
+ "ScheduledTaskStartedWithName": "{0} - \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e",
+ "ScheduledTaskCancelledWithName": "{0} - \u0431\u044b\u043b\u043e \u043e\u0442\u043c\u0435\u043d\u0435\u043d\u043e",
+ "ScheduledTaskCompletedWithName": "{0} - \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e",
+ "ScheduledTaskFailed": "\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u043e\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e",
+ "PluginInstalledWithName": "{0} - \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e",
+ "PluginUpdatedWithName": "{0} - \u0431\u044b\u043b\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043e",
+ "PluginUninstalledWithName": "{0} - \u0431\u044b\u043b\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u043e",
+ "ScheduledTaskFailedWithName": "{0} - \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u043e",
+ "ItemAddedWithName": "{0} (\u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0432 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0443)",
+ "ItemRemovedWithName": "{0} (\u0438\u0437\u044a\u044f\u0442\u043e \u0438\u0437 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438)",
+ "DeviceOnlineWithName": "{0} - \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e",
+ "UserOnlineFromDevice": "{0} - \u043f\u043e\u0434\u043a\u043b-\u0438\u0435 \u0441 {1} \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e",
+ "DeviceOfflineWithName": "{0} - \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0440\u0432\u0430\u043d\u043e",
+ "UserOfflineFromDevice": "{0} - \u043f\u043e\u0434\u043a\u043b-\u0438\u0435 \u0441 {1} \u043f\u0440\u0435\u0440\u0432\u0430\u043d\u043e",
+ "SubtitlesDownloadedForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u0434\u043b\u044f {0} \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b\u0438\u0441\u044c",
+ "SubtitleDownloadFailureForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u0434\u043b\u044f {0} \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c",
+ "LabelRunningTimeValue": "\u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f: {0}",
+ "LabelIpAddressValue": "IP \u0430\u0434\u0440\u0435\u0441: {0}",
+ "UserConfigurationUpdatedWithName": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f {0} \u0431\u044b\u043b\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0430",
+ "UserCreatedWithName": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c {0} \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d",
+ "UserPasswordChangedWithName": "\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f {0} \u0431\u044b\u043b \u0438\u0437\u043c\u0435\u043d\u0451\u043d",
+ "UserDeletedWithName": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c {0} \u0431\u044b\u043b \u0443\u0434\u0430\u043b\u0451\u043d",
+ "MessageServerConfigurationUpdated": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0431\u044b\u043b\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0430",
+ "MessageNamedServerConfigurationUpdatedWithValue": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 (\u0440\u0430\u0437\u0434\u0435\u043b {0}) \u0431\u044b\u043b\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0430",
+ "MessageApplicationUpdated": "Media Browser Server \u0431\u044b\u043b \u043e\u0431\u043d\u043e\u0432\u043b\u0451\u043d",
+ "AuthenticationSucceededWithUserName": "{0} - \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u0430",
+ "FailedLoginAttemptWithUserName": "{0} - \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u0430",
+ "UserStartedPlayingItemWithValues": "{0} - \u0432\u043e\u0441\u043f\u0440-\u0438\u0435 \u00ab{1}\u00bb \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e",
+ "UserStoppedPlayingItemWithValues": "{0} - \u0432\u043e\u0441\u043f\u0440-\u0438\u0435 \u00ab{1}\u00bb \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e",
+ "AppDeviceValues": "\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435: {0}, \u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e: {1}",
+ "ProviderValue": "\u041f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a: {0}",
+ "LabelChannelDownloadSizeLimit": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0413\u0411:",
+ "LabelChannelDownloadSizeLimitHelp": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0430\u043f\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u0430\u043d\u0430\u043b\u043e\u0432",
+ "HeaderRecentActivity": "\u041d\u0435\u0434\u0430\u0432\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f"
} \ 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 3b6bcdf51..21eb0c1c9 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/server.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json
@@ -1,837 +1,1114 @@
{
"LabelExit": "Exit",
- "LabelVisitCommunity": "Visit Community",
- "LabelGithubWiki": "Github Wiki",
- "LabelSwagger": "Swagger",
- "LabelStandard": "Standard",
- "LabelViewApiDocumentation": "View Api Documentation",
- "LabelBrowseLibrary": "Browse Library",
- "LabelConfigureMediaBrowser": "Configure Media Browser",
- "LabelOpenLibraryViewer": "Open Library Viewer",
- "LabelRestartServer": "Restart Server",
- "LabelShowLogWindow": "Show Log Window",
- "LabelPrevious": "Previous",
- "LabelFinish": "Finish",
- "LabelNext": "Next",
- "LabelYoureDone": "You're Done!",
- "WelcomeToMediaBrowser": "Welcome to Media Browser!",
- "TitleMediaBrowser": "Media Browser",
- "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.",
- "TellUsAboutYourself": "Tell us about yourself",
- "LabelYourFirstName": "Your first name:",
- "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.",
- "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.",
- "LabelWindowsService": "Windows Service",
- "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.",
- "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.",
- "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.",
- "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish</b> to view the <b>Dashboard</b>.",
- "LabelConfigureSettings": "Configure settings",
- "LabelEnableVideoImageExtraction": "Enable video image extraction",
- "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.",
- "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
- "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
- "LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
- "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
- "ButtonOk": "Ok",
- "ButtonCancel": "Cancel",
- "ButtonNew": "New",
- "HeaderSetupLibrary": "Setup your media library",
- "ButtonAddMediaFolder": "Add media folder",
- "LabelFolderType": "Folder type:",
- "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
- "ReferToMediaLibraryWiki": "Refer to the media library wiki.",
- "LabelCountry": "Country:",
- "LabelLanguage": "Language:",
- "HeaderPreferredMetadataLanguage": "Preferred metadata language:",
- "LabelSaveLocalMetadata": "Save artwork and metadata into media folders",
- "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.",
- "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet",
- "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.",
- "TabPreferences": "Preferences",
- "TabPassword": "Password",
- "TabLibraryAccess": "Library Access",
- "TabImage": "Image",
- "TabProfile": "Profile",
- "TabMetadata": "Metadata",
- "TabImages": "Images",
- "TabNotifications": "Notifications",
- "TabCollectionTitles": "Titles",
- "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons",
- "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons",
- "HeaderVideoPlaybackSettings": "Video Playback Settings",
- "HeaderPlaybackSettings": "Playback Settings",
- "LabelAudioLanguagePreference": "Audio language preference:",
- "LabelSubtitleLanguagePreference": "Subtitle language preference:",
- "OptionDefaultSubtitles": "Default",
- "OptionOnlyForcedSubtitles": "Only forced subtitles",
- "OptionAlwaysPlaySubtitles": "Always play subtitles",
- "OptionNoSubtitles": "None",
- "OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
- "OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
- "OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
- "OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
- "TabProfiles": "Profiles",
- "TabSecurity": "Security",
- "ButtonAddUser": "Add User",
- "ButtonSave": "Save",
- "ButtonResetPassword": "Reset Password",
- "LabelNewPassword": "New password:",
- "LabelNewPasswordConfirm": "New password confirm:",
- "HeaderCreatePassword": "Create Password",
- "LabelCurrentPassword": "Current password:",
- "LabelMaxParentalRating": "Maximum allowed parental rating:",
- "MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.",
- "LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.",
- "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
- "ButtonDeleteImage": "Delete Image",
- "LabelSelectUsers": "Select users:",
- "ButtonUpload": "Upload",
- "HeaderUploadNewImage": "Upload New Image",
- "LabelDropImageHere": "Drop Image Here",
- "ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG/PNG only.",
- "MessageNothingHere": "Nothing here.",
- "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
- "TabSuggested": "Suggested",
- "TabLatest": "Latest",
- "TabUpcoming": "Upcoming",
- "TabShows": "Shows",
- "TabEpisodes": "Episodes",
- "TabGenres": "Genres",
- "TabPeople": "People",
- "TabNetworks": "Networks",
- "HeaderUsers": "Users",
- "HeaderFilters": "Filters:",
- "ButtonFilter": "Filter",
- "OptionFavorite": "Favorites",
- "OptionLikes": "Likes",
- "OptionDislikes": "Dislikes",
- "OptionActors": "Actors",
- "OptionGuestStars": "Guest Stars",
- "OptionDirectors": "Directors",
- "OptionWriters": "Writers",
- "OptionProducers": "Producers",
- "HeaderResume": "Resume",
- "HeaderNextUp": "Next Up",
- "NoNextUpItemsMessage": "None found. Start watching your shows!",
- "HeaderLatestEpisodes": "Latest Episodes",
- "HeaderPersonTypes": "Person Types:",
- "TabSongs": "Songs",
- "TabAlbums": "Albums",
- "TabArtists": "Artists",
- "TabAlbumArtists": "Album Artists",
- "TabMusicVideos": "Music Videos",
- "ButtonSort": "Sort",
- "HeaderSortBy": "Sort By:",
- "HeaderSortOrder": "Sort Order:",
- "OptionPlayed": "Played",
- "OptionUnplayed": "Unplayed",
- "OptionAscending": "Ascending",
- "OptionDescending": "Descending",
- "OptionRuntime": "Runtime",
- "OptionReleaseDate": "Release Date",
- "OptionPlayCount": "Play Count",
- "OptionDatePlayed": "Date Played",
- "OptionDateAdded": "Date Added",
- "OptionAlbumArtist": "Album Artist",
- "OptionArtist": "Artist",
- "OptionAlbum": "Album",
- "OptionTrackName": "Track Name",
- "OptionCommunityRating": "Community Rating",
- "OptionNameSort": "Name",
- "OptionFolderSort": "Folders",
- "OptionBudget": "Budget",
- "OptionRevenue": "Revenue",
- "OptionPoster": "Poster",
- "OptionBackdrop": "Backdrop",
- "OptionTimeline": "Timeline",
- "OptionThumb": "Thumb",
- "OptionBanner": "Banner",
- "OptionCriticRating": "Critic Rating",
- "OptionVideoBitrate": "Video Bitrate",
- "OptionResumable": "Resumable",
- "ScheduledTasksHelp": "Click a task to adjust its schedule.",
- "ScheduledTasksTitle": "Scheduled Tasks",
- "TabMyPlugins": "My Plugins",
- "TabCatalog": "Catalog",
- "PluginsTitle": "Plugins",
- "HeaderAutomaticUpdates": "Automatic Updates",
- "HeaderNowPlaying": "Now Playing",
- "HeaderLatestAlbums": "Latest Albums",
- "HeaderLatestSongs": "Latest Songs",
- "HeaderRecentlyPlayed": "Recently Played",
- "HeaderFrequentlyPlayed": "Frequently Played",
- "DevBuildWarning": "Dev builds are the bleeding edge. Released often, these build have not been tested. The application may crash and entire features may not work at all.",
- "LabelVideoType": "Video Type:",
- "OptionBluray": "Bluray",
- "OptionDvd": "Dvd",
- "OptionIso": "Iso",
- "Option3D": "3D",
- "LabelFeatures": "Features:",
- "LabelService": "Service:",
- "LabelStatus": "Status:",
- "LabelVersion": "Version:",
- "LabelLastResult": "Last result:",
- "OptionHasSubtitles": "Subtitles",
- "OptionHasTrailer": "Trailer",
- "OptionHasThemeSong": "Theme Song",
- "OptionHasThemeVideo": "Theme Video",
- "TabMovies": "Movies",
- "TabStudios": "Studios",
- "TabTrailers": "Trailers",
- "HeaderLatestMovies": "Latest Movies",
- "HeaderLatestTrailers": "Latest Trailers",
- "OptionHasSpecialFeatures": "Special Features",
- "OptionImdbRating": "IMDb Rating",
- "OptionParentalRating": "Parental Rating",
- "OptionPremiereDate": "Premiere Date",
- "TabBasic": "Basic",
- "TabAdvanced": "Advanced",
- "HeaderStatus": "Status",
- "OptionContinuing": "Continuing",
- "OptionEnded": "Ended",
- "HeaderAirDays": "Air Days:",
- "OptionSunday": "Sunday",
- "OptionMonday": "Monday",
- "OptionTuesday": "Tuesday",
- "OptionWednesday": "Wednesday",
- "OptionThursday": "Thursday",
- "OptionFriday": "Friday",
- "OptionSaturday": "Saturday",
- "HeaderManagement": "Management:",
- "OptionMissingImdbId": "Missing IMDb Id",
- "OptionMissingTvdbId": "Missing TheTVDB Id",
- "OptionMissingOverview": "Missing Overview",
- "OptionFileMetadataYearMismatch": "File/Metadata Years Mismatched",
- "TabGeneral": "General",
- "TitleSupport": "Support",
- "TabLog": "Log",
- "TabAbout": "About",
- "TabSupporterKey": "Supporter Key",
- "TabBecomeSupporter": "Become a Supporter",
- "MediaBrowserHasCommunity": "Media Browser has a thriving community of users and contributors.",
- "CheckoutKnowledgeBase": "Check out our knowledge base to help you get the most out of Media Browser.",
- "SearchKnowledgeBase": "Search the Knowledge Base",
- "VisitTheCommunity": "Visit the Community",
- "VisitMediaBrowserWebsite": "Visit the Media Browser Web Site",
- "VisitMediaBrowserWebsiteLong": "Visit the Media Browser Web site to catch the latest news and keep up with the developer blog.",
- "OptionHideUser": "Hide this user from login screens",
- "OptionDisableUser": "Disable this user",
- "OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.",
- "HeaderAdvancedControl": "Advanced Control",
- "LabelName": "Name:",
- "OptionAllowUserToManageServer": "Allow this user to manage the server",
- "HeaderFeatureAccess": "Feature Access",
- "OptionAllowMediaPlayback": "Allow media playback",
- "OptionAllowBrowsingLiveTv": "Allow browsing of live tv",
- "OptionAllowDeleteLibraryContent": "Allow this user to delete library content",
- "OptionAllowManageLiveTv": "Allow management of live tv recordings",
- "OptionAllowRemoteControlOthers": "Allow this user to remote control other users",
- "OptionMissingTmdbId": "Missing Tmdb Id",
- "OptionIsHD": "HD",
- "OptionIsSD": "SD",
- "OptionMetascore": "Metascore",
- "ButtonSelect": "Select",
- "ButtonSearch": "Search",
- "ButtonGroupVersions": "Group Versions",
- "ButtonAddToCollection": "Add to Collection",
- "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",
- "TabTranscoding": "Transcoding",
- "TitleAdvanced": "Advanced",
- "LabelAutomaticUpdateLevel": "Automatic update level",
- "OptionRelease": "Official Release",
- "OptionBeta": "Beta",
- "OptionDev": "Dev (Unstable)",
- "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates",
- "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods, when no users are active.",
- "LabelEnableDebugLogging": "Enable debug logging",
- "LabelRunServerAtStartup": "Run server at startup",
- "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",
- "LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.",
- "LabelCachePath": "Cache path:",
- "LabelCachePathHelp": "This folder contains server cache files, such as images.",
- "LabelImagesByNamePath": "Images by name path:",
- "LabelImagesByNamePathHelp": "This folder contains actor, artist, genre and studio images.",
- "LabelMetadataPath": "Metadata path:",
- "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.",
- "LabelTranscodingTempPath": "Transcoding temporary path:",
- "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder.",
- "TabBasics": "Basics",
- "TabTV": "TV",
- "TabGames": "Games",
- "TabMusic": "Music",
- "TabOthers": "Others",
- "HeaderExtractChapterImagesFor": "Extract chapter images for:",
- "OptionMovies": "Movies",
- "OptionEpisodes": "Episodes",
- "OptionOtherVideos": "Other Videos",
- "TitleMetadata": "Metadata",
- "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv",
- "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.",
- "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
- "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
- "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
- "LabelMetadataDownloadLanguage": "Preferred download language:",
- "ButtonAutoScroll": "Auto-scroll",
- "LabelImageSavingConvention": "Image saving convention:",
- "LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
- "OptionImageSavingCompatible": "Compatible - Media Browser/Plex/Xbmc",
- "OptionImageSavingStandard": "Standard - MB2",
- "ButtonSignIn": "Sign In",
- "TitleSignIn": "Sign In",
- "HeaderPleaseSignIn": "Please sign in",
- "LabelUser": "User:",
- "LabelPassword": "Password:",
- "ButtonManualLogin": "Manual Login",
- "PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
- "TabGuide": "Guide",
- "TabChannels": "Channels",
- "TabCollections": "Collections",
- "HeaderChannels": "Channels",
- "TabRecordings": "Recordings",
- "TabScheduled": "Scheduled",
- "TabSeries": "Series",
- "TabFavorites": "Favorites",
- "TabMyLibrary": "My Library",
- "ButtonCancelRecording": "Cancel Recording",
- "HeaderPrePostPadding": "Pre/Post Padding",
- "LabelPrePaddingMinutes": "Pre-padding minutes:",
- "OptionPrePaddingRequired": "Pre-padding is required in order to record.",
- "LabelPostPaddingMinutes": "Post-padding minutes:",
- "OptionPostPaddingRequired": "Post-padding is required in order to record.",
- "HeaderWhatsOnTV": "What's On",
- "HeaderUpcomingTV": "Upcoming TV",
- "TabStatus": "Status",
- "TabSettings": "Settings",
- "ButtonRefreshGuideData": "Refresh Guide Data",
- "OptionPriority": "Priority",
- "OptionRecordOnAllChannels": "Record program on all channels",
- "OptionRecordAnytime": "Record program at any time",
- "OptionRecordOnlyNewEpisodes": "Record only new episodes",
- "HeaderDays": "Days",
- "HeaderActiveRecordings": "Active Recordings",
- "HeaderLatestRecordings": "Latest Recordings",
- "HeaderAllRecordings": "All Recordings",
- "ButtonPlay": "Play",
- "ButtonEdit": "Edit",
- "ButtonRecord": "Record",
- "ButtonDelete": "Delete",
- "ButtonRemove": "Remove",
- "OptionRecordSeries": "Record Series",
- "HeaderDetails": "Details",
- "ButtonCancelRecording": "Cancel Recording",
- "TitleLiveTV": "Live TV",
- "LabelNumberOfGuideDays": "Number of days of guide data to download:",
- "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.",
- "LabelActiveService": "Active Service:",
- "LabelActiveServiceHelp": "Multiple tv plugins can be installed but only one can be active at a time.",
- "OptionAutomatic": "Auto",
- "LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
- "LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
- "LabelCustomizeOptionsPerMediaType": "Customize for media type:",
- "OptionDownloadThumbImage": "Thumb",
- "OptionDownloadMenuImage": "Menu",
- "OptionDownloadLogoImage": "Logo",
- "OptionDownloadBoxImage": "Box",
- "OptionDownloadDiscImage": "Disc",
- "OptionDownloadBannerImage": "Banner",
- "OptionDownloadBackImage": "Back",
- "OptionDownloadArtImage": "Art",
- "OptionDownloadPrimaryImage": "Primary",
- "HeaderFetchImages": "Fetch Images:",
- "HeaderImageSettings": "Image Settings",
- "TabOther": "Other",
- "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
- "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
- "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
- "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:",
- "ButtonAddScheduledTaskTrigger": "Add Task Trigger",
- "HeaderAddScheduledTaskTrigger": "Add Task Trigger",
- "ButtonAdd": "Add",
- "LabelTriggerType": "Trigger Type:",
- "OptionDaily": "Daily",
- "OptionWeekly": "Weekly",
- "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:",
- "HeaderTvTuners": "Tuners",
- "HeaderGallery": "Gallery",
- "HeaderLatestGames": "Latest Games",
- "HeaderRecentlyPlayedGames": "Recently Played Games",
- "TabGameSystems": "Game Systems",
- "TitleMediaLibrary": "Media Library",
- "TabFolders": "Folders",
- "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",
- "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",
- "ButtonSplitVersionsApart": "Split Versions Apart",
- "ButtonPlayTrailer": "Trailer",
- "LabelMissing": "Missing",
- "LabelOffline": "Offline",
- "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",
- "HeaderTo": "To",
- "LabelFrom": "From:",
- "LabelFromHelp": "Example: D:\\Movies (on the server)",
- "LabelTo": "To:",
- "LabelToHelp": "Example: \\\\MyServer\\Movies (a path clients can access)",
- "ButtonAddPathSubstitution": "Add Substitution",
- "OptionSpecialEpisode": "Specials",
- "OptionMissingEpisode": "Missing Episodes",
- "OptionUnairedEpisode": "Unaired Episodes",
- "OptionEpisodeSortName": "Episode Sort Name",
- "OptionSeriesSortName": "Series Name",
- "OptionTvdbRating": "Tvdb Rating",
- "HeaderTranscodingQualityPreference": "Transcoding Quality Preference:",
- "OptionAutomaticTranscodingHelp": "The server will decide quality and speed",
- "OptionHighSpeedTranscodingHelp": "Lower quality, but faster encoding",
- "OptionHighQualityTranscodingHelp": "Higher quality, but slower encoding",
- "OptionMaxQualityTranscodingHelp": "Best quality with slower encoding and high CPU usage",
- "OptionHighSpeedTranscoding": "Higher speed",
- "OptionHighQualityTranscoding": "Higher quality",
- "OptionMaxQualityTranscoding": "Max quality",
- "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging",
- "OptionEnableDebugTranscodingLoggingHelp": "This will create very large log files and is only recommended as needed for troubleshooting purposes.",
- "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging",
- "OptionUpscaling": "Allow clients to request upscaled video",
- "OptionUpscalingHelp": "In some cases this will result in improved video quality but will increase CPU usage.",
- "EditCollectionItemsHelp": "Add or remove any movies, series, albums, books or games you wish to group within this collection.",
- "HeaderAddTitles": "Add Titles",
- "LabelEnableDlnaPlayTo": "Enable DLNA Play To",
- "LabelEnableDlnaPlayToHelp": "Media Browser can detect devices within your network and offer the ability to remote control them.",
- "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging",
- "LabelEnableDlnaDebugLoggingHelp": "This will create large log files and should only be used as needed for troubleshooting purposes.",
- "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)",
- "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Media Browser.",
- "HeaderCustomDlnaProfiles": "Custom Profiles",
- "HeaderSystemDlnaProfiles": "System Profiles",
- "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.",
- "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.",
- "TitleDashboard": "Dashboard",
- "TabHome": "Home",
- "TabInfo": "Info",
- "HeaderLinks": "Links",
- "HeaderSystemPaths": "System Paths",
- "LinkCommunity": "Community",
- "LinkGithub": "Github",
- "LinkApiDocumentation": "Api Documentation",
- "LabelFriendlyServerName": "Friendly server name:",
- "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.",
- "LabelPreferredDisplayLanguage": "Preferred display language",
- "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.",
- "LabelReadHowYouCanContribute": "Read about how you can contribute.",
- "HeaderNewCollection": "New Collection",
- "HeaderAddToCollection": "Add to Collection",
- "ButtonSubmit": "Submit",
- "NewCollectionNameExample": "Example: Star Wars Collection",
- "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata",
- "ButtonCreate": "Create",
- "LabelHttpServerPortNumber": "Http server port number:",
- "LabelWebSocketPortNumber": "Web socket port number:",
- "LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
- "LabelEnableAutomaticPortHelp": "UPnP allows automated router configuration for remote access. This may not work with some router models.",
- "LabelExternalDDNS": "External DDNS:",
- "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.",
- "TabResume": "Resume",
- "TabWeather": "Weather",
- "TitleAppSettings": "App Settings",
- "LabelMinResumePercentage": "Min resume percentage:",
- "LabelMaxResumePercentage": "Max resume percentage:",
- "LabelMinResumeDuration": "Min resume duration (seconds):",
- "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time",
- "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time",
- "LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable",
- "TitleAutoOrganize": "Auto-Organize",
- "TabActivityLog": "Activity Log",
- "HeaderName": "Name",
- "HeaderDate": "Date",
- "HeaderSource": "Source",
- "HeaderStatus": "Status",
- "HeaderDestination": "Destination",
- "HeaderProgram": "Program",
- "HeaderClients": "Clients",
- "LabelCompleted": "Completed",
- "LabelFailed": "Failed",
- "LabelSkipped": "Skipped",
- "HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeries": "Series:",
- "LabelSeasonNumber": "Season number:",
- "LabelEpisodeNumber": "Episode number:",
- "LabelEndingEpisodeNumber": "Ending episode number:",
- "LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
- "HeaderSupportTheTeam": "Support the Media Browser Team",
- "LabelSupportAmount": "Amount (USD)",
- "HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.",
- "ButtonEnterSupporterKey": "Enter supporter key",
- "DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.",
- "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.",
- "AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.",
- "OptionEnableEpisodeOrganization": "Enable new episode organization",
- "LabelWatchFolder": "Watch folder:",
- "LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.",
- "ButtonViewScheduledTasks": "View scheduled tasks",
- "LabelMinFileSizeForOrganize": "Minimum file size (MB):",
- "LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.",
- "LabelSeasonFolderPattern": "Season folder pattern:",
- "LabelSeasonZeroFolderName": "Season zero folder name:",
- "HeaderEpisodeFilePattern": "Episode file pattern",
- "LabelEpisodePattern": "Episode pattern:",
- "LabelMultiEpisodePattern": "Multi-Episode pattern:",
- "HeaderSupportedPatterns": "Supported Patterns",
- "HeaderTerm": "Term",
- "HeaderPattern": "Pattern",
- "HeaderResult": "Result",
- "LabelDeleteEmptyFolders": "Delete empty folders after organizing",
- "LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.",
- "LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:",
- "LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt",
- "OptionOverwriteExistingEpisodes": "Overwrite existing episodes",
- "LabelTransferMethod": "Transfer method",
- "OptionCopy": "Copy",
- "OptionMove": "Move",
- "LabelTransferMethodHelp": "Copy or move files from the watch folder",
- "HeaderLatestNews": "Latest News",
- "HeaderHelpImproveMediaBrowser": "Help Improve Media Browser",
- "HeaderRunningTasks": "Running Tasks",
- "HeaderActiveDevices": "Active Devices",
- "HeaderPendingInstallations": "Pending Installations",
- "HeaerServerInformation": "Server Information",
- "ButtonRestartNow": "Restart Now",
- "ButtonRestart": "Restart",
- "ButtonShutdown": "Shutdown",
- "ButtonUpdateNow": "Update Now",
- "PleaseUpdateManually": "Please shutdown the server and update manually.",
- "NewServerVersionAvailable": "A new version of Media Browser Server is available!",
- "ServerUpToDate": "Media Browser Server is up to date",
- "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.",
- "LabelComponentsUpdated": "The following components have been installed or updated:",
- "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.",
- "LabelDownMixAudioScale": "Audio boost when downmixing:",
- "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.",
- "ButtonLinkKeys": "Link Keys",
- "LabelOldSupporterKey": "Old supporter key",
- "LabelNewSupporterKey": "New supporter key",
- "HeaderMultipleKeyLinking": "Multiple Key Linking",
- "MultipleKeyLinkingHelp": "If you have more than one supporter key, use this form to link the old key's registrations with your new one.",
- "LabelCurrentEmailAddress": "Current email address",
- "LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.",
- "HeaderForgotKey": "Forgot Key",
- "LabelEmailAddress": "Email address",
- "LabelSupporterEmailAddress": "The email address that was used to purchase the key.",
- "ButtonRetrieveKey": "Retrieve Key",
- "LabelSupporterKey": "Supporter Key (paste from email)",
- "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
- "MessageInvalidKey": "Supporter key is missing or invalid.",
- "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
- "HeaderDisplaySettings": "Display Settings",
- "TabPlayTo": "Play To",
- "LabelEnableDlnaServer": "Enable Dlna server",
- "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Media Browser content.",
- "LabelEnableBlastAliveMessages": "Blast alive messages",
- "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.",
- "LabelBlastMessageInterval": "Alive message interval (seconds)",
- "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.",
- "LabelDefaultUser": "Default user:",
- "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.",
- "TitleDlna": "DLNA",
- "TitleChannels": "Channels",
- "HeaderServerSettings": "Server Settings",
- "LabelWeatherDisplayLocation": "Weather display location:",
- "LabelWeatherDisplayLocationHelp": "US zip code / City, State, Country / City, Country",
- "LabelWeatherDisplayUnit": "Weather display unit:",
- "OptionCelsius": "Celsius",
- "OptionFahrenheit": "Fahrenheit",
- "HeaderRequireManualLogin": "Require manual username entry for:",
- "HeaderRequireManualLoginHelp": "When disabled clients may present a login screen with a visual selection of users.",
- "OptionOtherApps": "Other apps",
- "OptionMobileApps": "Mobile apps",
- "HeaderNotificationList": "Click on a notification to configure it's sending options.",
- "NotificationOptionApplicationUpdateAvailable": "Application update available",
- "NotificationOptionApplicationUpdateInstalled": "Application update installed",
- "NotificationOptionPluginUpdateInstalled": "Plugin update installed",
- "NotificationOptionPluginInstalled": "Plugin installed",
- "NotificationOptionPluginUninstalled": "Plugin uninstalled",
- "NotificationOptionVideoPlayback": "Video playback started",
- "NotificationOptionAudioPlayback": "Audio playback started",
- "NotificationOptionGamePlayback": "Game playback started",
- "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
- "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
- "NotificationOptionGamePlaybackStopped": "Game playback stopped",
- "NotificationOptionTaskFailed": "Scheduled task failure",
- "NotificationOptionInstallationFailed": "Installation failure",
- "NotificationOptionNewLibraryContent": "New content added",
- "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
- "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.",
- "NotificationOptionServerRestartRequired": "Server restart required",
- "LabelNotificationEnabled": "Enable this notification",
- "LabelMonitorUsers": "Monitor activity from:",
- "LabelSendNotificationToUsers": "Send the notification to:",
- "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.",
- "LabelUseNotificationServices": "Use the following services:",
- "CategoryUser": "User",
- "CategorySystem": "System",
- "CategoryApplication": "Application",
- "CategoryPlugin": "Plugin",
- "LabelMessageTitle": "Message title:",
- "LabelAvailableTokens": "Available tokens:",
- "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.",
- "OptionAllUsers": "All users",
- "OptionAdminUsers": "Administrators",
- "OptionCustomUsers": "Custom",
- "ButtonArrowUp": "Up",
- "ButtonArrowDown": "Down",
- "ButtonArrowLeft": "Left",
- "ButtonArrowRight": "Right",
- "ButtonBack": "Back",
- "ButtonInfo": "Info",
- "ButtonOsd": "On screen display",
- "ButtonPageUp": "Page Up",
- "ButtonPageDown": "Page Down",
- "PageAbbreviation": "PG",
- "ButtonHome": "Home",
- "ButtonSearch": "Search",
- "ButtonSettings": "Settings",
- "ButtonTakeScreenshot": "Capture Screenshot",
- "ButtonLetterUp": "Letter Up",
- "ButtonLetterDown": "Letter Down",
- "PageButtonAbbreviation": "PG",
- "LetterButtonAbbreviation": "A",
- "TabNowPlaying": "Now Playing",
- "TabNavigation": "Navigation",
- "TabControls": "Controls",
- "ButtonFullscreen": "Toggle fullscreen",
- "ButtonScenes": "Scenes",
- "ButtonSubtitles": "Subtitles",
- "ButtonAudioTracks": "Audio tracks",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "ButtonStop": "Stop",
- "ButtonPlay": "Play",
- "ButtonPause": "Pause",
- "LabelGroupMoviesIntoCollections": "Group movies into collections",
- "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.",
- "NotificationOptionPluginError": "Plugin failure",
- "ButtonVolumeUp": "Volume up",
- "ButtonVolumeDown": "Volume down",
- "ButtonMute": "Mute",
- "HeaderLatestMedia": "Latest Media",
- "OptionNoSubtitles": "No Subtitles",
- "OptionSpecialFeatures": "Special Features",
- "HeaderCollections": "Collections",
- "HeaderChannels": "Channels",
- "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
- "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
- "HeaderResponseProfile": "Response Profile",
- "LabelType": "Type:",
- "LabelProfileContainer": "Container:",
- "LabelProfileVideoCodecs": "Video codecs:",
- "LabelProfileAudioCodecs": "Audio codecs:",
- "LabelProfileCodecs": "Codecs:",
- "HeaderDirectPlayProfile": "Direct Play Profile",
- "HeaderTranscodingProfile": "Transcoding Profile",
- "HeaderCodecProfile": "Codec Profile",
- "HeaderCodecProfileHelp": "Define additional conditions that must be met in order for a codec to be direct played.",
- "HeaderContainerProfile": "Container Profile",
- "HeaderContainerProfileHelp": "Define additional conditions that must be met in order for a file to be direct played.",
- "OptionProfileVideo": "Video",
- "OptionProfileAudio": "Audio",
- "OptionProfileVideoAudio": "Video Audio",
- "OptionProfilePhoto": "Photo",
- "LabelUserLibrary": "User library:",
- "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.",
- "OptionPlainStorageFolders": "Display all folders as plain storage folders",
- "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".",
- "OptionPlainVideoItems": "Display all videos as plain video items",
- "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".",
- "LabelSupportedMediaTypes": "Supported Media Types:",
- "TabIdentification": "Identification",
- "TabDirectPlay": "Direct Play",
- "TabContainers": "Containers",
- "TabCodecs": "Codecs",
- "TabResponses": "Responses",
- "HeaderProfileInformation": "Profile Information",
- "LabelEmbedAlbumArtDidl": "Embed album art in Didl",
- "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.",
- "LabelAlbumArtPN": "Album art PN:",
- "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.",
- "LabelAlbumArtMaxWidth": "Album art max width:",
- "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
- "LabelAlbumArtMaxHeight": "Album art max height:",
- "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
- "LabelIconMaxWidth": "Icon max width:",
- "LabelIconMaxWidthHelp": "Max resolution of icons exposed via upnp:icon.",
- "LabelIconMaxHeight": "Icon max height:",
- "LabelIconMaxHeightHelp": "Max resolution of icons exposed via upnp:icon.",
- "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.",
- "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
- "LabelMaxBitrate": "Max bitrate:",
- "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
- "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
- "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
- "LabelFriendlyName": "Friendly name",
- "LabelManufacturer": "Manufacturer",
- "LabelManufacturerUrl": "Manufacturer url",
- "LabelModelName": "Model name",
- "LabelModelNumber": "Model number",
- "LabelModelDescription": "Model description",
- "LabelModelUrl": "Model url",
- "LabelSerialNumber": "Serial number",
- "LabelDeviceDescription": "Device description",
- "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.",
- "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.",
- "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.",
- "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.",
- "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.",
- "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.",
- "LabelXDlnaCap": "X-Dlna cap:",
- "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.",
- "LabelXDlnaDoc": "X-Dlna doc:",
- "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.",
- "LabelSonyAggregationFlags": "Sony aggregation flags:",
- "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.",
- "LabelTranscodingContainer": "Container:",
- "LabelTranscodingVideoCodec": "Video codec:",
- "LabelTranscodingVideoProfile": "Video profile:",
- "LabelTranscodingAudioCodec": "Audio codec:",
- "OptionEnableM2tsMode": "Enable M2ts mode",
- "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.",
- "OptionEstimateContentLength": "Estimate content length when transcoding",
- "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding",
- "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.",
- "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
- "HeaderDownloadSubtitlesFor": "Download subtitles for:",
- "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.",
- "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
- "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "TabSubtitles": "Subtitles",
- "TabChapters": "Chapters",
- "HeaderDownloadChaptersFor": "Download chapter names for:",
- "LabelOpenSubtitlesUsername": "Open Subtitles username:",
- "LabelOpenSubtitlesPassword": "Open Subtitles password:",
- "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.",
- "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
- "LabelSubtitlePlaybackMode": "Subtitle mode:",
- "LabelDownloadLanguages": "Download languages:",
- "ButtonRegister": "Register",
- "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
- "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
- "HeaderSendMessage": "Send Message",
- "ButtonSend": "Send",
- "LabelMessageText": "Message text:",
- "LabelMessageTitle": "Message title:",
- "MessageNoAvailablePlugins": "No available plugins.",
- "LabelDisplayPluginsFor": "Display plugins for:",
- "PluginTabMediaBrowserClassic": "MB Classic",
- "PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
- "ValueSeriesNamePeriod": "Series.name",
- "ValueSeriesNameUnderscore": "Series_name",
- "ValueEpisodeNamePeriod": "Episode.name",
- "ValueEpisodeNameUnderscore": "Episode_name",
- "LabelSeasonNumber": "Season number",
- "LabelEpisodeNumber": "Episode number",
- "LabelEndingEpisodeNumber": "Ending episode number",
- "HeaderTypeText": "Enter Text",
- "LabelTypeText": "Text",
- "HeaderSearchForSubtitles": "Search for Subtitles",
- "MessageNoSubtitleSearchResultsFound": "No search results founds.",
- "TabDisplay": "Display",
- "TabLanguages": "Languages",
- "TabWebClient": "Web Client",
- "LabelEnableThemeSongs": "Enable theme songs",
- "LabelEnableBackdrops": "Enable backdrops",
- "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.",
- "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.",
- "HeaderHomePage": "Home Page",
- "HeaderSettingsForThisDevice": "Settings for This Device",
- "OptionAuto": "Auto",
- "OptionYes": "Yes",
- "OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
- "OptionResumablemedia": "Resume",
- "OptionLatestMedia": "Latest media",
- "OptionLatestChannelMedia": "Latest channel items",
- "HeaderLatestChannelItems": "Latest Channel Items",
- "OptionNone": "None",
- "HeaderLiveTv": "Live TV",
- "HeaderReports": "Reports",
- "HeaderMetadataManager": "Metadata Manager",
- "HeaderPreferences": "Preferences",
- "MessageLoadingChannels": "Loading channel content...",
- "ButtonMarkRead": "Mark Read",
- "OptionDefaultSort": "Default",
- "OptionCommunityMostWatchedSort": "Most Watched",
- "TabNextUp": "Next Up",
- "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 New button to start creating Collections.",
- "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
- "ButtonDismiss": "Dismiss",
- "MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
- "ButtonEditOtherUserPreferences": "Edit this user's personal preferences.",
- "LabelChannelStreamQuality": "Preferred internet stream quality:",
- "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.",
- "OptionBestAvailableStreamQuality": "Best available",
- "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:",
- "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.",
- "LabelChannelDownloadPath": "Channel content download path:",
- "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.",
- "LabelChannelDownloadAge": "Delete content after: (days)",
- "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.",
- "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.",
- "LabelSelectCollection": "Select collection:",
- "ViewTypeMovies": "Movies",
- "ViewTypeTvShows": "TV",
- "ViewTypeGames": "Games",
- "ViewTypeMusic": "Music",
- "ViewTypeBoxSets": "Collections",
- "ViewTypeChannels": "Channels",
- "ViewTypeLiveTV": "Live TV",
- "HeaderOtherDisplaySettings": "Display Settings",
- "HeaderMyViews": "My Views",
- "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",
- "TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
-} \ No newline at end of file
+ "LabelVisitCommunity": "Visit Community",
+ "LabelGithubWiki": "Github Wiki",
+ "LabelSwagger": "Swagger",
+ "LabelStandard": "Standard",
+ "LabelViewApiDocumentation": "View Api Documentation",
+ "LabelBrowseLibrary": "Browse Library",
+ "LabelConfigureMediaBrowser": "Configure Media Browser",
+ "LabelOpenLibraryViewer": "Open Library Viewer",
+ "LabelRestartServer": "Restart Server",
+ "LabelShowLogWindow": "Show Log Window",
+ "LabelPrevious": "Previous",
+ "LabelFinish": "Finish",
+ "LabelNext": "Next",
+ "LabelYoureDone": "You're Done!",
+ "WelcomeToMediaBrowser": "Welcome to Media Browser!",
+ "TitleMediaBrowser": "Media Browser",
+ "ThisWizardWillGuideYou": "This wizard will help guide you through the setup process. To begin, please select your preferred language.",
+ "TellUsAboutYourself": "Tell us about yourself",
+ "LabelYourFirstName": "Your first name:",
+ "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.",
+ "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.",
+ "LabelWindowsService": "Windows Service",
+ "AWindowsServiceHasBeenInstalled": "A Windows Service has been installed.",
+ "WindowsServiceIntro1": "Media Browser Server normally runs as a desktop application with a tray icon, but if you prefer to run it as a background service, it can be started from the windows services control panel instead.",
+ "WindowsServiceIntro2": "If using the windows service, please note that it cannot be run at the same time as the tray icon, so you'll need to exit the tray in order to run the service. The service will also need to be configured with administrative privileges via the control panel. Please note that at this time the service is unable to self-update, so new versions will require manual interaction.",
+ "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish</b> to view the <b>Dashboard</b>.",
+ "LabelConfigureSettings": "Configure settings",
+ "LabelEnableVideoImageExtraction": "Enable video image extraction",
+ "VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.",
+ "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
+ "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
+ "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "ButtonOk": "Ok",
+ "ButtonCancel": "Cancel",
+ "ButtonNew": "New",
+ "HeaderSetupLibrary": "Setup your media library",
+ "ButtonAddMediaFolder": "Add media folder",
+ "LabelFolderType": "Folder type:",
+ "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
+ "ReferToMediaLibraryWiki": "Refer to the media library wiki.",
+ "LabelCountry": "Country:",
+ "LabelLanguage": "Language:",
+ "HeaderPreferredMetadataLanguage": "Preferred metadata language:",
+ "LabelSaveLocalMetadata": "Save artwork and metadata into media folders",
+ "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.",
+ "LabelDownloadInternetMetadata": "Download artwork and metadata from the internet",
+ "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.",
+ "TabPreferences": "Preferences",
+ "TabPassword": "Password",
+ "TabLibraryAccess": "Library Access",
+ "TabImage": "Image",
+ "TabProfile": "Profile",
+ "TabMetadata": "Metadata",
+ "TabImages": "Images",
+ "TabNotifications": "Notifications",
+ "TabCollectionTitles": "Titles",
+ "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons",
+ "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons",
+ "HeaderVideoPlaybackSettings": "Video Playback Settings",
+ "HeaderPlaybackSettings": "Playback Settings",
+ "LabelAudioLanguagePreference": "Audio language preference:",
+ "LabelSubtitleLanguagePreference": "Subtitle language preference:",
+ "OptionDefaultSubtitles": "Default",
+ "OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "OptionNoSubtitles": "None",
+ "OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "TabProfiles": "Profiles",
+ "TabSecurity": "Security",
+ "ButtonAddUser": "Add User",
+ "ButtonSave": "Save",
+ "ButtonResetPassword": "Reset Password",
+ "LabelNewPassword": "New password:",
+ "LabelNewPasswordConfirm": "New password confirm:",
+ "HeaderCreatePassword": "Create Password",
+ "LabelCurrentPassword": "Current password:",
+ "LabelMaxParentalRating": "Maximum allowed parental rating:",
+ "MaxParentalRatingHelp": "Content with a higher rating will be hidden from this user.",
+ "LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.",
+ "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "ButtonDeleteImage": "Delete Image",
+ "LabelSelectUsers": "Select users:",
+ "ButtonUpload": "Upload",
+ "HeaderUploadNewImage": "Upload New Image",
+ "LabelDropImageHere": "Drop Image Here",
+ "ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG/PNG only.",
+ "MessageNothingHere": "Nothing here.",
+ "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
+ "TabSuggested": "Suggested",
+ "TabLatest": "Latest",
+ "TabUpcoming": "Upcoming",
+ "TabShows": "Shows",
+ "TabEpisodes": "Episodes",
+ "TabGenres": "Genres",
+ "TabPeople": "People",
+ "TabNetworks": "Networks",
+ "HeaderUsers": "Users",
+ "HeaderFilters": "Filters:",
+ "ButtonFilter": "Filter",
+ "OptionFavorite": "Favorites",
+ "OptionLikes": "Likes",
+ "OptionDislikes": "Dislikes",
+ "OptionActors": "Actors",
+ "OptionGuestStars": "Guest Stars",
+ "OptionDirectors": "Directors",
+ "OptionWriters": "Writers",
+ "OptionProducers": "Producers",
+ "HeaderResume": "Resume",
+ "HeaderNextUp": "Next Up",
+ "NoNextUpItemsMessage": "None found. Start watching your shows!",
+ "HeaderLatestEpisodes": "Latest Episodes",
+ "HeaderPersonTypes": "Person Types:",
+ "TabSongs": "Songs",
+ "TabAlbums": "Albums",
+ "TabArtists": "Artists",
+ "TabAlbumArtists": "Album Artists",
+ "TabMusicVideos": "Music Videos",
+ "ButtonSort": "Sort",
+ "HeaderSortBy": "Sort By:",
+ "HeaderSortOrder": "Sort Order:",
+ "OptionPlayed": "Played",
+ "OptionUnplayed": "Unplayed",
+ "OptionAscending": "Ascending",
+ "OptionDescending": "Descending",
+ "OptionRuntime": "Runtime",
+ "OptionReleaseDate": "Release Date",
+ "OptionPlayCount": "Play Count",
+ "OptionDatePlayed": "Date Played",
+ "OptionDateAdded": "Date Added",
+ "OptionAlbumArtist": "Album Artist",
+ "OptionArtist": "Artist",
+ "OptionAlbum": "Album",
+ "OptionTrackName": "Track Name",
+ "OptionCommunityRating": "Community Rating",
+ "OptionNameSort": "Name",
+ "OptionFolderSort": "Folders",
+ "OptionBudget": "Budget",
+ "OptionRevenue": "Revenue",
+ "OptionPoster": "Poster",
+ "OptionBackdrop": "Backdrop",
+ "OptionTimeline": "Timeline",
+ "OptionThumb": "Thumb",
+ "OptionBanner": "Banner",
+ "OptionCriticRating": "Critic Rating",
+ "OptionVideoBitrate": "Video Bitrate",
+ "OptionResumable": "Resumable",
+ "ScheduledTasksHelp": "Click a task to adjust its schedule.",
+ "ScheduledTasksTitle": "Scheduled Tasks",
+ "TabMyPlugins": "My Plugins",
+ "TabCatalog": "Catalog",
+ "PluginsTitle": "Plugins",
+ "HeaderAutomaticUpdates": "Automatic Updates",
+ "HeaderNowPlaying": "Now Playing",
+ "HeaderLatestAlbums": "Latest Albums",
+ "HeaderLatestSongs": "Latest Songs",
+ "HeaderRecentlyPlayed": "Recently Played",
+ "HeaderFrequentlyPlayed": "Frequently Played",
+ "DevBuildWarning": "Dev builds are the bleeding edge. Released often, these build have not been tested. The application may crash and entire features may not work at all.",
+ "LabelVideoType": "Video Type:",
+ "OptionBluray": "Bluray",
+ "OptionDvd": "Dvd",
+ "OptionIso": "Iso",
+ "Option3D": "3D",
+ "LabelFeatures": "Features:",
+ "LabelService": "Service:",
+ "LabelStatus": "Status:",
+ "LabelVersion": "Version:",
+ "LabelLastResult": "Last result:",
+ "OptionHasSubtitles": "Subtitles",
+ "OptionHasTrailer": "Trailer",
+ "OptionHasThemeSong": "Theme Song",
+ "OptionHasThemeVideo": "Theme Video",
+ "TabMovies": "Movies",
+ "TabStudios": "Studios",
+ "TabTrailers": "Trailers",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
+ "HeaderLatestMovies": "Latest Movies",
+ "HeaderLatestTrailers": "Latest Trailers",
+ "OptionHasSpecialFeatures": "Special Features",
+ "OptionImdbRating": "IMDb Rating",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPremiereDate": "Premiere Date",
+ "TabBasic": "Basic",
+ "TabAdvanced": "Advanced",
+ "HeaderStatus": "Status",
+ "OptionContinuing": "Continuing",
+ "OptionEnded": "Ended",
+ "HeaderAirDays": "Air Days",
+ "OptionSunday": "Sunday",
+ "OptionMonday": "Monday",
+ "OptionTuesday": "Tuesday",
+ "OptionWednesday": "Wednesday",
+ "OptionThursday": "Thursday",
+ "OptionFriday": "Friday",
+ "OptionSaturday": "Saturday",
+ "HeaderManagement": "Management",
+ "LabelManagement": "Management:",
+ "OptionMissingImdbId": "Missing IMDb Id",
+ "OptionMissingTvdbId": "Missing TheTVDB Id",
+ "OptionMissingOverview": "Missing Overview",
+ "OptionFileMetadataYearMismatch": "File/Metadata Years Mismatched",
+ "TabGeneral": "General",
+ "TitleSupport": "Support",
+ "TabLog": "Log",
+ "TabAbout": "About",
+ "TabSupporterKey": "Supporter Key",
+ "TabBecomeSupporter": "Become a Supporter",
+ "MediaBrowserHasCommunity": "Media Browser has a thriving community of users and contributors.",
+ "CheckoutKnowledgeBase": "Check out our knowledge base to help you get the most out of Media Browser.",
+ "SearchKnowledgeBase": "Search the Knowledge Base",
+ "VisitTheCommunity": "Visit the Community",
+ "VisitMediaBrowserWebsite": "Visit the Media Browser Web Site",
+ "VisitMediaBrowserWebsiteLong": "Visit the Media Browser Web site to catch the latest news and keep up with the developer blog.",
+ "OptionHideUser": "Hide this user from login screens",
+ "OptionDisableUser": "Disable this user",
+ "OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.",
+ "HeaderAdvancedControl": "Advanced Control",
+ "LabelName": "Name:",
+ "OptionAllowUserToManageServer": "Allow this user to manage the server",
+ "HeaderFeatureAccess": "Feature Access",
+ "OptionAllowMediaPlayback": "Allow media playback",
+ "OptionAllowBrowsingLiveTv": "Allow browsing of live tv",
+ "OptionAllowDeleteLibraryContent": "Allow this user to delete library content",
+ "OptionAllowManageLiveTv": "Allow management of live tv recordings",
+ "OptionAllowRemoteControlOthers": "Allow this user to remote control other users",
+ "OptionMissingTmdbId": "Missing Tmdb Id",
+ "OptionIsHD": "HD",
+ "OptionIsSD": "SD",
+ "OptionMetascore": "Metascore",
+ "ButtonSelect": "Select",
+ "ButtonGroupVersions": "Group Versions",
+ "ButtonAddToCollection": "Add to Collection",
+ "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",
+ "TabTranscoding": "Transcoding",
+ "TitleAdvanced": "Advanced",
+ "LabelAutomaticUpdateLevel": "Automatic update level",
+ "OptionRelease": "Official Release",
+ "OptionBeta": "Beta",
+ "OptionDev": "Dev (Unstable)",
+ "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates",
+ "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods, when no users are active.",
+ "LabelEnableDebugLogging": "Enable debug logging",
+ "LabelRunServerAtStartup": "Run server at startup",
+ "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",
+ "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.",
+ "LabelImagesByNamePath": "Images by name path:",
+ "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.",
+ "LabelMetadataPath": "Metadata path:",
+ "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",
+ "HeaderExtractChapterImagesFor": "Extract chapter images for:",
+ "OptionMovies": "Movies",
+ "OptionEpisodes": "Episodes",
+ "OptionOtherVideos": "Other Videos",
+ "TitleMetadata": "Metadata",
+ "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv",
+ "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.",
+ "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
+ "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
+ "ExtractChapterImagesHelp": "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 when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelMetadataDownloadLanguage": "Preferred download language:",
+ "ButtonAutoScroll": "Auto-scroll",
+ "LabelImageSavingConvention": "Image saving convention:",
+ "LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
+ "OptionImageSavingCompatible": "Compatible - Media Browser/Xbmc/Plex",
+ "OptionImageSavingStandard": "Standard - MB2",
+ "ButtonSignIn": "Sign In",
+ "TitleSignIn": "Sign In",
+ "HeaderPleaseSignIn": "Please sign in",
+ "LabelUser": "User:",
+ "LabelPassword": "Password:",
+ "ButtonManualLogin": "Manual Login",
+ "PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
+ "TabGuide": "Guide",
+ "TabChannels": "Channels",
+ "TabCollections": "Collections",
+ "HeaderChannels": "Channels",
+ "TabRecordings": "Recordings",
+ "TabScheduled": "Scheduled",
+ "TabSeries": "Series",
+ "TabFavorites": "Favorites",
+ "TabMyLibrary": "My Library",
+ "ButtonCancelRecording": "Cancel Recording",
+ "HeaderPrePostPadding": "Pre/Post Padding",
+ "LabelPrePaddingMinutes": "Pre-padding minutes:",
+ "OptionPrePaddingRequired": "Pre-padding is required in order to record.",
+ "LabelPostPaddingMinutes": "Post-padding minutes:",
+ "OptionPostPaddingRequired": "Post-padding is required in order to record.",
+ "HeaderWhatsOnTV": "What's On",
+ "HeaderUpcomingTV": "Upcoming TV",
+ "TabStatus": "Status",
+ "TabSettings": "Settings",
+ "ButtonRefreshGuideData": "Refresh Guide Data",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
+ "OptionPriority": "Priority",
+ "OptionRecordOnAllChannels": "Record program on all channels",
+ "OptionRecordAnytime": "Record program at any time",
+ "OptionRecordOnlyNewEpisodes": "Record only new episodes",
+ "HeaderDays": "Days",
+ "HeaderActiveRecordings": "Active Recordings",
+ "HeaderLatestRecordings": "Latest Recordings",
+ "HeaderAllRecordings": "All Recordings",
+ "ButtonPlay": "Play",
+ "ButtonEdit": "Edit",
+ "ButtonRecord": "Record",
+ "ButtonDelete": "Delete",
+ "ButtonRemove": "Remove",
+ "OptionRecordSeries": "Record Series",
+ "HeaderDetails": "Details",
+ "ButtonCancelRecording": "Cancel Recording",
+ "TitleLiveTV": "Live TV",
+ "LabelNumberOfGuideDays": "Number of days of guide data to download:",
+ "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.",
+ "LabelActiveService": "Active Service:",
+ "LabelActiveServiceHelp": "Multiple tv plugins can be installed but only one can be active at a time.",
+ "OptionAutomatic": "Auto",
+ "LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
+ "LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
+ "LabelCustomizeOptionsPerMediaType": "Customize for media type:",
+ "OptionDownloadThumbImage": "Thumb",
+ "OptionDownloadMenuImage": "Menu",
+ "OptionDownloadLogoImage": "Logo",
+ "OptionDownloadBoxImage": "Box",
+ "OptionDownloadDiscImage": "Disc",
+ "OptionDownloadBannerImage": "Banner",
+ "OptionDownloadBackImage": "Back",
+ "OptionDownloadArtImage": "Art",
+ "OptionDownloadPrimaryImage": "Primary",
+ "HeaderFetchImages": "Fetch Images:",
+ "HeaderImageSettings": "Image Settings",
+ "TabOther": "Other",
+ "LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
+ "LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
+ "LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
+ "LabelMinScreenshotDownloadWidth": "Minimum screenshot download width:",
+ "ButtonAddScheduledTaskTrigger": "Add Task Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Task Trigger",
+ "ButtonAdd": "Add",
+ "LabelTriggerType": "Trigger Type:",
+ "OptionDaily": "Daily",
+ "OptionWeekly": "Weekly",
+ "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:",
+ "HeaderTvTuners": "Tuners",
+ "HeaderGallery": "Gallery",
+ "HeaderLatestGames": "Latest Games",
+ "HeaderRecentlyPlayedGames": "Recently Played Games",
+ "TabGameSystems": "Game Systems",
+ "TitleMediaLibrary": "Media Library",
+ "TabFolders": "Folders",
+ "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",
+ "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",
+ "ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
+ "LabelMissing": "Missing",
+ "LabelOffline": "Offline",
+ "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",
+ "HeaderTo": "To",
+ "LabelFrom": "From:",
+ "LabelFromHelp": "Example: D:\\Movies (on the server)",
+ "LabelTo": "To:",
+ "LabelToHelp": "Example: \\\\MyServer\\Movies (a path clients can access)",
+ "ButtonAddPathSubstitution": "Add Substitution",
+ "OptionSpecialEpisode": "Specials",
+ "OptionMissingEpisode": "Missing Episodes",
+ "OptionUnairedEpisode": "Unaired Episodes",
+ "OptionEpisodeSortName": "Episode Sort Name",
+ "OptionSeriesSortName": "Series Name",
+ "OptionTvdbRating": "Tvdb Rating",
+ "HeaderTranscodingQualityPreference": "Transcoding Quality Preference:",
+ "OptionAutomaticTranscodingHelp": "The server will decide quality and speed",
+ "OptionHighSpeedTranscodingHelp": "Lower quality, but faster encoding",
+ "OptionHighQualityTranscodingHelp": "Higher quality, but slower encoding",
+ "OptionMaxQualityTranscodingHelp": "Best quality with slower encoding and high CPU usage",
+ "OptionHighSpeedTranscoding": "Higher speed",
+ "OptionHighQualityTranscoding": "Higher quality",
+ "OptionMaxQualityTranscoding": "Max quality",
+ "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging",
+ "OptionEnableDebugTranscodingLoggingHelp": "This will create very large log files and is only recommended as needed for troubleshooting purposes.",
+ "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging",
+ "OptionUpscaling": "Allow clients to request upscaled video",
+ "OptionUpscalingHelp": "In some cases this will result in improved video quality but will increase CPU usage.",
+ "EditCollectionItemsHelp": "Add or remove any movies, series, albums, books or games you wish to group within this collection.",
+ "HeaderAddTitles": "Add Titles",
+ "LabelEnableDlnaPlayTo": "Enable DLNA Play To",
+ "LabelEnableDlnaPlayToHelp": "Media Browser can detect devices within your network and offer the ability to remote control them.",
+ "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging",
+ "LabelEnableDlnaDebugLoggingHelp": "This will create large log files and should only be used as needed for troubleshooting purposes.",
+ "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)",
+ "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Media Browser.",
+ "HeaderCustomDlnaProfiles": "Custom Profiles",
+ "HeaderSystemDlnaProfiles": "System Profiles",
+ "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.",
+ "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.",
+ "TitleDashboard": "Dashboard",
+ "TabHome": "Home",
+ "TabInfo": "Info",
+ "HeaderLinks": "Links",
+ "HeaderSystemPaths": "System Paths",
+ "LinkCommunity": "Community",
+ "LinkGithub": "Github",
+ "LinkApiDocumentation": "Api Documentation",
+ "LabelFriendlyServerName": "Friendly server name:",
+ "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.",
+ "LabelPreferredDisplayLanguage": "Preferred display language",
+ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.",
+ "LabelReadHowYouCanContribute": "Read about how you can contribute.",
+ "HeaderNewCollection": "New Collection",
+ "HeaderAddToCollection": "Add to Collection",
+ "ButtonSubmit": "Submit",
+ "NewCollectionNameExample": "Example: Star Wars Collection",
+ "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata",
+ "ButtonCreate": "Create",
+ "LabelHttpServerPortNumber": "Http server port number:",
+ "LabelWebSocketPortNumber": "Web socket port number:",
+ "LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
+ "LabelEnableAutomaticPortHelp": "UPnP allows automated router configuration for remote access. This may not work with some router models.",
+ "LabelExternalDDNS": "External DDNS:",
+ "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.",
+ "TabResume": "Resume",
+ "TabWeather": "Weather",
+ "TitleAppSettings": "App Settings",
+ "LabelMinResumePercentage": "Min resume percentage:",
+ "LabelMaxResumePercentage": "Max resume percentage:",
+ "LabelMinResumeDuration": "Min resume duration (seconds):",
+ "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time",
+ "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time",
+ "LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable",
+ "TitleAutoOrganize": "Auto-Organize",
+ "TabActivityLog": "Activity Log",
+ "HeaderName": "Name",
+ "HeaderDate": "Date",
+ "HeaderSource": "Source",
+ "HeaderStatus": "Status",
+ "HeaderDestination": "Destination",
+ "HeaderProgram": "Program",
+ "HeaderClients": "Clients",
+ "LabelCompleted": "Completed",
+ "LabelFailed": "Failed",
+ "LabelSkipped": "Skipped",
+ "HeaderEpisodeOrganization": "Episode Organization",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
+ "LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
+ "HeaderSupportTheTeam": "Support the Media Browser Team",
+ "LabelSupportAmount": "Amount (USD)",
+ "HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.",
+ "ButtonEnterSupporterKey": "Enter supporter key",
+ "DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.",
+ "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.",
+ "AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.",
+ "OptionEnableEpisodeOrganization": "Enable new episode organization",
+ "LabelWatchFolder": "Watch folder:",
+ "LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.",
+ "ButtonViewScheduledTasks": "View scheduled tasks",
+ "LabelMinFileSizeForOrganize": "Minimum file size (MB):",
+ "LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.",
+ "LabelSeasonFolderPattern": "Season folder pattern:",
+ "LabelSeasonZeroFolderName": "Season zero folder name:",
+ "HeaderEpisodeFilePattern": "Episode file pattern",
+ "LabelEpisodePattern": "Episode pattern:",
+ "LabelMultiEpisodePattern": "Multi-Episode pattern:",
+ "HeaderSupportedPatterns": "Supported Patterns",
+ "HeaderTerm": "Term",
+ "HeaderPattern": "Pattern",
+ "HeaderResult": "Result",
+ "LabelDeleteEmptyFolders": "Delete empty folders after organizing",
+ "LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.",
+ "LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:",
+ "LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt",
+ "OptionOverwriteExistingEpisodes": "Overwrite existing episodes",
+ "LabelTransferMethod": "Transfer method",
+ "OptionCopy": "Copy",
+ "OptionMove": "Move",
+ "LabelTransferMethodHelp": "Copy or move files from the watch folder",
+ "HeaderLatestNews": "Latest News",
+ "HeaderHelpImproveMediaBrowser": "Help Improve Media Browser",
+ "HeaderRunningTasks": "Running Tasks",
+ "HeaderActiveDevices": "Active Devices",
+ "HeaderPendingInstallations": "Pending Installations",
+ "HeaerServerInformation": "Server Information",
+ "ButtonRestartNow": "Restart Now",
+ "ButtonRestart": "Restart",
+ "ButtonShutdown": "Shutdown",
+ "ButtonUpdateNow": "Update Now",
+ "PleaseUpdateManually": "Please shutdown the server and update manually.",
+ "NewServerVersionAvailable": "A new version of Media Browser Server is available!",
+ "ServerUpToDate": "Media Browser Server is up to date",
+ "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.",
+ "LabelComponentsUpdated": "The following components have been installed or updated:",
+ "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.",
+ "LabelDownMixAudioScale": "Audio boost when downmixing:",
+ "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.",
+ "ButtonLinkKeys": "Link Keys",
+ "LabelOldSupporterKey": "Old supporter key",
+ "LabelNewSupporterKey": "New supporter key",
+ "HeaderMultipleKeyLinking": "Multiple Key Linking",
+ "MultipleKeyLinkingHelp": "If you have more than one supporter key, use this form to link the old key's registrations with your new one.",
+ "LabelCurrentEmailAddress": "Current email address",
+ "LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.",
+ "HeaderForgotKey": "Forgot Key",
+ "LabelEmailAddress": "Email address",
+ "LabelSupporterEmailAddress": "The email address that was used to purchase the key.",
+ "ButtonRetrieveKey": "Retrieve Key",
+ "LabelSupporterKey": "Supporter Key (paste from email)",
+ "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
+ "MessageInvalidKey": "Supporter key is missing or invalid.",
+ "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
+ "HeaderDisplaySettings": "Display Settings",
+ "TabPlayTo": "Play To",
+ "LabelEnableDlnaServer": "Enable Dlna server",
+ "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Media Browser content.",
+ "LabelEnableBlastAliveMessages": "Blast alive messages",
+ "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.",
+ "LabelBlastMessageInterval": "Alive message interval (seconds)",
+ "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.",
+ "LabelDefaultUser": "Default user:",
+ "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.",
+ "TitleDlna": "DLNA",
+ "TitleChannels": "Channels",
+ "HeaderServerSettings": "Server Settings",
+ "LabelWeatherDisplayLocation": "Weather display location:",
+ "LabelWeatherDisplayLocationHelp": "US zip code / City, State, Country / City, Country",
+ "LabelWeatherDisplayUnit": "Weather display unit:",
+ "OptionCelsius": "Celsius",
+ "OptionFahrenheit": "Fahrenheit",
+ "HeaderRequireManualLogin": "Require manual username entry for:",
+ "HeaderRequireManualLoginHelp": "When disabled clients may present a login screen with a visual selection of users.",
+ "OptionOtherApps": "Other apps",
+ "OptionMobileApps": "Mobile apps",
+ "HeaderNotificationList": "Click on a notification to configure it's sending options.",
+ "NotificationOptionApplicationUpdateAvailable": "Application update available",
+ "NotificationOptionApplicationUpdateInstalled": "Application update installed",
+ "NotificationOptionPluginUpdateInstalled": "Plugin update installed",
+ "NotificationOptionPluginInstalled": "Plugin installed",
+ "NotificationOptionPluginUninstalled": "Plugin uninstalled",
+ "NotificationOptionVideoPlayback": "Video playback started",
+ "NotificationOptionAudioPlayback": "Audio playback started",
+ "NotificationOptionGamePlayback": "Game playback started",
+ "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
+ "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
+ "NotificationOptionGamePlaybackStopped": "Game playback stopped",
+ "NotificationOptionTaskFailed": "Scheduled task failure",
+ "NotificationOptionInstallationFailed": "Installation failure",
+ "NotificationOptionNewLibraryContent": "New content added",
+ "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
+ "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.",
+ "NotificationOptionServerRestartRequired": "Server restart required",
+ "LabelNotificationEnabled": "Enable this notification",
+ "LabelMonitorUsers": "Monitor activity from:",
+ "LabelSendNotificationToUsers": "Send the notification to:",
+ "LabelUseNotificationServices": "Use the following services:",
+ "CategoryUser": "User",
+ "CategorySystem": "System",
+ "CategoryApplication": "Application",
+ "CategoryPlugin": "Plugin",
+ "LabelMessageTitle": "Message title:",
+ "LabelAvailableTokens": "Available tokens:",
+ "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.",
+ "OptionAllUsers": "All users",
+ "OptionAdminUsers": "Administrators",
+ "OptionCustomUsers": "Custom",
+ "ButtonArrowUp": "Up",
+ "ButtonArrowDown": "Down",
+ "ButtonArrowLeft": "Left",
+ "ButtonArrowRight": "Right",
+ "ButtonBack": "Back",
+ "ButtonInfo": "Info",
+ "ButtonOsd": "On screen display",
+ "ButtonPageUp": "Page Up",
+ "ButtonPageDown": "Page Down",
+ "PageAbbreviation": "PG",
+ "ButtonHome": "Home",
+ "ButtonSearch": "Search",
+ "ButtonSettings": "Settings",
+ "ButtonTakeScreenshot": "Capture Screenshot",
+ "ButtonLetterUp": "Letter Up",
+ "ButtonLetterDown": "Letter Down",
+ "PageButtonAbbreviation": "PG",
+ "LetterButtonAbbreviation": "A",
+ "TabNowPlaying": "Now Playing",
+ "TabNavigation": "Navigation",
+ "TabControls": "Controls",
+ "ButtonFullscreen": "Toggle fullscreen",
+ "ButtonScenes": "Scenes",
+ "ButtonSubtitles": "Subtitles",
+ "ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
+ "ButtonStop": "Stop",
+ "ButtonPlay": "Play",
+ "ButtonPause": "Pause",
+ "LabelGroupMoviesIntoCollections": "Group movies into collections",
+ "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.",
+ "NotificationOptionPluginError": "Plugin failure",
+ "ButtonVolumeUp": "Volume up",
+ "ButtonVolumeDown": "Volume down",
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderChannels": "Channels",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
+ "LabelProfileContainer": "Container:",
+ "LabelProfileVideoCodecs": "Video codecs:",
+ "LabelProfileAudioCodecs": "Audio codecs:",
+ "LabelProfileCodecs": "Codecs:",
+ "HeaderDirectPlayProfile": "Direct Play Profile",
+ "HeaderTranscodingProfile": "Transcoding Profile",
+ "HeaderCodecProfile": "Codec Profile",
+ "HeaderCodecProfileHelp": "Define additional conditions that must be met in order for a codec to be direct played.",
+ "HeaderContainerProfile": "Container Profile",
+ "HeaderContainerProfileHelp": "Define additional conditions that must be met in order for a file to be direct played.",
+ "OptionProfileVideo": "Video",
+ "OptionProfileAudio": "Audio",
+ "OptionProfileVideoAudio": "Video Audio",
+ "OptionProfilePhoto": "Photo",
+ "LabelUserLibrary": "User library:",
+ "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.",
+ "OptionPlainStorageFolders": "Display all folders as plain storage folders",
+ "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".",
+ "OptionPlainVideoItems": "Display all videos as plain video items",
+ "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".",
+ "LabelSupportedMediaTypes": "Supported Media Types:",
+ "TabIdentification": "Identification",
+ "TabDirectPlay": "Direct Play",
+ "TabContainers": "Containers",
+ "TabCodecs": "Codecs",
+ "TabResponses": "Responses",
+ "HeaderProfileInformation": "Profile Information",
+ "LabelEmbedAlbumArtDidl": "Embed album art in Didl",
+ "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.",
+ "LabelAlbumArtPN": "Album art PN:",
+ "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.",
+ "LabelAlbumArtMaxWidth": "Album art max width:",
+ "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "Album art max height:",
+ "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
+ "LabelIconMaxWidth": "Icon max width:",
+ "LabelIconMaxWidthHelp": "Max resolution of icons exposed via upnp:icon.",
+ "LabelIconMaxHeight": "Icon max height:",
+ "LabelIconMaxHeightHelp": "Max resolution of icons exposed via upnp:icon.",
+ "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.",
+ "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
+ "LabelMaxBitrate": "Max bitrate:",
+ "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
+ "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
+ "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
+ "LabelFriendlyName": "Friendly name",
+ "LabelManufacturer": "Manufacturer",
+ "LabelManufacturerUrl": "Manufacturer url",
+ "LabelModelName": "Model name",
+ "LabelModelNumber": "Model number",
+ "LabelModelDescription": "Model description",
+ "LabelModelUrl": "Model url",
+ "LabelSerialNumber": "Serial number",
+ "LabelDeviceDescription": "Device description",
+ "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.",
+ "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.",
+ "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.",
+ "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.",
+ "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.",
+ "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.",
+ "LabelXDlnaCap": "X-Dlna cap:",
+ "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.",
+ "LabelXDlnaDoc": "X-Dlna doc:",
+ "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.",
+ "LabelSonyAggregationFlags": "Sony aggregation flags:",
+ "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.",
+ "LabelTranscodingContainer": "Container:",
+ "LabelTranscodingVideoCodec": "Video codec:",
+ "LabelTranscodingVideoProfile": "Video profile:",
+ "LabelTranscodingAudioCodec": "Audio codec:",
+ "OptionEnableM2tsMode": "Enable M2ts mode",
+ "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.",
+ "OptionEstimateContentLength": "Estimate content length when transcoding",
+ "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.",
+ "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "Download subtitles for:",
+ "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "TabChapters": "Chapters",
+ "HeaderDownloadChaptersFor": "Download chapter names for:",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.",
+ "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
+ "LabelSubtitlePlaybackMode": "Subtitle mode:",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:",
+ "LabelMessageTitle": "Message title:",
+ "MessageNoAvailablePlugins": "No available plugins.",
+ "LabelDisplayPluginsFor": "Display plugins for:",
+ "PluginTabMediaBrowserClassic": "MB Classic",
+ "PluginTabMediaBrowserTheater": "MB Theater",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
+ "ValueSeriesNamePeriod": "Series.name",
+ "ValueSeriesNameUnderscore": "Series_name",
+ "ValueEpisodeNamePeriod": "Episode.name",
+ "ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
+ "HeaderTypeText": "Enter Text",
+ "LabelTypeText": "Text",
+ "HeaderSearchForSubtitles": "Search for Subtitles",
+ "MessageNoSubtitleSearchResultsFound": "No search results founds.",
+ "TabDisplay": "Display",
+ "TabLanguages": "Languages",
+ "TabWebClient": "Web Client",
+ "LabelEnableThemeSongs": "Enable theme songs",
+ "LabelEnableBackdrops": "Enable backdrops",
+ "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.",
+ "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.",
+ "HeaderHomePage": "Home Page",
+ "HeaderSettingsForThisDevice": "Settings for This Device",
+ "OptionAuto": "Auto",
+ "OptionYes": "Yes",
+ "OptionNo": "No",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
+ "OptionResumablemedia": "Resume",
+ "OptionLatestMedia": "Latest media",
+ "OptionLatestChannelMedia": "Latest channel items",
+ "HeaderLatestChannelItems": "Latest Channel Items",
+ "OptionNone": "None",
+ "HeaderLiveTv": "Live TV",
+ "HeaderReports": "Reports",
+ "HeaderMetadataManager": "Metadata Manager",
+ "HeaderPreferences": "Preferences",
+ "MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
+ "ButtonMarkRead": "Mark Read",
+ "OptionDefaultSort": "Default",
+ "OptionCommunityMostWatchedSort": "Most Watched",
+ "TabNextUp": "Next Up",
+ "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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
+ "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
+ "ButtonDismiss": "Dismiss",
+ "MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
+ "ButtonEditOtherUserPreferences": "Edit this user's personal preferences.",
+ "LabelChannelStreamQuality": "Preferred internet stream quality:",
+ "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.",
+ "OptionBestAvailableStreamQuality": "Best available",
+ "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:",
+ "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.",
+ "LabelChannelDownloadPath": "Channel content download path:",
+ "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.",
+ "LabelChannelDownloadAge": "Delete content after: (days)",
+ "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.",
+ "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.",
+ "LabelSelectCollection": "Select collection:",
+ "ViewTypeMovies": "Movies",
+ "ViewTypeTvShows": "TV",
+ "ViewTypeGames": "Games",
+ "ViewTypeMusic": "Music",
+ "ViewTypeBoxSets": "Collections",
+ "ViewTypeChannels": "Channels",
+ "ViewTypeLiveTV": "Live TV",
+ "HeaderOtherDisplaySettings": "Display Settings",
+ "HeaderMyViews": "My Views",
+ "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",
+ "TitleRemoteControl": "Remote Control",
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "ButtonEnterSupporterKey": "Enter supporter key",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonUpload": "Upload",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add/Update Image",
+ "LabelDropImageHere": "Drop image here",
+ "LabelJpgPngOnly": "JPG/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBackdrop": "Backdrop",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity",
+ "HeaderPeople": "People",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
+ "OptionComposers": "Composers",
+ "OptionOthers": "Others",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
+ "ViewTypeFolders": "Folders",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
+ "ViewTypeLiveTvChannels": "Channels",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
+ "HeaderPassword": "Password",
+ "HeaderLocalAccess": "Local Access",
+ "HeaderViewOrder": "View Order",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
+ "LabelImageRefreshMode": "Image refresh mode:",
+ "OptionDownloadMissingImages": "Download missing images",
+ "OptionReplaceExistingImages": "Replace existing images",
+ "OptionRefreshAllData": "Refresh all data",
+ "OptionAddMissingDataOnly": "Add missing data only",
+ "OptionLocalRefreshOnly": "Local refresh only",
+ "HeaderRefreshMetadata": "Refresh Metadata",
+ "HeaderPersonInfo": "Person Info",
+ "HeaderIdentifyItem": "Identify Item",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
+ "ButtonIdentify": "Identify",
+ "LabelAlbumArtist": "Album artist:",
+ "LabelAlbum": "Album:",
+ "LabelCommunityRating": "Community rating:",
+ "LabelVoteCount": "Vote count:",
+ "LabelMetascore": "Metascore:",
+ "LabelCriticRating": "Critic rating:",
+ "LabelCriticRatingSummary": "Critic rating summary:",
+ "LabelAwardSummary": "Award summary:",
+ "LabelWebsite": "Website:",
+ "LabelTagline": "Tagline:",
+ "LabelOverview": "Overview:",
+ "LabelShortOverview": "Short overview:",
+ "LabelReleaseDate": "Release date:",
+ "LabelYear": "Year:",
+ "LabelPlaceOfBirth": "Place of birth:",
+ "LabelEndDate": "End date:",
+ "LabelAirDate": "Air days:",
+ "LabelAirTime:": "Air time:",
+ "LabelRuntimeMinutes": "Run time (minutes):",
+ "LabelParentalRating": "Parental rating:",
+ "LabelCustomRating": "Custom rating:",
+ "LabelBudget": "Budget",
+ "LabelRevenue": "Revenue ($):",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
+ "LabelPlayers": "Players:",
+ "Label3DFormat": "3D format:",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
+ "HeaderExternalIds": "External Id's:",
+ "LabelDvdSeasonNumber": "Dvd season number:",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
+ "LabelAirsBeforeSeason": "Airs before season:",
+ "LabelAirsAfterSeason": "Airs after season:",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
+ "HeaderDisplaySettings": "Display Settings",
+ "LabelTreatImageAs": "Treat image as:",
+ "LabelDisplayOrder": "Display order:",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
+ "HeaderCountries": "Countries",
+ "HeaderGenres": "Genres",
+ "HeaderPeople": "People",
+ "HeaderPlotKeywords": "Plot Keywords",
+ "HeaderStudios": "Studios",
+ "HeaderTags": "Tags",
+ "HeaderMetadataSettings": "Metadata Settings",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
+ "TabSupporterClub": "Supporter Club",
+ "HeaderDonationType": "Donation type:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
+ "OptionNoTrailer": "No Trailer",
+ "OptionNoThemeSong": "No Theme Song",
+ "OptionNoThemeVideo": "No Theme Video",
+ "LabelOneTimeDonationAmount": "Donation amount:",
+ "OptionActor": "Actor",
+ "OptionComposer": "Composer",
+ "OptionDirector": "Director",
+ "OptionGuestStar": "Guest star",
+ "OptionProducer": "Producer",
+ "OptionWriter": "Writer",
+ "LabelAirDays": "Air days:",
+ "LabelAirTime": "Air time:",
+ "HeaderMediaInfo": "Media Info",
+ "HeaderPhotoInfo": "Photo Info"
+}
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/sv.json b/MediaBrowser.Server.Implementations/Localization/Server/sv.json
index ea44176ed..445071cdd 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/sv.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/sv.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Meddela administrat\u00f6rer n\u00e4r:",
- "HeaderEnableNotificationForPlayback": "Meddela n\u00e4r anv\u00e4ndare spelar:",
- "OptionNotifyOnUpdates": "Uppdateringar \u00e4r tillg\u00e4ngliga",
- "OptionNotifyOnVideoPlayback": "Video",
- "OptionNotifyOnAudioPlayback": "Audio",
- "OptionNotifyOnGamePlayback": "Spel",
- "OptionNotifyOnFailedTasks": "Schemalagda aktiviteter misslyckas",
- "OptionNotifyOnNewLibraryContent": "Nytt inneh\u00e5ll finns i biblioteket",
- "OptionNotifyOnServerRestartRequired": "Servern m\u00e5ste startas om",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Uppdateringar",
- "HeaderUpdateLevel": "Uppdatera versionsniv\u00e5",
- "LabelRequireTextSubtitles": "Ladda ner \u00e4ven om videon redan inneh\u00e5ller grafiska undertexter",
- "LabelRequireTextSubtitlesHelp": "Att spara textversioner av undertexter ger b\u00e4ttre resultat vid anv\u00e4ndning av mobila enheter.",
- "HeaderSubtitleDownloadingMoreHelp": "Undertexter betraktas som saknade d\u00e5 ljudsp\u00e5ret \u00e4r p\u00e5 ett fr\u00e4mmande spr\u00e5k och undertexter p\u00e5 det \u00f6nskade spr\u00e5ket ej finns tillg\u00e4ngliga.",
- "LabelDisplayForcedSubtitlesOnly": "Visa endast tvingande undertexter",
- "HeaderCustomizeOptionsPerMediaType": "Inst\u00e4llningar baserade p\u00e5 typ av media",
- "LabelAudioLanguagePreferenceHelp": "Om ej angivet kommer det f\u00f6rvalda ljudsp\u00e5ret att v\u00e4ljas, oavsett spr\u00e5k.",
- "TabCustomizations": "Anpassningar",
- "HeaderAllDevices": "Alla enheter",
- "HeaderThisDevice": "Den h\u00e4r enheten",
- "OptionLibraryButtons": "Biblioteksknappar",
- "OptionLibraryTiles": "Biblioteksbrickor",
- "OptionSmallLibraryTiles": "Biblioteksbrickor (sm\u00e5)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Misslyckades",
- "LabelSeries": "Serie:",
- "ButtonPreviousTrack": "F\u00f6reg\u00e5ende sp\u00e5r",
- "ButtonNextTrack": "N\u00e4sta sp\u00e5r",
- "HeaderMyLibrary": "Mitt bibliotek",
- "HeaderLibraryViews": "Biblioteksvyer",
+ "HeaderPeople": "People",
"LabelExit": "Avsluta",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "Bes\u00f6k v\u00e5rt diskussionsforum",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "F\u00f6rval",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "L\u00e4s API-dokumentationen",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "Bl\u00e4ddra i biblioteket",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "Konfigurera Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "\u00d6ppna biblioteksbl\u00e4ddraren",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "Starta om servern",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "Visa loggf\u00f6nstret",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "F\u00f6reg\u00e5ende",
+ "HeaderPassword": "Password",
"LabelFinish": "Klart",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "N\u00e4sta",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "Klart!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "V\u00e4lkommen till Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "Den h\u00e4r guiden hj\u00e4lper dig att g\u00f6ra de f\u00f6rsta inst\u00e4llningarna. F\u00f6r att b\u00f6rja var v\u00e4nlig v\u00e4lj \u00f6nskat spr\u00e5k.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "Ber\u00e4tta om dig sj\u00e4lv",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "Ditt f\u00f6rnamn:",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "Flera anv\u00e4ndare kan skapas senare i Kontrollpanelen.",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser har inbyggt st\u00f6d f\u00f6r anv\u00e4ndarprofiler, s\u00e5 varje anv\u00e4ndare kan ha sina egna utseendeinst\u00e4llningar, visad-markeringar och f\u00f6r\u00e4ldral\u00e5s.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Windows-tj\u00e4nst",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "En Windows-tj\u00e4nst har installerats.",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser Server k\u00f6rs normalt som ett anv\u00e4ndarprogram med ikon i aktivitetsf\u00e4ltet, men om s\u00e5 \u00f6nskas kan den k\u00f6ras som en Windows-tj\u00e4nst och startas fr\u00e5n kontrollpanelen Tj\u00e4nster (Services).",
+ "HeaderIdentifyItem": "Identify Item",
"WindowsServiceIntro2": "Om Media Browser k\u00f6rs som en tj\u00e4nst, notera att den inte kan k\u00f6ras samtidigt som aktivitetsf\u00e4ltsikonen, s\u00e5 f\u00f6r att k\u00f6ra tj\u00e4nsten m\u00e5ste ikonen st\u00e4ngas. Tj\u00e4nsten m\u00e5ste ocks\u00e5 k\u00f6ras med administrat\u00f6rsr\u00e4ttigheter (st\u00e4lls in i kontrollpanelen Tj\u00e4nster). Automatiska uppdateringar fungerar heller inte med tj\u00e4nsten, dvs tj\u00e4nsten m\u00e5ste stoppas f\u00f6re manuell uppdatering och sedan \u00e5terstartas.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "Det var allt f\u00f6r tillf\u00e4llet. Media Browser har b\u00f6rjat samla information om ditt mediebibliotek. Ta en titt p\u00e5 n\u00e5gra av v\u00e5ra appar och klicka sedan p\u00e5 <b>Klart<\/b> f\u00f6r att komma till <b>Kontrollpanelen<\/b>.",
+ "HeaderConfirmDeletion": "Bekr\u00e4fta radering",
"LabelConfigureSettings": "Inst\u00e4llningar",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Ta fram bildrutor ur videofiler",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"VideoImageExtractionHelp": "Dessa anv\u00e4nds f\u00f6r objekt som saknar bilder och d\u00e4r vi inte hittar n\u00e5gra vid s\u00f6kning p\u00e5 Internet. Detta g\u00f6r att den f\u00f6rsta genoms\u00f6kningen av biblioteket tar lite l\u00e4ngre tid, men ger en snyggare presentation.",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Ta fram kapitelbildrutor ur filmfiler",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "Detta m\u00f6jligg\u00f6r grafisk visning av menyer f\u00f6r val av kapitel. Processen kan vara tids- och CPU-kr\u00e4vande och beh\u00f6va flera gigabyte lagringsutrymme. Processen k\u00f6rs varje natt kl 04:00 men intervallet kan anpassas enligt \u00f6nskem\u00e5l i Schemal\u00e4ggaren. Vi rekommenderar inte att den k\u00f6rs vid tider d\u00e5 anv\u00e4ndare \u00e4r aktiva.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Aktivera automatisk koppling av portar",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP m\u00f6jligg\u00f6r automatisk inst\u00e4llning av din router s\u00e5 att du enkelt kan n\u00e5 Media Browser fr\u00e5n Internet. Detta kanske inte fungerar med alla routrar.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "OK",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Avbryt",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "Nytillkommet",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "Konfigurera mediabiblioteket",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "Skapa mediamapp",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Typ av mapp:",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Kr\u00e4ver att ett till\u00e4gg, t ex GameBrowser eller MB Bookshelf, \u00e4r installerat.",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Se avsnittet om mediabibliotek i v\u00e5r Wiki.",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "Land:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "Spr\u00e5k:",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "\u00d6nskat spr\u00e5k f\u00f6r metadata:",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "Spara grafik och metadata i mediamapparna",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "Om grafik och metadata sparas tillsammans med media \u00e4r de enkelt \u00e5tkomliga f\u00f6r redigering.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "H\u00e4mta grafik och metadata fr\u00e5n Internet",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser kan h\u00e4mta informatiom om dina media fr\u00e5n Internet f\u00f6r att ge en visuellt full\u00e4ndad presentation.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "Inst\u00e4llningar",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "L\u00f6senord",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "\u00c5tkomst till biblioteket",
+ "LabelBudget": "Budget",
"TabImage": "Bild",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "Profil",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "Bilder",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Meddelanden",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "Titlar",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Visa saknade avsnitt i s\u00e4songer",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Visa \u00e4nnu ej s\u00e4nda avsnitt i s\u00e4songer",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "Inst\u00e4llningar f\u00f6r videouppspelning",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Uppspelningsinst\u00e4llningar",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "\u00d6nskat spr\u00e5k f\u00f6r ljudsp\u00e5r",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "\u00d6nskat spr\u00e5k f\u00f6r undertexter",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "F\u00f6rval",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Endast tvingande undertexter",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Visa alltid undertexter",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "Inga undertexter",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Om ljudsp\u00e5ret \u00e4r p\u00e5 ett fr\u00e4mmande spr\u00e5k laddas undertexter p\u00e5 det \u00f6nskade spr\u00e5ket.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Endast undertexter markerade som tvingande kommer att laddas.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Undertexter p\u00e5 det \u00f6nskade spr\u00e5ket kommer att laddas oavsett ljudsp\u00e5rets spr\u00e5k.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Ladda normalt inte undertexter.",
+ "HeaderStudios": "Studios",
"TabProfiles": "Profiler",
+ "HeaderTags": "Tags",
"TabSecurity": "S\u00e4kerhet",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "Ny anv\u00e4ndare",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "Spara",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "\u00c5terst\u00e4ll l\u00f6senord",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "Nytt l\u00f6senord:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "Bekr\u00e4fta nytt l\u00f6senord:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "Skapa l\u00f6senord",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "Nuvarande l\u00f6senord:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "H\u00f6gsta till\u00e5tna \u00e5ldersgr\u00e4ns",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "Inneh\u00e5ll med h\u00f6gre gr\u00e4ns visas ej f\u00f6r den h\u00e4r anv\u00e4ndaren.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "Ange vilka mediamappar den h\u00e4r anv\u00e4ndaren ska ha tillg\u00e5ng till. Administrat\u00f6rer har r\u00e4ttighet att redigera alla mappar i metadatahanteraren.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "V\u00e4lj kanaler att dela med denna anv\u00e4ndare. Administrat\u00f6rer kan redigera alla kanaler med hj\u00e4lp av metadatahanteraren.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "Ta bort bild",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "V\u00e4lj anv\u00e4ndare:",
+ "OptionActor": "Actor",
"ButtonUpload": "Ladda upp",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "Ladda upp ny bild",
+ "OptionDirector": "Director",
"LabelDropImageHere": "Dra-och-sl\u00e4pp bild h\u00e4r",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "Bildf\u00f6rh\u00e5llande 1:1 rekommenderas. Endast JPG\/PNG.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Ingenting h\u00e4r.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "Var god se till att h\u00e4mtning av metadata via Internet \u00e4r aktiverad.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Rekommenderas",
+ "LabelAirTime": "Air time:",
"TabLatest": "Nytillkommet",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "Kommande",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Serier",
"TabEpisodes": "Avsnitt",
"TabGenres": "Genrer",
@@ -163,7 +225,7 @@
"OptionAscending": "Stigande",
"OptionDescending": "Sjunkande",
"OptionRuntime": "Speltid",
- "OptionReleaseDate": "Lanseringsdatum",
+ "OptionReleaseDate": "Release Date",
"OptionPlayCount": "Antal visningar",
"OptionDatePlayed": "Senast visad",
"OptionDateAdded": "Inlagd den",
@@ -213,6 +275,8 @@
"TabMovies": "Filmer",
"TabStudios": "Studior",
"TabTrailers": "Trailers",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "Nytillkomna filmer",
"HeaderLatestTrailers": "Nytillkomna trailers",
"OptionHasSpecialFeatures": "Extramaterial:",
@@ -233,6 +297,7 @@
"OptionFriday": "Fredag",
"OptionSaturday": "L\u00f6rdag",
"HeaderManagement": "Administration:",
+ "LabelManagement": "Administration:",
"OptionMissingImdbId": "IMDB-ID saknas",
"OptionMissingTvdbId": "TVDB-ID saknas",
"OptionMissingOverview": "Synopsis saknas",
@@ -266,7 +331,6 @@
"OptionIsSD": "SD",
"OptionMetascore": "Metabetyg",
"ButtonSelect": "V\u00e4lj",
- "ButtonSearch": "S\u00f6k",
"ButtonGroupVersions": "Gruppera versioner",
"ButtonAddToCollection": "L\u00e4gg till samling",
"PismoMessage": "Anv\u00e4nder Pismo File Mount baserat p\u00e5 en sk\u00e4nkt licens",
@@ -347,6 +411,8 @@
"TabStatus": "Status",
"TabSettings": "Inst\u00e4llningar",
"ButtonRefreshGuideData": "Uppdatera programguiden",
+ "ButtonRefresh": "Uppdatera",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Prioritet",
"OptionRecordOnAllChannels": "Spela in fr\u00e5n alla kanaler",
"OptionRecordAnytime": "Spela in vid alla tidpunkter",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Rollista & bes\u00e4ttning",
"HeaderAdditionalParts": "Ytterligare delar",
"ButtonSplitVersionsApart": "Hantera olika versioner separat",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Saknas",
"LabelOffline": "Offline",
"PathSubstitutionHelp": "S\u00f6kv\u00e4gsutbyte betyder att en plats p\u00e5 servern kopplas till en lokal fils\u00f6kv\u00e4g p\u00e5 en klient. P\u00e5 s\u00e5 s\u00e4tt f\u00e5r klienten direkt tillg\u00e5ng till material p\u00e5 servern och kan spela upp det direkt via n\u00e4tverket utan att f\u00f6rbruka serverresurser f\u00f6r str\u00f6mning och omkodning.",
@@ -512,8 +579,10 @@
"HeaderProgram": "Program",
"HeaderClients": "Klienter",
"LabelCompleted": "Klar",
+ "LabelFailed": "Misslyckades",
"LabelSkipped": "Hoppades \u00f6ver",
"HeaderEpisodeOrganization": "Katalogisering av avsnitt",
+ "LabelSeries": "Serie:",
"LabelSeasonNumber": "S\u00e4songsnummer:",
"LabelEpisodeNumber": "Avsnittsnummer:",
"LabelEndingEpisodeNumber": "Avslutande avsnittsnummer:",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Aktivera denna meddelandetyp",
"LabelMonitorUsers": "\u00d6vervaka aktivitet fr\u00e5n:",
"LabelSendNotificationToUsers": "Skicka meddelande till:",
- "UsersNotNotifiedAboutSelfActivity": "Anv\u00e4ndare f\u00e5r inte meddelanden om sina egna aktiviteter.",
"LabelUseNotificationServices": "Anv\u00e4nd f\u00f6ljande tj\u00e4nster:",
"CategoryUser": "Anv\u00e4ndare",
"CategorySystem": "System",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Sida ned",
"PageAbbreviation": "Sid",
"ButtonHome": "Hem",
+ "ButtonSearch": "S\u00f6k",
"ButtonSettings": "Inst\u00e4llningar",
"ButtonTakeScreenshot": "Ta sk\u00e4rmbild",
"ButtonLetterUp": "Bokstav upp",
@@ -661,6 +730,8 @@
"ButtonScenes": "Scener",
"ButtonSubtitles": "Undertexter",
"ButtonAudioTracks": "Ljudsp\u00e5r",
+ "ButtonPreviousTrack": "F\u00f6reg\u00e5ende sp\u00e5r:",
+ "ButtonNextTrack": "N\u00e4sta sp\u00e5r:",
"ButtonStop": "Stopp",
"ButtonPause": "Paus",
"LabelGroupMoviesIntoCollections": "Gruppera filmer i samlingsboxar",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "\u00c5tskilda med kommatecken, detta kan l\u00e4mnas tomt f\u00f6r att g\u00e4lla f\u00f6r alla beh\u00e5llare.",
"HeaderResponseProfile": "Svarsprofil",
"LabelType": "Typ:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Beh\u00e5llare:",
"LabelProfileVideoCodecs": "Kodning av video:",
"LabelProfileAudioCodecs": "Kodning av ljud:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "Dessa v\u00e4rden styr hur Media Browser presenterar sig f\u00f6r enheten.",
"LabelMaxBitrate": "H\u00f6gsta bithastighet:",
"LabelMaxBitrateHelp": "Ange en h\u00f6gsta bithastighet i bandbreddsbegr\u00e4nsade milj\u00f6er, eller i fall d\u00e4r enheten har sina egna begr\u00e4nsningar.",
+ "LabelMaxStreamingBitrate": "Max bithastighet f\u00f6r str\u00f6mning:",
+ "LabelMaxStreamingBitrateHelp": "Ange h\u00f6gsta bithastighet f\u00f6r str\u00f6mning.",
+ "LabelMaxStaticBitrate": "Max bithastighet vid synkronisering:",
+ "LabelMaxStaticBitrateHelp": "Ange h\u00f6gsta bithastighet vid synkronisering.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignorera beg\u00e4ran om \"byte range\" vid omkodning",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "Om aktiverad kommer beg\u00e4ran att uppfyllas, men \"byte range\"-rubriken ignoreras.",
"LabelFriendlyName": "\u00d6nskat namn",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Visa till\u00e4gg f\u00f6r:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "\u00d6vriga",
- "LabelEpisodeName": "Avsnittstitel",
- "LabelSeriesName": "Serietitel",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Ange text",
"LabelTypeText": "Text",
"HeaderSearchForSubtitles": "S\u00f6k efter undertexter",
@@ -800,9 +883,9 @@
"LabelHomePageSection2": "Hemsk\u00e4rmens del 2:",
"LabelHomePageSection3": "Hemsk\u00e4rmens del 3:",
"LabelHomePageSection4": "Hemsidans del 4:",
- "OptionMyLibraryButtons": "Mitt bibliotek (knappar)",
- "OptionMyLibrary": "Mitt bibliotek",
- "OptionMyLibrarySmall": "Mitt bibliotek (litet)",
+ "OptionMyViewsButtons": "Mina vyer (knappar)",
+ "OptionMyViews": "Mina vyer",
+ "OptionMyViewsSmall": "Mina vyer (liten)",
"OptionResumablemedia": "\u00c5teruppta",
"OptionLatestMedia": "Nytillkommet",
"OptionLatestChannelMedia": "Senaste objekten i Kanaler",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadatahanteraren",
"HeaderPreferences": "Inst\u00e4llningar",
"MessageLoadingChannels": "H\u00e4mtar kanalinneh\u00e5ll...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Markera som l\u00e4st",
"OptionDefaultSort": "F\u00f6rval",
"OptionCommunityMostWatchedSort": "Oftast visade",
"TabNextUp": "N\u00e4stkommande",
"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 skapa skr\u00e4ddarsydda grupper av filmer, serier, album, b\u00f6cker och spel. Klicka p\u00e5 \"Ny\" f\u00f6r att b\u00f6rja med 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\".",
+ "MessageNoPlaylistItemsAvailable": "Den h\u00e4r spellistan \u00e4r tom.",
"HeaderWelcomeToMediaBrowserWebClient": "V\u00e4lkommen till Media Browsers webbklient",
"ButtonDismiss": "Avvisa",
"MessageLearnHowToCustomize": "L\u00e4r dig hur du anpassar den h\u00e4r sidan till din personliga smak. Klicka p\u00e5 anv\u00e4ndarikonen uppe till h\u00f6ger f\u00f6r att visa och \u00e4ndra dina inst\u00e4llningar.",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Visa erotiskt inneh\u00e5ll",
"OptionLibraryFolders": "Mappvy",
"TitleRemoteControl": "Fj\u00e4rrkontroll",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Senaste inspelningar",
+ "LabelProtocolInfo": "Protokollinfo:",
+ "LabelProtocolInfoHelp": "V\u00e4rde att anv\u00e4nda vid svar p\u00e5 GetProtocolInfo-beg\u00e4ran fr\u00e5n enheter.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser har inbyggt st\u00f6d f\u00f6r Xbmc-metadata och bilder enligt Nfo-format. F\u00f6r att aktivera\/avaktivera Xbmc-metadata, anv\u00e4nd Avancerat-fliken f\u00f6r att g\u00f6ra inst\u00e4llningar f\u00f6r dina olika typer av media.",
+ "LabelXbmcMetadataUser": "St\u00e4ll in anv\u00e4ndare att bevaka nfo-data f\u00f6r:",
+ "LabelXbmcMetadataUserHelp": "Aktivera detta f\u00f6r att synkronisera bevakade data mellan Media Browser och Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Format f\u00f6r premi\u00e4rdatum:",
+ "LabelXbmcMetadataDateFormatHelp": "Alla datum i nfo-filer kommer att l\u00e4sas och skrivas i detta format.",
+ "LabelXbmcMetadataSaveImagePaths": "Spara bilds\u00f6kv\u00e4gar i nfo-filer",
+ "LabelXbmcMetadataSaveImagePathsHelp": "Detta rekommenderas om du har bilder med filnamn som inte uppfyller Xbmc:s riktlinjer.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Aktivera s\u00f6kv\u00e4gsutbyte",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Aktiverar s\u00f6kv\u00e4gsutbyte enligt serverns inst\u00e4llningar.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "Se \"s\u00f6kv\u00e4gsutbyte\".",
+ "LabelGroupChannelsIntoViews": "Visa dessa kanaler direkt i mina vyer:",
+ "LabelGroupChannelsIntoViewsHelp": "Om aktiverat kommer dessa kanaler att visas tillsammans med andra vyer. Annars visas de i en separat vy f\u00f6r Kanaler.",
+ "LabelDisplayCollectionsView": "Visa en Samlingar-vy f\u00f6r filmsamlingar",
+ "LabelXbmcMetadataEnableExtraThumbs": "Kopiera extrafanart till extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "N\u00e4r bilder h\u00e4mtas fr\u00e5n Internet kan de sparas i b\u00e5de extrafanart- och extrathumbs-mapparna f\u00f6r att ge maximal kompatibilitet med Xbmc-skins.",
+ "TabServices": "Tj\u00e4nster",
+ "TabLogs": "Loggfiler",
+ "HeaderServerLogFiles": "Serverloggfiler:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Anpassa utseendet p\u00e5 Media Browser till din grupp eller f\u00f6retags \u00f6nskem\u00e5l.",
+ "LabelLoginDisclaimer": "Ansvarsbegr\u00e4nsning vid inloggning:",
+ "LabelLoginDisclaimerHelp": "Detta visas l\u00e4ngst ned p\u00e5 inloggningssidan.",
+ "LabelAutomaticallyDonate": "Donera automatiskt detta belopp varje m\u00e5nad",
+ "LabelAutomaticallyDonateHelp": "Du kan avbryta n\u00e4r som helst via ditt PayPal-konto.",
+ "OptionList": "Lista",
+ "TabDashboard": "Kontrollpanel",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Loggfiler:",
+ "LabelMetadata": "Metadata",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Tillf\u00e4lliga omkodningsfiler:",
+ "HeaderLatestMusic": "Nytillkommen musik",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "API-nycklar",
+ "HeaderApiKeysHelp": "Externa program m\u00e5ste ha en API-nyckel f\u00f6r att kommunicera med Media Browser. Nycklar skapas genom inloggning med ett Media Browser-konto eller genom att manuellt tilldela ett program en nyckel.",
+ "HeaderApiKey": "API-nyckel",
+ "HeaderApp": "App",
+ "HeaderDevice": "Enhet",
+ "HeaderUser": "Anv\u00e4ndare",
+ "HeaderDateIssued": "Utgivningsdatum",
+ "LabelChapterName": "Kapitel {0}",
+ "HeaderNewApiKey": "Ny API-nyckel",
+ "LabelAppName": "Appens namn",
+ "LabelAppNameExample": "Exempel: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Till\u00e5t en app att kommunicera med Media Browser",
+ "HeaderHttpHeaders": "Http-rubriker",
+ "HeaderIdentificationHeader": "ID-rubrik",
+ "LabelValue": "V\u00e4rde:",
+ "LabelMatchType": "Matchningstyp:",
+ "OptionEquals": "Lika med",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Delstr\u00e4ng",
+ "TabView": "Vy",
+ "TabSort": "Sortera",
+ "TabFilter": "Filtrera",
+ "ButtonView": "Visa",
+ "LabelPageSize": "Max antal objekt:",
+ "LabelPath": "Path:",
+ "LabelView": "Vy:",
+ "TabUsers": "Anv\u00e4ndare",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Extramaterial",
+ "HeaderAdvanced": "Avancerat",
+ "ButtonSync": "Synk",
+ "TabScheduledTasks": "Schemalagda aktiviteter",
+ "HeaderChapters": "Kapitel",
+ "HeaderResumeSettings": "\u00c5teruppta-inst\u00e4llningar",
+ "TabSync": "Synk",
+ "TitleUsers": "Anv\u00e4ndare",
+ "LabelProtocol": "Protokoll:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Live-str\u00f6mning via Http",
+ "LabelContext": "Metod:",
+ "OptionContextStreaming": "Str\u00f6mning",
+ "OptionContextStatic": "Synk",
+ "ButtonAddToPlaylist": "L\u00e4gg till i spellista",
+ "TabPlaylists": "Spellistor",
+ "ButtonClose": "St\u00e4ng",
+ "LabelAllLanguages": "Alla spr\u00e5k",
+ "HeaderBrowseOnlineImages": "Bl\u00e4ddra bland bilder online",
+ "LabelSource": "K\u00e4lla:",
+ "OptionAll": "Alla",
+ "LabelImage": "Bild:",
+ "ButtonBrowseImages": "Bl\u00e4ddra bland bilder",
+ "HeaderImages": "Bilder",
+ "HeaderBackdrops": "Fondbilder",
+ "HeaderScreenshots": "Sk\u00e4rmklipp",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Oidentifierad",
+ "OptionMissingParentalRating": "\u00c5ldersgr\u00e4ns saknas",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Avsnitt:",
+ "OptionSeason0": "S\u00e4song 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "L\u00e5tar",
+ "OptionReportSeries": "Serier",
+ "OptionReportSeasons": "S\u00e4songer",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Musikvideos",
+ "OptionReportMovies": "Filmer",
+ "OptionReportHomeVideos": "Hemvideos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "Mer...",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/tr.json b/MediaBrowser.Server.Implementations/Localization/Server/tr.json
new file mode 100644
index 000000000..ea2a7e95d
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Localization/Server/tr.json
@@ -0,0 +1,1098 @@
+{
+ "HeaderPeople": "People",
+ "LabelExit": "Cikis",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
+ "LabelVisitCommunity": "Bizi Ziyaret Edin",
+ "OptionComposers": "Composers",
+ "LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
+ "LabelSwagger": "Swagger",
+ "LabelStandard": "Standart",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
+ "LabelViewApiDocumentation": "Api D\u00f6k\u00fcman\u0131 Goruntule",
+ "ViewTypeFolders": "Folders",
+ "LabelBrowseLibrary": "K\u00fct\u00fcphane",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
+ "LabelConfigureMediaBrowser": "Media Taray\u0131c\u0131 Konfig\u00fcrasyon",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
+ "LabelOpenLibraryViewer": "K\u00fct\u00fcphane G\u00f6r\u00fcnt\u00fcleyici",
+ "ViewTypeLiveTvChannels": "Channels",
+ "LabelRestartServer": "Server Yeniden Baslat",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
+ "LabelShowLogWindow": "Log Ekran\u0131n\u0131 G\u00f6r\u00fcnt\u00fcle",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
+ "LabelPrevious": "\u00d6nceki",
+ "HeaderPassword": "Password",
+ "LabelFinish": "Bitir",
+ "HeaderLocalAccess": "Local Access",
+ "LabelNext": "Sonraki",
+ "HeaderViewOrder": "View Order",
+ "LabelYoureDone": "Haz\u0131rs\u0131n!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
+ "WelcomeToMediaBrowser": "Media Taray\u0131c\u0131ya Hosgeldiniz !",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
+ "TitleMediaBrowser": "Media Taray\u0131c\u0131",
+ "LabelImageRefreshMode": "Image refresh mode:",
+ "ThisWizardWillGuideYou": "Bu sihirbaz kurulum i\u015flemi boyunca size yard\u0131mc\u0131 olacakt\u0131r. Ba\u015flamak i\u00e7in, tercih etti\u011finiz dili se\u00e7iniz.",
+ "OptionDownloadMissingImages": "Download missing images",
+ "TellUsAboutYourself": "Kendinizden Bahsedin",
+ "OptionReplaceExistingImages": "Replace existing images",
+ "LabelYourFirstName": "\u0130lk Ad",
+ "OptionRefreshAllData": "Refresh all data",
+ "MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.",
+ "OptionAddMissingDataOnly": "Add missing data only",
+ "UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.",
+ "OptionLocalRefreshOnly": "Local refresh only",
+ "LabelWindowsService": "Windows Servis",
+ "HeaderRefreshMetadata": "Refresh Metadata",
+ "AWindowsServiceHasBeenInstalled": "Windows Servisi Y\u00fcklenmistir.",
+ "HeaderPersonInfo": "Person Info",
+ "WindowsServiceIntro1": "Medya Taray\u0131c\u0131 Sunucu normalde bir tepsi simgesi ile bir masa\u00fcst\u00fc uygulamas\u0131 olarak cal\u0131s\u0131r, ancak bir arka plan servisi olarak \u00e7al\u0131\u015ft\u0131rmak isterseniz, bunun yerine windows servisleri kontrol panelinden baslat\u0131labilirsiniz.",
+ "HeaderIdentifyItem": "Identify Item",
+ "WindowsServiceIntro2": "Windows hizmeti kullan\u0131yorsan\u0131z, o tepsi simgesi olarak ayn\u0131 anda cal\u0131st\u0131rabilirsiniz unutmay\u0131n, b\u00f6ylece hizmetini cal\u0131st\u0131rmak i\u00e7in tepsiyi \u00e7\u0131kmak gerekir l\u00fctfen. Hizmeti de kontrol paneli \u00fczerinden y\u00f6netim ayr\u0131cal\u0131klar\u0131yla yap\u0131land\u0131r\u0131lm\u0131\u015f olmas\u0131 gerekir. Su anda hizmet kendine g\u00fcncelleme m\u00fcmk\u00fcn oldugunu unutmay\u0131n, bu y\u00fczden yeni s\u00fcr\u00fcmleri manuel etkilesimi gerektirir.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
+ "WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Dashboard<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
+ "LabelConfigureSettings": "Ayarlar\u0131 Degistir",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
+ "LabelEnableVideoImageExtraction": "Enable video image extraction",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
+ "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.",
+ "ButtonIdentify": "Identify",
+ "LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
+ "LabelAlbumArtist": "Album artist:",
+ "LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelAlbum": "Album:",
+ "LabelEnableAutomaticPortMapping": "Enable automatic port mapping",
+ "LabelCommunityRating": "Community rating:",
+ "LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "LabelVoteCount": "Vote count:",
+ "ButtonOk": "Tamam",
+ "LabelMetascore": "Metascore:",
+ "ButtonCancel": "\u0130ptal",
+ "LabelCriticRating": "Critic rating:",
+ "ButtonNew": "Yeni",
+ "LabelCriticRatingSummary": "Critic rating summary:",
+ "HeaderSetupLibrary": "Medya k\u00fct\u00fcphaneni kur",
+ "LabelAwardSummary": "Award summary:",
+ "ButtonAddMediaFolder": "Yeni Media Klas\u00f6r\u00fc",
+ "LabelWebsite": "Website:",
+ "LabelFolderType": "Klas\u00f6r T\u00fcr\u00fc:",
+ "LabelTagline": "Tagline:",
+ "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
+ "LabelOverview": "Overview:",
+ "ReferToMediaLibraryWiki": "Refer to the media library wiki.",
+ "LabelShortOverview": "Short overview:",
+ "LabelCountry": "\u00dclke",
+ "LabelReleaseDate": "Release date:",
+ "LabelLanguage": "Dil",
+ "LabelYear": "Year:",
+ "HeaderPreferredMetadataLanguage": "Tercih edilen Meta Dili:",
+ "LabelPlaceOfBirth": "Place of birth:",
+ "LabelSaveLocalMetadata": "Medya meta dosyalar\u0131n\u0131 ayn\u0131 klas\u00f6rlere i\u015fle",
+ "LabelEndDate": "End date:",
+ "LabelSaveLocalMetadataHelp": "Saving artwork and metadata directly into media folders will put them in a place where they can be easily edited.",
+ "LabelAirDate": "Air days:",
+ "LabelDownloadInternetMetadata": "\u0130nternetten \u0130\u00e7erik Y\u00fckleyin",
+ "LabelAirTime:": "Air time:",
+ "LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.",
+ "LabelRuntimeMinutes": "Run time (minutes):",
+ "TabPreferences": "Tercihler",
+ "LabelParentalRating": "Parental rating:",
+ "TabPassword": "\u015eifre",
+ "LabelCustomRating": "Custom rating:",
+ "TabLibraryAccess": "K\u00fct\u00fcphane Eri\u015fim",
+ "LabelBudget": "Budget",
+ "TabImage": "Resim",
+ "LabelRevenue": "Revenue ($):",
+ "TabProfile": "Profil",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
+ "TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
+ "TabImages": "Resimler",
+ "Label3DFormat": "3D format:",
+ "TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
+ "TabCollectionTitles": "Titles",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
+ "LabelDisplayMissingEpisodesWithinSeasons": "Sezondaki kay\u0131p b\u00f6l\u00fcmleri g\u00f6ster",
+ "HeaderExternalIds": "External Id's:",
+ "LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons",
+ "LabelDvdSeasonNumber": "Dvd season number:",
+ "HeaderVideoPlaybackSettings": "Video Oynatma Ayarlar\u0131",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
+ "HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
+ "LabelAudioLanguagePreference": "Ses Dili Tercihi:",
+ "LabelAirsBeforeSeason": "Airs before season:",
+ "LabelSubtitleLanguagePreference": "Altyaz\u0131 Dili Tercihi:",
+ "LabelAirsAfterSeason": "Airs after season:",
+ "OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
+ "OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
+ "OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
+ "OptionNoSubtitles": "Altyaz\u0131 Yok",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
+ "OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
+ "OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
+ "OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
+ "OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
+ "TabProfiles": "Profiller",
+ "HeaderTags": "Tags",
+ "TabSecurity": "G\u00fcvenlik",
+ "HeaderMetadataSettings": "Metadata Settings",
+ "ButtonAddUser": "Kullan\u0131c\u0131 Ekle",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
+ "ButtonSave": "Kay\u0131t",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
+ "ButtonResetPassword": "\u015eifre S\u0131f\u0131rla",
+ "TabSupporterClub": "Supporter Club",
+ "LabelNewPassword": "Yeni \u015eifre",
+ "HeaderDonationType": "Donation type:",
+ "LabelNewPasswordConfirm": "Yeni \u015eifreyi Onayla",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
+ "HeaderCreatePassword": "\u015eifre Olu\u015ftur",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
+ "LabelCurrentPassword": "Kullan\u0131mdaki \u015eifreniz",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
+ "LabelMaxParentalRating": "Maksimum izin verilen ebeveyn de\u011ferlendirmesi:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
+ "MaxParentalRatingHelp": "Daha y\u00fcksek bir derece ile \u0130\u00e7erik Bu kullan\u0131c\u0131dan gizli olacak.",
+ "OptionNoTrailer": "No Trailer",
+ "LibraryAccessHelp": "Bu kullan\u0131c\u0131 ile payla\u015fmak i\u00e7in medya klas\u00f6rleri se\u00e7in. Y\u00f6neticiler meta y\u00f6neticisini kullanarak t\u00fcm klas\u00f6rleri d\u00fczenlemesi m\u00fcmk\u00fcn olacakt\u0131r.",
+ "OptionNoThemeSong": "No Theme Song",
+ "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
+ "ButtonDeleteImage": "Resim Sil",
+ "LabelOneTimeDonationAmount": "Donation amount:",
+ "LabelSelectUsers": "Select users:",
+ "OptionActor": "Actor",
+ "ButtonUpload": "Y\u00fckle",
+ "OptionComposer": "Composer",
+ "HeaderUploadNewImage": "Yeni Resim Y\u00fckle",
+ "OptionDirector": "Director",
+ "LabelDropImageHere": "Resmi buraya s\u00fcr\u00fckle",
+ "OptionGuestStar": "Guest star",
+ "ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.",
+ "OptionProducer": "Producer",
+ "MessageNothingHere": "Nothing here.",
+ "OptionWriter": "Writer",
+ "MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
+ "LabelAirDays": "Air days:",
+ "TabSuggested": "\u00d6nerilen",
+ "LabelAirTime": "Air time:",
+ "TabLatest": "Son",
+ "HeaderMediaInfo": "Media Info",
+ "TabUpcoming": "Gelecek",
+ "HeaderPhotoInfo": "Photo Info",
+ "TabShows": "G\u00f6steriler",
+ "TabEpisodes": "B\u00f6l\u00fcmler",
+ "TabGenres": "T\u00fcrler",
+ "TabPeople": "Oyuncular",
+ "TabNetworks": "A\u011flar",
+ "HeaderUsers": "Kullan\u0131c\u0131lar",
+ "HeaderFilters": "Filtrelemeler",
+ "ButtonFilter": "Filtre",
+ "OptionFavorite": "Favoriler",
+ "OptionLikes": "Be\u011feniler",
+ "OptionDislikes": "Be\u011fenmeyenler",
+ "OptionActors": "Akt\u00f6rler",
+ "OptionGuestStars": "Konuk oylar\u0131",
+ "OptionDirectors": "Y\u00f6netmenler",
+ "OptionWriters": "Yazarlar",
+ "OptionProducers": "\u00dcreticiler",
+ "HeaderResume": "Devam",
+ "HeaderNextUp": "Sonraki hafta",
+ "NoNextUpItemsMessage": "None found. Start watching your shows!",
+ "HeaderLatestEpisodes": "Latest Episodes",
+ "HeaderPersonTypes": "Person Types:",
+ "TabSongs": "\u015eark\u0131lar",
+ "TabAlbums": "Alb\u00fcm",
+ "TabArtists": "Sanat\u00e7\u0131",
+ "TabAlbumArtists": "Sanat\u00e7\u0131 Alb\u00fcm\u00fc",
+ "TabMusicVideos": "Klipler",
+ "ButtonSort": "S\u0131rala",
+ "HeaderSortBy": "\u015euna g\u00f6re s\u0131rala",
+ "HeaderSortOrder": "Sipari\u015fe g\u00f6re s\u0131rala",
+ "OptionPlayed": "\u00c7al\u0131n\u0131yor",
+ "OptionUnplayed": "\u00c7al\u0131nm\u0131yor",
+ "OptionAscending": "Y\u00fckselen",
+ "OptionDescending": "D\u00fc\u015fen",
+ "OptionRuntime": "\u00c7al\u0131\u015fma s\u00fcresi",
+ "OptionReleaseDate": "Release Date",
+ "OptionPlayCount": "Oynatma sayac\u0131",
+ "OptionDatePlayed": "Oynatma Tarihi",
+ "OptionDateAdded": "Eklenme Tarihi",
+ "OptionAlbumArtist": "Sanat\u00e7\u0131 Alb\u00fcm\u00fc",
+ "OptionArtist": "Sanat\u00e7\u0131",
+ "OptionAlbum": "Alb\u00fcm",
+ "OptionTrackName": "Par\u00e7a \u0130smi",
+ "OptionCommunityRating": "Community Rating",
+ "OptionNameSort": "\u0130sim",
+ "OptionFolderSort": "Klas\u00f6r",
+ "OptionBudget": "Budget",
+ "OptionRevenue": "Revenue",
+ "OptionPoster": "Poster",
+ "OptionBackdrop": "Backdrop",
+ "OptionTimeline": "Timeline",
+ "OptionThumb": "Thumb",
+ "OptionBanner": "Banner",
+ "OptionCriticRating": "Kritik Rating",
+ "OptionVideoBitrate": "Video Kalitesi",
+ "OptionResumable": "Resumable",
+ "ScheduledTasksHelp": "Click a task to adjust its schedule.",
+ "ScheduledTasksTitle": "Zamanlanm\u0131\u015f G\u00f6revler",
+ "TabMyPlugins": "Eklentilerim",
+ "TabCatalog": "Katalog",
+ "PluginsTitle": "Eklentiler",
+ "HeaderAutomaticUpdates": "Otomatik G\u00fcncelleme",
+ "HeaderNowPlaying": "\u015eimdi \u00c7al\u0131n\u0131yor",
+ "HeaderLatestAlbums": "Son Alb\u00fcmler",
+ "HeaderLatestSongs": "Son Par\u00e7alar",
+ "HeaderRecentlyPlayed": "Son oynat\u0131lan",
+ "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 Tipi",
+ "OptionBluray": "Bluray",
+ "OptionDvd": "Dvd",
+ "OptionIso": "\u0130so",
+ "Option3D": "3D",
+ "LabelFeatures": "Features:",
+ "LabelService": "Servis:",
+ "LabelStatus": "Status:",
+ "LabelVersion": "Version:",
+ "LabelLastResult": "Last result:",
+ "OptionHasSubtitles": "Altyaz\u0131",
+ "OptionHasTrailer": "Tan\u0131t\u0131m Video",
+ "OptionHasThemeSong": "Tema \u015eark\u0131s\u0131",
+ "OptionHasThemeVideo": "Tema Videosu",
+ "TabMovies": "Filmler",
+ "TabStudios": "St\u00fcdyo",
+ "TabTrailers": "Fragmanlar",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
+ "HeaderLatestMovies": "Son filmler",
+ "HeaderLatestTrailers": "Son fragmanlar",
+ "OptionHasSpecialFeatures": "Special Features",
+ "OptionImdbRating": "\u0130MDb Reyting",
+ "OptionParentalRating": "Parental Rating",
+ "OptionPremiereDate": "Premiere Date",
+ "TabBasic": "Basit",
+ "TabAdvanced": "Geli\u015fmi\u015f",
+ "HeaderStatus": "Durum",
+ "OptionContinuing": "Topluluk",
+ "OptionEnded": "Bitmi\u015f",
+ "HeaderAirDays": "Air Days",
+ "OptionSunday": "Pazar",
+ "OptionMonday": "Pazartesi",
+ "OptionTuesday": "Sal\u0131",
+ "OptionWednesday": "\u00c7ar\u015famba",
+ "OptionThursday": "Per\u015fembe",
+ "OptionFriday": "Cuma",
+ "OptionSaturday": "Cumartesi",
+ "HeaderManagement": "Y\u00f6netim",
+ "LabelManagement": "Management:",
+ "OptionMissingImdbId": "Missing IMDb Id",
+ "OptionMissingTvdbId": "Missing TheTVDB Id",
+ "OptionMissingOverview": "Missing Overview",
+ "OptionFileMetadataYearMismatch": "File\/Metadata Years Mismatched",
+ "TabGeneral": "Genel",
+ "TitleSupport": "Destek",
+ "TabLog": "Kay\u0131t",
+ "TabAbout": "Hakk\u0131nda",
+ "TabSupporterKey": "Destek\u00e7i kodu",
+ "TabBecomeSupporter": "Destek\u00e7i ol",
+ "MediaBrowserHasCommunity": "Media Browser has a thriving community of users and contributors.",
+ "CheckoutKnowledgeBase": "Check out our knowledge base to help you get the most out of Media Browser.",
+ "SearchKnowledgeBase": "Search the Knowledge Base",
+ "VisitTheCommunity": "Visit the Community",
+ "VisitMediaBrowserWebsite": "Visit the Media Browser Web Site",
+ "VisitMediaBrowserWebsiteLong": "Visit the Media Browser Web site to catch the latest news and keep up with the developer blog.",
+ "OptionHideUser": "Hide this user from login screens",
+ "OptionDisableUser": "Kullan\u0131c\u0131 Devre D\u0131\u015f\u0131 B\u0131rak",
+ "OptionDisableUserHelp": "If disabled the server will not allow any connections from this user. Existing connections will be abruptly terminated.",
+ "HeaderAdvancedControl": "Geli\u015fmi\u015f Kontrol",
+ "LabelName": "\u0130sim",
+ "OptionAllowUserToManageServer": "Allow this user to manage the server",
+ "HeaderFeatureAccess": "Feature Access",
+ "OptionAllowMediaPlayback": "Allow media playback",
+ "OptionAllowBrowsingLiveTv": "Allow browsing of live tv",
+ "OptionAllowDeleteLibraryContent": "Allow this user to delete library content",
+ "OptionAllowManageLiveTv": "Allow management of live tv recordings",
+ "OptionAllowRemoteControlOthers": "Allow this user to remote control other users",
+ "OptionMissingTmdbId": "Missing Tmdb Id",
+ "OptionIsHD": "HD",
+ "OptionIsSD": "SD",
+ "OptionMetascore": "Metascore",
+ "ButtonSelect": "Se\u00e7im",
+ "ButtonGroupVersions": "Grup Versionlar\u0131",
+ "ButtonAddToCollection": "Add to Collection",
+ "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": "Versiyon {0}",
+ "TabPaths": "Paths",
+ "TabServer": "Sunucu",
+ "TabTranscoding": "Kodlay\u0131c\u0131",
+ "TitleAdvanced": "Geli\u015fmi\u015f",
+ "LabelAutomaticUpdateLevel": "Otomatik G\u00fcncelleme seviyesi",
+ "OptionRelease": "Resmi Yay\u0131n",
+ "OptionBeta": "Deneme",
+ "OptionDev": "Gelistirici",
+ "LabelAllowServerAutoRestart": "Allow the server to restart automatically to apply updates",
+ "LabelAllowServerAutoRestartHelp": "The server will only restart during idle periods, when no users are active.",
+ "LabelEnableDebugLogging": "Enable debug logging",
+ "LabelRunServerAtStartup": "Ba\u015flang\u0131\u00e7ta Server\u0131 \u00c7al\u0131\u015ft\u0131r",
+ "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",
+ "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.",
+ "LabelImagesByNamePath": "Images by name path:",
+ "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.",
+ "LabelMetadataPath": "Metadata path:",
+ "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": "Oyunlar",
+ "TabMusic": "Muzik",
+ "TabOthers": "Di\u011ferleri",
+ "HeaderExtractChapterImagesFor": "Extract chapter images for:",
+ "OptionMovies": "Filmler",
+ "OptionEpisodes": "Episodes",
+ "OptionOtherVideos": "Di\u011fer Videolar",
+ "TitleMetadata": "Metadata",
+ "LabelAutomaticUpdatesFanart": "Enable automatic updates from FanArt.tv",
+ "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.",
+ "LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
+ "LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
+ "ExtractChapterImagesHelp": "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 when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelMetadataDownloadLanguage": "Preferred download language:",
+ "ButtonAutoScroll": "Auto-scroll",
+ "LabelImageSavingConvention": "Image saving convention:",
+ "LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
+ "OptionImageSavingStandard": "Standart - MB2",
+ "ButtonSignIn": "Giri\u015f Yap\u0131n",
+ "TitleSignIn": "Giri\u015f Yap\u0131n",
+ "HeaderPleaseSignIn": "L\u00fctfen Giri\u015f Yap\u0131n",
+ "LabelUser": "Kullan\u0131c\u0131",
+ "LabelPassword": "\u015eifre",
+ "ButtonManualLogin": "Manuel Giri\u015f",
+ "PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
+ "TabGuide": "K\u0131lavuz",
+ "TabChannels": "Kanallar",
+ "TabCollections": "Collections",
+ "HeaderChannels": "Kanallar",
+ "TabRecordings": "Kay\u0131tlar",
+ "TabScheduled": "G\u00f6revler",
+ "TabSeries": "Seriler",
+ "TabFavorites": "Favoriler",
+ "TabMyLibrary": "My Library",
+ "ButtonCancelRecording": "Kay\u0131t \u0130ptal",
+ "HeaderPrePostPadding": "Pre\/Post Padding",
+ "LabelPrePaddingMinutes": "Pre-padding minutes:",
+ "OptionPrePaddingRequired": "Pre-padding is required in order to record.",
+ "LabelPostPaddingMinutes": "Post-padding minutes:",
+ "OptionPostPaddingRequired": "Post-padding is required in order to record.",
+ "HeaderWhatsOnTV": "What's On",
+ "HeaderUpcomingTV": "Yak\u0131nda TV'de",
+ "TabStatus": "Durum",
+ "TabSettings": "Ayarlar",
+ "ButtonRefreshGuideData": "K\u0131lavuzu Yinele",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
+ "OptionPriority": "\u00d6ncelik",
+ "OptionRecordOnAllChannels": "T\u00fcm kanallardaki program\u0131 kaydet",
+ "OptionRecordAnytime": "Program\u0131 herhangi bir zamanda kaydet",
+ "OptionRecordOnlyNewEpisodes": "Sadece yeni b\u00f6l\u00fcmleri kaydet",
+ "HeaderDays": "G\u00fcnler",
+ "HeaderActiveRecordings": "Aktif Kay\u0131tlar",
+ "HeaderLatestRecordings": "Ge\u00e7mi\u015f Kay\u0131tlar",
+ "HeaderAllRecordings": "T\u00fcm Kay\u0131tlar",
+ "ButtonPlay": "\u00c7al",
+ "ButtonEdit": "D\u00fczenle",
+ "ButtonRecord": "Kay\u0131t",
+ "ButtonDelete": "Sil",
+ "ButtonRemove": "Sil",
+ "OptionRecordSeries": "Kay\u0131t Serisi",
+ "HeaderDetails": "Detaylar",
+ "TitleLiveTV": "Canl\u0131 TV",
+ "LabelNumberOfGuideDays": "Number of days of guide data to download:",
+ "LabelNumberOfGuideDaysHelp": "Downloading more days worth of guide data provides the ability to schedule out further in advance and view more listings, but it will also take longer to download. Auto will choose based on the number of channels.",
+ "LabelActiveService": "Aktif Servis:",
+ "LabelActiveServiceHelp": "Multiple tv plugins can be installed but only one can be active at a time.",
+ "OptionAutomatic": "Otomatik",
+ "LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
+ "LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
+ "LabelCustomizeOptionsPerMediaType": "Customize for media type:",
+ "OptionDownloadThumbImage": "K\u00fc\u00e7\u00fck Resim",
+ "OptionDownloadMenuImage": "Men\u00fc",
+ "OptionDownloadLogoImage": "Logo",
+ "OptionDownloadBoxImage": "Kutu",
+ "OptionDownloadDiscImage": "Disk",
+ "OptionDownloadBannerImage": "Banner",
+ "OptionDownloadBackImage": "Geri",
+ "OptionDownloadArtImage": "Galeri",
+ "OptionDownloadPrimaryImage": "Birincil",
+ "HeaderFetchImages": "Fetch Images:",
+ "HeaderImageSettings": "Resim Ayarlar\u0131",
+ "TabOther": "Other",
+ "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 Task Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Task Trigger",
+ "ButtonAdd": "Ekle",
+ "LabelTriggerType": "Trigger Type:",
+ "OptionDaily": "G\u00fcnl\u00fck",
+ "OptionWeekly": "Haftal\u0131k",
+ "OptionOnInterval": "On an interval",
+ "OptionOnAppStartup": "On application startup",
+ "OptionAfterSystemEvent": "After a system event",
+ "LabelDay": "G\u00fcn:",
+ "LabelTime": "Zaman:",
+ "LabelEvent": "Event:",
+ "OptionWakeFromSleep": "Wake from sleep",
+ "LabelEveryXMinutes": "Every:",
+ "HeaderTvTuners": "Tuners",
+ "HeaderGallery": "Galeri",
+ "HeaderLatestGames": "Ge\u00e7mi\u015f Oyunlar",
+ "HeaderRecentlyPlayedGames": "Silinen Oyanan Oyunlar",
+ "TabGameSystems": "Oyun Sistemleri",
+ "TitleMediaLibrary": "Medya K\u00fct\u00fcphanesi",
+ "TabFolders": "Klas\u00f6rler",
+ "TabPathSubstitution": "Path Substitution",
+ "LabelSeasonZeroDisplayName": "Season 0 display name:",
+ "LabelEnableRealtimeMonitor": "Enable real time monitoring",
+ "LabelEnableRealtimeMonitorHelp": "Changes will be processed immediately, on supported file systems.",
+ "ButtonScanLibrary": "K\u00fct\u00fcphaneyi Tara",
+ "HeaderNumberOfPlayers": "Oyuncular",
+ "OptionAnyNumberOfPlayers": "Hepsi",
+ "Option1Player": "1+",
+ "Option2Player": "2+",
+ "Option3Player": "3+",
+ "Option4Player": "4+",
+ "HeaderMediaFolders": "Media Klas\u00f6rleri",
+ "HeaderThemeVideos": "Video Temalar\u0131",
+ "HeaderThemeSongs": "Tema \u015eark\u0131lar",
+ "HeaderScenes": "Diziler",
+ "HeaderAwardsAndReviews": "\u00d6d\u00fcller ve ilk bak\u0131\u015f",
+ "HeaderSoundtracks": "Film m\u00fczikleri",
+ "HeaderMusicVideos": "M\u00fczik vidyolar\u0131",
+ "HeaderSpecialFeatures": "Special Features",
+ "HeaderCastCrew": "Cast & Crew",
+ "HeaderAdditionalParts": "Additional Parts",
+ "ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
+ "LabelMissing": "Kay\u0131p",
+ "LabelOffline": "\u00c7evrimd\u0131\u015f\u0131",
+ "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": "Buradan",
+ "HeaderTo": "Buraya",
+ "LabelFrom": "Buradan",
+ "LabelFromHelp": "\u00d6rnek: D:\\Movies (sunucu \u00fczerinde)",
+ "LabelTo": "Buraya",
+ "LabelToHelp": "Example: \\\\MyServer\\Movies (a path clients can access)",
+ "ButtonAddPathSubstitution": "Add Substitution",
+ "OptionSpecialEpisode": "\u00d6zel",
+ "OptionMissingEpisode": "Missing Episodes",
+ "OptionUnairedEpisode": "Unaired Episodes",
+ "OptionEpisodeSortName": "Episode Sort Name",
+ "OptionSeriesSortName": "Seri Ad\u0131",
+ "OptionTvdbRating": "Tvdb Reyting",
+ "HeaderTranscodingQualityPreference": "Kodlay\u0131c\u0131 Kalite Ayarlar\u0131",
+ "OptionAutomaticTranscodingHelp": "The server will decide quality and speed",
+ "OptionHighSpeedTranscodingHelp": "D\u00fc\u015f\u00fck Kalite,H\u0131zl\u0131 Kodlama",
+ "OptionHighQualityTranscodingHelp": "Y\u00fcksek Kalite,Yava\u015f Kodlama",
+ "OptionMaxQualityTranscodingHelp": "En iyi Kalite,Yava\u015f Kodlama,Y\u00fcksek CPU Kullan\u0131m\u0131",
+ "OptionHighSpeedTranscoding": "Y\u00fcksek H\u0131z",
+ "OptionHighQualityTranscoding": "Y\u00fcksek Kalite",
+ "OptionMaxQualityTranscoding": "Max Kalite",
+ "OptionEnableDebugTranscodingLogging": "Enable debug transcoding logging",
+ "OptionEnableDebugTranscodingLoggingHelp": "This will create very large log files and is only recommended as needed for troubleshooting purposes.",
+ "OptionUpscaling": "Allow clients to request upscaled video",
+ "OptionUpscalingHelp": "In some cases this will result in improved video quality but will increase CPU usage.",
+ "EditCollectionItemsHelp": "Add or remove any movies, series, albums, books or games you wish to group within this collection.",
+ "HeaderAddTitles": "Add Titles",
+ "LabelEnableDlnaPlayTo": "Enable DLNA Play To",
+ "LabelEnableDlnaPlayToHelp": "Media Browser can detect devices within your network and offer the ability to remote control them.",
+ "LabelEnableDlnaDebugLogging": "Enable DLNA debug logging",
+ "LabelEnableDlnaDebugLoggingHelp": "This will create large log files and should only be used as needed for troubleshooting purposes.",
+ "LabelEnableDlnaClientDiscoveryInterval": "Client discovery interval (seconds)",
+ "LabelEnableDlnaClientDiscoveryIntervalHelp": "Determines the duration in seconds between SSDP searches performed by Media Browser.",
+ "HeaderCustomDlnaProfiles": "\u00d6zel Profiller",
+ "HeaderSystemDlnaProfiles": "Sistem Profilleri",
+ "CustomDlnaProfilesHelp": "Create a custom profile to target a new device or override a system profile.",
+ "SystemDlnaProfilesHelp": "System profiles are read-only. Changes to a system profile will be saved to a new custom profile.",
+ "TitleDashboard": "Dashboard",
+ "TabHome": "Anasayfa",
+ "TabInfo": "Bilgi",
+ "HeaderLinks": "Links",
+ "HeaderSystemPaths": "System Paths",
+ "LinkCommunity": "Community",
+ "LinkGithub": "Github",
+ "LinkApiDocumentation": "Api D\u00f6k\u00fcmanlar\u0131",
+ "LabelFriendlyServerName": "Friendly server name:",
+ "LabelFriendlyServerNameHelp": "This name will be used to identify this server. If left blank, the computer name will be used.",
+ "LabelPreferredDisplayLanguage": "Preferred display language",
+ "LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.",
+ "LabelReadHowYouCanContribute": "Read about how you can contribute.",
+ "HeaderNewCollection": "Yeni Koleksiyon",
+ "HeaderAddToCollection": "Add to Collection",
+ "ButtonSubmit": "Submit",
+ "NewCollectionNameExample": "Example: Star Wars Collection",
+ "OptionSearchForInternetMetadata": "Search the internet for artwork and metadata",
+ "ButtonCreate": "Create",
+ "LabelHttpServerPortNumber": "Http server port number:",
+ "LabelWebSocketPortNumber": "Web socket port number:",
+ "LabelEnableAutomaticPortHelp": "UPnP allows automated router configuration for remote access. This may not work with some router models.",
+ "LabelExternalDDNS": "External DDNS:",
+ "LabelExternalDDNSHelp": "If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.",
+ "TabResume": "Resume",
+ "TabWeather": "Weather",
+ "TitleAppSettings": "App Settings",
+ "LabelMinResumePercentage": "Min resume percentage:",
+ "LabelMaxResumePercentage": "Max resume percentage:",
+ "LabelMinResumeDuration": "Min resume duration (seconds):",
+ "LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time",
+ "LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time",
+ "LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable",
+ "TitleAutoOrganize": "Auto-Organize",
+ "TabActivityLog": "Activity Log",
+ "HeaderName": "Name",
+ "HeaderDate": "Date",
+ "HeaderSource": "Source",
+ "HeaderDestination": "Destination",
+ "HeaderProgram": "Program",
+ "HeaderClients": "Clients",
+ "LabelCompleted": "Completed",
+ "LabelFailed": "Failed",
+ "LabelSkipped": "Skipped",
+ "HeaderEpisodeOrganization": "Episode Organization",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
+ "LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
+ "HeaderSupportTheTeam": "Support the Media Browser Team",
+ "LabelSupportAmount": "Amount (USD)",
+ "HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.",
+ "ButtonEnterSupporterKey": "Enter supporter key",
+ "DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.",
+ "AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.",
+ "AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.",
+ "OptionEnableEpisodeOrganization": "Enable new episode organization",
+ "LabelWatchFolder": "Watch folder:",
+ "LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.",
+ "ButtonViewScheduledTasks": "View scheduled tasks",
+ "LabelMinFileSizeForOrganize": "Minimum file size (MB):",
+ "LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.",
+ "LabelSeasonFolderPattern": "Season folder pattern:",
+ "LabelSeasonZeroFolderName": "Season zero folder name:",
+ "HeaderEpisodeFilePattern": "Episode file pattern",
+ "LabelEpisodePattern": "Episode pattern:",
+ "LabelMultiEpisodePattern": "Multi-Episode pattern:",
+ "HeaderSupportedPatterns": "Supported Patterns",
+ "HeaderTerm": "Term",
+ "HeaderPattern": "Pattern",
+ "HeaderResult": "Result",
+ "LabelDeleteEmptyFolders": "Delete empty folders after organizing",
+ "LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.",
+ "LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:",
+ "LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt",
+ "OptionOverwriteExistingEpisodes": "Overwrite existing episodes",
+ "LabelTransferMethod": "Transfer method",
+ "OptionCopy": "Copy",
+ "OptionMove": "Move",
+ "LabelTransferMethodHelp": "Copy or move files from the watch folder",
+ "HeaderLatestNews": "Latest News",
+ "HeaderHelpImproveMediaBrowser": "Help Improve Media Browser",
+ "HeaderRunningTasks": "Running Tasks",
+ "HeaderActiveDevices": "Active Devices",
+ "HeaderPendingInstallations": "Pending Installations",
+ "HeaerServerInformation": "Sunucu bilgisi",
+ "ButtonRestartNow": "Restart Now",
+ "ButtonRestart": "Restart",
+ "ButtonShutdown": "Shutdown",
+ "ButtonUpdateNow": "Update Now",
+ "PleaseUpdateManually": "Please shutdown the server and update manually.",
+ "NewServerVersionAvailable": "A new version of Media Browser Server is available!",
+ "ServerUpToDate": "Media Browser Server G\u00fcncel",
+ "ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.",
+ "LabelComponentsUpdated": "The following components have been installed or updated:",
+ "MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates.",
+ "LabelDownMixAudioScale": "Audio boost when downmixing:",
+ "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.",
+ "ButtonLinkKeys": "Link Keys",
+ "LabelOldSupporterKey": "Old supporter key",
+ "LabelNewSupporterKey": "New supporter key",
+ "HeaderMultipleKeyLinking": "Multiple Key Linking",
+ "MultipleKeyLinkingHelp": "If you have more than one supporter key, use this form to link the old key's registrations with your new one.",
+ "LabelCurrentEmailAddress": "Current email address",
+ "LabelCurrentEmailAddressHelp": "The current email address to which your new key was sent.",
+ "HeaderForgotKey": "Forgot Key",
+ "LabelEmailAddress": "Email address",
+ "LabelSupporterEmailAddress": "The email address that was used to purchase the key.",
+ "ButtonRetrieveKey": "Retrieve Key",
+ "LabelSupporterKey": "Supporter Key (paste from email)",
+ "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
+ "MessageInvalidKey": "Supporter key is missing or invalid.",
+ "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
+ "HeaderDisplaySettings": "Display Settings",
+ "TabPlayTo": "Play To",
+ "LabelEnableDlnaServer": "DLNA Sunucusu etkin",
+ "LabelEnableDlnaServerHelp": "Allows UPnP devices on your network to browse and play Media Browser content.",
+ "LabelEnableBlastAliveMessages": "Blast alive messages",
+ "LabelEnableBlastAliveMessagesHelp": "Enable this if the server is not detected reliably by other UPnP devices on your network.",
+ "LabelBlastMessageInterval": "Alive message interval (seconds)",
+ "LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.",
+ "LabelDefaultUser": "Default user:",
+ "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.",
+ "TitleDlna": "DLNA",
+ "TitleChannels": "Channels",
+ "HeaderServerSettings": "Sunucu ayarlar\u0131",
+ "LabelWeatherDisplayLocation": "Weather display location:",
+ "LabelWeatherDisplayLocationHelp": "US zip code \/ City, State, Country \/ City, Country",
+ "LabelWeatherDisplayUnit": "Weather display unit:",
+ "OptionCelsius": "Celsius",
+ "OptionFahrenheit": "Fahrenheit",
+ "HeaderRequireManualLogin": "Require manual username entry for:",
+ "HeaderRequireManualLoginHelp": "When disabled clients may present a login screen with a visual selection of users.",
+ "OptionOtherApps": "Other apps",
+ "OptionMobileApps": "Mobile apps",
+ "HeaderNotificationList": "Click on a notification to configure it's sending options.",
+ "NotificationOptionApplicationUpdateAvailable": "Application update available",
+ "NotificationOptionApplicationUpdateInstalled": "Application update installed",
+ "NotificationOptionPluginUpdateInstalled": "Plugin update installed",
+ "NotificationOptionPluginInstalled": "Plugin installed",
+ "NotificationOptionPluginUninstalled": "Plugin uninstalled",
+ "NotificationOptionVideoPlayback": "Video playback started",
+ "NotificationOptionAudioPlayback": "Audio playback started",
+ "NotificationOptionGamePlayback": "Game playback started",
+ "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
+ "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
+ "NotificationOptionGamePlaybackStopped": "Game playback stopped",
+ "NotificationOptionTaskFailed": "Scheduled task failure",
+ "NotificationOptionInstallationFailed": "Installation failure",
+ "NotificationOptionNewLibraryContent": "New content added",
+ "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
+ "SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.",
+ "NotificationOptionServerRestartRequired": "Sunucu yeniden ba\u015flat\u0131lmal\u0131",
+ "LabelNotificationEnabled": "Enable this notification",
+ "LabelMonitorUsers": "Monitor activity from:",
+ "LabelSendNotificationToUsers": "Send the notification to:",
+ "LabelUseNotificationServices": "Use the following services:",
+ "CategoryUser": "User",
+ "CategorySystem": "System",
+ "CategoryApplication": "Uygulamalar",
+ "CategoryPlugin": "Eklenti",
+ "LabelMessageTitle": "Message title:",
+ "LabelAvailableTokens": "Available tokens:",
+ "AdditionalNotificationServices": "Browse the plugin catalog to install additional notification services.",
+ "OptionAllUsers": "All users",
+ "OptionAdminUsers": "Administrators",
+ "OptionCustomUsers": "Custom",
+ "ButtonArrowUp": "Up",
+ "ButtonArrowDown": "Down",
+ "ButtonArrowLeft": "Left",
+ "ButtonArrowRight": "Sa\u011f",
+ "ButtonBack": "Geri",
+ "ButtonInfo": "Bilgi",
+ "ButtonOsd": "On screen display",
+ "ButtonPageUp": "Sayfa Ba\u015f\u0131",
+ "ButtonPageDown": "Sayfa Sonu",
+ "PageAbbreviation": "PG",
+ "ButtonHome": "Anasayfa",
+ "ButtonSearch": "Arama",
+ "ButtonSettings": "Ayarlar",
+ "ButtonTakeScreenshot": "Ekran G\u00f6r\u00fcnt\u00fcs\u00fc Al",
+ "ButtonLetterUp": "Letter Up",
+ "ButtonLetterDown": "Letter Down",
+ "PageButtonAbbreviation": "PG",
+ "LetterButtonAbbreviation": "A",
+ "TabNowPlaying": "\u015eimdi \u00c7al\u0131n\u0131yor",
+ "TabNavigation": "Navigasyon",
+ "TabControls": "Kontrol",
+ "ButtonFullscreen": "Toggle fullscreen",
+ "ButtonScenes": "Sahneler",
+ "ButtonSubtitles": "Altyaz\u0131lar",
+ "ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
+ "ButtonStop": "Durdur",
+ "ButtonPause": "Duraklat",
+ "LabelGroupMoviesIntoCollections": "Group movies into collections",
+ "LabelGroupMoviesIntoCollectionsHelp": "When displaying movie lists, movies belonging to a collection will be displayed as one grouped item.",
+ "NotificationOptionPluginError": "Eklenti Ba\u015far\u0131s\u0131z",
+ "ButtonVolumeUp": "Ses A\u00e7",
+ "ButtonVolumeDown": "Ses Azalt",
+ "ButtonMute": "Sessiz",
+ "HeaderLatestMedia": "En Son G\u00f6r\u00fcnt\u00fclemeler",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Koleksiyon",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Profil G\u00f6r\u00fcnt\u00fcleme",
+ "LabelType": "T\u00fcr",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
+ "LabelProfileContainer": "Container:",
+ "LabelProfileVideoCodecs": "Video Codec",
+ "LabelProfileAudioCodecs": "Ses Codec",
+ "LabelProfileCodecs": "Codecler",
+ "HeaderDirectPlayProfile": "Direct Play Profile",
+ "HeaderTranscodingProfile": "Kodlama Profili",
+ "HeaderCodecProfile": "Codec Profili",
+ "HeaderCodecProfileHelp": "Codec profiles indicate the limitations of a device when playing specific codecs. If a limitation applies then the media will be transcoded, even if the codec is configured for direct play.",
+ "HeaderContainerProfile": "Container Profile",
+ "HeaderContainerProfileHelp": "Container profiles indicate the limitations of a device when playing specific formats. If a limitation applies then the media will be transcoded, even if the format is configured for direct play.",
+ "OptionProfileVideo": "Vidyo",
+ "OptionProfileAudio": "Ses",
+ "OptionProfileVideoAudio": "Video Sesi",
+ "OptionProfilePhoto": "Foto\u011fraf",
+ "LabelUserLibrary": "Kullan\u0131c\u0131 K\u00fct\u00fcphanesi:",
+ "LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.",
+ "OptionPlainStorageFolders": "Display all folders as plain storage folders",
+ "OptionPlainStorageFoldersHelp": "If enabled, all folders are represented in DIDL as \"object.container.storageFolder\" instead of a more specific type, such as \"object.container.person.musicArtist\".",
+ "OptionPlainVideoItems": "Display all videos as plain video items",
+ "OptionPlainVideoItemsHelp": "If enabled, all videos are represented in DIDL as \"object.item.videoItem\" instead of a more specific type, such as \"object.item.videoItem.movie\".",
+ "LabelSupportedMediaTypes": "Supported Media Types:",
+ "TabIdentification": "Identification",
+ "TabDirectPlay": "Direct Play",
+ "TabContainers": "Containers",
+ "TabCodecs": "Codecler",
+ "TabResponses": "Responses",
+ "HeaderProfileInformation": "Profile Information",
+ "LabelEmbedAlbumArtDidl": "Embed album art in Didl",
+ "LabelEmbedAlbumArtDidlHelp": "Some devices prefer this method for obtaining album art. Others may fail to play with this option enabled.",
+ "LabelAlbumArtPN": "Album art PN:",
+ "LabelAlbumArtHelp": "PN used for album art, within the dlna:profileID attribute on upnp:albumArtURI. Some clients require a specific value, regardless of the size of the image.",
+ "LabelAlbumArtMaxWidth": "Album art max width:",
+ "LabelAlbumArtMaxWidthHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "Album art max height:",
+ "LabelAlbumArtMaxHeightHelp": "Max resolution of album art exposed via upnp:albumArtURI.",
+ "LabelIconMaxWidth": "ikon Max Y\u00fckseklik:",
+ "LabelIconMaxWidthHelp": "Max resolution of icons exposed via upnp:icon.",
+ "LabelIconMaxHeight": "\u0130kon Max Geni\u015flik:",
+ "LabelIconMaxHeightHelp": "Max resolution of icons exposed via upnp:icon.",
+ "LabelIdentificationFieldHelp": "A case-insensitive substring or regex expression.",
+ "HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
+ "LabelMaxBitrate": "Max bitrate:",
+ "LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
+ "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
+ "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
+ "LabelFriendlyName": "Friendly name",
+ "LabelManufacturer": "\u00dcretici",
+ "LabelManufacturerUrl": "Manufacturer url",
+ "LabelModelName": "Model name",
+ "LabelModelNumber": "Model number",
+ "LabelModelDescription": "Model description",
+ "LabelModelUrl": "Model url",
+ "LabelSerialNumber": "Seri Numaras\u0131",
+ "LabelDeviceDescription": "Device description",
+ "HeaderIdentificationCriteriaHelp": "Enter at least one identification criteria.",
+ "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.",
+ "HeaderTranscodingProfileHelp": "Add transcoding profiles to indicate which formats should be used when transcoding is required.",
+ "HeaderResponseProfileHelp": "Response profiles provide a way to customize information sent to the device when playing certain kinds of media.",
+ "LabelXDlnaCap": "X-Dlna cap:",
+ "LabelXDlnaCapHelp": "Determines the content of the X_DLNACAP element in the urn:schemas-dlna-org:device-1-0 namespace.",
+ "LabelXDlnaDoc": "X-Dlna doc:",
+ "LabelXDlnaDocHelp": "Determines the content of the X_DLNADOC element in the urn:schemas-dlna-org:device-1-0 namespace.",
+ "LabelSonyAggregationFlags": "Sony aggregation flags:",
+ "LabelSonyAggregationFlagsHelp": "Determines the content of the aggregationFlags element in the urn:schemas-sonycom:av namespace.",
+ "LabelTranscodingContainer": "Container:",
+ "LabelTranscodingVideoCodec": "Video codec:",
+ "LabelTranscodingVideoProfile": "Video profile:",
+ "LabelTranscodingAudioCodec": "Audio codec:",
+ "OptionEnableM2tsMode": "Enable M2ts mode",
+ "OptionEnableM2tsModeHelp": "Enable m2ts mode when encoding to mpegts.",
+ "OptionEstimateContentLength": "Estimate content length when transcoding",
+ "OptionReportByteRangeSeekingWhenTranscoding": "Report that the server supports byte seeking when transcoding",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "This is required for some devices that don't time seek very well.",
+ "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "Download subtitles for:",
+ "MessageNoChapterProviders": "Install a chapter provider plugin such as ChapterDb to enable additional chapter options.",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Altyaz\u0131lar",
+ "TabChapters": "Chapters",
+ "HeaderDownloadChaptersFor": "Download chapter names for:",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "HeaderChapterDownloadingHelp": "When Media Browser scans your video files it can download friendly chapter names from the internet using chapter plugins such as ChapterDb.",
+ "LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
+ "LabelSubtitlePlaybackMode": "Subtitle mode:",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Kay\u0131t",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Mesaj G\u00f6nder",
+ "ButtonSend": "G\u00f6nder",
+ "LabelMessageText": "Mesaj Metni:",
+ "MessageNoAvailablePlugins": "No available plugins.",
+ "LabelDisplayPluginsFor": "Display plugins for:",
+ "PluginTabMediaBrowserClassic": "MB Classic",
+ "PluginTabMediaBrowserTheater": "MB Theater",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
+ "ValueSeriesNamePeriod": "Series.name",
+ "ValueSeriesNameUnderscore": "Series_name",
+ "ValueEpisodeNamePeriod": "Episode.name",
+ "ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
+ "HeaderTypeText": "Enter Text",
+ "LabelTypeText": "Text",
+ "HeaderSearchForSubtitles": "Search for Subtitles",
+ "MessageNoSubtitleSearchResultsFound": "No search results founds.",
+ "TabDisplay": "Display",
+ "TabLanguages": "Languages",
+ "TabWebClient": "Web Client",
+ "LabelEnableThemeSongs": "Enable theme songs",
+ "LabelEnableBackdrops": "Enable backdrops",
+ "LabelEnableThemeSongsHelp": "If enabled, theme songs will be played in the background while browsing the library.",
+ "LabelEnableBackdropsHelp": "If enabled, backdrops will be displayed in the background of some pages while browsing the library.",
+ "HeaderHomePage": "Anasayfa",
+ "HeaderSettingsForThisDevice": "Settings for This Device",
+ "OptionAuto": "Auto",
+ "OptionYes": "Yes",
+ "OptionNo": "No",
+ "LabelHomePageSection1": "Anasayfa Secenek 1:",
+ "LabelHomePageSection2": "Anasayfa Secenek 2:",
+ "LabelHomePageSection3": "Anasayfa Secenek 3:",
+ "LabelHomePageSection4": "Anasayfa Secenek 4:",
+ "OptionMyViewsButtons": "My views (buttons)",
+ "OptionMyViews": "My views",
+ "OptionMyViewsSmall": "My views (small)",
+ "OptionResumablemedia": "Resume",
+ "OptionLatestMedia": "En Son G\u00f6r\u00fcnt\u00fclemeler",
+ "OptionLatestChannelMedia": "Latest channel items",
+ "HeaderLatestChannelItems": "Latest Channel Items",
+ "OptionNone": "None",
+ "HeaderLiveTv": "Live TV",
+ "HeaderReports": "Reports",
+ "HeaderMetadataManager": "Metadata Manager",
+ "HeaderPreferences": "Preferences",
+ "MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
+ "ButtonMarkRead": "Mark Read",
+ "OptionDefaultSort": "Default",
+ "OptionCommunityMostWatchedSort": "Most Watched",
+ "TabNextUp": "Sonraki hafta",
+ "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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
+ "HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
+ "ButtonDismiss": "Dismiss",
+ "MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
+ "ButtonEditOtherUserPreferences": "Edit this user's personal preferences.",
+ "LabelChannelStreamQuality": "Preferred internet stream quality:",
+ "LabelChannelStreamQualityHelp": "In a low bandwidth environment, limiting quality can help ensure a smooth streaming experience.",
+ "OptionBestAvailableStreamQuality": "Best available",
+ "LabelEnableChannelContentDownloadingFor": "Enable channel content downloading for:",
+ "LabelEnableChannelContentDownloadingForHelp": "Some channels support downloading content prior to viewing. Enable this in low bandwidth enviornments to download channel content during off hours. Content is downloaded as part of the channel download scheduled task.",
+ "LabelChannelDownloadPath": "Channel content download path:",
+ "LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.",
+ "LabelChannelDownloadAge": "Delete content after: (days)",
+ "LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.",
+ "ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.",
+ "LabelSelectCollection": "Select collection:",
+ "ViewTypeMovies": "Movies",
+ "ViewTypeTvShows": "TV",
+ "ViewTypeGames": "Games",
+ "ViewTypeMusic": "Music",
+ "ViewTypeBoxSets": "Collections",
+ "ViewTypeChannels": "Channels",
+ "ViewTypeLiveTV": "Live TV",
+ "HeaderOtherDisplaySettings": "Display Settings",
+ "HeaderMyViews": "My Views",
+ "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 Klas\u00f6rleri",
+ "TitleRemoteControl": "Remote Control",
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Sunucu",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
+} \ 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 eca1f5a61..3590a5fea 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/vi.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/vi.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "Updates",
- "HeaderUpdateLevel": "Update Level",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
- "HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "Trailer",
- "LabelFailed": "Failed",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "HeaderMyLibrary": "My Library",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "Tho\u00e1t",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "Gh\u00e9 th\u0103m trang C\u1ed9ng \u0111\u1ed3ng",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Github Wiki",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "Ti\u00eau chu\u1ea9n",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "T\u00e0i li\u1ec7u xem Api",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "Duy\u1ec7t th\u01b0 vi\u1ec7n",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "C\u1ea5u h\u00ecnh Media Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "Open Library Viewer",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "Kh\u1edfi \u0111\u1ed9ng l\u1ea1i m\u00e1y ch\u1ee7",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "Show Log Window",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "Tr\u01b0\u1edbc",
+ "HeaderPassword": "Password",
"LabelFinish": "K\u1ebft th\u00fac",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "Ti\u1ebfp theo",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "B\u1ea1n \u0111\u00e3 ho\u00e0n th\u00e0nh!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "Ch\u00e0o m\u1eebng \u0111\u1ebfn B\u1ea1n \u0111\u1ebfn v\u1edbi Media Browser!",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "Th\u1ee7 thu\u1eadt n\u00e0y s\u1ebd h\u01b0\u1edbng d\u1eabn qu\u00e1 tr\u00ecnh c\u00e0i \u0111\u1eb7t cho b\u1ea1n. \u0110\u1ec3 b\u1eaft \u0111\u1ea7u, vui l\u00f2ng l\u1ef1a ch\u1ecdn ng\u00f4n ng\u1eef b\u1ea1n \u01b0a th\u00edch.",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "N\u00f3i cho ch\u00fang t\u00f4i bi\u1ebft \u0111\u00f4i \u0111i\u1ec1u v\u1ec1 B\u1ea1n",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "T\u00ean c\u1ee7a B\u1ea1n",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "More users can be added later within the Dashboard.",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser includes built-in support for user profiles, enabling each user to have their own display settings, playstate and parental controls.",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "D\u1ecbch v\u1ee5 c\u1ee7a Windows",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "M\u1ed9t d\u1ecbch v\u1ee5 c\u1ee7a Windows \u0111\u00e3 \u0111\u01b0\u1ee3c c\u00e0i \u0111\u1eb7t",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser Server ch\u1ea1y b\u00ecnh th\u01b0\u1eddng nh\u01b0 m\u1ed9t \u1ee9ng d\u1ee5ng m\u00e1y t\u00ednh v\u1edbi khay bi\u1ec3u t\u01b0\u1ee3ng, nh\u01b0ng n\u1ebfu b\u1ea1n th\u00edch \u0111\u1ec3 n\u00f3 ch\u1ea1y nh\u01b0 m\u1ed9t d\u1ecbch v\u1ee5 n\u1ec1n, n\u00f3 c\u00f3t h\u1ec3 kh\u1edfi \u0111\u1ed9ng c\u00f9ng c\u00e1c d\u1ecbch v\u1ee5 c\u1ee7a h\u1ec7 \u0111i\u1ec1u h\u00e0nh windows",
+ "HeaderIdentifyItem": "Identify Item",
"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.",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "That's all we need for now. Media Browser has begun collecting information about your media library. Check out some of our apps, and then click <b>Finish<\/b> to view the <b>Dashboard<\/b>.",
+ "HeaderConfirmDeletion": "Confirm Deletion",
"LabelConfigureSettings": "C\u00e0i \u0111\u1eb7t c\u1ea5u h\u00ecnh",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "Enable video image extraction",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"VideoImageExtractionHelp": "\u0110\u1ed1i v\u1edbi c\u00e1c video kh\u00f4ng c\u00f3 s\u1eb5n h\u00ecnh \u1ea3nh v\u00e0 ch\u00fang ta kh\u00f4ng t\u00ecm th\u1ea5y c\u00e1c h\u00ecnh \u1ea3nh \u0111\u00f3 tr\u00ean internet. \u0110i\u1ec1u n\u00e0y s\u1ebd",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "Cho ph\u00e9p t\u1ef1 \u0111\u1ed9ng \u00e1nh x\u1ea1 c\u1ed5ng (port)",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "Ok",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "Tho\u00e1t",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "M\u1edbi",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "C\u00e0i \u0111\u1eb7t th\u01b0 vi\u1ec7n media c\u1ee7a b\u1ea1n",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "Th\u00eam m\u1ed9t th\u01b0 m\u1ee5c media",
+ "LabelWebsite": "Website:",
"LabelFolderType": "Lo\u1ea1i th\u01b0 m\u1ee5c",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "Tham kh\u1ea3o th\u01b0 vi\u1ec7n wiki media.",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "Qu\u1ed1c gia:",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "Ng\u00f4n ng\u1eef",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "Ng\u00f4n ng\u1eef metadata \u01b0a th\u00edch",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "L\u01b0u c\u00e1c \u1ea3nh ngh\u1ec7 thu\u1eadt v\u00e0 metadata v\u00e0o trong c\u00e1c th\u01b0 m\u1ee5c media",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "L\u01b0u c\u00e1c \u1ea3nh ngh\u1ec7 thu\u1eadt v\u00e0 metadata v\u00e0o trong c\u00e1c th\u01b0 m\u1ee5c media, s\u1ebd \u0111\u01b0a ch\u00fang v\u00e0o m\u1ed9t n\u01a1i b\u1ea1n c\u00f3 th\u1ec3 ch\u1ec9nh s\u1eeda d\u1ec5 d\u00e0ng h\u01a1n.",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "T\u1ea3i \u1ea3nh ngh\u1ec7 thu\u1eadt v\u00e0 metadata t\u1eeb internet",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser c\u00f3 th\u1ec3 t\u1ea3i th\u00f4ng tin v\u1ec1 media c\u1ee7a b\u1ea1n \u0111\u1ec3 cho ph\u00e9p tr\u00ecnh di\u1ec5n ch\u00fang m\u1ed9t c\u00e1ch phong ph\u00faho\u01a1n",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "\u01afa th\u00edch",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "M\u1eadt kh\u1ea9u",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "Truy c\u1eadp th\u01b0 vi\u1ec7n",
+ "LabelBudget": "Budget",
"TabImage": "H\u00ecnh \u1ea3nh",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "H\u1ed3 s\u01a1",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "Metadata",
+ "LabelPlayers": "Players:",
"TabImages": "H\u00ecnh \u1ea3nh",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "Ti\u00eau \u0111\u1ec1",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "C\u00e1c c\u00e0i \u0111\u1eb7t ph\u00e1t Video",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "Ng\u00f4n ng\u1eef tho\u1ea1i \u01b0a th\u00edch:",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "Ng\u00f4n ng\u1eef ph\u1ee5 \u0111\u1ec1 \u01b0a th\u00edch:",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
"TabProfiles": "H\u1ed3 s\u01a1",
+ "HeaderTags": "Tags",
"TabSecurity": "B\u1ea3o m\u1eadt",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "Th\u00eam ng\u01b0\u1eddi d\u00f9ng",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "L\u01b0u",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "Reset m\u1eadt kh\u1ea9u",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "M\u1eadt kh\u1ea9u m\u1edbi:",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "X\u00e1c nh\u1eadn m\u1eadt kh\u1ea9u m\u1edbi:",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "T\u1ea1o m\u1eadt kh\u1ea9u",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "M\u1eadt kh\u1ea9u hi\u1ec7n t\u1ea1i:",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "Maximum allowed parental rating:",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "N\u1ed9i dung v\u1edbi \u0111\u00e1nh gi\u00e1 cao h\u01a1n s\u1ebd \u0111\u01b0\u1ee3c \u1ea9n \u0111i t\u1eeb ng\u01b0\u1eddi d\u00f9ng n\u00e0y.",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "Select the media folders to share with this user. Administrators will be able to edit all folders using the metadata manager.",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "X\u00f3a h\u00ecnh \u1ea3nh",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "Select users:",
+ "OptionActor": "Actor",
"ButtonUpload": "T\u1ea3i l\u00ean",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "T\u1ea3i l\u00ean m\u1ed9t \u1ea3nh m\u1edbi",
+ "OptionDirector": "Director",
"LabelDropImageHere": "K\u00e9o\/Th\u1ea3 h\u00ecnh \u1ea3nh t\u1ea1i \u0111\u00e2y",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "1:1 Aspect Ratio Recommended. JPG\/PNG only.",
+ "OptionProducer": "Producer",
"MessageNothingHere": "Kh\u00f4ng c\u00f3 g\u00ec \u1edf \u0111\u00e2y.",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "Please ensure downloading of internet metadata is enabled.",
+ "LabelAirDays": "Air days:",
"TabSuggested": "Suggested",
+ "LabelAirTime": "Air time:",
"TabLatest": "M\u1edbi nh\u1ea5t",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "S\u1eafp di\u1ec5n ra",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "Shows",
"TabEpisodes": "C\u00e1c t\u1eadp phim",
"TabGenres": "C\u00e1c th\u1ec3 lo\u1ea1i",
@@ -163,7 +225,7 @@
"OptionAscending": "Ascending",
"OptionDescending": "Descending",
"OptionRuntime": "Th\u1eddi gian ph\u00e1t",
- "OptionReleaseDate": "Ng\u00e0y ph\u00e1t h\u00e0nh",
+ "OptionReleaseDate": "Release Date",
"OptionPlayCount": "S\u1ed1 l\u1ea7n ph\u00e1t",
"OptionDatePlayed": "Ng\u00e0y ph\u00e1t",
"OptionDateAdded": "Ng\u00e0y th\u00eam",
@@ -213,6 +275,8 @@
"TabMovies": "C\u00e1c phim",
"TabStudios": "H\u00e3ng phim",
"TabTrailers": "Trailers",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "Phim m\u1edbi nh\u1ea5t",
"HeaderLatestTrailers": "Latest Trailers",
"OptionHasSpecialFeatures": "T\u00ednh n\u0103ng \u0111\u1eb7c bi\u1ec7t",
@@ -224,7 +288,7 @@
"HeaderStatus": "Tr\u1ea1ng th\u00e1i",
"OptionContinuing": "Continuing",
"OptionEnded": "Ended",
- "HeaderAirDays": "Air Days:",
+ "HeaderAirDays": "Air Days",
"OptionSunday": "Ch\u1ee7 Nh\u1eadt",
"OptionMonday": "Th\u1ee9 Hai",
"OptionTuesday": "Tuesday",
@@ -233,6 +297,7 @@
"OptionFriday": "Friday",
"OptionSaturday": "Th\u1ee9 B\u1ea3y",
"HeaderManagement": "Qu\u1ea3n l\u00fd:",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "Thi\u1ebfu IMDb ID",
"OptionMissingTvdbId": "Missing TheTVDB Id",
"OptionMissingOverview": "Missing Overview",
@@ -266,7 +331,6 @@
"OptionIsSD": "\u0110\u1ed9 n\u00e9t ti\u00eau chu\u1ea9n",
"OptionMetascore": "Metascore",
"ButtonSelect": "L\u1ef1a ch\u1ecdn",
- "ButtonSearch": "T\u00ecm ki\u1ebfm",
"ButtonGroupVersions": "Group Versions",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
@@ -290,13 +354,13 @@
"ButtonSelectDirectory": "L\u1ef1a ch\u1ecdn tr\u1ef1c ti\u1ebfp",
"LabelCustomPaths": "Specify custom paths where desired. Leave fields empty to use the defaults.",
"LabelCachePath": "Cache path:",
- "LabelCachePathHelp": "This folder contains server cache files, such as images.",
+ "LabelCachePathHelp": "Specify a custom location for server cache files, such as images.",
"LabelImagesByNamePath": "Images by name path:",
- "LabelImagesByNamePathHelp": "This folder contains actor, artist, genre and studio images.",
+ "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.",
"LabelMetadataPath": "Metadata path:",
- "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.",
+ "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.",
+ "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",
@@ -313,12 +377,12 @@
"LabelAutomaticUpdatesFanartHelp": "If enabled, new images will be downloaded automatically as they're added to fanart.tv. Existing images will not be replaced.",
"LabelAutomaticUpdatesTmdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheMovieDB.org. Existing images will not be replaced.",
"LabelAutomaticUpdatesTvdbHelp": "If enabled, new images will be downloaded automatically as they're added to TheTVDB.com. Existing images will not be replaced.",
- "ExtractChapterImagesHelp": "Extracting chapter images will allow clients to display graphical scene selection menus. The process can be slow, cpu-intensive and may require several gigabytes of space. It runs as a nightly scheduled task at 4am, although this is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
+ "ExtractChapterImagesHelp": "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 when videos are discovered, and also as a nightly scheduled task at 4am. The schedule is configurable in the scheduled tasks area. It is not recommended to run this task during peak usage hours.",
"LabelMetadataDownloadLanguage": "Preferred download language:",
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
- "OptionImageSavingCompatible": "Compatible - Media Browser\/Plex\/Xbmc",
+ "OptionImageSavingCompatible": "Compatible - Media Browser\/Xbmc\/Plex",
"OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
@@ -347,6 +411,8 @@
"TabStatus": "Status",
"TabSettings": "Settings",
"ButtonRefreshGuideData": "Refresh Guide Data",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "Priority",
"OptionRecordOnAllChannels": "Record program on all channels",
"OptionRecordAnytime": "Record program at any time",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "Cast & Crew",
"HeaderAdditionalParts": "Additional Parts",
"ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "Missing",
"LabelOffline": "Offline",
"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.",
@@ -512,11 +579,13 @@
"HeaderProgram": "Ch\u01b0\u01a1ng tr\u00ecnh",
"HeaderClients": "C\u00e1c m\u00e1y kh\u00e1ch",
"LabelCompleted": "Ho\u00e0n th\u00e0nh",
+ "LabelFailed": "Failed",
"LabelSkipped": "B\u1ecf qua",
"HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeasonNumber": "Season number",
- "LabelEpisodeNumber": "Episode number",
- "LabelEndingEpisodeNumber": "Ending episode number",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Enable this notification",
"LabelMonitorUsers": "Monitor activity from:",
"LabelSendNotificationToUsers": "Send the notification to:",
- "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.",
"LabelUseNotificationServices": "Use the following services:",
"CategoryUser": "User",
"CategorySystem": "System",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
"ButtonHome": "Home",
+ "ButtonSearch": "T\u00ecm ki\u1ebfm",
"ButtonSettings": "Settings",
"ButtonTakeScreenshot": "Capture Screenshot",
"ButtonLetterUp": "Letter Up",
@@ -661,6 +730,8 @@
"ButtonScenes": "Scenes",
"ButtonSubtitles": "Subtitles",
"ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Group movies into collections",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
"LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "Friendly name",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text",
"HeaderSearchForSubtitles": "Search for Subtitles",
@@ -796,13 +879,13 @@
"OptionAuto": "Auto",
"OptionYes": "Yes",
"OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferences",
"MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Mark Read",
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
"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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
"ButtonDismiss": "Dismiss",
"MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Display adult content",
"OptionLibraryFolders": "Media folders",
"TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 838d947cd..50a794ec8 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json
@@ -1,134 +1,196 @@
{
- "LabelMediaBrowser": "Media Browser",
- "OptionNotifyOnPlayback": "When users play content",
- "HeaderEnableNotificationForEvents": "Nofity administrative users when:",
- "HeaderEnableNotificationForPlayback": "Notify when users play:",
- "OptionNotifyOnUpdates": "Updates available",
- "OptionNotifyOnVideoPlayback": "Video playback",
- "OptionNotifyOnAudioPlayback": "Audio playback",
- "OptionNotifyOnGamePlayback": "Games playback",
- "OptionNotifyOnFailedTasks": "Scheduled task failure",
- "OptionNotifyOnNewLibraryContent": "New library content added",
- "OptionNotifyOnServerRestartRequired": "Server restart required",
- "NotificationOptionUpdatesAvailable": "Updates available",
- "NotificationOptionFailedTasks": "Scheduled task failure",
- "TabUpdates": "\u66f4\u65b0",
- "HeaderUpdateLevel": "\u66f4\u65b0\u7d1a\u5225",
- "LabelRequireTextSubtitles": "Download even if the video already contains graphical subtitles",
- "LabelRequireTextSubtitlesHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
- "HeaderSubtitleDownloadingMoreHelp": "Subtitles are considered missing when the audio track is in a foreign language, and there are no subtitles available in the preferred language.",
- "LabelDisplayForcedSubtitlesOnly": "\u53ea\u986f\u793a\u5f37\u5236\u5b57\u5e55",
- "HeaderCustomizeOptionsPerMediaType": "\u81ea\u5b9a\u7fa9\u6bcf\u500b\u5a92\u9ad4\u985e\u578b\u7684\u9078\u9805",
- "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
- "TabCustomizations": "Customizations",
- "HeaderAllDevices": "All Devices",
- "HeaderThisDevice": "This Device",
- "OptionLibraryButtons": "Library buttons",
- "OptionLibraryTiles": "Library tiles (large)",
- "OptionSmallLibraryTiles": "Library tiles (small)",
- "ButtonPlayTrailer": "\u9810\u544a",
- "LabelFailed": "Failed",
- "LabelSeries": "Series:",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "HeaderMyLibrary": "My Library",
- "HeaderLibraryViews": "Library Views",
+ "HeaderPeople": "People",
"LabelExit": "\u96e2\u958b",
+ "HeaderDownloadPeopleMetadataFor": "Download biography and images for:",
"LabelVisitCommunity": "\u8a2a\u554f\u793e\u5340",
+ "OptionComposers": "Composers",
"LabelGithubWiki": "Github \u7ef4\u57fa",
+ "OptionOthers": "Others",
"LabelSwagger": "Swagger",
"LabelStandard": "\u6a19\u6dee",
+ "HeaderDownloadPeopleMetadataForHelp": "Enabling additional options will provide more on-screen information but will result in slower library scans.",
"LabelViewApiDocumentation": "\u67e5\u770bAPI\u6587\u6a94",
+ "ViewTypeFolders": "Folders",
"LabelBrowseLibrary": "\u700f\u89bd\u5a92\u9ad4\u5eab",
+ "LabelDisplayFoldersView": "Display a folders view to show plain media folders",
"LabelConfigureMediaBrowser": "\u8a2d\u5b9aMedia Browser",
+ "ViewTypeLiveTvRecordingGroups": "Recordings",
"LabelOpenLibraryViewer": "\u6253\u958b\u5a92\u9ad4\u5eab\u700f\u89bd\u5668",
+ "ViewTypeLiveTvChannels": "Channels",
"LabelRestartServer": "\u91cd\u65b0\u555f\u52d5\u4f3a\u5668\u670d",
+ "LabelAllowLocalAccessWithoutPassword": "Allow local access without a password",
"LabelShowLogWindow": "\u986f\u793a\u65e5\u8a8c",
+ "LabelAllowLocalAccessWithoutPasswordHelp": "When enabled, a password will not be required when signing in from within your home network.",
"LabelPrevious": "\u4e0a\u4e00\u500b",
+ "HeaderPassword": "Password",
"LabelFinish": "\u5b8c\u7d50",
+ "HeaderLocalAccess": "Local Access",
"LabelNext": "\u4e0b\u4e00\u500b",
+ "HeaderViewOrder": "View Order",
"LabelYoureDone": "\u5b8c\u6210!",
+ "LabelSelectUserViewOrder": "Choose the order your views will be displayed in within Media Browser apps",
"WelcomeToMediaBrowser": "\u6b61\u8fce\u4f86\u5230 Media Browser\uff01",
+ "LabelMetadataRefreshMode": "Metadata refresh mode:",
"TitleMediaBrowser": "Media Browser",
+ "LabelImageRefreshMode": "Image refresh mode:",
"ThisWizardWillGuideYou": "\u56ae\u5c0e\u5c07\u5f15\u5c0e\u4f60\u5b8c\u6210\u5b89\u88dd\u7a0b\u5e8f\u3002",
+ "OptionDownloadMissingImages": "Download missing images",
"TellUsAboutYourself": "\u8acb\u4ecb\u7d39\u4e00\u4e0b\u81ea\u5df1",
+ "OptionReplaceExistingImages": "Replace existing images",
"LabelYourFirstName": "\u4f60\u7684\u540d\u5b57\uff1a",
+ "OptionRefreshAllData": "Refresh all data",
"MoreUsersCanBeAddedLater": "\u5f80\u5f8c\u53ef\u4ee5\u5728\u63a7\u5236\u53f0\u5167\u6dfb\u52a0\u66f4\u591a\u7528\u6236\u3002",
+ "OptionAddMissingDataOnly": "Add missing data only",
"UserProfilesIntro": "Media Browser \u5167\u7f6e\u652f\u6301\u591a\u500b\u7528\u6236\u914d\u7f6e\uff0c\u4f7f\u6bcf\u500b\u7528\u6236\u90fd\u64c1\u6709\u81ea\u5df1\u5c08\u5c6c\u7684\u986f\u793a\u8a2d\u7f6e\uff0c\u64ad\u653e\u72c0\u614b\u548c\u5bb6\u9577\u63a7\u5236\u8a2d\u7f6e\u3002",
+ "OptionLocalRefreshOnly": "Local refresh only",
"LabelWindowsService": "Windows\u670d\u52d9",
+ "HeaderRefreshMetadata": "Refresh Metadata",
"AWindowsServiceHasBeenInstalled": "Windows\u670d\u52d9\u5df2\u7d93\u5b89\u88dd\u5b8c\u7562\u3002",
+ "HeaderPersonInfo": "Person Info",
"WindowsServiceIntro1": "Media Browser \u4f3a\u670d\u5668\u901a\u5e38\u6703\u4f5c\u70ba\u4e00\u500b\u6709\u7a0b\u5f0f\u76e4\u5716\u6a19\u7684\u684c\u9762\u61c9\u7528\u7a0b\u5f0f\u904b\u884c\uff0c\u4f46\u5982\u679c\u4f60\u66f4\u559c\u6b61\u5c07\u5b83\u4f5c\u70ba\u5f8c\u53f0\u670d\u52d9\uff0c\u5b83\u53ef\u4ee5\u5f9eWindows\u670d\u52d9\u63a7\u5236\u53f0\u555f\u52d5\u3002",
+ "HeaderIdentifyItem": "Identify Item",
"WindowsServiceIntro2": "\u5982\u679c\u4f7f\u7528Windows\u670d\u52d9\uff0c\u8acb\u6ce8\u610f\uff0c\u5b83\u4e0d\u80fd\u540c\u6642\u4f5c\u70ba\u7a0b\u5f0f\u76e4\u5716\u6a19\u684c\u9762\u61c9\u7528\u7a0b\u5f0f\u904b\u884c\uff0c\u6240\u4ee5\u4f60\u9700\u8981\u5f9e\u7a0b\u5f0f\u76e4\u5716\u6a19\u9000\u51fa\uff0c\u4ee5\u904b\u884cWindows\u670d\u52d9\u3002\u8a72\u670d\u52d9\u9084\u9700\u8981\u5177\u6709\u7ba1\u7406\u54e1\u6b0a\u9650\uff0c\u9019\u53ef\u4ee5\u901a\u904eWindows\u670d\u52d9\u63a7\u5236\u53f0\u9032\u884c\u914d\u7f6e\u3002\u8acb\u6ce8\u610f\uff0c\u6b64\u6642\u7684 Media Browser \u4f3a\u670d\u5668\u670d\u52d9\u662f\u7121\u6cd5\u81ea\u52d5\u66f4\u65b0\uff0c\u56e0\u6b64\u65b0\u7248\u672c\u5c07\u9700\u8981\u624b\u52d5\u66f4\u65b0\u3002",
+ "HeaderIdentifyItemHelp": "Enter one or more search criteria. Remove criteria to increase search results.",
"WizardCompleted": "\u9019\u5c31\u662f\u6211\u5011\u73fe\u5728\u6240\u9700\u8981\u77e5\u9053\u7684\u3002Media Browser \u5df2\u7d93\u958b\u59cb\u6536\u96c6\u4f60\u7684\u5a92\u9ad4\u5eab\u7684\u8cc7\u6599\u3002\u8acb\u7e7c\u7e8c\u700f\u89bd\u6211\u5011\u5176\u4ed6\u7684\u7a0b\u5f0f\uff0c\u7136\u5f8c\u55ae\u64ca<b>\u5b8c\u6210<\/b>\u4f86\u67e5\u770b<b>\u63a7\u5236\u53f0<\/b>\u3002",
+ "HeaderConfirmDeletion": "Confirm Deletion",
"LabelConfigureSettings": "\u914d\u7f6e\u8a2d\u5b9a",
+ "LabelFollowingFileWillBeDeleted": "The following file will be deleted:",
"LabelEnableVideoImageExtraction": "\u555f\u52d5\u8996\u983b\u622a\u5716\u63d0\u53d6",
+ "LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"VideoImageExtractionHelp": "\u5c0d\u65bc\u6c92\u6709\u622a\u5716\u4ee5\u53ca\u6211\u5011\u76ee\u524d\u7121\u6cd5\u5f9e\u4e92\u806f\u7db2\u627e\u5230\u6709\u95dc\u622a\u5716\u7684\u8996\u983b\uff0c\u5728\u521d\u59cb\u5a92\u9ad4\u5eab\u6383\u63cf\u6642\uff0c\u6703\u589e\u52a0\u4e00\u4e9b\u984d\u5916\u7684\u6383\u63cf\u6642\u9593\uff0c\u4f46\u4f60\u5c07\u6703\u770b\u5230\u4e00\u500b\u66f4\u6085\u76ee\u7684\u4ecb\u7d39\u4ecb\u9762\u3002",
+ "ButtonIdentify": "Identify",
"LabelEnableChapterImageExtractionForMovies": "\u63d0\u53d6\u96fb\u5f71\u7ae0\u7bc0\u622a\u5716",
+ "LabelAlbumArtist": "Album artist:",
"LabelChapterImageExtractionForMoviesHelp": "\u5f9e\u8996\u983b\u7ae0\u7bc0\u4e2d\u63d0\u53d6\u622a\u5716\u5c07\u5141\u8a31\u5ba2\u6236\u7aef\u7528\u5716\u50cf\u986f\u793a\u9078\u64c7\u83dc\u55ae\u3002\u9019\u500b\u904e\u7a0b\u53ef\u80fd\u6703\u5f88\u6162\uff0c\u4f54\u7528\u66f4\u591a\u7684CPU\u8cc7\u6e90\uff0c\u4e26\u4e14\u53ef\u80fd\u9700\u8981\u7684\u6578GB\u786c\u789f\u7a7a\u9593\u3002\u5b83\u9ed8\u8a8d\u9810\u5b9a\u5728\u6bcf\u665a\u7684\u51cc\u66684\u9ede\u904b\u884c\uff0c\u4f46\u9019\u662f\u53ef\u4ee5\u5f9e\u4efb\u52d9\u8868\u9032\u884c\u8a2d\u5b9a\u7684\u3002\u4e0d\u5efa\u8b70\u5728\u9ad8\u5cf0\u4f7f\u7528\u6642\u9593\u904b\u884c\u6b64\u4efb\u52d9\u3002",
+ "LabelAlbum": "Album:",
"LabelEnableAutomaticPortMapping": "\u555f\u7528\u81ea\u52d5\u7aef\u53e3\u8f49\u767c",
+ "LabelCommunityRating": "Community rating:",
"LabelEnableAutomaticPortMappingHelp": "UPnP\u5141\u8a31\u8def\u7531\u5668\u81ea\u52d5\u8a2d\u7f6e\u5f9e\u800c\u53ef\u4ee5\u66f4\u65b9\u4fbf\u5730\u9060\u7a0b\u8a2a\u554f\u4f3a\u670d\u5668\u3002\u9019\u53ef\u80fd\u4e0d\u9069\u7528\u65bc\u67d0\u4e9b\u8def\u7531\u5668\u578b\u865f\u3002",
+ "LabelVoteCount": "Vote count:",
"ButtonOk": "OK",
+ "LabelMetascore": "Metascore:",
"ButtonCancel": "\u53d6\u6d88",
+ "LabelCriticRating": "Critic rating:",
"ButtonNew": "\u5275\u5efa",
+ "LabelCriticRatingSummary": "Critic rating summary:",
"HeaderSetupLibrary": "\u8a2d\u7f6e\u4f60\u7684\u5a92\u9ad4\u5eab",
+ "LabelAwardSummary": "Award summary:",
"ButtonAddMediaFolder": "\u6dfb\u52a0\u5a92\u9ad4\u6587\u4ef6\u593e",
+ "LabelWebsite": "Website:",
"LabelFolderType": "\u5a92\u9ad4\u6587\u4ef6\u593e\u985e\u578b\uff1a",
+ "LabelTagline": "Tagline:",
"MediaFolderHelpPluginRequired": "*\u9700\u8981\u4f7f\u7528\u4e00\u500b\u63d2\u4ef6\uff0c\u4f8b\u5982GameBrowser\u6216MB Bookshelf\u3002",
+ "LabelOverview": "Overview:",
"ReferToMediaLibraryWiki": "\u53c3\u7167\u5a92\u9ad4\u5eab\u7ef4\u57fa",
+ "LabelShortOverview": "Short overview:",
"LabelCountry": "\u570b\u5bb6\uff1a",
+ "LabelReleaseDate": "Release date:",
"LabelLanguage": "\u8a9e\u8a00\uff1a",
+ "LabelYear": "Year:",
"HeaderPreferredMetadataLanguage": "\u9996\u9078\u5a92\u9ad4\u8cc7\u6599\u8a9e\u8a00\uff1a",
+ "LabelPlaceOfBirth": "Place of birth:",
"LabelSaveLocalMetadata": "\u4fdd\u5b58\u5a92\u9ad4\u5716\u50cf\u53ca\u8cc7\u6599\u5230\u5a92\u9ad4\u6a94\u6848\u6240\u5728\u7684\u6587\u4ef6\u593e",
+ "LabelEndDate": "End date:",
"LabelSaveLocalMetadataHelp": "\u76f4\u63a5\u4fdd\u5b58\u5a92\u9ad4\u5716\u50cf\u53ca\u8cc7\u6599\u5230\u5a92\u9ad4\u6240\u5728\u7684\u6587\u4ef6\u593e\u80fd\u4f7f\u7de8\u8f2f\u5de5\u4f5c\u66f4\u5bb9\u6613\u3002",
+ "LabelAirDate": "Air days:",
"LabelDownloadInternetMetadata": "\u5f9e\u4e92\u806f\u7db2\u4e0b\u8f09\u5a92\u9ad4\u5716\u50cf\u53ca\u8cc7\u6599",
+ "LabelAirTime:": "Air time:",
"LabelDownloadInternetMetadataHelp": "Media Browser\u53ef\u4ee5\u5f9e\u4e92\u806f\u7db2\u4e0b\u8f09\u5a92\u9ad4\u5716\u50cf\u53ca\u8cc7\u6599\u5f9e\u800c\u63d0\u4f9b\u66f4\u8c50\u5bcc\u7684\u5a92\u9ad4\u8868\u9054\u65b9\u5f0f\u3002",
+ "LabelRuntimeMinutes": "Run time (minutes):",
"TabPreferences": "\u504f\u597d",
+ "LabelParentalRating": "Parental rating:",
"TabPassword": "\u5bc6\u78bc",
+ "LabelCustomRating": "Custom rating:",
"TabLibraryAccess": "\u5a92\u9ad4\u5eab\u700f\u89bd\u6b0a\u9650",
+ "LabelBudget": "Budget",
"TabImage": "\u5716\u50cf",
+ "LabelRevenue": "Revenue ($):",
"TabProfile": "\u914d\u7f6e",
+ "LabelOriginalAspectRatio": "Original aspect ratio:",
"TabMetadata": "\u5a92\u9ad4\u8cc7\u6599",
+ "LabelPlayers": "Players:",
"TabImages": "\u5716\u50cf",
+ "Label3DFormat": "3D format:",
"TabNotifications": "Notifications",
+ "HeaderAlternateEpisodeNumbers": "Alternate Episode Numbers",
"TabCollectionTitles": "\u6a19\u984c",
+ "HeaderSpecialEpisodeInfo": "Special Episode Info",
"LabelDisplayMissingEpisodesWithinSeasons": "\u986f\u793a\u7bc0\u76ee\u5b63\u5ea6\u5167\u7f3a\u5c11\u7684\u55ae\u5143",
+ "HeaderExternalIds": "External Id's:",
"LabelUnairedMissingEpisodesWithinSeasons": "\u5728\u7bc0\u76ee\u5b63\u5ea6\u5167\u986f\u793a\u9084\u672a\u767c\u4f48\u7684\u55ae\u5143",
+ "LabelDvdSeasonNumber": "Dvd season number:",
"HeaderVideoPlaybackSettings": "\u8996\u983b\u56de\u653e\u8a2d\u7f6e",
+ "LabelDvdEpisodeNumber": "Dvd episode number:",
"HeaderPlaybackSettings": "Playback Settings",
+ "LabelAbsoluteEpisodeNumber": "Absolute episode number:",
"LabelAudioLanguagePreference": "\u97f3\u983b\u8a9e\u8a00\u504f\u597d\u9078\u9805\uff1a",
+ "LabelAirsBeforeSeason": "Airs before season:",
"LabelSubtitleLanguagePreference": "\u5b57\u5e55\u8a9e\u8a00\u504f\u597d\u9078\u9805\uff1a",
+ "LabelAirsAfterSeason": "Airs after season:",
"OptionDefaultSubtitles": "Default",
+ "LabelAirsBeforeEpisode": "Airs before episode:",
"OptionOnlyForcedSubtitles": "Only forced subtitles",
+ "LabelTreatImageAs": "Treat image as:",
"OptionAlwaysPlaySubtitles": "Always play subtitles",
+ "LabelDisplayOrder": "Display order:",
"OptionNoSubtitles": "No Subtitles",
+ "LabelDisplaySpecialsWithinSeasons": "Display specials within seasons they aired in",
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
+ "HeaderCountries": "Countries",
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
+ "HeaderGenres": "Genres",
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
+ "HeaderPlotKeywords": "Plot Keywords",
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
+ "HeaderStudios": "Studios",
"TabProfiles": "\u914d\u7f6e",
+ "HeaderTags": "Tags",
"TabSecurity": "\u5b89\u5168\u6027",
+ "HeaderMetadataSettings": "Metadata Settings",
"ButtonAddUser": "\u6dfb\u52a0\u7528\u6236",
+ "LabelLockItemToPreventChanges": "Lock this item to prevent future changes",
"ButtonSave": "\u4fdd\u5b58",
+ "MessageLeaveEmptyToInherit": "Leave empty to inherit settings from a parent item, or the global default value.",
"ButtonResetPassword": "\u91cd\u8a2d\u5bc6\u78bc",
+ "TabSupporterClub": "Supporter Club",
"LabelNewPassword": "\u65b0\u5bc6\u78bc\uff1a",
+ "HeaderDonationType": "Donation type:",
"LabelNewPasswordConfirm": "\u78ba\u8a8d\u65b0\u5bc6\u78bc\uff1a",
+ "OptionMakeOneTimeDonation": "Make a separate donation",
"HeaderCreatePassword": "\u5275\u5efa\u5bc6\u78bc",
+ "OptionOneTimeDescription": "This is an additional donation to the team to show your support. It does not have any additional benefits.",
"LabelCurrentPassword": "\u7576\u524d\u7684\u5bc6\u78bc\uff1a",
+ "OptionLifeTimeSupporterClubMembership": "Lifetime supporter club membership",
"LabelMaxParentalRating": "\u6700\u5927\u5141\u8a31\u7684\u5bb6\u9577\u8a55\u7d1a\uff1a",
+ "HeaderSupporterBenefit": "Becoming a supporter club member provides additional benefits such as access to premium plugins, internet channel content, and more.",
"MaxParentalRatingHelp": "\u5177\u6709\u8f03\u9ad8\u7684\u5bb6\u9577\u8a55\u7d1a\u5167\u5bb9\u5c07\u5f9e\u9019\u7528\u6236\u88ab\u96b1\u85cf",
+ "OptionNoTrailer": "No Trailer",
"LibraryAccessHelp": "\u9078\u64c7\u5a92\u9ad4\u6587\u4ef6\u593e\u8207\u9019\u7528\u6236\u5171\u4eab\u3002\u7ba1\u7406\u54e1\u5c07\u53ef\u4ee5\u4f7f\u7528\u5a92\u9ad4\u8cc7\u6599\u64da\u7ba1\u7406\u5668\u7de8\u8f2f\u6240\u6709\u7684\u5a92\u9ad4\u6587\u4ef6\u593e\u3002",
+ "OptionNoThemeSong": "No Theme Song",
"ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "OptionNoThemeVideo": "No Theme Video",
"ButtonDeleteImage": "\u522a\u9664\u5716\u50cf",
+ "LabelOneTimeDonationAmount": "Donation amount:",
"LabelSelectUsers": "Select users:",
+ "OptionActor": "Actor",
"ButtonUpload": "\u4e0a\u8f09",
+ "OptionComposer": "Composer",
"HeaderUploadNewImage": "\u4e0a\u8f09\u65b0\u5716\u50cf",
+ "OptionDirector": "Director",
"LabelDropImageHere": "\u5728\u9019\u88e1\u653e\u4e0b\u5716\u50cf",
+ "OptionGuestStar": "Guest star",
"ImageUploadAspectRatioHelp": "\u63a8\u85a6\u4f7f\u67091:1\u5bec\u9ad8\u6bd4\u4f8b\u7684\u5716\u50cf\u3002\u53ea\u5141\u8a31JPG\/PNG\u683c\u5f0f",
+ "OptionProducer": "Producer",
"MessageNothingHere": "\u9019\u88e1\u6c92\u6709\u4ec0\u9ebc\u3002",
+ "OptionWriter": "Writer",
"MessagePleaseEnsureInternetMetadata": "\u8acb\u78ba\u4fdd\u5df2\u555f\u7528\u5f9e\u4e92\u806f\u7db2\u4e0b\u8f09\u5a92\u9ad4\u8cc7\u6599\u3002",
+ "LabelAirDays": "Air days:",
"TabSuggested": "\u5efa\u8b70",
+ "LabelAirTime": "Air time:",
"TabLatest": "\u6700\u65b0",
+ "HeaderMediaInfo": "Media Info",
"TabUpcoming": "\u5373\u5c07\u767c\u5e03",
+ "HeaderPhotoInfo": "Photo Info",
"TabShows": "\u7bc0\u76ee",
"TabEpisodes": "\u55ae\u5143",
"TabGenres": "\u985e\u578b",
@@ -163,7 +225,7 @@
"OptionAscending": "\u5347\u5e8f",
"OptionDescending": "\u964d\u5e8f",
"OptionRuntime": "\u64ad\u653e\u9577\u5ea6",
- "OptionReleaseDate": "\u767c\u5e03\u65e5\u671f",
+ "OptionReleaseDate": "Release Date",
"OptionPlayCount": "\u64ad\u653e\u6b21\u6578",
"OptionDatePlayed": "\u64ad\u653e\u65e5\u671f",
"OptionDateAdded": "\u6dfb\u52a0\u65e5\u671f",
@@ -213,6 +275,8 @@
"TabMovies": "\u96fb\u5f71",
"TabStudios": "\u5de5\u4f5c\u5ba4",
"TabTrailers": "\u9810\u544a",
+ "LabelArtists": "Artists:",
+ "LabelArtistsHelp": "Separate multiple using ;",
"HeaderLatestMovies": "\u6700\u65b0\u96fb\u5f71",
"HeaderLatestTrailers": "\u6700\u65b0\u9810\u544a",
"OptionHasSpecialFeatures": "Special Features",
@@ -233,6 +297,7 @@
"OptionFriday": "\u661f\u671f\u4e94",
"OptionSaturday": "\u661f\u671f\u516d",
"HeaderManagement": "\u7ba1\u7406\uff1a",
+ "LabelManagement": "Management:",
"OptionMissingImdbId": "\u7f3a\u5c11IMDB\u7de8\u865f",
"OptionMissingTvdbId": "\u7f3a\u5c11TheTVDB\u7de8\u865f",
"OptionMissingOverview": "\u7f3a\u5c11\u6982\u8ff0",
@@ -266,7 +331,6 @@
"OptionIsSD": "\u6a19\u6e05",
"OptionMetascore": "\u8a55\u5206",
"ButtonSelect": "\u9078\u64c7",
- "ButtonSearch": "\u641c\u7d22",
"ButtonGroupVersions": "\u7248\u672c",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "\u901a\u904e\u6350\u8d08\u7684\u8edf\u4ef6\u8a31\u53ef\u8b49\u4f7f\u7528Pismo File Mount\u3002",
@@ -294,9 +358,9 @@
"LabelImagesByNamePath": "\u540d\u7a31\u5716\u50cf\u6587\u4ef6\u593e\u8def\u5f91\uff1a",
"LabelImagesByNamePathHelp": "\u6b64\u6587\u4ef6\u593e\u5305\u542b\u6f14\u54e1\uff0c\u6b4c\u624b\uff0c\u5a92\u9ad4\u7a2e\u985e\u548c\u5de5\u4f5c\u5ba4\u7684\u5716\u50cf\u3002",
"LabelMetadataPath": "\u5a92\u9ad4\u8cc7\u6599\u6587\u4ef6\u593e\u8def\u5f91\uff1a",
- "LabelMetadataPathHelp": "This location contains downloaded artwork and metadata that is not configured to be stored in media folders.",
+ "LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.",
"LabelTranscodingTempPath": "\u8f49\u78bc\u81e8\u6642\u8def\u5f91\uff1a",
- "LabelTranscodingTempPathHelp": "This folder contains working files used by the transcoder.",
+ "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": "\u57fa\u672c",
"TabTV": "\u96fb\u8996\u7bc0\u76ee",
"TabGames": "\u904a\u6232",
@@ -347,6 +411,8 @@
"TabStatus": "Status",
"TabSettings": "\u8a2d\u5b9a",
"ButtonRefreshGuideData": "\u5237\u65b0\u96fb\u8996\u6307\u5357\u8cc7\u6599",
+ "ButtonRefresh": "Refresh",
+ "ButtonAdvancedRefresh": "Advanced Refresh",
"OptionPriority": "\u512a\u5148",
"OptionRecordOnAllChannels": "\u9304\u5f71\u6240\u4ee5\u983b\u5ea6\u7684\u7bc0\u76ee",
"OptionRecordAnytime": "\u9304\u5f71\u6240\u6709\u6642\u6bb5\u7684\u7bc0\u76ee",
@@ -430,6 +496,7 @@
"HeaderCastCrew": "\u62cd\u651d\u4eba\u54e1\u53ca\u6f14\u54e1",
"HeaderAdditionalParts": "\u9644\u52a0\u90e8\u4efd",
"ButtonSplitVersionsApart": "Split Versions Apart",
+ "ButtonPlayTrailer": "Trailer",
"LabelMissing": "\u7f3a\u5c11",
"LabelOffline": "\u96e2\u7dda",
"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.",
@@ -512,11 +579,13 @@
"HeaderProgram": "Program",
"HeaderClients": "Clients",
"LabelCompleted": "Completed",
+ "LabelFailed": "Failed",
"LabelSkipped": "Skipped",
"HeaderEpisodeOrganization": "Episode Organization",
- "LabelSeasonNumber": "Season number",
- "LabelEpisodeNumber": "Episode number",
- "LabelEndingEpisodeNumber": "Ending episode number",
+ "LabelSeries": "Series:",
+ "LabelSeasonNumber": "Season number:",
+ "LabelEpisodeNumber": "Episode number:",
+ "LabelEndingEpisodeNumber": "Ending episode number:",
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
"HeaderSupportTheTeam": "Support the Media Browser Team",
"LabelSupportAmount": "Amount (USD)",
@@ -625,7 +694,6 @@
"LabelNotificationEnabled": "Enable this notification",
"LabelMonitorUsers": "Monitor activity from:",
"LabelSendNotificationToUsers": "Send the notification to:",
- "UsersNotNotifiedAboutSelfActivity": "Users will not be notified about their own activities.",
"LabelUseNotificationServices": "Use the following services:",
"CategoryUser": "User",
"CategorySystem": "System",
@@ -648,6 +716,7 @@
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
"ButtonHome": "Home",
+ "ButtonSearch": "\u641c\u7d22",
"ButtonSettings": "Settings",
"ButtonTakeScreenshot": "Capture Screenshot",
"ButtonLetterUp": "Letter Up",
@@ -661,6 +730,8 @@
"ButtonScenes": "Scenes",
"ButtonSubtitles": "Subtitles",
"ButtonAudioTracks": "Audio tracks",
+ "ButtonPreviousTrack": "Previous track",
+ "ButtonNextTrack": "Next track",
"ButtonStop": "Stop",
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Group movies into collections",
@@ -676,6 +747,8 @@
"LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
"HeaderResponseProfile": "Response Profile",
"LabelType": "Type:",
+ "LabelPersonRole": "Role:",
+ "LabelPersonRoleHelp": "Role is generally only applicable to actors.",
"LabelProfileContainer": "Container:",
"LabelProfileVideoCodecs": "Video codecs:",
"LabelProfileAudioCodecs": "Audio codecs:",
@@ -719,6 +792,14 @@
"HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
+ "LabelMaxStreamingBitrate": "Max streaming bitrate:",
+ "LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
+ "LabelMaxStaticBitrate": "Max sync bitrate:",
+ "LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
+ "LabelMusicStaticBitrate": "Music sync bitrate:",
+ "LabelMusicStaticBitrateHelp": "Specify a max bitrate when syncing music",
+ "LabelMusicStreamingTranscodingBitrate": "Music transcoding bitrate:",
+ "LabelMusicStreamingTranscodingBitrateHelp": "Specify a max bitrate when streaming music",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "Friendly name",
@@ -773,13 +854,15 @@
"LabelDisplayPluginsFor": "Display plugins for:",
"PluginTabMediaBrowserClassic": "MB Classic",
"PluginTabMediaBrowserTheater": "MB Theater",
- "TabOtherPlugins": "Others",
- "LabelEpisodeName": "Episode name",
- "LabelSeriesName": "Series name",
+ "LabelEpisodeNamePlain": "Episode name",
+ "LabelSeriesNamePlain": "Series name",
"ValueSeriesNamePeriod": "Series.name",
"ValueSeriesNameUnderscore": "Series_name",
"ValueEpisodeNamePeriod": "Episode.name",
"ValueEpisodeNameUnderscore": "Episode_name",
+ "LabelSeasonNumberPlain": "Season number",
+ "LabelEpisodeNumberPlain": "Episode number",
+ "LabelEndingEpisodeNumberPlain": "Ending episode number",
"HeaderTypeText": "Enter Text",
"LabelTypeText": "Text",
"HeaderSearchForSubtitles": "Search for Subtitles",
@@ -796,13 +879,13 @@
"OptionAuto": "Auto",
"OptionYes": "Yes",
"OptionNo": "No",
- "LabelHomePageSection1": "Home page section one:",
- "LabelHomePageSection2": "Home page section two:",
- "LabelHomePageSection3": "Home page section three:",
- "LabelHomePageSection4": "Home page section four:",
- "OptionMyLibraryButtons": "My library (buttons)",
- "OptionMyLibrary": "My library",
- "OptionMyLibrarySmall": "My library (small)",
+ "LabelHomePageSection1": "Home page section 1:",
+ "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)",
"OptionResumablemedia": "Resume",
"OptionLatestMedia": "Latest media",
"OptionLatestChannelMedia": "Latest channel items",
@@ -813,12 +896,15 @@
"HeaderMetadataManager": "Metadata Manager",
"HeaderPreferences": "Preferences",
"MessageLoadingChannels": "Loading channel content...",
+ "MessageLoadingContent": "Loading content...",
"ButtonMarkRead": "Mark Read",
"OptionDefaultSort": "Default",
"OptionCommunityMostWatchedSort": "Most Watched",
"TabNextUp": "Next Up",
"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 New 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.",
+ "MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
"ButtonDismiss": "Dismiss",
"MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
@@ -848,5 +934,165 @@
"OptionDisplayAdultContent": "Display adult content",
"OptionLibraryFolders": "Media folders",
"TitleRemoteControl": "Remote Control",
- "OptionLatestTvRecordings": "Latest recordings"
+ "OptionLatestTvRecordings": "Latest recordings",
+ "LabelProtocolInfo": "Protocol info:",
+ "LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
+ "TabXbmcMetadata": "Xbmc",
+ "HeaderXbmcMetadataHelp": "Media Browser includes native support for Xbmc Nfo metadata and images. To enable or disable Xbmc metadata, use the Advanced tab to configure options for your media types.",
+ "LabelXbmcMetadataUser": "Add user watch data to nfo's for:",
+ "LabelXbmcMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Xbmc.",
+ "LabelXbmcMetadataDateFormat": "Release date format:",
+ "LabelXbmcMetadataDateFormatHelp": "All dates within nfo's will be read and written to using this format.",
+ "LabelXbmcMetadataSaveImagePaths": "Save image paths within nfo files",
+ "LabelXbmcMetadataSaveImagePathsHelp": "This is recommended if you have image file names that don't conform to Xbmc guidelines.",
+ "LabelXbmcMetadataEnablePathSubstitution": "Enable path substitution",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp": "Enables path substitution of image paths using the server's path substitution settings.",
+ "LabelXbmcMetadataEnablePathSubstitutionHelp2": "See path substitution.",
+ "LabelGroupChannelsIntoViews": "Display the following channels directly within my views:",
+ "LabelGroupChannelsIntoViewsHelp": "If enabled, these channels will be displayed directly alongside other views. If disabled, they'll be displayed within a separate Channels view.",
+ "LabelDisplayCollectionsView": "Display a collections view to show movie collections",
+ "LabelXbmcMetadataEnableExtraThumbs": "Copy extrafanart into extrathumbs",
+ "LabelXbmcMetadataEnableExtraThumbsHelp": "When downloading images they can be saved into both extrafanart and extrathumbs for maximum Xbmc skin compatibility.",
+ "TabServices": "Services",
+ "TabLogs": "Logs",
+ "HeaderServerLogFiles": "Server log files:",
+ "TabBranding": "Branding",
+ "HeaderBrandingHelp": "Customize the appearance of Media Browser to fit the needs of your group or organization.",
+ "LabelLoginDisclaimer": "Login disclaimer:",
+ "LabelLoginDisclaimerHelp": "This will be displayed at the bottom of the login page.",
+ "LabelAutomaticallyDonate": "Automatically donate this amount every month",
+ "LabelAutomaticallyDonateHelp": "You can cancel at any time via your PayPal account.",
+ "OptionList": "List",
+ "TabDashboard": "Dashboard",
+ "TitleServer": "Server",
+ "LabelCache": "Cache:",
+ "LabelLogs": "Logs:",
+ "LabelMetadata": "Metadata:",
+ "LabelImagesByName": "Images by name:",
+ "LabelTranscodingTemporaryFiles": "Transcoding temporary files:",
+ "HeaderLatestMusic": "Latest Music",
+ "HeaderBranding": "Branding",
+ "HeaderApiKeys": "Api Keys",
+ "HeaderApiKeysHelp": "External applications are required to have an Api key in order to communicate with Media Browser. Keys are issued by logging in with a Media Browser account, or by manually granting the application a key.",
+ "HeaderApiKey": "Api Key",
+ "HeaderApp": "App",
+ "HeaderDevice": "Device",
+ "HeaderUser": "User",
+ "HeaderDateIssued": "Date Issued",
+ "LabelChapterName": "Chapter {0}",
+ "HeaderNewApiKey": "New Api Key",
+ "LabelAppName": "App name",
+ "LabelAppNameExample": "Example: Sickbeard, NzbDrone",
+ "HeaderNewApiKeyHelp": "Grant an application permission to communicate with Media Browser.",
+ "HeaderHttpHeaders": "Http Headers",
+ "HeaderIdentificationHeader": "Identification Header",
+ "LabelValue": "Value:",
+ "LabelMatchType": "Match type:",
+ "OptionEquals": "Equals",
+ "OptionRegex": "Regex",
+ "OptionSubstring": "Substring",
+ "TabView": "View",
+ "TabSort": "Sort",
+ "TabFilter": "Filter",
+ "ButtonView": "View",
+ "LabelPageSize": "Item limit:",
+ "LabelPath": "Path:",
+ "LabelView": "View:",
+ "TabUsers": "Users",
+ "LabelSortName": "Sort name:",
+ "LabelDateAdded": "Date added:",
+ "HeaderFeatures": "Features",
+ "HeaderAdvanced": "Advanced",
+ "ButtonSync": "Sync",
+ "TabScheduledTasks": "Scheduled Tasks",
+ "HeaderChapters": "Chapters",
+ "HeaderResumeSettings": "Resume Settings",
+ "TabSync": "Sync",
+ "TitleUsers": "Users",
+ "LabelProtocol": "Protocol:",
+ "OptionProtocolHttp": "Http",
+ "OptionProtocolHls": "Http Live Streaming",
+ "LabelContext": "Context:",
+ "OptionContextStreaming": "Streaming",
+ "OptionContextStatic": "Sync",
+ "ButtonAddToPlaylist": "Add to playlist",
+ "TabPlaylists": "Playlists",
+ "ButtonClose": "Close",
+ "LabelAllLanguages": "All languages",
+ "HeaderBrowseOnlineImages": "Browse Online Images",
+ "LabelSource": "Source:",
+ "OptionAll": "All",
+ "LabelImage": "Image:",
+ "ButtonBrowseImages": "Browse Images",
+ "HeaderImages": "Images",
+ "HeaderBackdrops": "Backdrops",
+ "HeaderScreenshots": "Screenshots",
+ "HeaderAddUpdateImage": "Add\/Update Image",
+ "LabelJpgPngOnly": "JPG\/PNG only",
+ "LabelImageType": "Image type:",
+ "OptionPrimary": "Primary",
+ "OptionArt": "Art",
+ "OptionBox": "Box",
+ "OptionBoxRear": "Box rear",
+ "OptionDisc": "Disc",
+ "OptionLogo": "Logo",
+ "OptionMenu": "Menu",
+ "OptionScreenshot": "Screenshot",
+ "OptionLocked": "Locked",
+ "OptionUnidentified": "Unidentified",
+ "OptionMissingParentalRating": "Missing parental rating",
+ "OptionStub": "Stub",
+ "HeaderEpisodes": "Episodes:",
+ "OptionSeason0": "Season 0",
+ "LabelReport": "Report:",
+ "OptionReportSongs": "Songs",
+ "OptionReportSeries": "Series",
+ "OptionReportSeasons": "Seasons",
+ "OptionReportTrailers": "Trailers",
+ "OptionReportMusicVideos": "Music videos",
+ "OptionReportMovies": "Movies",
+ "OptionReportHomeVideos": "Home videos",
+ "OptionReportGames": "Games",
+ "OptionReportEpisodes": "Episodes",
+ "OptionReportCollections": "Collections",
+ "OptionReportBooks": "Books",
+ "OptionReportArtists": "Artists",
+ "OptionReportAlbums": "Albums",
+ "OptionReportAdultVideos": "Adult videos",
+ "ButtonMore": "More",
+ "HeaderActivity": "Activity",
+ "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskCancelledWithName": "{0} was cancelled",
+ "ScheduledTaskCompletedWithName": "{0} completed",
+ "ScheduledTaskFailed": "Scheduled task completed",
+ "PluginInstalledWithName": "{0} was installed",
+ "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",
+ "DeviceOnlineWithName": "{0} is connected",
+ "UserOnlineFromDevice": "{0} is online from {1}",
+ "DeviceOfflineWithName": "{0} has disconnected",
+ "UserOfflineFromDevice": "{0} has disconnected from {1}",
+ "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
+ "LabelRunningTimeValue": "Running time: {0}",
+ "LabelIpAddressValue": "Ip address: {0}",
+ "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
+ "UserCreatedWithName": "User {0} has been created",
+ "UserPasswordChangedWithName": "Password has been changed for user {0}",
+ "UserDeletedWithName": "User {0} has been deleted",
+ "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "Media Browser Server has been updated",
+ "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "UserStartedPlayingItemWithValues": "{0} has started playing {1}",
+ "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
+ "AppDeviceValues": "App: {0}, Device: {1}",
+ "ProviderValue": "Provider: {0}",
+ "LabelChannelDownloadSizeLimit": "Download size limit (GB):",
+ "LabelChannelDownloadSizeLimitHelp": "Limit the size of the channel download folder",
+ "HeaderRecentActivity": "Recent Activity"
} \ 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 c6a105e22..bda147f68 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -45,15 +45,16 @@
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<ItemGroup>
- <Reference Include="Alchemy">
- <HintPath>..\packages\Alchemy.2.2.1\lib\net40\Alchemy.dll</HintPath>
+ <Reference Include="Imazen.WebP, Version=0.2.0.0, Culture=neutral, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\ThirdParty\libwebp\Imazen.WebP.dll</HintPath>
</Reference>
- <Reference Include="Mono.Nat, Version=1.2.13.0, Culture=neutral, processorArchitecture=MSIL">
+ <Reference Include="Mono.Nat, Version=1.2.21.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\Mono.Nat.1.2.13.0\lib\net40\Mono.Nat.dll</HintPath>
+ <HintPath>..\packages\Mono.Nat.1.2.21.0\lib\net40\Mono.Nat.dll</HintPath>
</Reference>
- <Reference Include="Nowin">
- <HintPath>..\ThirdParty\Nowin\Nowin.dll</HintPath>
+ <Reference Include="MoreLinq">
+ <HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Api.Swagger">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll</HintPath>
@@ -70,9 +71,6 @@
<Reference Include="System.Security" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
- <Reference Include="MoreLinq">
- <HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath>
- </Reference>
<Reference Include="System.Data.SQLite" Condition=" '$(ConfigurationName)' == 'Release Mono' ">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\ThirdParty\System.Data.SQLite.ManagedOnly\x86\1.0.90.0\net40\System.Data.SQLite.dll</HintPath>
@@ -96,11 +94,19 @@
<HintPath>..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="Mono.Posix" Condition=" '$(ConfigurationName)' == 'Release Mono' " />
+ <Reference Include="websocket-sharp, Version=1.0.2.508, Culture=neutral, PublicKeyToken=5660b08a1845a91e, processorArchitecture=MSIL">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\ThirdParty\WebsocketSharp\websocket-sharp.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
+ <Compile Include="Activity\ActivityManager.cs" />
+ <Compile Include="Activity\ActivityRepository.cs" />
+ <Compile Include="Branding\BrandingConfigurationFactory.cs" />
+ <Compile Include="Channels\ChannelConfigurations.cs" />
<Compile Include="Channels\ChannelDownloadScheduledTask.cs" />
<Compile Include="Channels\ChannelImageProvider.cs" />
<Compile Include="Channels\ChannelItemImageProvider.cs" />
@@ -110,11 +116,15 @@
<Compile Include="Collections\CollectionsDynamicFolder.cs" />
<Compile Include="Collections\ManualCollectionsFolder.cs" />
<Compile Include="Configuration\ServerConfigurationManager.cs" />
+ <Compile Include="Connect\ConnectData.cs" />
+ <Compile Include="Connect\ConnectManager.cs" />
+ <Compile Include="Connect\ServerRegistrationResponse.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" />
<Compile Include="EntryPoints\ExternalPortForwarding.cs" />
<Compile Include="EntryPoints\LibraryChangedNotifier.cs" />
@@ -124,7 +134,9 @@
<Compile Include="EntryPoints\Notifications\WebSocketNotifier.cs" />
<Compile Include="EntryPoints\RefreshUsersMetadata.cs" />
<Compile Include="EntryPoints\UsageEntryPoint.cs" />
+ <Compile Include="Connect\ConnectEntryPoint.cs" />
<Compile Include="FileOrganization\EpisodeFileOrganizer.cs" />
+ <Compile Include="FileOrganization\Extensions.cs" />
<Compile Include="FileOrganization\FileOrganizationService.cs" />
<Compile Include="FileOrganization\NameUtils.cs" />
<Compile Include="FileOrganization\TvFolderOrganizer.cs" />
@@ -132,6 +144,9 @@
<Compile Include="EntryPoints\ServerEventNotifier.cs" />
<Compile Include="EntryPoints\UserDataChangeNotifier.cs" />
<Compile Include="FileOrganization\OrganizerScheduledTask.cs" />
+ <Compile Include="HttpServer\NetListener\HttpListenerServer.cs" />
+ <Compile Include="HttpServer\IHttpListener.cs" />
+ <Compile Include="HttpServer\Security\AuthorizationContext.cs" />
<Compile Include="HttpServer\ContainerAdapter.cs" />
<Compile Include="HttpServer\GetSwaggerResource.cs" />
<Compile Include="HttpServer\HttpListenerHost.cs" />
@@ -140,17 +155,29 @@
<Compile Include="HttpServer\NativeWebSocket.cs" />
<Compile Include="HttpServer\RangeRequestWriter.cs" />
<Compile Include="HttpServer\ResponseFilter.cs" />
+ <Compile Include="HttpServer\Security\AuthService.cs" />
+ <Compile Include="HttpServer\Security\SessionAuthProvider.cs" />
<Compile Include="HttpServer\ServerFactory.cs" />
<Compile Include="HttpServer\ServerLogFactory.cs" />
<Compile Include="HttpServer\ServerLogger.cs" />
+ <Compile Include="HttpServer\Security\SessionContext.cs" />
+ <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="IO\LibraryMonitor.cs" />
<Compile Include="Library\CoreResolutionIgnoreRule.cs" />
<Compile Include="Library\LibraryManager.cs" />
<Compile Include="Library\MusicManager.cs" />
+ <Compile Include="Library\Resolvers\PhotoAlbumResolver.cs" />
<Compile Include="Library\Resolvers\PhotoResolver.cs" />
+ <Compile Include="Library\Resolvers\PlaylistResolver.cs" />
<Compile Include="Library\SearchEngine.cs" />
<Compile Include="Library\ResolverHelper.cs" />
<Compile Include="Library\Resolvers\Audio\AudioResolver.cs" />
@@ -184,6 +211,7 @@
<Compile Include="Library\Validators\YearsPostScanTask.cs" />
<Compile Include="LiveTv\ChannelImageProvider.cs" />
<Compile Include="LiveTv\CleanDatabaseScheduledTask.cs" />
+ <Compile Include="LiveTv\LiveTvConfigurationFactory.cs" />
<Compile Include="LiveTv\LiveTvDtoService.cs" />
<Compile Include="LiveTv\LiveTvManager.cs" />
<Compile Include="LiveTv\ProgramImageProvider.cs" />
@@ -195,6 +223,7 @@
<Compile Include="News\NewsService.cs" />
<Compile Include="Notifications\CoreNotificationTypes.cs" />
<Compile Include="Notifications\InternalNotificationService.cs" />
+ <Compile Include="Notifications\NotificationConfigurationFactory.cs" />
<Compile Include="Notifications\NotificationManager.cs" />
<Compile Include="Persistence\SqliteChapterRepository.cs" />
<Compile Include="Persistence\SqliteExtensions.cs" />
@@ -204,11 +233,16 @@
<Compile Include="Persistence\SqliteProviderInfoRepository.cs" />
<Compile Include="Persistence\SqliteShrinkMemoryTimer.cs" />
<Compile Include="Persistence\TypeMapper.cs" />
+ <Compile Include="Playlists\ManualPlaylistsFolder.cs" />
+ <Compile Include="Playlists\PlaylistImageEnhancer.cs" />
+ <Compile Include="Playlists\PlaylistManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ScheduledTasks\PeopleValidationTask.cs" />
<Compile Include="ScheduledTasks\ChapterImagesTask.cs" />
<Compile Include="ScheduledTasks\RefreshIntrosTask.cs" />
<Compile Include="ScheduledTasks\RefreshMediaLibraryTask.cs" />
+ <Compile Include="Security\AuthenticationException.cs" />
+ <Compile Include="Security\AuthenticationRepository.cs" />
<Compile Include="Security\EncryptionManager.cs" />
<Compile Include="ServerApplicationPaths.cs" />
<Compile Include="ServerManager\ServerManager.cs" />
@@ -253,11 +287,14 @@
<Compile Include="Persistence\SqliteUserRepository.cs" />
<Compile Include="Sorting\StudioComparer.cs" />
<Compile Include="Sorting\VideoBitRateComparer.cs" />
+ <Compile Include="Sync\AppSyncProvider.cs" />
+ <Compile Include="Sync\CloudSyncProvider.cs" />
+ <Compile Include="Sync\MockSyncProvider.cs" />
+ <Compile Include="Sync\SyncManager.cs" />
+ <Compile Include="Sync\SyncRepository.cs" />
<Compile Include="Themes\AppThemeManager.cs" />
<Compile Include="Udp\UdpMessageReceivedEventArgs.cs" />
<Compile Include="Udp\UdpServer.cs" />
- <Compile Include="WebSocket\AlchemyServer.cs" />
- <Compile Include="WebSocket\AlchemyWebSocket.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Common.Implementations\MediaBrowser.Common.Implementations.csproj">
@@ -344,12 +381,24 @@
<EmbeddedResource Include="Localization\JavaScript\vi.json" />
<EmbeddedResource Include="Localization\Server\da.json" />
<EmbeddedResource Include="Localization\Server\vi.json" />
+ <EmbeddedResource Include="Localization\JavaScript\pl.json" />
+ <EmbeddedResource Include="Localization\Server\pl.json" />
+ <EmbeddedResource Include="Localization\JavaScript\es_ES.json" />
+ <EmbeddedResource Include="Localization\Server\es_ES.json" />
+ <EmbeddedResource Include="Localization\Server\ko.json" />
+ <EmbeddedResource Include="Localization\JavaScript\en_GB.json" />
+ <EmbeddedResource Include="Localization\JavaScript\tr.json" />
+ <EmbeddedResource Include="Localization\Server\tr.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Localization\Ratings\ca.txt" />
</ItemGroup>
<ItemGroup>
+ <Content Include="..\ThirdParty\libwebp\windows\x86\libwebp.dll">
+ <Link>libwebp.dll</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="..\ThirdParty\ServiceStack\swagger-ui\css\highlight.default.css">
<Link>swagger-ui\css\highlight.default.css</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -451,7 +500,7 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="$(SolutionDir)\.nuget\nuget.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.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">
diff --git a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
index 056a526f6..d35282e55 100644
--- a/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
+++ b/MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs
@@ -1,12 +1,15 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Chapters;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.MediaEncoding;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.MediaInfo;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -14,7 +17,6 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Server.Implementations.MediaEncoder
{
@@ -61,23 +63,25 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
return false;
}
+ var options = _chapterManager.GetConfiguration();
+
if (video is Movie)
{
- if (!_config.Configuration.ChapterOptions.EnableMovieChapterImageExtraction)
+ if (!options.EnableMovieChapterImageExtraction)
{
return false;
}
}
else if (video is Episode)
{
- if (!_config.Configuration.ChapterOptions.EnableEpisodeChapterImageExtraction)
+ if (!options.EnableEpisodeChapterImageExtraction)
{
return false;
}
}
else
{
- if (!_config.Configuration.ChapterOptions.EnableOtherVideoChapterImageExtraction)
+ if (!options.EnableOtherVideoChapterImageExtraction)
{
return false;
}
diff --git a/MediaBrowser.Server.Implementations/Notifications/NotificationConfigurationFactory.cs b/MediaBrowser.Server.Implementations/Notifications/NotificationConfigurationFactory.cs
new file mode 100644
index 000000000..a336eba0e
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Notifications/NotificationConfigurationFactory.cs
@@ -0,0 +1,21 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Notifications;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Server.Implementations.Notifications
+{
+ public class NotificationConfigurationFactory : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new List<ConfigurationStore>
+ {
+ new ConfigurationStore
+ {
+ Key = "notifications",
+ ConfigurationType = typeof (NotificationOptions)
+ }
+ };
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs
index 416b29e86..3558922d8 100644
--- a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs
+++ b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs
@@ -1,9 +1,9 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Notifications;
-using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Notifications;
using System;
@@ -30,16 +30,20 @@ namespace MediaBrowser.Server.Implementations.Notifications
_logger = logManager.GetLogger(GetType().Name);
}
+ private NotificationOptions GetConfiguration()
+ {
+ return _config.GetConfiguration<NotificationOptions>("notifications");
+ }
+
public Task SendNotification(NotificationRequest request, CancellationToken cancellationToken)
{
var notificationType = request.NotificationType;
var options = string.IsNullOrWhiteSpace(notificationType) ?
null :
- _config.Configuration.NotificationOptions.GetOptions(notificationType);
+ GetConfiguration().GetOptions(notificationType);
var users = GetUserIds(request, options)
- .Except(request.ExcludeUserIds)
.Select(i => _userManager.GetUserById(new Guid(i)));
var title = GetTitle(request, options);
@@ -87,8 +91,11 @@ namespace MediaBrowser.Server.Implementations.Notifications
if (options != null && !string.IsNullOrWhiteSpace(request.NotificationType))
{
- return _userManager.Users.Where(i => _config.Configuration.NotificationOptions.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N"), i.Configuration))
- .Select(i => i.Id.ToString("N"));
+ var config = GetConfiguration();
+
+ return _userManager.Users
+ .Where(i => config.IsEnabledToSendToUser(request.NotificationType, i.Id.ToString("N"), i.Configuration))
+ .Select(i => i.Id.ToString("N"));
}
return request.UserIds;
@@ -223,7 +230,7 @@ namespace MediaBrowser.Server.Implementations.Notifications
private bool IsEnabled(INotificationService service, string notificationType)
{
return string.IsNullOrEmpty(notificationType) ||
- _config.Configuration.NotificationOptions.IsServiceEnabled(service.Name, notificationType);
+ GetConfiguration().IsServiceEnabled(service.Name, notificationType);
}
public void AddParts(IEnumerable<INotificationService> services, IEnumerable<INotificationTypeFactory> notificationTypeFactories)
@@ -248,9 +255,11 @@ namespace MediaBrowser.Server.Implementations.Notifications
}).SelectMany(i => i).ToList();
+ var config = GetConfiguration();
+
foreach (var i in list)
{
- i.Enabled = _config.Configuration.NotificationOptions.IsEnabled(i.Type);
+ i.Enabled = config.IsEnabled(i.Type);
}
return list;
diff --git a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs
index 2424a6652..d34d5a293 100644
--- a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs
+++ b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs
@@ -207,46 +207,6 @@ namespace MediaBrowser.Server.Implementations.Notifications
}
/// <summary>
- /// Gets the notification.
- /// </summary>
- /// <param name="id">The id.</param>
- /// <param name="userId">The user id.</param>
- /// <returns>Notification.</returns>
- /// <exception cref="System.ArgumentNullException">
- /// id
- /// or
- /// userId
- /// </exception>
- public Notification GetNotification(string id, string userId)
- {
- if (string.IsNullOrEmpty(id))
- {
- throw new ArgumentNullException("id");
- }
- if (string.IsNullOrEmpty(userId))
- {
- throw new ArgumentNullException("userId");
- }
-
- using (var cmd = _connection.CreateCommand())
- {
- cmd.CommandText = "select Id,UserId,Date,Name,Description,Url,Level,IsRead,Category,RelatedId where Id=@Id And UserId = @UserId";
-
- cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = new Guid(id);
- cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = new Guid(userId);
-
- using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
- {
- if (reader.Read())
- {
- return GetNotification(reader);
- }
- }
- return null;
- }
- }
-
- /// <summary>
/// Gets the level.
/// </summary>
/// <param name="reader">The reader.</param>
@@ -290,32 +250,6 @@ namespace MediaBrowser.Server.Implementations.Notifications
}
/// <summary>
- /// Updates the notification.
- /// </summary>
- /// <param name="notification">The notification.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- public async Task UpdateNotification(Notification notification, CancellationToken cancellationToken)
- {
- await ReplaceNotification(notification, cancellationToken).ConfigureAwait(false);
-
- if (NotificationUpdated != null)
- {
- try
- {
- NotificationUpdated(this, new NotificationUpdateEventArgs
- {
- Notification = notification
- });
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error in NotificationUpdated event handler", ex);
- }
- }
- }
-
- /// <summary>
/// Replaces the notification.
/// </summary>
/// <param name="notification">The notification.</param>
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs
index 0b3d5f784..6e484413a 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs
@@ -4,6 +4,7 @@ using System.Data;
using System.Data.SQLite;
using System.IO;
using System.Threading.Tasks;
+using MediaBrowser.Model.Serialization;
namespace MediaBrowser.Server.Implementations.Persistence
{
@@ -151,5 +152,26 @@ namespace MediaBrowser.Server.Implementations.Persistence
return connection;
}
+
+ /// <summary>
+ /// Serializes to bytes.
+ /// </summary>
+ /// <param name="json">The json.</param>
+ /// <param name="obj">The obj.</param>
+ /// <returns>System.Byte[][].</returns>
+ /// <exception cref="System.ArgumentNullException">obj</exception>
+ public static byte[] SerializeToBytes(this IJsonSerializer json, object obj)
+ {
+ if (obj == null)
+ {
+ throw new ArgumentNullException("obj");
+ }
+
+ using (var stream = new MemoryStream())
+ {
+ json.SerializeToStream(obj, stream);
+ return stream.ToArray();
+ }
+ }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs
index df32ac021..5d5855bf8 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs
@@ -14,7 +14,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Persistence
{
- public class SqliteFileOrganizationRepository : IFileOrganizationRepository
+ public class SqliteFileOrganizationRepository : IFileOrganizationRepository, IDisposable
{
private IDbConnection _connection;
diff --git a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
new file mode 100644
index 000000000..3d0e36ead
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
@@ -0,0 +1,71 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Playlists;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace MediaBrowser.Server.Implementations.Playlists
+{
+ public class PlaylistsFolder : BasePluginFolder
+ {
+ public PlaylistsFolder()
+ {
+ Name = "Playlists";
+ }
+
+ public override bool IsVisible(User user)
+ {
+ return base.IsVisible(user) && GetRecursiveChildren(user, false)
+ .OfType<Playlist>()
+ .Any(i => string.Equals(i.OwnerUserId, user.Id.ToString("N")));
+ }
+
+ protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
+ {
+ return RecursiveChildren
+ .OfType<Playlist>();
+ }
+
+ public override bool IsHidden
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public override bool IsHiddenFromUser(User user)
+ {
+ return false;
+ }
+
+ public override string CollectionType
+ {
+ get { return Model.Entities.CollectionType.Playlists; }
+ }
+ }
+
+ public class PlaylistssDynamicFolder : IVirtualFolderCreator
+ {
+ private readonly IApplicationPaths _appPaths;
+
+ public PlaylistssDynamicFolder(IApplicationPaths appPaths)
+ {
+ _appPaths = appPaths;
+ }
+
+ public BasePluginFolder GetFolder()
+ {
+ var path = Path.Combine(_appPaths.DataPath, "playlists");
+
+ Directory.CreateDirectory(path);
+
+ return new PlaylistsFolder
+ {
+ Path = path
+ };
+ }
+ }
+}
+
diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistImageEnhancer.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistImageEnhancer.cs
new file mode 100644
index 000000000..baf5202c4
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Playlists/PlaylistImageEnhancer.cs
@@ -0,0 +1,292 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Playlists;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Drawing;
+using MediaBrowser.Model.Entities;
+using MoreLinq;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Playlists
+{
+ public class PlaylistImageEnhancer : IImageEnhancer
+ {
+ private readonly IFileSystem _fileSystem;
+
+ public PlaylistImageEnhancer(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
+ public bool Supports(IHasImages item, ImageType imageType)
+ {
+ return (imageType == ImageType.Primary || imageType == ImageType.Thumb) && item is Playlist;
+ }
+
+ public MetadataProviderPriority Priority
+ {
+ get { return MetadataProviderPriority.First; }
+ }
+
+ private List<BaseItem> GetItemsWithImages(IHasImages item)
+ {
+ var playlist = (Playlist)item;
+
+ var items = playlist.GetManageableItems()
+ .Select(i =>
+ {
+ var subItem = i.Item2;
+
+ var episode = subItem as Episode;
+
+ if (episode != null)
+ {
+ var series = episode.Series;
+ if (series != null && series.HasImage(ImageType.Primary))
+ {
+ return series;
+ }
+ }
+
+ if (subItem.HasImage(ImageType.Primary))
+ {
+ return subItem;
+ }
+
+ var parent = subItem.Parent;
+
+ if (parent != null && parent.HasImage(ImageType.Primary))
+ {
+ if (parent is MusicAlbum)
+ {
+ return parent;
+ }
+ }
+
+ return null;
+ })
+ .Where(i => i != null)
+ .DistinctBy(i => i.Id)
+ .ToList();
+
+ // Rotate the images no more than once per day
+ var random = new Random(DateTime.Now.DayOfYear).Next();
+
+ return items
+ .OrderBy(i => random - items.IndexOf(i))
+ .Take(4)
+ .OrderBy(i => i.Name)
+ .ToList();
+ }
+
+ private const string Version = "3";
+
+ public string GetConfigurationCacheKey(List<BaseItem> items)
+ {
+ return Version + "_" + string.Join(",", items.Select(i => i.Id.ToString("N")).ToArray());
+ }
+
+ public string GetConfigurationCacheKey(IHasImages item, ImageType imageType)
+ {
+ var items = GetItemsWithImages(item);
+
+ return GetConfigurationCacheKey(items);
+ }
+
+ private const int SquareImageSize = 800;
+ private const int ThumbImageWidth = 1600;
+ private const int ThumbImageHeight = 900;
+
+ public ImageSize GetEnhancedImageSize(IHasImages item, ImageType imageType, int imageIndex, ImageSize originalImageSize)
+ {
+ var items = GetItemsWithImages(item);
+
+ if (items.Count == 0)
+ {
+ return originalImageSize;
+ }
+
+ if (imageType == ImageType.Thumb)
+ {
+ return new ImageSize
+ {
+ Height = ThumbImageHeight,
+ Width = ThumbImageWidth
+ };
+ }
+
+ return new ImageSize
+ {
+ Height = SquareImageSize,
+ Width = SquareImageSize
+ };
+ }
+
+ public async Task<Image> EnhanceImageAsync(IHasImages item, Image originalImage, ImageType imageType, int imageIndex)
+ {
+ var items = GetItemsWithImages(item);
+
+ if (items.Count == 0)
+ {
+ return originalImage;
+ }
+
+ var img = imageType == ImageType.Thumb ?
+ await GetThumbCollage(items).ConfigureAwait(false) :
+ await GetSquareCollage(items).ConfigureAwait(false);
+
+ using (originalImage)
+ {
+ return img;
+ }
+ }
+
+ private Task<Image> GetThumbCollage(List<BaseItem> items)
+ {
+ return GetThumbCollage(items.Select(i => i.GetImagePath(ImageType.Primary)).ToList());
+ }
+
+ private Task<Image> GetSquareCollage(List<BaseItem> items)
+ {
+ return GetSquareCollage(items.Select(i => i.GetImagePath(ImageType.Primary)).ToList());
+ }
+
+ private async Task<Image> GetThumbCollage(List<string> files)
+ {
+ if (files.Count < 3)
+ {
+ return await GetSingleImage(files).ConfigureAwait(false);
+ }
+
+ const int rows = 1;
+ const int cols = 3;
+
+ const int cellWidth = 2 * (ThumbImageWidth / 3);
+ const int cellHeight = ThumbImageHeight;
+ var index = 0;
+
+ var img = new Bitmap(ThumbImageWidth, ThumbImageHeight, 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())
+ {
+ await fileStream.CopyToAsync(memoryStream).ConfigureAwait(false);
+
+ memoryStream.Position = 0;
+
+ using (var imgtemp = Image.FromStream(memoryStream, true, false))
+ {
+ graphics.DrawImage(imgtemp, x, y, cellWidth, cellHeight);
+ }
+ }
+ }
+ }
+
+ index++;
+ }
+ }
+ }
+
+ return img;
+ }
+
+ private async Task<Image> GetSquareCollage(List<string> files)
+ {
+ if (files.Count < 4)
+ {
+ return await GetSingleImage(files).ConfigureAwait(false);
+ }
+
+ const int rows = 2;
+ const int cols = 2;
+
+ const int singleSize = SquareImageSize / 2;
+ var index = 0;
+
+ var img = new Bitmap(SquareImageSize, SquareImageSize, 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())
+ {
+ await fileStream.CopyToAsync(memoryStream).ConfigureAwait(false);
+
+ memoryStream.Position = 0;
+
+ using (var imgtemp = Image.FromStream(memoryStream, true, false))
+ {
+ graphics.DrawImage(imgtemp, x, y, singleSize, singleSize);
+ }
+ }
+ }
+
+ index++;
+ }
+ }
+ }
+
+ return img;
+ }
+
+ private Task<Image> GetSingleImage(List<string> files)
+ {
+ return GetImage(files[0]);
+ }
+
+ private async Task<Image> GetImage(string file)
+ {
+ using (var fileStream = _fileSystem.GetFileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, true))
+ {
+ var memoryStream = new MemoryStream();
+
+ await fileStream.CopyToAsync(memoryStream).ConfigureAwait(false);
+
+ memoryStream.Position = 0;
+
+ return Image.FromStream(memoryStream, true, false);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs
new file mode 100644
index 000000000..ee2114aa4
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Playlists/PlaylistManager.cs
@@ -0,0 +1,234 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Playlists;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Playlists;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Playlists
+{
+ public class PlaylistManager : IPlaylistManager
+ {
+ private readonly ILibraryManager _libraryManager;
+ private readonly IFileSystem _fileSystem;
+ private readonly ILibraryMonitor _iLibraryMonitor;
+ private readonly ILogger _logger;
+ private readonly IUserManager _userManager;
+
+ public PlaylistManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor, ILogger logger, IUserManager userManager)
+ {
+ _libraryManager = libraryManager;
+ _fileSystem = fileSystem;
+ _iLibraryMonitor = iLibraryMonitor;
+ _logger = logger;
+ _userManager = userManager;
+ }
+
+ public IEnumerable<Playlist> GetPlaylists(string userId)
+ {
+ var user = _userManager.GetUserById(new Guid(userId));
+
+ return GetPlaylistsFolder(userId).GetChildren(user, true).OfType<Playlist>();
+ }
+
+ public async Task<PlaylistCreationResult> CreatePlaylist(PlaylistCreationRequest options)
+ {
+ var name = options.Name;
+
+ var folderName = _fileSystem.GetValidFilename(name) + " [playlist]";
+
+ var parentFolder = GetPlaylistsFolder(null);
+
+ if (parentFolder == null)
+ {
+ throw new ArgumentException();
+ }
+
+ if (string.IsNullOrWhiteSpace(options.MediaType))
+ {
+ foreach (var itemId in options.ItemIdList)
+ {
+ var item = _libraryManager.GetItemById(itemId);
+
+ if (item == null)
+ {
+ throw new ArgumentException("No item exists with the supplied Id");
+ }
+
+ if (!string.IsNullOrWhiteSpace(item.MediaType))
+ {
+ options.MediaType = item.MediaType;
+ }
+ else if (item is MusicArtist || item is MusicAlbum || item is MusicGenre)
+ {
+ options.MediaType = MediaType.Audio;
+ }
+ else if (item is Genre)
+ {
+ options.MediaType = MediaType.Video;
+ }
+ else
+ {
+ var folder = item as Folder;
+ if (folder != null)
+ {
+ options.MediaType = folder.GetRecursiveChildren()
+ .Where(i => !i.IsFolder && i.SupportsAddingToPlaylist)
+ .Select(i => i.MediaType)
+ .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
+ }
+ }
+
+ if (!string.IsNullOrWhiteSpace(options.MediaType))
+ {
+ break;
+ }
+ }
+ }
+
+ if (string.IsNullOrWhiteSpace(options.MediaType))
+ {
+ throw new ArgumentException("A playlist media type is required.");
+ }
+
+ var user = _userManager.GetUserById(new Guid(options.UserId));
+
+ var path = Path.Combine(parentFolder.Path, folderName);
+ path = GetTargetPath(path);
+
+ _iLibraryMonitor.ReportFileSystemChangeBeginning(path);
+
+ try
+ {
+ Directory.CreateDirectory(path);
+
+ var playlist = new Playlist
+ {
+ Name = name,
+ Parent = parentFolder,
+ Path = path,
+ OwnerUserId = options.UserId
+ };
+
+ playlist.SetMediaType(options.MediaType);
+
+ await parentFolder.AddChild(playlist, CancellationToken.None).ConfigureAwait(false);
+
+ await playlist.RefreshMetadata(new MetadataRefreshOptions { ForceSave = true }, CancellationToken.None)
+ .ConfigureAwait(false);
+
+ if (options.ItemIdList.Count > 0)
+ {
+ await AddToPlaylistInternal(playlist.Id.ToString("N"), options.ItemIdList, user);
+ }
+
+ return new PlaylistCreationResult
+ {
+ Id = playlist.Id.ToString("N")
+ };
+ }
+ finally
+ {
+ // Refresh handled internally
+ _iLibraryMonitor.ReportFileSystemChangeComplete(path, false);
+ }
+ }
+
+ private string GetTargetPath(string path)
+ {
+ while (Directory.Exists(path))
+ {
+ path += "1";
+ }
+
+ return path;
+ }
+
+ private IEnumerable<BaseItem> GetPlaylistItems(IEnumerable<string> itemIds, string playlistMediaType, User user)
+ {
+ var items = itemIds.Select(i => _libraryManager.GetItemById(i)).Where(i => i != null);
+
+ return Playlist.GetPlaylistItems(playlistMediaType, items, user);
+ }
+
+ public Task AddToPlaylist(string playlistId, IEnumerable<string> itemIds, string userId)
+ {
+ var user = string.IsNullOrWhiteSpace(userId) ? null : _userManager.GetUserById(new Guid(userId));
+
+ return AddToPlaylistInternal(playlistId, itemIds, user);
+ }
+
+ private async Task AddToPlaylistInternal(string playlistId, IEnumerable<string> itemIds, User user)
+ {
+ var playlist = _libraryManager.GetItemById(playlistId) as Playlist;
+
+ if (playlist == null)
+ {
+ throw new ArgumentException("No Playlist exists with the supplied Id");
+ }
+
+ var list = new List<LinkedChild>();
+ var itemList = new List<BaseItem>();
+
+ var items = GetPlaylistItems(itemIds, playlist.MediaType, user)
+ .Where(i => i.SupportsAddingToPlaylist)
+ .ToList();
+
+ foreach (var item in items)
+ {
+ itemList.Add(item);
+ list.Add(LinkedChild.Create(item));
+ }
+
+ playlist.LinkedChildren.AddRange(list);
+
+ await playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
+ await playlist.RefreshMetadata(new MetadataRefreshOptions
+ {
+ ForceSave = true
+
+ }, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ public async Task RemoveFromPlaylist(string playlistId, IEnumerable<string> entryIds)
+ {
+ var playlist = _libraryManager.GetItemById(playlistId) as Playlist;
+
+ if (playlist == null)
+ {
+ throw new ArgumentException("No Playlist exists with the supplied Id");
+ }
+
+ var children = playlist.GetManageableItems().ToList();
+
+ var idList = entryIds.ToList();
+
+ var removals = children.Where(i => idList.Contains(i.Item1.Id));
+
+ playlist.LinkedChildren = children.Except(removals)
+ .Select(i => i.Item1)
+ .ToList();
+
+ await playlist.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
+ await playlist.RefreshMetadata(new MetadataRefreshOptions
+ {
+ ForceSave = true
+ }, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ public Folder GetPlaylistsFolder(string userId)
+ {
+ return _libraryManager.RootFolder.Children.OfType<PlaylistsFolder>()
+ .FirstOrDefault();
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Security/AuthenticationException.cs b/MediaBrowser.Server.Implementations/Security/AuthenticationException.cs
new file mode 100644
index 000000000..f4ba2fb63
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Security/AuthenticationException.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace MediaBrowser.Server.Implementations.Security
+{
+ public class AuthenticationException : Exception
+ {
+ public AuthenticationException(string message)
+ : base(message)
+ {
+ }
+
+ public AuthenticationException()
+ {
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs
new file mode 100644
index 000000000..cd20ad74d
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs
@@ -0,0 +1,348 @@
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Security;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Querying;
+using MediaBrowser.Server.Implementations.Persistence;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Globalization;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Security
+{
+ public class AuthenticationRepository : IAuthenticationRepository
+ {
+ private IDbConnection _connection;
+ private readonly ILogger _logger;
+ private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1);
+ private readonly IServerApplicationPaths _appPaths;
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
+ private IDbCommand _saveInfoCommand;
+
+ public AuthenticationRepository(ILogger logger, IServerApplicationPaths appPaths)
+ {
+ _logger = logger;
+ _appPaths = appPaths;
+ }
+
+ public async Task Initialize()
+ {
+ var dbFile = Path.Combine(_appPaths.DataPath, "authentication.db");
+
+ _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
+
+ string[] queries = {
+
+ "create table if not exists AccessTokens (Id GUID PRIMARY KEY, AccessToken TEXT NOT NULL, DeviceId TEXT, AppName TEXT, DeviceName TEXT, UserId TEXT, IsActive BIT, DateCreated DATETIME NOT NULL, DateRevoked DATETIME)",
+ "create index if not exists idx_AccessTokens on AccessTokens(Id)",
+
+ //pragmas
+ "pragma temp_store = memory",
+
+ "pragma shrink_memory"
+ };
+
+ _connection.RunQueries(queries, _logger);
+
+ PrepareStatements();
+ }
+
+ private void PrepareStatements()
+ {
+ _saveInfoCommand = _connection.CreateCommand();
+ _saveInfoCommand.CommandText = "replace into AccessTokens (Id, AccessToken, DeviceId, AppName, DeviceName, UserId, IsActive, DateCreated, DateRevoked) values (@Id, @AccessToken, @DeviceId, @AppName, @DeviceName, @UserId, @IsActive, @DateCreated, @DateRevoked)";
+
+ _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@Id");
+ _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@AccessToken");
+ _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DeviceId");
+ _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@AppName");
+ _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DeviceName");
+ _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@UserId");
+ _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@IsActive");
+ _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DateCreated");
+ _saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DateRevoked");
+ }
+
+ public Task Create(AuthenticationInfo info, CancellationToken cancellationToken)
+ {
+ info.Id = Guid.NewGuid().ToString("N");
+
+ return Update(info, cancellationToken);
+ }
+
+ public async Task Update(AuthenticationInfo info, CancellationToken cancellationToken)
+ {
+ if (info == null)
+ {
+ throw new ArgumentNullException("info");
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+ IDbTransaction transaction = null;
+
+ try
+ {
+ transaction = _connection.BeginTransaction();
+
+ var index = 0;
+
+ _saveInfoCommand.GetParameter(index++).Value = new Guid(info.Id);
+ _saveInfoCommand.GetParameter(index++).Value = info.AccessToken;
+ _saveInfoCommand.GetParameter(index++).Value = info.DeviceId;
+ _saveInfoCommand.GetParameter(index++).Value = info.AppName;
+ _saveInfoCommand.GetParameter(index++).Value = info.DeviceName;
+ _saveInfoCommand.GetParameter(index++).Value = info.UserId;
+ _saveInfoCommand.GetParameter(index++).Value = info.IsActive;
+ _saveInfoCommand.GetParameter(index++).Value = info.DateCreated;
+ _saveInfoCommand.GetParameter(index++).Value = info.DateRevoked;
+
+ _saveInfoCommand.Transaction = transaction;
+
+ _saveInfoCommand.ExecuteNonQuery();
+
+ transaction.Commit();
+ }
+ catch (OperationCanceledException)
+ {
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ catch (Exception e)
+ {
+ _logger.ErrorException("Failed to save record:", e);
+
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ finally
+ {
+ if (transaction != null)
+ {
+ transaction.Dispose();
+ }
+
+ _writeLock.Release();
+ }
+ }
+
+ private const string BaseSelectText = "select Id, AccessToken, DeviceId, AppName, DeviceName, UserId, IsActive, DateCreated, DateRevoked from AccessTokens";
+
+ public QueryResult<AuthenticationInfo> Get(AuthenticationInfoQuery query)
+ {
+ if (query == null)
+ {
+ throw new ArgumentNullException("query");
+ }
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = BaseSelectText;
+
+ var whereClauses = new List<string>();
+
+ var startIndex = query.StartIndex ?? 0;
+
+ if (!string.IsNullOrWhiteSpace(query.AccessToken))
+ {
+ whereClauses.Add("AccessToken=@AccessToken");
+ cmd.Parameters.Add(cmd, "@AccessToken", DbType.String).Value = query.AccessToken;
+ }
+
+ if (!string.IsNullOrWhiteSpace(query.UserId))
+ {
+ whereClauses.Add("UserId=@UserId");
+ cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId;
+ }
+
+ if (!string.IsNullOrWhiteSpace(query.DeviceId))
+ {
+ whereClauses.Add("DeviceId=@DeviceId");
+ cmd.Parameters.Add(cmd, "@DeviceId", DbType.String).Value = query.DeviceId;
+ }
+
+ if (query.IsActive.HasValue)
+ {
+ whereClauses.Add("IsActive=@IsActive");
+ cmd.Parameters.Add(cmd, "@IsActive", DbType.Boolean).Value = query.IsActive.Value;
+ }
+
+ var whereTextWithoutPaging = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ if (startIndex > 0)
+ {
+ var pagingWhereText = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM AccessTokens {0} ORDER BY DateCreated LIMIT {1})",
+ pagingWhereText,
+ startIndex.ToString(_usCulture)));
+ }
+
+ var whereText = whereClauses.Count == 0 ?
+ string.Empty :
+ " where " + string.Join(" AND ", whereClauses.ToArray());
+
+ cmd.CommandText += whereText;
+
+ cmd.CommandText += " ORDER BY DateCreated";
+
+ if (query.Limit.HasValue)
+ {
+ cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture);
+ }
+
+ cmd.CommandText += "; select count (Id) from AccessTokens" + whereTextWithoutPaging;
+
+ var list = new List<AuthenticationInfo>();
+ var count = 0;
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
+ {
+ while (reader.Read())
+ {
+ list.Add(Get(reader));
+ }
+
+ if (reader.NextResult() && reader.Read())
+ {
+ count = reader.GetInt32(0);
+ }
+ }
+
+ return new QueryResult<AuthenticationInfo>()
+ {
+ Items = list.ToArray(),
+ TotalRecordCount = count
+ };
+ }
+ }
+
+ public AuthenticationInfo Get(string id)
+ {
+ if (string.IsNullOrEmpty(id))
+ {
+ throw new ArgumentNullException("id");
+ }
+
+ var guid = new Guid(id);
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = BaseSelectText + " where Id=@Id";
+
+ cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid;
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
+ {
+ if (reader.Read())
+ {
+ return Get(reader);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private AuthenticationInfo Get(IDataReader reader)
+ {
+ var s = "select Id, AccessToken, DeviceId, AppName, DeviceName, UserId, IsActive, DateCreated, DateRevoked from AccessTokens";
+
+ var info = new AuthenticationInfo
+ {
+ Id = reader.GetGuid(0).ToString("N"),
+ AccessToken = reader.GetString(1)
+ };
+
+ if (!reader.IsDBNull(2))
+ {
+ info.DeviceId = reader.GetString(2);
+ }
+
+ if (!reader.IsDBNull(3))
+ {
+ info.AppName = reader.GetString(3);
+ }
+
+ if (!reader.IsDBNull(4))
+ {
+ info.DeviceName = reader.GetString(4);
+ }
+
+ if (!reader.IsDBNull(5))
+ {
+ info.UserId = reader.GetString(5);
+ }
+
+ info.IsActive = reader.GetBoolean(6);
+ info.DateCreated = reader.GetDateTime(7).ToUniversalTime();
+
+ if (!reader.IsDBNull(8))
+ {
+ info.DateRevoked = reader.GetDateTime(8).ToUniversalTime();
+ }
+
+ return info;
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ private readonly object _disposeLock = new object();
+
+ /// <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)
+ {
+ try
+ {
+ lock (_disposeLock)
+ {
+ if (_connection != null)
+ {
+ if (_connection.IsOpen())
+ {
+ _connection.Close();
+ }
+
+ _connection.Dispose();
+ _connection = null;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error disposing database", ex);
+ }
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs b/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs
index 73a4e3004..cd9b9651e 100644
--- a/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs
+++ b/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs
@@ -1,6 +1,5 @@
using MediaBrowser.Controller.Security;
using System;
-using System.Security.Cryptography;
using System.Text;
namespace MediaBrowser.Server.Implementations.Security
@@ -17,7 +16,7 @@ namespace MediaBrowser.Server.Implementations.Security
{
if (value == null) throw new ArgumentNullException("value");
- return Encoding.Default.GetString(ProtectedData.Protect(Encoding.Default.GetBytes(value), null, DataProtectionScope.LocalMachine));
+ return EncryptStringUniversal(value);
}
/// <summary>
@@ -30,7 +29,23 @@ namespace MediaBrowser.Server.Implementations.Security
{
if (value == null) throw new ArgumentNullException("value");
- return Encoding.Default.GetString(ProtectedData.Unprotect(Encoding.Default.GetBytes(value), null, DataProtectionScope.LocalMachine));
+ return DecryptStringUniversal(value);
+ }
+
+ private string EncryptStringUniversal(string value)
+ {
+ // Yes, this isn't good, but ProtectedData in mono is throwing exceptions, so use this for now
+
+ var bytes = Encoding.UTF8.GetBytes(value);
+ return Convert.ToBase64String(bytes);
+ }
+
+ private string DecryptStringUniversal(string value)
+ {
+ // Yes, this isn't good, but ProtectedData in mono is throwing exceptions, so use this for now
+
+ var bytes = Convert.FromBase64String(value);
+ return Encoding.UTF8.GetString(bytes);
}
}
}
diff --git a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
index e66b87b0c..7a23d8e08 100644
--- a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
+++ b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs
@@ -46,12 +46,6 @@ namespace MediaBrowser.Server.Implementations.ServerManager
}
/// <summary>
- /// Gets or sets the external web socket server.
- /// </summary>
- /// <value>The external web socket server.</value>
- private IWebSocketServer ExternalWebSocketServer { get; set; }
-
- /// <summary>
/// The _logger
/// </summary>
private readonly ILogger _logger;
@@ -68,24 +62,6 @@ namespace MediaBrowser.Server.Implementations.ServerManager
private IServerConfigurationManager ConfigurationManager { get; set; }
/// <summary>
- /// Gets a value indicating whether [supports web socket].
- /// </summary>
- /// <value><c>true</c> if [supports web socket]; otherwise, <c>false</c>.</value>
- public bool SupportsNativeWebSocket
- {
- get { return HttpServer != null && HttpServer.SupportsWebSockets; }
- }
-
- /// <summary>
- /// Gets the web socket port number.
- /// </summary>
- /// <value>The web socket port number.</value>
- public int WebSocketPortNumber
- {
- get { return SupportsNativeWebSocket ? ConfigurationManager.Configuration.HttpServerPortNumber : ConfigurationManager.Configuration.LegacyWebSocketPortNumber; }
- }
-
- /// <summary>
/// Gets the web socket listeners.
/// </summary>
/// <value>The web socket listeners.</value>
@@ -123,43 +99,21 @@ namespace MediaBrowser.Server.Implementations.ServerManager
/// <summary>
/// Starts this instance.
/// </summary>
- public void Start(IEnumerable<string> urlPrefixes, bool enableHttpLogging)
+ public void Start(IEnumerable<string> urlPrefixes)
{
- ReloadHttpServer(urlPrefixes, enableHttpLogging);
- }
-
- public void StartWebSocketServer()
- {
- if (!SupportsNativeWebSocket)
- {
- ReloadExternalWebSocketServer(ConfigurationManager.Configuration.LegacyWebSocketPortNumber);
- }
- }
-
- /// <summary>
- /// Starts the external web socket server.
- /// </summary>
- private void ReloadExternalWebSocketServer(int portNumber)
- {
- DisposeExternalWebSocketServer();
-
- ExternalWebSocketServer = _applicationHost.Resolve<IWebSocketServer>();
-
- ExternalWebSocketServer.Start(portNumber);
- ExternalWebSocketServer.WebSocketConnected += HttpServer_WebSocketConnected;
+ ReloadHttpServer(urlPrefixes);
}
/// <summary>
/// Restarts the Http Server, or starts it if not currently running
/// </summary>
- private void ReloadHttpServer(IEnumerable<string> urlPrefixes, bool enableHttpLogging)
+ private void ReloadHttpServer(IEnumerable<string> urlPrefixes)
{
_logger.Info("Loading Http Server");
try
{
HttpServer = _applicationHost.Resolve<IHttpServer>();
- HttpServer.EnableHttpRequestLogging = enableHttpLogging;
HttpServer.StartServer(urlPrefixes);
}
catch (SocketException ex)
@@ -199,6 +153,8 @@ namespace MediaBrowser.Server.Implementations.ServerManager
/// <param name="result">The result.</param>
private async void ProcessWebSocketMessageReceived(WebSocketMessageInfo result)
{
+ //_logger.Debug("Websocket message received: {0}", result.MessageType);
+
var tasks = _webSocketListeners.Select(i => Task.Run(async () =>
{
try
@@ -286,13 +242,13 @@ namespace MediaBrowser.Server.Implementations.ServerManager
_logger.Info("Sending web socket message {0}", messageType);
var message = new WebSocketMessage<T> { MessageType = messageType, Data = dataFunction() };
- var bytes = _jsonSerializer.SerializeToBytes(message);
+ var json = _jsonSerializer.SerializeToString(message);
var tasks = connectionsList.Select(s => Task.Run(() =>
{
try
{
- s.SendAsync(bytes, cancellationToken);
+ s.SendAsync(json, cancellationToken);
}
catch (OperationCanceledException)
{
@@ -302,7 +258,8 @@ namespace MediaBrowser.Server.Implementations.ServerManager
{
_logger.ErrorException("Error sending web socket message {0} to {1}", ex, messageType, s.RemoteEndPoint);
}
- }));
+
+ }, cancellationToken));
await Task.WhenAll(tasks).ConfigureAwait(false);
}
@@ -326,8 +283,6 @@ namespace MediaBrowser.Server.Implementations.ServerManager
HttpServer.WebSocketConnected -= HttpServer_WebSocketConnected;
HttpServer.Dispose();
}
-
- DisposeExternalWebSocketServer();
}
/// <summary>
@@ -352,18 +307,6 @@ namespace MediaBrowser.Server.Implementations.ServerManager
}
/// <summary>
- /// Disposes the external web socket server.
- /// </summary>
- private void DisposeExternalWebSocketServer()
- {
- if (ExternalWebSocketServer != null)
- {
- _logger.Info("Disposing {0}", ExternalWebSocketServer.GetType().Name);
- ExternalWebSocketServer.Dispose();
- }
- }
-
- /// <summary>
/// Adds the web socket listeners.
/// </summary>
/// <param name="listeners">The listeners.</param>
diff --git a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
index 2b60f3116..3c3d7740a 100644
--- a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
+++ b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
@@ -194,9 +194,9 @@ namespace MediaBrowser.Server.Implementations.ServerManager
throw new ArgumentNullException("message");
}
- var bytes = _jsonSerializer.SerializeToBytes(message);
+ var json = _jsonSerializer.SerializeToString(message);
- return SendAsync(bytes, cancellationToken);
+ return SendAsync(json, cancellationToken);
}
/// <summary>
@@ -205,24 +205,46 @@ namespace MediaBrowser.Server.Implementations.ServerManager
/// <param name="buffer">The buffer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- public Task SendAsync(byte[] buffer, CancellationToken cancellationToken)
+ public async Task SendAsync(byte[] buffer, CancellationToken cancellationToken)
{
- return SendAsync(buffer, WebSocketMessageType.Text, cancellationToken);
+ if (buffer == null)
+ {
+ throw new ArgumentNullException("buffer");
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ // Per msdn docs, attempting to send simultaneous messages will result in one failing.
+ // This should help us workaround that and ensure all messages get sent
+ await _sendSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+ try
+ {
+ await _socket.SendAsync(buffer, true, cancellationToken);
+ }
+ catch (OperationCanceledException)
+ {
+ _logger.Info("WebSocket message to {0} was cancelled", RemoteEndPoint);
+
+ throw;
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error sending WebSocket message {0}", ex, RemoteEndPoint);
+
+ throw;
+ }
+ finally
+ {
+ _sendSemaphore.Release();
+ }
}
- /// <summary>
- /// Sends a message asynchronously.
- /// </summary>
- /// <param name="buffer">The buffer.</param>
- /// <param name="type">The type.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException">buffer</exception>
- public async Task SendAsync(byte[] buffer, WebSocketMessageType type, CancellationToken cancellationToken)
+ public async Task SendAsync(string text, CancellationToken cancellationToken)
{
- if (buffer == null)
+ if (string.IsNullOrWhiteSpace(text))
{
- throw new ArgumentNullException("buffer");
+ throw new ArgumentNullException("text");
}
cancellationToken.ThrowIfCancellationRequested();
@@ -233,7 +255,7 @@ namespace MediaBrowser.Server.Implementations.ServerManager
try
{
- await _socket.SendAsync(buffer, type, true, cancellationToken);
+ await _socket.SendAsync(text, true, cancellationToken);
}
catch (OperationCanceledException)
{
diff --git a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs
index 1be4eca23..d2ace23a9 100644
--- a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs
+++ b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs
@@ -54,7 +54,7 @@ namespace MediaBrowser.Server.Implementations.Session
{
get
{
- return (DateTime.UtcNow - Session.LastActivityDate).TotalMinutes <= 10;
+ return (DateTime.UtcNow - Session.LastActivityDate).TotalMinutes <= 20;
}
}
@@ -157,10 +157,10 @@ namespace MediaBrowser.Server.Implementations.Session
throw new ArgumentException("SeekPositionTicks cannot be null");
}
- args["StartPositionTicks"] = command.SeekPositionTicks.Value.ToString(CultureInfo.InvariantCulture);
+ args["SeekPositionTicks"] = command.SeekPositionTicks.Value.ToString(CultureInfo.InvariantCulture);
}
- return SendMessage(command.Command.ToString(), cancellationToken);
+ return SendMessage(command.Command.ToString(), args, cancellationToken);
}
public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index afde4af93..d55d26e44 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -11,12 +11,16 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session;
+using MediaBrowser.Model.Users;
+using MediaBrowser.Server.Implementations.Security;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -59,6 +63,8 @@ namespace MediaBrowser.Server.Implementations.Session
private readonly IJsonSerializer _jsonSerializer;
private readonly IServerApplicationHost _appHost;
+ private readonly IAuthenticationRepository _authRepo;
+
/// <summary>
/// Gets or sets the configuration manager.
/// </summary>
@@ -71,6 +77,10 @@ namespace MediaBrowser.Server.Implementations.Session
private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections =
new ConcurrentDictionary<string, SessionInfo>(StringComparer.OrdinalIgnoreCase);
+ public event EventHandler<GenericEventArgs<AuthenticationRequest>> AuthenticationFailed;
+
+ public event EventHandler<GenericEventArgs<AuthenticationRequest>> AuthenticationSucceeded;
+
/// <summary>
/// Occurs when [playback start].
/// </summary>
@@ -101,7 +111,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// <param name="logger">The logger.</param>
/// <param name="userRepository">The user repository.</param>
/// <param name="libraryManager">The library manager.</param>
- public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient)
+ public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient, IAuthenticationRepository authRepo)
{
_userDataRepository = userDataRepository;
_configurationManager = configurationManager;
@@ -116,6 +126,7 @@ namespace MediaBrowser.Server.Implementations.Session
_jsonSerializer = jsonSerializer;
_appHost = appHost;
_httpClient = httpClient;
+ _authRepo = authRepo;
}
/// <summary>
@@ -201,7 +212,12 @@ namespace MediaBrowser.Server.Implementations.Session
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">user</exception>
/// <exception cref="System.UnauthorizedAccessException"></exception>
- public async Task<SessionInfo> LogSessionActivity(string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user)
+ public async Task<SessionInfo> LogSessionActivity(string clientType,
+ string appVersion,
+ string deviceId,
+ string deviceName,
+ string remoteEndPoint,
+ User user)
{
if (string.IsNullOrEmpty(clientType))
{
@@ -222,7 +238,7 @@ namespace MediaBrowser.Server.Implementations.Session
if (user != null && user.Configuration.IsDisabled)
{
- throw new UnauthorizedAccessException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
+ throw new AuthenticationException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
}
var activityDate = DateTime.UtcNow;
@@ -356,7 +372,7 @@ namespace MediaBrowser.Server.Implementations.Session
private string GetSessionKey(string clientType, string appVersion, string deviceId)
{
- return clientType + deviceId + appVersion;
+ return clientType + deviceId;
}
/// <summary>
@@ -388,6 +404,11 @@ namespace MediaBrowser.Server.Implementations.Session
Id = Guid.NewGuid().ToString("N")
};
+ sessionInfo.DeviceName = deviceName;
+ sessionInfo.UserId = userId;
+ sessionInfo.UserName = username;
+ sessionInfo.RemoteEndPoint = remoteEndPoint;
+
OnSessionStarted(sessionInfo);
return sessionInfo;
@@ -613,6 +634,20 @@ namespace MediaBrowser.Server.Implementations.Session
info.MediaSourceId = info.ItemId;
}
+ if (!string.IsNullOrWhiteSpace(info.ItemId) && libraryItem != null)
+ {
+ var current = session.NowPlayingItem;
+
+ if (current == null || !string.Equals(current.Id, info.ItemId, StringComparison.OrdinalIgnoreCase))
+ {
+ info.Item = GetItemInfo(libraryItem, libraryItem, info.MediaSourceId);
+ }
+ else
+ {
+ info.Item = current;
+ }
+ }
+
RemoveNowPlayingItem(session);
var users = GetUsers(session);
@@ -1087,12 +1122,7 @@ namespace MediaBrowser.Server.Implementations.Session
{
var session = GetSession(sessionId);
- if (!session.UserId.HasValue)
- {
- throw new UnauthorizedAccessException("Cannot modify additional users without authenticating first.");
- }
-
- if (session.UserId.Value == userId)
+ if (session.UserId.HasValue && session.UserId.Value == userId)
{
throw new ArgumentException("The requested user is already the primary user of the session.");
}
@@ -1120,12 +1150,7 @@ namespace MediaBrowser.Server.Implementations.Session
{
var session = GetSession(sessionId);
- if (!session.UserId.HasValue)
- {
- throw new UnauthorizedAccessException("Cannot modify additional users without authenticating first.");
- }
-
- if (session.UserId.Value == userId)
+ if (session.UserId.HasValue && session.UserId.Value == userId)
{
throw new ArgumentException("The requested user is already the primary user of the session.");
}
@@ -1138,28 +1163,175 @@ namespace MediaBrowser.Server.Implementations.Session
}
}
+ public void ValidateSecurityToken(string token)
+ {
+ if (string.IsNullOrWhiteSpace(token))
+ {
+ throw new AuthenticationException();
+ }
+
+ var result = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ AccessToken = token
+ });
+
+ var info = result.Items.FirstOrDefault();
+
+ if (info == null)
+ {
+ throw new AuthenticationException();
+ }
+
+ if (!info.IsActive)
+ {
+ throw new AuthenticationException("Access token has expired.");
+ }
+
+ if (!string.IsNullOrWhiteSpace(info.UserId))
+ {
+ var user = _userManager.GetUserById(new Guid(info.UserId));
+
+ if (user == null || user.Configuration.IsDisabled)
+ {
+ throw new AuthenticationException("User account has been disabled.");
+ }
+ }
+ }
+
/// <summary>
/// Authenticates the new session.
/// </summary>
- /// <param name="user">The user.</param>
- /// <param name="password">The password.</param>
- /// <param name="clientType">Type of the client.</param>
- /// <param name="appVersion">The application version.</param>
- /// <param name="deviceId">The device identifier.</param>
- /// <param name="deviceName">Name of the device.</param>
- /// <param name="remoteEndPoint">The remote end point.</param>
+ /// <param name="request">The request.</param>
+ /// <param name="isLocal">if set to <c>true</c> [is local].</param>
/// <returns>Task{SessionInfo}.</returns>
- /// <exception cref="UnauthorizedAccessException"></exception>
- public async Task<SessionInfo> AuthenticateNewSession(User user, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint)
+ /// <exception cref="AuthenticationException">Invalid user or password entered.</exception>
+ /// <exception cref="System.UnauthorizedAccessException">Invalid user or password entered.</exception>
+ /// <exception cref="UnauthorizedAccessException">Invalid user or password entered.</exception>
+ public async Task<AuthenticationResult> AuthenticateNewSession(AuthenticationRequest request,
+ bool isLocal)
{
- var result = await _userManager.AuthenticateUser(user, password).ConfigureAwait(false);
+ var result = (isLocal && string.Equals(request.App, "Dashboard", StringComparison.OrdinalIgnoreCase)) ||
+ await _userManager.AuthenticateUser(request.Username, request.Password, request.RemoteEndPoint).ConfigureAwait(false);
if (!result)
{
- throw new UnauthorizedAccessException("Invalid user or password entered.");
+ EventHelper.FireEventIfNotNull(AuthenticationFailed, this, new GenericEventArgs<AuthenticationRequest>(request), _logger);
+
+ throw new AuthenticationException("Invalid user or password entered.");
}
- return await LogSessionActivity(clientType, appVersion, deviceId, deviceName, remoteEndPoint, user).ConfigureAwait(false);
+ var user = _userManager.Users
+ .First(i => string.Equals(request.Username, i.Name, StringComparison.OrdinalIgnoreCase));
+
+ var token = await GetAuthorizationToken(user.Id.ToString("N"), request.DeviceId, request.App, request.DeviceName).ConfigureAwait(false);
+
+ EventHelper.FireEventIfNotNull(AuthenticationSucceeded, this, new GenericEventArgs<AuthenticationRequest>(request), _logger);
+
+ var session = await LogSessionActivity(request.App,
+ request.AppVersion,
+ request.DeviceId,
+ request.DeviceName,
+ request.RemoteEndPoint,
+ user)
+ .ConfigureAwait(false);
+
+ return new AuthenticationResult
+ {
+ User = _userManager.GetUserDto(user, request.RemoteEndPoint),
+ SessionInfo = GetSessionInfoDto(session),
+ AccessToken = token,
+ ServerId = _appHost.ServerId
+ };
+ }
+
+ private async Task<string> GetAuthorizationToken(string userId, string deviceId, string app, string deviceName)
+ {
+ var existing = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ DeviceId = deviceId,
+ IsActive = true,
+ UserId = userId,
+ Limit = 1
+ });
+
+ if (existing.Items.Length > 0)
+ {
+ _logger.Debug("Reissuing access token");
+ return existing.Items[0].AccessToken;
+ }
+
+ var newToken = new AuthenticationInfo
+ {
+ AppName = app,
+ DateCreated = DateTime.UtcNow,
+ DeviceId = deviceId,
+ DeviceName = deviceName,
+ UserId = userId,
+ IsActive = true,
+ AccessToken = Guid.NewGuid().ToString("N")
+ };
+
+ _logger.Debug("Creating new access token for user {0}", userId);
+ await _authRepo.Create(newToken, CancellationToken.None).ConfigureAwait(false);
+
+ return newToken.AccessToken;
+ }
+
+ public async Task Logout(string accessToken)
+ {
+ if (string.IsNullOrWhiteSpace(accessToken))
+ {
+ throw new ArgumentNullException("accessToken");
+ }
+
+ var existing = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ Limit = 1,
+ AccessToken = accessToken
+
+ }).Items.FirstOrDefault();
+
+ if (existing != null)
+ {
+ existing.IsActive = false;
+
+ await _authRepo.Update(existing, CancellationToken.None).ConfigureAwait(false);
+
+ var sessions = Sessions
+ .Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase))
+ .ToList();
+
+ foreach (var session in sessions)
+ {
+ try
+ {
+ ReportSessionEnded(session.Id);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error reporting session ended", ex);
+ }
+ }
+ }
+ }
+
+ public async Task RevokeUserTokens(string userId)
+ {
+ var existing = _authRepo.Get(new AuthenticationInfoQuery
+ {
+ IsActive = true,
+ UserId = userId
+ });
+
+ foreach (var info in existing.Items)
+ {
+ await Logout(info.AccessToken).ConfigureAwait(false);
+ }
+ }
+
+ public Task RevokeToken(string token)
+ {
+ return Logout(token);
}
/// <summary>
@@ -1260,15 +1432,10 @@ namespace MediaBrowser.Server.Implementations.Session
DeviceName = session.DeviceName,
Id = session.Id,
LastActivityDate = session.LastActivityDate,
- NowPlayingPositionTicks = session.PlayState.PositionTicks,
- IsPaused = session.PlayState.IsPaused,
- IsMuted = session.PlayState.IsMuted,
NowViewingItem = session.NowViewingItem,
ApplicationVersion = session.ApplicationVersion,
- CanSeek = session.PlayState.CanSeek,
QueueableMediaTypes = session.QueueableMediaTypes,
PlayableMediaTypes = session.PlayableMediaTypes,
- RemoteEndPoint = session.RemoteEndPoint,
AdditionalUsers = session.AdditionalUsers,
SupportedCommands = session.SupportedCommands,
UserName = session.UserName,
@@ -1516,5 +1683,11 @@ namespace MediaBrowser.Server.Implementations.Session
{
ReportTranscodingInfo(deviceId, null);
}
+
+ public SessionInfo GetSession(string deviceId, string client, string version)
+ {
+ return Sessions.FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) &&
+ string.Equals(i.Client, client));
+ }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
index 365845f41..ed590a1f2 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Common.Net;
-using MediaBrowser.Controller;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
@@ -113,21 +112,13 @@ namespace MediaBrowser.Server.Implementations.Session
var version = vals[2];
var deviceName = vals.Length > 3 ? vals[3] : string.Empty;
- var session = _sessionManager.Sessions
- .FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) &&
- string.Equals(i.Client, client) &&
- string.Equals(i.ApplicationVersion, version));
+ var session = _sessionManager.GetSession(deviceId, client, version);
if (session == null && !string.IsNullOrEmpty(deviceName))
{
_logger.Debug("Logging session activity");
- await _sessionManager.LogSessionActivity(client, version, deviceId, deviceName, message.Connection.RemoteEndPoint, null).ConfigureAwait(false);
-
- session = _sessionManager.Sessions
- .FirstOrDefault(i => string.Equals(i.DeviceId, deviceId) &&
- string.Equals(i.Client, client) &&
- string.Equals(i.ApplicationVersion, version));
+ session = await _sessionManager.LogSessionActivity(client, version, deviceId, deviceName, message.Connection.RemoteEndPoint, null).ConfigureAwait(false);
}
if (session != null)
@@ -197,7 +188,7 @@ namespace MediaBrowser.Server.Implementations.Session
}
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
-
+
/// <summary>
/// Reports the playback start.
/// </summary>
@@ -284,7 +275,7 @@ namespace MediaBrowser.Server.Implementations.Session
_sessionManager.OnPlaybackProgress(info);
}
}
-
+
/// <summary>
/// Reports the playback progress.
/// </summary>
@@ -362,7 +353,7 @@ namespace MediaBrowser.Server.Implementations.Session
_sessionManager.OnPlaybackStopped(info);
}
}
-
+
/// <summary>
/// Reports the playback stopped.
/// </summary>
diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
index 5fc28e81b..2d5a30f3d 100644
--- a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
+++ b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
@@ -62,14 +62,28 @@ namespace MediaBrowser.Server.Implementations.Session
void connection_Closed(object sender, EventArgs e)
{
- var capabilities = new SessionCapabilities
+ if (!GetActiveSockets().Any())
{
- PlayableMediaTypes = Session.PlayableMediaTypes,
- SupportedCommands = Session.SupportedCommands,
- SupportsMediaControl = SupportsMediaControl
- };
+ try
+ {
+ _sessionManager.ReportSessionEnded(Session.Id);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error reporting session ended.", ex);
+ }
+ }
+ else
+ {
+ var capabilities = new SessionCapabilities
+ {
+ PlayableMediaTypes = Session.PlayableMediaTypes,
+ SupportedCommands = Session.SupportedCommands,
+ SupportsMediaControl = SupportsMediaControl
+ };
- _sessionManager.ReportCapabilities(Session.Id, capabilities);
+ _sessionManager.ReportCapabilities(Session.Id, capabilities);
+ }
}
private IWebSocketConnection GetActiveSocket()
@@ -220,6 +234,8 @@ namespace MediaBrowser.Server.Implementations.Session
private Task SendMessage<T>(WebSocketMessage<T> message, CancellationToken cancellationToken)
{
+ if (SkipSending()) return Task.FromResult(true);
+
var socket = GetActiveSocket();
return socket.SendAsync(message, cancellationToken);
@@ -227,6 +243,8 @@ namespace MediaBrowser.Server.Implementations.Session
private Task SendMessages<T>(WebSocketMessage<T> message, CancellationToken cancellationToken)
{
+ if (SkipSending()) return Task.FromResult(true);
+
var tasks = GetActiveSockets().Select(i => Task.Run(async () =>
{
try
@@ -243,6 +261,27 @@ namespace MediaBrowser.Server.Implementations.Session
return Task.WhenAll(tasks);
}
+ private bool SkipSending()
+ {
+ if (Session != null)
+ {
+ if (string.Equals(Session.Client, "mb-classic", StringComparison.OrdinalIgnoreCase))
+ {
+ Version version;
+
+ if (!string.IsNullOrWhiteSpace(Session.ApplicationVersion) && Version.TryParse(Session.ApplicationVersion, out version))
+ {
+ if (version < new Version(3, 0, 196))
+ {
+ _logger.Debug("Skipping web socket message to MBC version {0}.", version);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
public void Dispose()
{
foreach (var socket in Sockets.ToList())
diff --git a/MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs b/MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs
index 46c3df07b..7e6a252cd 100644
--- a/MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs
+++ b/MediaBrowser.Server.Implementations/Sorting/AirTimeComparer.cs
@@ -26,13 +26,36 @@ namespace MediaBrowser.Server.Implementations.Sorting
/// <returns>System.String.</returns>
private DateTime GetValue(BaseItem x)
{
- var series = (x as Series) ?? x.FindParent<Series>();
+ var series = x as Series;
- DateTime result;
- if (series != null && DateTime.TryParse(series.AirTime, out result))
+ if (series == null)
{
- return result;
- }
+ var season = x as Season;
+
+ if (season != null)
+ {
+ series = season.Series;
+ }
+ else
+ {
+ var episode = x as Episode;
+
+ if (episode != null)
+ {
+ series = episode.Series;
+ }
+ }
+ }
+
+ if (series != null)
+ {
+ DateTime result;
+ if (DateTime.TryParse(series.AirTime, out result))
+ {
+ return result;
+ }
+ }
+
return DateTime.MinValue;
}
diff --git a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs
new file mode 100644
index 000000000..c3cd047b6
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs
@@ -0,0 +1,26 @@
+using MediaBrowser.Controller.Sync;
+using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Sync;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Server.Implementations.Sync
+{
+ public class AppSyncProvider : ISyncProvider
+ {
+ public IEnumerable<SyncTarget> GetSyncTargets()
+ {
+ return new List<SyncTarget>();
+ }
+
+ public DeviceProfile GetDeviceProfile(SyncTarget target)
+ {
+ return new DeviceProfile();
+ }
+
+ public string Name
+ {
+ get { return "App Sync"; }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs
new file mode 100644
index 000000000..fd12b1f8a
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Sync/CloudSyncProvider.cs
@@ -0,0 +1,35 @@
+using MediaBrowser.Common;
+using MediaBrowser.Controller.Sync;
+using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Sync;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace MediaBrowser.Server.Implementations.Sync
+{
+ public class CloudSyncProvider : ISyncProvider
+ {
+ private ICloudSyncProvider[] _providers = new ICloudSyncProvider[] {};
+
+ public CloudSyncProvider(IApplicationHost appHost)
+ {
+ _providers = appHost.GetExports<ICloudSyncProvider>().ToArray();
+ }
+
+ public IEnumerable<SyncTarget> GetSyncTargets()
+ {
+ return new List<SyncTarget>();
+ }
+
+ public DeviceProfile GetDeviceProfile(SyncTarget target)
+ {
+ return new DeviceProfile();
+ }
+
+ public string Name
+ {
+ get { return "Cloud Sync"; }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Sync/MockSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/MockSyncProvider.cs
new file mode 100644
index 000000000..bc079ad80
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Sync/MockSyncProvider.cs
@@ -0,0 +1,33 @@
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Sync;
+using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Sync;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Server.Implementations.Sync
+{
+ public class MockSyncProvider : ISyncProvider
+ {
+ public string Name
+ {
+ get { return "Dummy Sync"; }
+ }
+
+ public IEnumerable<SyncTarget> GetSyncTargets()
+ {
+ return new List<SyncTarget>
+ {
+ new SyncTarget
+ {
+ Id = "mock".GetMD5().ToString("N"),
+ Name = "Mock Sync"
+ }
+ };
+ }
+
+ public DeviceProfile GetDeviceProfile(SyncTarget target)
+ {
+ return new DeviceProfile();
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
new file mode 100644
index 000000000..b5e13e306
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
@@ -0,0 +1,237 @@
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Sync;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Querying;
+using MediaBrowser.Model.Sync;
+using MoreLinq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Sync
+{
+ public class SyncManager : ISyncManager
+ {
+ private readonly ILibraryManager _libraryManager;
+ private readonly ISyncRepository _repo;
+ private readonly IImageProcessor _imageProcessor;
+ private readonly ILogger _logger;
+
+ private ISyncProvider[] _providers = { };
+
+ public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger)
+ {
+ _libraryManager = libraryManager;
+ _repo = repo;
+ _imageProcessor = imageProcessor;
+ _logger = logger;
+ }
+
+ public void AddParts(IEnumerable<ISyncProvider> providers)
+ {
+ _providers = providers.ToArray();
+ }
+
+ public async Task<SyncJobCreationResult> CreateJob(SyncJobRequest request)
+ {
+ var items = GetItemsForSync(request.ItemIds).ToList();
+
+ if (items.Count == 1)
+ {
+ request.Name = GetDefaultName(items[0]);
+ }
+
+ if (string.IsNullOrWhiteSpace(request.Name))
+ {
+ throw new ArgumentException("Please supply a name for the sync job.");
+ }
+
+ var target = GetSyncTargets(request.UserId)
+ .First(i => string.Equals(request.TargetId, i.Id));
+
+ var jobId = Guid.NewGuid().ToString("N");
+
+ var job = new SyncJob
+ {
+ Id = jobId,
+ Name = request.Name,
+ TargetId = target.Id,
+ UserId = request.UserId,
+ UnwatchedOnly = request.UnwatchedOnly,
+ Limit = request.Limit,
+ LimitType = request.LimitType,
+ RequestedItemIds = request.ItemIds,
+ DateCreated = DateTime.UtcNow,
+ DateLastModified = DateTime.UtcNow,
+ ItemCount = 1
+ };
+
+ await _repo.Create(job).ConfigureAwait(false);
+
+ return new SyncJobCreationResult
+ {
+ Job = GetJob(jobId)
+ };
+ }
+
+ public QueryResult<SyncJob> GetJobs(SyncJobQuery query)
+ {
+ var result = _repo.GetJobs(query);
+
+ result.Items.ForEach(FillMetadata);
+
+ return result;
+ }
+
+ private void FillMetadata(SyncJob job)
+ {
+ var item = GetItemsForSync(job.RequestedItemIds)
+ .FirstOrDefault();
+
+ if (item != null)
+ {
+ var hasSeries = item as IHasSeries;
+ if (hasSeries != null)
+ {
+ job.ParentName = hasSeries.SeriesName;
+ }
+
+ var hasAlbumArtist = item as IHasAlbumArtist;
+ if (hasAlbumArtist != null)
+ {
+ job.ParentName = hasAlbumArtist.AlbumArtists.FirstOrDefault();
+ }
+
+ var primaryImage = item.GetImageInfo(ImageType.Primary, 0);
+
+ if (primaryImage != null)
+ {
+ try
+ {
+ job.PrimaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
+ job.PrimaryImageItemId = item.Id.ToString("N");
+
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error getting image info", ex);
+ }
+ }
+ }
+ }
+
+ public Task CancelJob(string id)
+ {
+ throw new NotImplementedException();
+ }
+
+ public SyncJob GetJob(string id)
+ {
+ return _repo.GetJob(id);
+ }
+
+ public IEnumerable<SyncTarget> GetSyncTargets(string userId)
+ {
+ return _providers
+ .SelectMany(i => GetSyncTargets(i, userId))
+ .OrderBy(i => i.Name);
+ }
+
+ private IEnumerable<SyncTarget> GetSyncTargets(ISyncProvider provider, string userId)
+ {
+ var providerId = GetSyncProviderId(provider);
+
+ return provider.GetSyncTargets().Select(i => new SyncTarget
+ {
+ Name = i.Name,
+ Id = providerId + "-" + i.Id
+ });
+ }
+
+ private ISyncProvider GetSyncProvider(SyncTarget target)
+ {
+ var providerId = target.Id.Split(new[] { '-' }, 2).First();
+
+ return _providers.First(i => string.Equals(providerId, GetSyncProviderId(i)));
+ }
+
+ private string GetSyncProviderId(ISyncProvider provider)
+ {
+ return (provider.GetType().Name + provider.Name).GetMD5().ToString("N");
+ }
+
+ public bool SupportsSync(BaseItem item)
+ {
+ if (item.LocationType == LocationType.Virtual)
+ {
+ return false;
+ }
+
+ if (string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
+ {
+ if (item.RunTimeTicks.HasValue)
+ {
+ var video = item as Video;
+
+ if (video != null)
+ {
+ if (video.VideoType != VideoType.VideoFile)
+ {
+ return false;
+ }
+
+ if (video.IsMultiPart)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ return false;
+ }
+
+ private IEnumerable<BaseItem> GetItemsForSync(IEnumerable<string> itemIds)
+ {
+ return itemIds.SelectMany(GetItemsForSync).DistinctBy(i => i.Id);
+ }
+
+ private IEnumerable<BaseItem> GetItemsForSync(string id)
+ {
+ var item = _libraryManager.GetItemById(id);
+
+ if (item == null)
+ {
+ throw new ArgumentException("Item with Id " + id + " not found.");
+ }
+
+ if (!SupportsSync(item))
+ {
+ throw new ArgumentException("Item with Id " + id + " does not support sync.");
+ }
+
+ return GetItemsForSync(item);
+ }
+
+ private IEnumerable<BaseItem> GetItemsForSync(BaseItem item)
+ {
+ return new[] { item };
+ }
+
+ private string GetDefaultName(BaseItem item)
+ {
+ return item.Name;
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
new file mode 100644
index 000000000..65da74f9e
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
@@ -0,0 +1,471 @@
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Sync;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Querying;
+using MediaBrowser.Model.Sync;
+using MediaBrowser.Server.Implementations.Persistence;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Server.Implementations.Sync
+{
+ public class SyncRepository : ISyncRepository, IDisposable
+ {
+ private IDbConnection _connection;
+ private readonly ILogger _logger;
+ private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1);
+ private readonly IServerApplicationPaths _appPaths;
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
+ private IDbCommand _saveJobCommand;
+ private IDbCommand _saveJobItemCommand;
+
+ public SyncRepository(ILogger logger, IServerApplicationPaths appPaths)
+ {
+ _logger = logger;
+ _appPaths = appPaths;
+ }
+
+ public async Task Initialize()
+ {
+ var dbFile = Path.Combine(_appPaths.DataPath, "sync.db");
+
+ _connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
+
+ string[] queries = {
+
+ "create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Quality TEXT NOT NULL, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, UnwatchedOnly BIT, SyncLimit BigInt, LimitType TEXT, IsDynamic BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)",
+ "create index if not exists idx_SyncJobs on SyncJobs(Id)",
+
+ "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, JobId TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT)",
+ "create index if not exists idx_SyncJobItems on SyncJobs(Id)",
+
+ //pragmas
+ "pragma temp_store = memory",
+
+ "pragma shrink_memory"
+ };
+
+ _connection.RunQueries(queries, _logger);
+
+ PrepareStatements();
+ }
+
+ private void PrepareStatements()
+ {
+ _saveJobCommand = _connection.CreateCommand();
+ _saveJobCommand.CommandText = "replace into SyncJobs (Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, UnwatchedOnly, SyncLimit, LimitType, IsDynamic, DateCreated, DateLastModified, ItemCount) values (@Id, @TargetId, @Name, @Quality, @Status, @Progress, @UserId, @ItemIds, @UnwatchedOnly, @SyncLimit, @LimitType, @IsDynamic, @DateCreated, @DateLastModified, @ItemCount)";
+
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@Id");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@TargetId");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@Name");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@Quality");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@Status");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@Progress");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@UserId");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@ItemIds");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@UnwatchedOnly");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@SyncLimit");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@LimitType");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@IsDynamic");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@DateCreated");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@DateLastModified");
+ _saveJobCommand.Parameters.Add(_saveJobCommand, "@ItemCount");
+
+ _saveJobItemCommand = _connection.CreateCommand();
+ _saveJobItemCommand.CommandText = "replace into SyncJobItems (Id, ItemId, JobId, OutputPath, Status, TargetId) values (@Id, @ItemId, @JobId, @OutputPath, @Status, @TargetId)";
+
+ _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@Id");
+ _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@ItemId");
+ _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@JobId");
+ _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@OutputPath");
+ _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@Status");
+ }
+
+ private const string BaseJobSelectText = "select Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, UnwatchedOnly, SyncLimit, LimitType, IsDynamic, DateCreated, DateLastModified, ItemCount from SyncJobs";
+ private const string BaseJobItemSelectText = "select Id, ItemId, JobId, OutputPath, Status, TargetId from SyncJobItems";
+
+ public SyncJob GetJob(string id)
+ {
+ if (string.IsNullOrEmpty(id))
+ {
+ throw new ArgumentNullException("id");
+ }
+
+ var guid = new Guid(id);
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = BaseJobSelectText + " where Id=@Id";
+
+ cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid;
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
+ {
+ if (reader.Read())
+ {
+ return GetJob(reader);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private SyncJob GetJob(IDataReader reader)
+ {
+ var info = new SyncJob
+ {
+ Id = reader.GetGuid(0).ToString("N"),
+ TargetId = reader.GetString(1),
+ Name = reader.GetString(2)
+ };
+
+ if (!reader.IsDBNull(3))
+ {
+ info.Quality = (SyncQuality)Enum.Parse(typeof(SyncQuality), reader.GetString(3), true);
+ }
+
+ if (!reader.IsDBNull(4))
+ {
+ info.Status = (SyncJobStatus)Enum.Parse(typeof(SyncJobStatus), reader.GetString(4), true);
+ }
+
+ if (!reader.IsDBNull(5))
+ {
+ info.Progress = reader.GetDouble(5);
+ }
+
+ if (!reader.IsDBNull(6))
+ {
+ info.UserId = reader.GetString(6);
+ }
+
+ if (!reader.IsDBNull(7))
+ {
+ info.RequestedItemIds = reader.GetString(7).Split(',').ToList();
+ }
+
+ if (!reader.IsDBNull(8))
+ {
+ info.UnwatchedOnly = reader.GetBoolean(8);
+ }
+
+ if (!reader.IsDBNull(9))
+ {
+ info.Limit = reader.GetInt64(9);
+ }
+
+ if (!reader.IsDBNull(10))
+ {
+ info.LimitType = (SyncLimitType)Enum.Parse(typeof(SyncLimitType), reader.GetString(10), true);
+ }
+
+ info.IsDynamic = reader.GetBoolean(11);
+ info.DateCreated = reader.GetDateTime(12).ToUniversalTime();
+ info.DateLastModified = reader.GetDateTime(13).ToUniversalTime();
+ info.ItemCount = reader.GetInt32(14);
+
+ return info;
+ }
+
+ public Task Create(SyncJob job)
+ {
+ return Update(job);
+ }
+
+ public async Task Update(SyncJob job)
+ {
+ if (job == null)
+ {
+ throw new ArgumentNullException("job");
+ }
+
+ await _writeLock.WaitAsync().ConfigureAwait(false);
+
+ IDbTransaction transaction = null;
+
+ try
+ {
+ transaction = _connection.BeginTransaction();
+
+ var index = 0;
+
+ _saveJobCommand.GetParameter(index++).Value = new Guid(job.Id);
+ _saveJobCommand.GetParameter(index++).Value = job.TargetId;
+ _saveJobCommand.GetParameter(index++).Value = job.Name;
+ _saveJobCommand.GetParameter(index++).Value = job.Quality;
+ _saveJobCommand.GetParameter(index++).Value = job.Status;
+ _saveJobCommand.GetParameter(index++).Value = job.Progress;
+ _saveJobCommand.GetParameter(index++).Value = job.UserId;
+ _saveJobCommand.GetParameter(index++).Value = string.Join(",", job.RequestedItemIds.ToArray());
+ _saveJobCommand.GetParameter(index++).Value = job.UnwatchedOnly;
+ _saveJobCommand.GetParameter(index++).Value = job.Limit;
+ _saveJobCommand.GetParameter(index++).Value = job.LimitType;
+ _saveJobCommand.GetParameter(index++).Value = job.IsDynamic;
+ _saveJobCommand.GetParameter(index++).Value = job.DateCreated;
+ _saveJobCommand.GetParameter(index++).Value = job.DateLastModified;
+ _saveJobCommand.GetParameter(index++).Value = job.ItemCount;
+
+ _saveJobCommand.Transaction = transaction;
+
+ _saveJobCommand.ExecuteNonQuery();
+
+ transaction.Commit();
+ }
+ catch (OperationCanceledException)
+ {
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ catch (Exception e)
+ {
+ _logger.ErrorException("Failed to save record:", e);
+
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ finally
+ {
+ if (transaction != null)
+ {
+ transaction.Dispose();
+ }
+
+ _writeLock.Release();
+ }
+ }
+
+ public QueryResult<SyncJob> GetJobs(SyncJobQuery query)
+ {
+ if (query == null)
+ {
+ throw new ArgumentNullException("query");
+ }
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = BaseJobSelectText;
+
+ var whereClauses = new List<string>();
+
+ var startIndex = query.StartIndex ?? 0;
+
+ if (startIndex > 0)
+ {
+ whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM SyncJobs ORDER BY DateLastModified DESC LIMIT {0})",
+ startIndex.ToString(_usCulture)));
+ }
+
+ if (whereClauses.Count > 0)
+ {
+ cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray());
+ }
+
+ cmd.CommandText += " ORDER BY DateLastModified DESC";
+
+ if (query.Limit.HasValue)
+ {
+ cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture);
+ }
+
+ cmd.CommandText += "; select count (Id) from SyncJobs";
+
+ var list = new List<SyncJob>();
+ var count = 0;
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
+ {
+ while (reader.Read())
+ {
+ list.Add(GetJob(reader));
+ }
+
+ if (reader.NextResult() && reader.Read())
+ {
+ count = reader.GetInt32(0);
+ }
+ }
+
+ return new QueryResult<SyncJob>()
+ {
+ Items = list.ToArray(),
+ TotalRecordCount = count
+ };
+ }
+ }
+
+ public SyncJobItem GetJobItem(string id)
+ {
+ if (string.IsNullOrEmpty(id))
+ {
+ throw new ArgumentNullException("id");
+ }
+
+ var guid = new Guid(id);
+
+ using (var cmd = _connection.CreateCommand())
+ {
+ cmd.CommandText = BaseJobItemSelectText + " where Id=@Id";
+
+ cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid;
+
+ using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
+ {
+ if (reader.Read())
+ {
+ return GetSyncJobItem(reader);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public Task Create(SyncJobItem jobItem)
+ {
+ return Update(jobItem);
+ }
+
+ public async Task Update(SyncJobItem jobItem)
+ {
+ if (jobItem == null)
+ {
+ throw new ArgumentNullException("jobItem");
+ }
+
+ await _writeLock.WaitAsync().ConfigureAwait(false);
+
+ IDbTransaction transaction = null;
+
+ try
+ {
+ transaction = _connection.BeginTransaction();
+
+ var index = 0;
+
+ _saveJobItemCommand.GetParameter(index++).Value = new Guid(jobItem.Id);
+ _saveJobItemCommand.GetParameter(index++).Value = jobItem.ItemId;
+ _saveJobItemCommand.GetParameter(index++).Value = jobItem.JobId;
+ _saveJobItemCommand.GetParameter(index++).Value = jobItem.OutputPath;
+ _saveJobItemCommand.GetParameter(index++).Value = jobItem.Status;
+ _saveJobItemCommand.GetParameter(index++).Value = jobItem.TargetId;
+
+ _saveJobItemCommand.Transaction = transaction;
+
+ _saveJobItemCommand.ExecuteNonQuery();
+
+ transaction.Commit();
+ }
+ catch (OperationCanceledException)
+ {
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ catch (Exception e)
+ {
+ _logger.ErrorException("Failed to save record:", e);
+
+ if (transaction != null)
+ {
+ transaction.Rollback();
+ }
+
+ throw;
+ }
+ finally
+ {
+ if (transaction != null)
+ {
+ transaction.Dispose();
+ }
+
+ _writeLock.Release();
+ }
+ }
+
+ private SyncJobItem GetSyncJobItem(IDataReader reader)
+ {
+ var info = new SyncJobItem
+ {
+ Id = reader.GetGuid(0).ToString("N"),
+ ItemId = reader.GetString(1),
+ JobId = reader.GetString(2)
+ };
+
+ if (!reader.IsDBNull(3))
+ {
+ info.OutputPath = reader.GetString(3);
+ }
+
+ if (!reader.IsDBNull(4))
+ {
+ info.Status = (SyncJobStatus)Enum.Parse(typeof(SyncJobStatus), reader.GetString(4), true);
+ }
+
+ info.TargetId = reader.GetString(5);
+
+ return info;
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ private readonly object _disposeLock = new object();
+
+ /// <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)
+ {
+ try
+ {
+ lock (_disposeLock)
+ {
+ if (_connection != null)
+ {
+ if (_connection.IsOpen())
+ {
+ _connection.Close();
+ }
+
+ _connection.Dispose();
+ _connection = null;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error disposing database", ex);
+ }
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs b/MediaBrowser.Server.Implementations/Udp/UdpServer.cs
index 6b5cac196..91a4940ae 100644
--- a/MediaBrowser.Server.Implementations/Udp/UdpServer.cs
+++ b/MediaBrowser.Server.Implementations/Udp/UdpServer.cs
@@ -1,8 +1,10 @@
using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller;
+using MediaBrowser.Model.ApiClient;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
@@ -25,81 +27,106 @@ namespace MediaBrowser.Server.Implementations.Udp
/// The _network manager
/// </summary>
private readonly INetworkManager _networkManager;
- /// <summary>
- /// The _HTTP server
- /// </summary>
- private readonly IHttpServer _httpServer;
-
- /// <summary>
- /// The _server configuration manager
- /// </summary>
- private readonly IServerConfigurationManager _serverConfigurationManager;
private bool _isDisposed;
+ private readonly List<Tuple<byte[], Action<string>>> _responders = new List<Tuple<byte[], Action<string>>>();
+
+ private readonly IServerApplicationHost _appHost;
+ private readonly IJsonSerializer _json;
+
/// <summary>
/// Initializes a new instance of the <see cref="UdpServer" /> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="networkManager">The network manager.</param>
- /// <param name="serverConfigurationManager">The server configuration manager.</param>
- /// <param name="httpServer">The HTTP server.</param>
- public UdpServer(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager, IHttpServer httpServer)
+ /// <param name="appHost">The application host.</param>
+ /// <param name="json">The json.</param>
+ public UdpServer(ILogger logger, INetworkManager networkManager, IServerApplicationHost appHost, IJsonSerializer json)
{
_logger = logger;
_networkManager = networkManager;
- _serverConfigurationManager = serverConfigurationManager;
- _httpServer = httpServer;
+ _appHost = appHost;
+ _json = json;
+
+ AddMessageResponder("who is MediaBrowserServer?", RespondToV1Message);
+ AddMessageResponder("who is MediaBrowserServer_v2?", RespondToV2Message);
+ }
+
+ private void AddMessageResponder(string message, Action<string> responder)
+ {
+ var expectedMessageBytes = Encoding.UTF8.GetBytes(message);
+
+ _responders.Add(new Tuple<byte[], Action<string>>(expectedMessageBytes, responder));
}
/// <summary>
/// Raises the <see cref="E:MessageReceived" /> event.
/// </summary>
/// <param name="e">The <see cref="UdpMessageReceivedEventArgs"/> instance containing the event data.</param>
- private async void OnMessageReceived(UdpMessageReceivedEventArgs e)
+ private void OnMessageReceived(UdpMessageReceivedEventArgs e)
{
- const string context = "Server";
-
- var expectedMessage = String.Format("who is MediaBrowser{0}?", context);
- var expectedMessageBytes = Encoding.UTF8.GetBytes(expectedMessage);
+ var responder = _responders.FirstOrDefault(i => i.Item1.SequenceEqual(e.Bytes));
- if (expectedMessageBytes.SequenceEqual(e.Bytes))
+ if (responder != null)
{
- _logger.Info("Received UDP server request from " + e.RemoteEndPoint);
+ try
+ {
+ responder.Item2(e.RemoteEndPoint);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error in OnMessageReceived", ex);
+ }
+ }
+ }
- var localAddress = GetLocalIpAddress();
+ private async void RespondToV1Message(string endpoint)
+ {
+ var info = _appHost.GetSystemInfo();
- if (!string.IsNullOrEmpty(localAddress))
- {
- // Send a response back with our ip address and port
- var response = String.Format("MediaBrowser{0}|{1}:{2}", context, GetLocalIpAddress(), _serverConfigurationManager.Configuration.HttpServerPortNumber);
+ var localAddress = info.LocalAddress;
- await SendAsync(Encoding.UTF8.GetBytes(response), e.RemoteEndPoint);
- }
- else
+ if (!string.IsNullOrEmpty(localAddress))
+ {
+ // This is how we did the old v1 search, so need to strip off the protocol
+ var index = localAddress.IndexOf("://", StringComparison.OrdinalIgnoreCase);
+
+ if (index != -1)
{
- _logger.Warn("Unable to respond to udp request because the local ip address could not be determined.");
+ localAddress = localAddress.Substring(index + 3);
}
+
+ // Send a response back with our ip address and port
+ var response = String.Format("MediaBrowserServer|{0}", localAddress);
+
+ await SendAsync(Encoding.UTF8.GetBytes(response), endpoint);
+ }
+ else
+ {
+ _logger.Warn("Unable to respond to udp request because the local ip address could not be determined.");
}
}
- /// <summary>
- /// Gets the local ip address.
- /// </summary>
- /// <returns>System.String.</returns>
- private string GetLocalIpAddress()
+ private async void RespondToV2Message(string endpoint)
{
- var localAddresses = _networkManager.GetLocalIpAddresses().ToList();
+ var info = _appHost.GetSystemInfo();
- // Cross-check the local ip addresses with addresses that have been received on with the http server
- var matchedAddress = _httpServer.LocalEndPoints
- .ToList()
- .Select(i => i.Split(':').FirstOrDefault())
- .Where(i => !string.IsNullOrEmpty(i))
- .FirstOrDefault(i => localAddresses.Contains(i, StringComparer.OrdinalIgnoreCase));
+ if (!string.IsNullOrEmpty(info.LocalAddress))
+ {
+ var response = new ServerDiscoveryInfo
+ {
+ Address = info.LocalAddress,
+ Id = info.Id,
+ Name = info.ServerName
+ };
- // Return the first matched address, if found, or the first known local address
- return matchedAddress ?? localAddresses.FirstOrDefault();
+ await SendAsync(Encoding.UTF8.GetBytes(_json.SerializeToString(response)), endpoint);
+ }
+ else
+ {
+ _logger.Warn("Unable to respond to udp request because the local ip address could not be determined.");
+ }
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/WebSocket/AlchemyServer.cs b/MediaBrowser.Server.Implementations/WebSocket/AlchemyServer.cs
deleted file mode 100644
index 454dff4b9..000000000
--- a/MediaBrowser.Server.Implementations/WebSocket/AlchemyServer.cs
+++ /dev/null
@@ -1,165 +0,0 @@
-using Alchemy;
-using Alchemy.Classes;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Net;
-#if __MonoCS__
-using Mono.Unix.Native;
-#endif
-
-namespace MediaBrowser.Server.Implementations.WebSocket
-{
- /// <summary>
- /// Class AlchemyServer
- /// </summary>
- public class AlchemyServer : IWebSocketServer
- {
- /// <summary>
- /// Occurs when [web socket connected].
- /// </summary>
- public event EventHandler<WebSocketConnectEventArgs> WebSocketConnected;
-
- /// <summary>
- /// Gets or sets the web socket server.
- /// </summary>
- /// <value>The web socket server.</value>
- private WebSocketServer WebSocketServer { get; set; }
-
- /// <summary>
- /// The _logger
- /// </summary>
- private readonly ILogger _logger;
-
- private bool _hasStopped;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="AlchemyServer" /> class.
- /// </summary>
- /// <param name="logger">The logger.</param>
- /// <exception cref="System.ArgumentNullException">logger</exception>
- public AlchemyServer(ILogger logger)
- {
- if (logger == null)
- {
- throw new ArgumentNullException("logger");
- }
- _logger = logger;
- }
-
- /// <summary>
- /// Gets the port.
- /// </summary>
- /// <value>The port.</value>
- public int Port { get; private set; }
-
- /// <summary>
- /// Starts the specified port number.
- /// </summary>
- /// <param name="portNumber">The port number.</param>
- public void Start(int portNumber)
- {
- _logger.Info("Starting Alchemy web socket server on port {0}", portNumber);
-
- try
- {
- WebSocketServer = new WebSocketServer(portNumber, IPAddress.Any)
- {
- OnConnected = OnAlchemyWebSocketClientConnected,
- TimeOut = TimeSpan.FromHours(24)
- };
-
- #if __MonoCS__
- //Linux: port below 1024 require root or cap_net_bind_service
- if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX)
- {
- if (Syscall.getuid() == 0)
- {
- WebSocketServer.FlashAccessPolicyEnabled = true;
- }
- else
- {
- WebSocketServer.FlashAccessPolicyEnabled = false;
- }
- }
- #endif
- WebSocketServer.Start();
- }
- catch (Exception ex)
- {
- _logger.ErrorException("The web socket server is unable to start on port {0} due to a Socket error. This can occasionally happen when the operating system takes longer than usual to release the IP bindings from the previous session. This can take up to five minutes. Please try waiting or rebooting the system.", ex, portNumber);
-
- throw;
- }
-
- Port = portNumber;
-
- _logger.Info("Alchemy Web Socket Server started");
- }
-
- /// <summary>
- /// Called when [alchemy web socket client connected].
- /// </summary>
- /// <param name="context">The context.</param>
- private void OnAlchemyWebSocketClientConnected(UserContext context)
- {
- if (_hasStopped)
- {
- return;
- }
-
- if (WebSocketConnected != null)
- {
- var socket = new AlchemyWebSocket(context, _logger);
-
- WebSocketConnected(this, new WebSocketConnectEventArgs
- {
- WebSocket = socket,
- Endpoint = context.ClientAddress.ToString()
- });
- }
- }
-
- /// <summary>
- /// Stops this instance.
- /// </summary>
- public void Stop()
- {
- if (WebSocketServer != null)
- {
- WebSocketServer.Stop();
- }
- }
-
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- private readonly object _syncLock = new object();
-
- /// <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)
- {
- _hasStopped = true;
-
- lock (_syncLock)
- {
- if (WebSocketServer != null)
- {
- _logger.Debug("Disposing alchemy server");
-
- WebSocketServer.Dispose();
- WebSocketServer = null;
- }
- }
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/WebSocket/AlchemyWebSocket.cs b/MediaBrowser.Server.Implementations/WebSocket/AlchemyWebSocket.cs
deleted file mode 100644
index 35c5e780b..000000000
--- a/MediaBrowser.Server.Implementations/WebSocket/AlchemyWebSocket.cs
+++ /dev/null
@@ -1,134 +0,0 @@
-using Alchemy.Classes;
-using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Net;
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Server.Implementations.WebSocket
-{
- /// <summary>
- /// Class AlchemyWebSocket
- /// </summary>
- public class AlchemyWebSocket : IWebSocket
- {
- /// <summary>
- /// The logger
- /// </summary>
- private readonly ILogger _logger;
-
- public event EventHandler<EventArgs> Closed;
-
- /// <summary>
- /// Gets or sets the web socket.
- /// </summary>
- /// <value>The web socket.</value>
- private UserContext UserContext { get; set; }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="AlchemyWebSocket" /> class.
- /// </summary>
- /// <param name="context">The context.</param>
- /// <param name="logger">The logger.</param>
- /// <exception cref="System.ArgumentNullException">context</exception>
- public AlchemyWebSocket(UserContext context, ILogger logger)
- {
- if (context == null)
- {
- throw new ArgumentNullException("context");
- }
-
- _logger = logger;
- UserContext = context;
-
- context.SetOnDisconnect(OnDisconnected);
- context.SetOnReceive(OnReceiveContext);
-
- _logger.Info("Client connected from {0}", context.ClientAddress);
- }
-
- /// <summary>
- /// The _disconnected
- /// </summary>
- private bool _disconnected;
- /// <summary>
- /// Gets or sets the state.
- /// </summary>
- /// <value>The state.</value>
- public WebSocketState State
- {
- get { return _disconnected ? WebSocketState.Closed : WebSocketState.Open; }
- }
-
- /// <summary>
- /// Called when [disconnected].
- /// </summary>
- /// <param name="context">The context.</param>
- private void OnDisconnected(UserContext context)
- {
- _disconnected = true;
-
- EventHelper.FireEventIfNotNull(Closed, this, EventArgs.Empty, _logger);
- }
-
- /// <summary>
- /// Called when [receive].
- /// </summary>
- /// <param name="context">The context.</param>
- private void OnReceiveContext(UserContext context)
- {
- if (OnReceive != null)
- {
- var json = context.DataFrame.ToString();
-
- OnReceive(json);
- }
- }
-
- private readonly Task _cachedTask = Task.FromResult(true);
- /// <summary>
- /// Sends the async.
- /// </summary>
- /// <param name="bytes">The bytes.</param>
- /// <param name="type">The type.</param>
- /// <param name="endOfMessage">if set to <c>true</c> [end of message].</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- public Task SendAsync(byte[] bytes, WebSocketMessageType type, bool endOfMessage, CancellationToken cancellationToken)
- {
- UserContext.Send(bytes);
-
- return _cachedTask;
- }
-
- /// <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)
- {
- }
-
- /// <summary>
- /// Gets or sets the receive action.
- /// </summary>
- /// <value>The receive action.</value>
- public Action<byte[]> OnReceiveBytes { get; set; }
-
- /// <summary>
- /// Gets or sets the on receive.
- /// </summary>
- /// <value>The on receive.</value>
- public Action<string> OnReceive { get; set; }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index fb04de92f..18739ddb3 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="Alchemy" version="2.2.1" targetFramework="net45" />
- <package id="Mono.Nat" version="1.2.13.0" targetFramework="net45" />
+ <package id="Mono.Nat" version="1.2.21.0" targetFramework="net45" />
<package id="morelinq" version="1.0.16006" targetFramework="net45" />
<package id="System.Data.SQLite.Core" version="1.0.91.3" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Server.Mono/Imazen.WebP.config b/MediaBrowser.Server.Mono/Imazen.WebP.config
new file mode 100644
index 000000000..34d8c73c1
--- /dev/null
+++ b/MediaBrowser.Server.Mono/Imazen.WebP.config
@@ -0,0 +1,5 @@
+<configuration>
+ <dllmap dll="libwebp" target="./libwebp/linux/lib/libwebp.so" os="linux"/>
+ <dllmap dll="libwebp" target="./libwebp/linux/lib64/libwebp.so" os="linux"/>
+ <dllmap dll="libwebp" target="./libwebp/mac/libwebp.dylib" os="osx"/>
+</configuration>
diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
index e94c297eb..a778809d2 100644
--- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
+++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
@@ -79,9 +79,6 @@
<Link>FFMpeg\FFMpegDownloader.cs</Link>
</Compile>
<Compile Include="IO\FileSystemFactory.cs" />
- <Compile Include="..\MediaBrowser.ServerApplication\EntryPoints\WanAddressEntryPoint.cs">
- <Link>EntryPoints\WanAddressEntryPoint.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.ServerApplication\FFMpeg\FFMpegDownloadInfo.cs">
<Link>FFMpeg\FFMpegDownloadInfo.cs</Link>
</Compile>
@@ -128,6 +125,14 @@
<Project>{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}</Project>
<Name>MediaBrowser.MediaEncoding</Name>
</ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj">
+ <Project>{7EF9F3E0-697D-42F3-A08F-19DEB5F84392}</Project>
+ <Name>MediaBrowser.LocalMetadata</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj">
+ <Project>{23499896-B135-4527-8574-C26E926EA99E}</Project>
+ <Name>MediaBrowser.XbmcMetadata</Name>
+ </ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="EntryPoints\" />
@@ -140,6 +145,14 @@
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
+ <Content Include="..\ThirdParty\libwebp\linux\x86\libwebp.so">
+ <Link>libwebp\linux\lib\libwebp.so</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="..\ThirdParty\libwebp\linux\x86_64\libwebp.so">
+ <Link>libwebp\linux\lib64\libwebp.so</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="..\ThirdParty\SQLite3\windows\x86\3.8.2\sqlite3.dll">
<Link>sqlite3.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -160,5 +173,9 @@
<Link>System.Data.SQLite.dll.config</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="Imazen.WebP.dll.config">
+ <Link>Imazen.WebP.dll.config</Link>
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/MediaBrowser.Server.Mono/Native/NativeApp.cs b/MediaBrowser.Server.Mono/Native/NativeApp.cs
index 1cf217910..1aa0f9004 100644
--- a/MediaBrowser.Server.Mono/Native/NativeApp.cs
+++ b/MediaBrowser.Server.Mono/Native/NativeApp.cs
@@ -1,4 +1,11 @@
using MediaBrowser.Server.Mono;
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Updates;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Updates;
namespace MediaBrowser.ServerApplication.Native
{
@@ -56,5 +63,16 @@ namespace MediaBrowser.ServerApplication.Native
{
}
+
+ public static Task<CheckForUpdateResult> CheckForApplicationUpdate(Version currentVersion,
+ PackageVersionClass updateLevel,
+ IInstallationManager installationManager,
+ CancellationToken cancellationToken,
+ IProgress<double> progress)
+ {
+ var result = new CheckForUpdateResult { AvailableVersion = currentVersion.ToString(), IsUpdateAvailable = false };
+
+ return Task.FromResult(result);
+ }
}
}
diff --git a/MediaBrowser.Server.Mono/Native/ServerAuthorization.cs b/MediaBrowser.Server.Mono/Native/ServerAuthorization.cs
index 6f43a12c0..bd456c88b 100644
--- a/MediaBrowser.Server.Mono/Native/ServerAuthorization.cs
+++ b/MediaBrowser.Server.Mono/Native/ServerAuthorization.cs
@@ -18,7 +18,7 @@ namespace MediaBrowser.ServerApplication.Native
/// <param name="webSocketPort">The web socket port.</param>
/// <param name="udpPort">The UDP port.</param>
/// <param name="tempDirectory">The temp directory.</param>
- public static void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int webSocketPort, int udpPort, string tempDirectory)
+ public static void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int udpPort, string tempDirectory)
{
}
diff --git a/MediaBrowser.Server.Mono/Networking/NetworkManager.cs b/MediaBrowser.Server.Mono/Networking/NetworkManager.cs
index a1cdf87e4..a3d23a0db 100644
--- a/MediaBrowser.Server.Mono/Networking/NetworkManager.cs
+++ b/MediaBrowser.Server.Mono/Networking/NetworkManager.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Implementations.Networking;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using System;
using System.Collections.Generic;
@@ -13,6 +14,11 @@ namespace MediaBrowser.ServerApplication.Networking
/// </summary>
public class NetworkManager : BaseNetworkManager, INetworkManager
{
+ public NetworkManager(ILogger logger)
+ : base(logger)
+ {
+ }
+
/// <summary>
/// Gets the network shares.
/// </summary>
diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs
index b849c7a44..a3e645c8e 100644
--- a/MediaBrowser.Server.Mono/Program.cs
+++ b/MediaBrowser.Server.Mono/Program.cs
@@ -42,7 +42,7 @@ namespace MediaBrowser.Server.Mono
#endif
// Allow this to be specified on the command line.
- var customProgramDataPath = ParseCommandLine();
+ var customProgramDataPath = ParseProgramDataPathFromCommandLine();
var appPaths = CreateApplicationPaths(applicationPath, customProgramDataPath);
@@ -74,7 +74,7 @@ namespace MediaBrowser.Server.Mono
}
}
- private static string ParseCommandLine()
+ private static string ParseProgramDataPathFromCommandLine()
{
var commandArgs = Environment.GetCommandLineArgs().ToList();
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index e93785bac..1b5bd8440 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -9,10 +9,12 @@ using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller;
+using MediaBrowser.Controller.Activity;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Chapters;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Connect;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
@@ -26,6 +28,7 @@ using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.News;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Playlists;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
@@ -33,14 +36,17 @@ using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Controller.Subtitles;
+using MediaBrowser.Controller.Sync;
using MediaBrowser.Controller.Themes;
using MediaBrowser.Dlna;
using MediaBrowser.Dlna.ConnectionManager;
using MediaBrowser.Dlna.ContentDirectory;
using MediaBrowser.Dlna.Main;
+using MediaBrowser.LocalMetadata.Providers;
using MediaBrowser.MediaEncoding.BdInfo;
using MediaBrowser.MediaEncoding.Encoder;
using MediaBrowser.MediaEncoding.Subtitles;
+using MediaBrowser.Model.FileOrganization;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.System;
@@ -49,14 +55,17 @@ using MediaBrowser.Providers.Chapters;
using MediaBrowser.Providers.Manager;
using MediaBrowser.Providers.Subtitles;
using MediaBrowser.Server.Implementations;
+using MediaBrowser.Server.Implementations.Activity;
using MediaBrowser.Server.Implementations.Channels;
using MediaBrowser.Server.Implementations.Collections;
using MediaBrowser.Server.Implementations.Configuration;
+using MediaBrowser.Server.Implementations.Connect;
using MediaBrowser.Server.Implementations.Drawing;
using MediaBrowser.Server.Implementations.Dto;
using MediaBrowser.Server.Implementations.EntryPoints;
using MediaBrowser.Server.Implementations.FileOrganization;
using MediaBrowser.Server.Implementations.HttpServer;
+using MediaBrowser.Server.Implementations.HttpServer.Security;
using MediaBrowser.Server.Implementations.IO;
using MediaBrowser.Server.Implementations.Library;
using MediaBrowser.Server.Implementations.LiveTv;
@@ -64,17 +73,18 @@ using MediaBrowser.Server.Implementations.Localization;
using MediaBrowser.Server.Implementations.MediaEncoder;
using MediaBrowser.Server.Implementations.Notifications;
using MediaBrowser.Server.Implementations.Persistence;
+using MediaBrowser.Server.Implementations.Playlists;
using MediaBrowser.Server.Implementations.Security;
using MediaBrowser.Server.Implementations.ServerManager;
using MediaBrowser.Server.Implementations.Session;
+using MediaBrowser.Server.Implementations.Sync;
using MediaBrowser.Server.Implementations.Themes;
-using MediaBrowser.Server.Implementations.WebSocket;
-using MediaBrowser.ServerApplication.EntryPoints;
using MediaBrowser.ServerApplication.FFMpeg;
using MediaBrowser.ServerApplication.IO;
using MediaBrowser.ServerApplication.Native;
using MediaBrowser.ServerApplication.Networking;
using MediaBrowser.WebDashboard.Api;
+using MediaBrowser.XbmcMetadata.Providers;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -176,6 +186,7 @@ namespace MediaBrowser.ServerApplication
/// <value>The media encoder.</value>
private IMediaEncoder MediaEncoder { get; set; }
+ private IConnectManager ConnectManager { get; set; }
private ISessionManager SessionManager { get; set; }
private ILiveTvManager LiveTvManager { get; set; }
@@ -184,6 +195,7 @@ namespace MediaBrowser.ServerApplication
private IEncodingManager EncodingManager { get; set; }
private IChannelManager ChannelManager { get; set; }
+ private ISyncManager SyncManager { get; set; }
/// <summary>
/// Gets or sets the user data repository.
@@ -203,11 +215,15 @@ namespace MediaBrowser.ServerApplication
private IUserViewManager UserViewManager { get; set; }
+ private IAuthenticationRepository AuthenticationRepository { get; set; }
+ private ISyncRepository SyncRepository { get; set; }
+
/// <summary>
- /// Initializes a new instance of the <see cref="ApplicationHost"/> class.
+ /// Initializes a new instance of the <see cref="ApplicationHost" /> class.
/// </summary>
/// <param name="applicationPaths">The application paths.</param>
/// <param name="logManager">The log manager.</param>
+ /// <param name="isRunningAsService">if set to <c>true</c> [is running as service].</param>
public ApplicationHost(ServerApplicationPaths applicationPaths, ILogManager logManager, bool isRunningAsService)
: base(applicationPaths, logManager)
{
@@ -271,11 +287,49 @@ namespace MediaBrowser.ServerApplication
LogManager.RemoveConsoleOutput();
}
- public override Task Init(IProgress<double> progress)
+ public override async Task Init(IProgress<double> progress)
+ {
+ PerformVersionMigration();
+
+ await base.Init(progress).ConfigureAwait(false);
+
+ MigrateModularConfigurations();
+ }
+
+ private void PerformVersionMigration()
{
DeleteDeprecatedModules();
+ }
+
+ private void MigrateModularConfigurations()
+ {
+ var saveConfig = false;
- return base.Init(progress);
+ if (ServerConfigurationManager.Configuration.DlnaOptions != null)
+ {
+ ServerConfigurationManager.SaveConfiguration("dlna", ServerConfigurationManager.Configuration.DlnaOptions);
+ ServerConfigurationManager.Configuration.DlnaOptions = null;
+ saveConfig = true;
+ }
+
+ if (ServerConfigurationManager.Configuration.LiveTvOptions != null)
+ {
+ ServerConfigurationManager.SaveConfiguration("livetv", ServerConfigurationManager.Configuration.LiveTvOptions);
+ ServerConfigurationManager.Configuration.LiveTvOptions = null;
+ saveConfig = true;
+ }
+
+ if (ServerConfigurationManager.Configuration.TvFileOrganizationOptions != null)
+ {
+ ServerConfigurationManager.SaveConfiguration("autoorganize", new AutoOrganizeOptions { TvOptions = ServerConfigurationManager.Configuration.TvFileOrganizationOptions });
+ ServerConfigurationManager.Configuration.TvFileOrganizationOptions = null;
+ saveConfig = true;
+ }
+
+ if (saveConfig)
+ {
+ ServerConfigurationManager.SaveConfiguration();
+ }
}
private void DeleteDeprecatedModules()
@@ -297,116 +351,14 @@ namespace MediaBrowser.ServerApplication
// Not there, no big deal
}
- Task.Run(() =>
+ try
{
- try
- {
- Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "remote-images"), true);
- }
- catch (IOException)
- {
- // Not there, no big deal
- }
-
- try
- {
- Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "chapter-images"), true);
- }
- catch (IOException)
- {
- // Not there, no big deal
- }
-
- try
- {
- Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "extracted-video-images"), true);
- }
- catch (IOException)
- {
- // Not there, no big deal
- }
-
- try
- {
- Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "extracted-audio-images"), true);
- }
- catch (IOException)
- {
- // Not there, no big deal
- }
-
- try
- {
- Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "tmdb-tv"), true);
- }
- catch (IOException)
- {
- // Not there, no big deal
- }
-
- try
- {
- Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "tmdb-collections"), true);
- }
- catch (IOException)
- {
- // Not there, no big deal
- }
-
- try
- {
- Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "tmdb-movies"), true);
- }
- catch (IOException)
- {
- // Not there, no big deal
- }
-
- try
- {
- Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "fanart-movies"), true);
- }
- catch (IOException)
- {
- // Not there, no big deal
- }
-
- try
- {
- Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "fanart-music"), true);
- }
- catch (IOException)
- {
- // Not there, no big deal
- }
-
- try
- {
- Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "fanart-tv"), true);
- }
- catch (IOException)
- {
- // Not there, no big deal
- }
-
- try
- {
- Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "tmdb-people"), true);
- }
- catch (IOException)
- {
- // Not there, no big deal
- }
-
- try
- {
- Directory.Delete(Path.Combine(ApplicationPaths.DataPath, "tvdb-v3"), true);
- }
- catch (IOException)
- {
- // Not there, no big deal
- }
- });
+ File.Delete(Path.Combine(ApplicationPaths.PluginsPath, "MediaBrowser.Plugins.XbmcMetadata.dll"));
+ }
+ catch (IOException)
+ {
+ // Not there, no big deal
+ }
}
private void MigrateUserFolders()
@@ -440,8 +392,6 @@ namespace MediaBrowser.ServerApplication
LocalizationManager = new LocalizationManager(ServerConfigurationManager, FileSystemManager, JsonSerializer);
RegisterSingleInstance(LocalizationManager);
- RegisterSingleInstance<IWebSocketServer>(() => new AlchemyServer(Logger));
-
RegisterSingleInstance<IBlurayExaminer>(() => new BdInfoExaminer());
UserDataManager = new UserDataManager(LogManager);
@@ -462,7 +412,13 @@ namespace MediaBrowser.ServerApplication
FileOrganizationRepository = await GetFileOrganizationRepository().ConfigureAwait(false);
RegisterSingleInstance(FileOrganizationRepository);
- UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer);
+ AuthenticationRepository = await GetAuthenticationRepository().ConfigureAwait(false);
+ RegisterSingleInstance(AuthenticationRepository);
+
+ //SyncRepository = await GetSyncRepository().ConfigureAwait(false);
+ //RegisterSingleInstance(SyncRepository);
+
+ UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService);
RegisterSingleInstance(UserManager);
LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager);
@@ -482,7 +438,7 @@ namespace MediaBrowser.ServerApplication
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
- HttpServer = ServerFactory.CreateServer(this, LogManager, "Media Browser", "mediabrowser", "dashboard/index.html");
+ HttpServer = ServerFactory.CreateServer(this, LogManager, "Media Browser", WebApplicationName, "dashboard/index.html");
RegisterSingleInstance(HttpServer, false);
progress.Report(10);
@@ -498,10 +454,19 @@ namespace MediaBrowser.ServerApplication
ImageProcessor = new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, MediaEncoder);
RegisterSingleInstance(ImageProcessor);
- DtoService = new DtoService(Logger, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager);
+ SyncManager = new SyncManager(LibraryManager, SyncRepository, ImageProcessor, LogManager.GetLogger("SyncManager"));
+ RegisterSingleInstance(SyncManager);
+
+ DtoService = new DtoService(Logger, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager, SyncManager);
RegisterSingleInstance(DtoService);
- SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient);
+ var encryptionManager = new EncryptionManager();
+ RegisterSingleInstance<IEncryptionManager>(encryptionManager);
+
+ ConnectManager = new ConnectManager(LogManager.GetLogger("Connect"), ApplicationPaths, JsonSerializer, encryptionManager, HttpClient, this, ServerConfigurationManager);
+ RegisterSingleInstance(ConnectManager);
+
+ SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient, AuthenticationRepository);
RegisterSingleInstance(SessionManager);
var newsService = new Server.Implementations.News.NewsService(ApplicationPaths, JsonSerializer);
@@ -521,26 +486,27 @@ namespace MediaBrowser.ServerApplication
var dlnaManager = new DlnaManager(XmlSerializer, FileSystemManager, ApplicationPaths, LogManager.GetLogger("Dlna"), JsonSerializer);
RegisterSingleInstance<IDlnaManager>(dlnaManager);
- var contentDirectory = new ContentDirectory(dlnaManager, UserDataManager, ImageProcessor, LibraryManager, ServerConfigurationManager, UserManager, LogManager.GetLogger("UpnpContentDirectory"), HttpClient);
- RegisterSingleInstance<IContentDirectory>(contentDirectory);
-
var connectionManager = new ConnectionManager(dlnaManager, ServerConfigurationManager, LogManager.GetLogger("UpnpConnectionManager"), HttpClient);
RegisterSingleInstance<IConnectionManager>(connectionManager);
- var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor);
+ var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("CollectionManager"));
RegisterSingleInstance<ICollectionManager>(collectionManager);
- LiveTvManager = new LiveTvManager(ServerConfigurationManager, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, JsonSerializer, LocalizationManager);
+ var playlistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("PlaylistManager"), UserManager);
+ RegisterSingleInstance<IPlaylistManager>(playlistManager);
+
+ LiveTvManager = new LiveTvManager(ServerConfigurationManager, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer);
RegisterSingleInstance(LiveTvManager);
- UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, FileSystemManager, UserManager, ChannelManager, LiveTvManager);
+ UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, FileSystemManager, UserManager, ChannelManager, LiveTvManager, ApplicationPaths, playlistManager);
RegisterSingleInstance(UserViewManager);
+ var contentDirectory = new ContentDirectory(dlnaManager, UserDataManager, ImageProcessor, LibraryManager, ServerConfigurationManager, UserManager, LogManager.GetLogger("UpnpContentDirectory"), HttpClient, UserViewManager, ChannelManager);
+ RegisterSingleInstance<IContentDirectory>(contentDirectory);
+
NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager);
RegisterSingleInstance(NotificationManager);
- RegisterSingleInstance<IEncryptionManager>(new EncryptionManager());
-
SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, ItemRepository);
RegisterSingleInstance(SubtitleManager);
@@ -551,7 +517,16 @@ namespace MediaBrowser.ServerApplication
MediaEncoder, ChapterManager);
RegisterSingleInstance(EncodingManager);
- RegisterSingleInstance<ISubtitleEncoder>(new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder));
+ var activityLogRepo = await GetActivityLogRepository().ConfigureAwait(false);
+ RegisterSingleInstance(activityLogRepo);
+ RegisterSingleInstance<IActivityManager>(new ActivityManager(LogManager.GetLogger("ActivityManager"), activityLogRepo));
+
+ var authContext = new AuthorizationContext();
+ RegisterSingleInstance<IAuthorizationContext>(authContext);
+ RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
+ RegisterSingleInstance<IAuthService>(new AuthService(UserManager, SessionManager, authContext, ServerConfigurationManager));
+
+ RegisterSingleInstance<ISubtitleEncoder>(new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer));
var displayPreferencesTask = Task.Run(async () => await ConfigureDisplayPreferencesRepositories().ConfigureAwait(false));
var itemsTask = Task.Run(async () => await ConfigureItemRepositories().ConfigureAwait(false));
@@ -570,9 +545,9 @@ namespace MediaBrowser.ServerApplication
SetKernelProperties();
}
- protected override INetworkManager CreateNetworkManager()
+ protected override INetworkManager CreateNetworkManager(ILogger logger)
{
- return new NetworkManager();
+ return new NetworkManager(logger);
}
protected override IFileSystem CreateFileSystemManager()
@@ -588,7 +563,7 @@ namespace MediaBrowser.ServerApplication
{
var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager).GetFFMpegInfo(progress).ConfigureAwait(false);
- MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ApplicationPaths, JsonSerializer, info.EncoderPath, info.ProbePath, info.Version, FileSystemManager);
+ MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), JsonSerializer, info.EncoderPath, info.ProbePath, info.Version);
RegisterSingleInstance(MediaEncoder);
}
@@ -626,6 +601,33 @@ namespace MediaBrowser.ServerApplication
return repo;
}
+ private async Task<IAuthenticationRepository> GetAuthenticationRepository()
+ {
+ var repo = new AuthenticationRepository(LogManager.GetLogger("AuthenticationRepository"), ServerConfigurationManager.ApplicationPaths);
+
+ await repo.Initialize().ConfigureAwait(false);
+
+ return repo;
+ }
+
+ private async Task<IActivityRepository> GetActivityLogRepository()
+ {
+ var repo = new ActivityRepository(LogManager.GetLogger("ActivityRepository"), ServerConfigurationManager.ApplicationPaths);
+
+ await repo.Initialize().ConfigureAwait(false);
+
+ return repo;
+ }
+
+ private async Task<ISyncRepository> GetSyncRepository()
+ {
+ var repo = new SyncRepository(LogManager.GetLogger("SyncRepository"), ServerConfigurationManager.ApplicationPaths);
+
+ await repo.Initialize().ConfigureAwait(false);
+
+ return repo;
+ }
+
/// <summary>
/// Configures the repositories.
/// </summary>
@@ -695,6 +697,8 @@ namespace MediaBrowser.ServerApplication
BaseItem.FileSystem = FileSystemManager;
BaseItem.UserDataManager = UserDataManager;
ChannelVideoItem.ChannelManager = ChannelManager;
+ BaseItem.LiveTvManager = LiveTvManager;
+ UserView.UserViewManager = UserViewManager;
}
/// <summary>
@@ -745,6 +749,7 @@ namespace MediaBrowser.ServerApplication
ChannelManager.AddParts(GetExports<IChannel>(), GetExports<IChannelFactory>());
NotificationManager.AddParts(GetExports<INotificationService>(), GetExports<INotificationTypeFactory>());
+ SyncManager.AddParts(GetExports<ISyncProvider>());
}
/// <summary>
@@ -755,7 +760,7 @@ namespace MediaBrowser.ServerApplication
{
try
{
- ServerManager.Start(HttpServerUrlPrefixes, ServerConfigurationManager.Configuration.EnableHttpLevelLogging);
+ ServerManager.Start(HttpServerUrlPrefixes);
}
catch (Exception ex)
{
@@ -772,8 +777,6 @@ namespace MediaBrowser.ServerApplication
throw;
}
}
-
- ServerManager.StartWebSocketServer();
}
/// <summary>
@@ -785,17 +788,10 @@ namespace MediaBrowser.ServerApplication
{
base.OnConfigurationUpdated(sender, e);
- HttpServer.EnableHttpRequestLogging = ServerConfigurationManager.Configuration.EnableHttpLevelLogging;
-
if (!HttpServer.UrlPrefixes.SequenceEqual(HttpServerUrlPrefixes, StringComparer.OrdinalIgnoreCase))
{
NotifyPendingRestart();
}
-
- else if (!ServerManager.SupportsNativeWebSocket && ServerManager.WebSocketPortNumber != ServerConfigurationManager.Configuration.LegacyWebSocketPortNumber)
- {
- NotifyPendingRestart();
- }
}
/// <summary>
@@ -881,6 +877,12 @@ namespace MediaBrowser.ServerApplication
// Dlna
list.Add(typeof(DlnaEntryPoint).Assembly);
+ // Local metadata
+ list.Add(typeof(AlbumXmlProvider).Assembly);
+
+ // Xbmc
+ list.Add(typeof(ArtistNfoProvider).Assembly);
+
list.AddRange(Assemblies.GetAssembliesWithParts());
// Include composable parts in the running assembly
@@ -910,6 +912,11 @@ namespace MediaBrowser.ServerApplication
private readonly string _systemId = Environment.MachineName.GetMD5().ToString();
+ public string ServerId
+ {
+ get { return _systemId; }
+ }
+
/// <summary>
/// Gets the system status.
/// </summary>
@@ -921,12 +928,12 @@ namespace MediaBrowser.ServerApplication
HasPendingRestart = HasPendingRestart,
Version = ApplicationVersion.ToString(),
IsNetworkDeployed = CanSelfUpdate,
- WebSocketPortNumber = ServerManager.WebSocketPortNumber,
- SupportsNativeWebSocket = ServerManager.SupportsNativeWebSocket,
+ WebSocketPortNumber = HttpServerPort,
+ SupportsNativeWebSocket = true,
FailedPluginAssemblies = FailedAssemblies.ToList(),
InProgressInstallations = InstallationManager.CurrentInstallations.Select(i => i.Item1).ToList(),
CompletedInstallations = InstallationManager.CompletedInstallations.ToList(),
- Id = _systemId,
+ Id = ServerId,
ProgramDataPath = ApplicationPaths.ProgramDataPath,
LogPath = ApplicationPaths.LogDirectoryPath,
ItemsByNamePath = ApplicationPaths.ItemsByNamePath,
@@ -937,42 +944,57 @@ namespace MediaBrowser.ServerApplication
OperatingSystem = Environment.OSVersion.ToString(),
CanSelfRestart = CanSelfRestart,
CanSelfUpdate = CanSelfUpdate,
- WanAddress = GetWanAddress(),
+ WanAddress = ConnectManager.WanApiAddress,
HasUpdateAvailable = HasUpdateAvailable,
SupportsAutoRunAtStartup = SupportsAutoRunAtStartup,
TranscodingTempPath = ApplicationPaths.TranscodingTempPath,
IsRunningAsService = IsRunningAsService,
- ServerName = string.IsNullOrWhiteSpace(ServerConfigurationManager.Configuration.ServerName) ? Environment.MachineName : ServerConfigurationManager.Configuration.ServerName
+ ServerName = FriendlyName,
+ LocalAddress = GetLocalIpAddress()
};
}
- public int HttpServerPort
+ /// <summary>
+ /// Gets the local ip address.
+ /// </summary>
+ /// <returns>System.String.</returns>
+ private string GetLocalIpAddress()
{
- get { return ServerConfigurationManager.Configuration.HttpServerPortNumber; }
- }
+ var localAddresses = NetworkManager.GetLocalIpAddresses().ToList();
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- private string GetWanAddress()
- {
- var ip = ServerConfigurationManager.Configuration.WanDdns;
+ // Cross-check the local ip addresses with addresses that have been received on with the http server
+ var matchedAddress = HttpServer.LocalEndPoints
+ .ToList()
+ .Select(i => i.Split(':').FirstOrDefault())
+ .Where(i => !string.IsNullOrEmpty(i))
+ .FirstOrDefault(i => localAddresses.Contains(i, StringComparer.OrdinalIgnoreCase));
+
+ // Return the first matched address, if found, or the first known local address
+ var address = matchedAddress ?? localAddresses.FirstOrDefault();
- if (string.IsNullOrWhiteSpace(ip))
+ if (!string.IsNullOrWhiteSpace(address))
{
- ip = WanAddressEntryPoint.WanAddress;
+ address = string.Format("http://{0}:{1}",
+ address,
+ ServerConfigurationManager.Configuration.HttpServerPortNumber.ToString(CultureInfo.InvariantCulture));
}
- if (!string.IsNullOrEmpty(ip))
- {
- if (!ip.StartsWith("http://", StringComparison.OrdinalIgnoreCase) &&
- !ip.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
- {
- ip = "http://" + ip;
- }
+ return address;
+ }
- return ip + ":" + ServerConfigurationManager.Configuration.HttpServerPortNumber.ToString(_usCulture);
+ public string FriendlyName
+ {
+ get
+ {
+ return string.IsNullOrWhiteSpace(ServerConfigurationManager.Configuration.ServerName)
+ ? Environment.MachineName
+ : ServerConfigurationManager.Configuration.ServerName;
}
+ }
- return null;
+ public int HttpServerPort
+ {
+ get { return ServerConfigurationManager.Configuration.HttpServerPortNumber; }
}
/// <summary>
@@ -1021,7 +1043,6 @@ namespace MediaBrowser.ServerApplication
ServerAuthorization.AuthorizeServer(
ServerConfigurationManager.Configuration.HttpServerPortNumber,
HttpServerUrlPrefixes.First(),
- ServerConfigurationManager.Configuration.LegacyWebSocketPortNumber,
UdpServerEntryPoint.PortNumber,
ConfigurationManager.CommonApplicationPaths.TempDirectory);
}
@@ -1058,15 +1079,18 @@ namespace MediaBrowser.ServerApplication
/// <returns>Task{CheckForUpdateResult}.</returns>
public override async Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress)
{
- var availablePackages = await InstallationManager.GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
+ var result = await NativeApp.CheckForApplicationUpdate(ApplicationVersion,
+ ConfigurationManager.CommonConfiguration.SystemUpdateLevel, InstallationManager,
+ cancellationToken, progress).ConfigureAwait(false);
- var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, "MBServer", null, ApplicationVersion,
- ConfigurationManager.CommonConfiguration.SystemUpdateLevel);
+ HasUpdateAvailable = result.IsUpdateAvailable;
- HasUpdateAvailable = version != null && version.version >= ApplicationVersion;
+ if (result.IsUpdateAvailable)
+ {
+ Logger.Info("New application version is available: {0}", result.AvailableVersion);
+ }
- return version != null ? new CheckForUpdateResult { AvailableVersion = version.version, IsUpdateAvailable = version.version > ApplicationVersion, Package = version } :
- new CheckForUpdateResult { AvailableVersion = ApplicationVersion, IsUpdateAvailable = false };
+ return result;
}
/// <summary>
diff --git a/MediaBrowser.ServerApplication/EntryPoints/WanAddressEntryPoint.cs b/MediaBrowser.ServerApplication/EntryPoints/WanAddressEntryPoint.cs
deleted file mode 100644
index 7b2a1314e..000000000
--- a/MediaBrowser.ServerApplication/EntryPoints/WanAddressEntryPoint.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Plugins;
-using System;
-using System.IO;
-using System.Threading;
-
-namespace MediaBrowser.ServerApplication.EntryPoints
-{
- public class WanAddressEntryPoint : IServerEntryPoint
- {
- public static string WanAddress;
- private Timer _timer;
- private readonly IHttpClient _httpClient;
-
- public WanAddressEntryPoint(IHttpClient httpClient)
- {
- _httpClient = httpClient;
- }
-
- public void Run()
- {
- _timer = new Timer(TimerCallback, null, TimeSpan.FromMinutes(1), TimeSpan.FromHours(24));
- }
-
- private async void TimerCallback(object state)
- {
- try
- {
- using (var stream = await _httpClient.Get(new HttpRequestOptions
- {
- Url = "http://bot.whatismyipaddress.com/"
-
- }).ConfigureAwait(false))
- {
- using (var reader = new StreamReader(stream))
- {
- WanAddress = await reader.ReadToEndAsync().ConfigureAwait(false);
- }
- }
- }
- catch
- {
- }
- }
-
- public void Dispose()
- {
- if (_timer != null)
- {
- _timer.Dispose();
- _timer = null;
- }
- }
- }
-}
diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs
index b8566ee51..738650df7 100644
--- a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs
+++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs
@@ -14,6 +14,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
// Windows builds: http://ffmpeg.zeranoe.com/builds/
// Linux builds: http://ffmpeg.gusari.org/static/
// OS X builds: http://ffmpegmac.net/
+ // OS X x64: http://www.evermeet.cx/ffmpeg/
public static string Version = ffmpegOsType("Version");
@@ -34,7 +35,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
switch (arg)
{
case "Version":
- return "20140612";
+ return "20140827";
case "FFMpegFilename":
return "ffmpeg.exe";
case "FFProbeFilename":
@@ -52,6 +53,21 @@ namespace MediaBrowser.ServerApplication.FFMpeg
switch (arg)
{
case "Version":
+ return "20140827";
+ case "FFMpegFilename":
+ return "ffmpeg";
+ case "FFProbeFilename":
+ return "ffprobe";
+ case "ArchiveType":
+ return "gz";
+ }
+ break;
+ }
+ if (PlatformDetection.IsX86)
+ {
+ switch (arg)
+ {
+ case "Version":
return "20131121";
case "FFMpegFilename":
return "ffmpeg";
@@ -110,18 +126,35 @@ namespace MediaBrowser.ServerApplication.FFMpeg
switch (pid)
{
case PlatformID.Win32NT:
+ if (PlatformDetection.IsX86_64)
+ {
+ return new[]
+ {
+ "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20140827-git-9e8ab36-win64-static.7z",
+ "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/windows/ffmpeg-20140827-git-9e8ab36-win64-static.7z"
+ };
+ }
+
return new[]
{
- "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20140612-git-3a1c895-win32-static.7z",
- "https://www.dropbox.com/s/lllit55bynbz6zc/ffmpeg-20140612-git-3a1c895-win32-static.7z?dl=1"
+ "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20140827-git-9e8ab36-win32-static.7z",
+ "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/windows/ffmpeg-20140827-git-9e8ab36-win32-static.7z"
};
case PlatformID.Unix:
+ if (PlatformDetection.IsMac && PlatformDetection.IsX86)
+ {
+ return new[]
+ {
+ "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/osx/ffmpeg-osx-20131121.gz"
+ };
+ }
+
if (PlatformDetection.IsMac && PlatformDetection.IsX86_64)
{
return new[]
{
- "https://www.dropbox.com/s/n188rxbulqem8ry/ffmpeg-osx-20131121.gz?dl=1"
+ "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.3.3.7z"
};
}
@@ -132,7 +165,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
return new[]
{
"http://ffmpeg.gusari.org/static/32bit/ffmpeg.static.32bit.latest.tar.gz",
- "https://www.dropbox.com/s/k9s02pv5to6slfb/ffmpeg.static.32bit.2014-05-06.tar.gz?dl=1"
+ "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/linux/ffmpeg.static.32bit.2014-05-06.tar.gz"
};
}
@@ -141,13 +174,13 @@ namespace MediaBrowser.ServerApplication.FFMpeg
return new[]
{
"http://ffmpeg.gusari.org/static/64bit/ffmpeg.static.64bit.latest.tar.gz",
- "https://www.dropbox.com/s/onuregwghywnzjo/ffmpeg.static.64bit.2014-05-05.tar.gz?dl=1"
+ "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/linux/ffmpeg.static.64bit.2014-05-05.tar.gz"
};
}
}
- //No Unix version available
+ // No Unix version available
return new string[] { };
default:
@@ -213,4 +246,4 @@ namespace MediaBrowser.ServerApplication.FFMpeg
public string sysname = string.Empty;
public string machine = string.Empty;
}
-}
+} \ No newline at end of file
diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs
index c550cb27f..4f94ebd67 100644
--- a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs
+++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs
@@ -1,12 +1,10 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
-using MediaBrowser.Common.Progress;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using System;
-using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
@@ -26,10 +24,10 @@ namespace MediaBrowser.ServerApplication.FFMpeg
private readonly IZipClient _zipClient;
private readonly IFileSystem _fileSystem;
- private readonly string[] _fontUrls = new[]
- {
- "https://www.dropbox.com/s/pj847twf7riq0j7/ARIALUNI.7z?dl=1"
- };
+ private readonly string[] _fontUrls =
+ {
+ "https://www.dropbox.com/s/pj847twf7riq0j7/ARIALUNI.7z?dl=1"
+ };
public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem)
{
@@ -101,7 +99,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
{
EncoderPath = encoder,
ProbePath = probe,
- Version = Path.GetFileNameWithoutExtension(Path.GetDirectoryName(probe))
+ Version = Path.GetFileName(Path.GetDirectoryName(probe))
};
}
}
@@ -140,13 +138,9 @@ namespace MediaBrowser.ServerApplication.FFMpeg
ExtractFFMpeg(tempFile, directory);
return;
}
- catch (HttpException ex)
- {
- _logger.ErrorException("Error downloading {0}", ex, url);
- }
catch (Exception ex)
{
- _logger.ErrorException("Error unpacking {0}", ex, url);
+ _logger.ErrorException("Error downloading {0}", ex, url);
}
}
@@ -251,6 +245,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
Task.Run(async () =>
{
await DownloadFontFile(fontsDirectory, fontFilename, new Progress<double>()).ConfigureAwait(false);
+
await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
});
}
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs
index 3ea45bc4f..81c04060a 100644
--- a/MediaBrowser.ServerApplication/MainStartup.cs
+++ b/MediaBrowser.ServerApplication/MainStartup.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Constants;
using MediaBrowser.Common.Implementations.Logging;
using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Implementations;
@@ -195,13 +194,7 @@ namespace MediaBrowser.ServerApplication
private static void BeginLog(ILogger logger, IApplicationPaths appPaths)
{
logger.Info("Media Browser Server started");
- logger.Info("Command line: {0}", string.Join(" ", Environment.GetCommandLineArgs()));
-
- logger.Info("Server: {0}", Environment.MachineName);
- logger.Info("Operating system: {0}", Environment.OSVersion.ToString());
- logger.Info("Program data path: {0}", appPaths.ProgramDataPath);
-
- logger.Info("Application Path: {0}", appPaths.ApplicationPath);
+ ApplicationHost.LogEnvironmentInfo(logger, appPaths);
}
private static readonly TaskCompletionSource<bool> ApplicationTaskCompletionSource = new TaskCompletionSource<bool>();
@@ -227,14 +220,9 @@ namespace MediaBrowser.ServerApplication
ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX);
}
- var task = _appHost.Init(initProgress);
- Task.WaitAll(task);
-
- task = _appHost.RunStartupTasks();
- Task.WaitAll(task);
- SystemEvents.SessionEnding += SystemEvents_SessionEnding;
- SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
+ var task = _appHost.Init(initProgress);
+ task = task.ContinueWith(new Action<Task>(a => _appHost.RunStartupTasks()));
if (runService)
{
@@ -242,6 +230,11 @@ namespace MediaBrowser.ServerApplication
}
else
{
+ Task.WaitAll(task);
+
+ SystemEvents.SessionEnding += SystemEvents_SessionEnding;
+ SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
+
HideSplashScreen();
ShowTrayIcon();
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index 7657fc091..2e33ee2d5 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -61,14 +61,14 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="MediaBrowser.IsoMounter">
- <HintPath>..\packages\MediaBrowser.IsoMounting.3.0.68\lib\net45\MediaBrowser.IsoMounter.dll</HintPath>
+ <HintPath>..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll</HintPath>
</Reference>
- <Reference Include="NLog, Version=3.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
+ <Reference Include="NLog, Version=3.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\NLog.3.0.0.0\lib\net45\NLog.dll</HintPath>
+ <HintPath>..\packages\NLog.3.1.0.0\lib\net45\NLog.dll</HintPath>
</Reference>
<Reference Include="pfmclrapi">
- <HintPath>..\packages\MediaBrowser.IsoMounting.3.0.68\lib\net45\pfmclrapi.dll</HintPath>
+ <HintPath>..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\pfmclrapi.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Interfaces">
<HintPath>..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll</HintPath>
@@ -100,7 +100,6 @@
<Compile Include="EntryPoints\KeepServerAwake.cs" />
<Compile Include="EntryPoints\ResourceEntryPoint.cs" />
<Compile Include="EntryPoints\StartupWizard.cs" />
- <Compile Include="EntryPoints\WanAddressEntryPoint.cs" />
<Compile Include="FFMpeg\FFMpegDownloader.cs" />
<Compile Include="FFMpeg\FFMpegDownloadInfo.cs" />
<Compile Include="FFMpeg\FFMpegInfo.cs" />
@@ -198,6 +197,10 @@
<Project>{734098eb-6dc1-4dd0-a1ca-3140dcd2737c}</Project>
<Name>MediaBrowser.Dlna</Name>
</ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj">
+ <Project>{7ef9f3e0-697d-42f3-a08f-19deb5f84392}</Project>
+ <Name>MediaBrowser.LocalMetadata</Name>
+ </ProjectReference>
<ProjectReference Include="..\MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj">
<Project>{0bd82fa6-eb8a-4452-8af5-74f9c3849451}</Project>
<Name>MediaBrowser.MediaEncoding</Name>
@@ -218,6 +221,10 @@
<Project>{5624b7b5-b5a7-41d8-9f10-cc5611109619}</Project>
<Name>MediaBrowser.WebDashboard</Name>
</ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj">
+ <Project>{23499896-b135-4527-8574-c26e926ea99e}</Project>
+ <Name>MediaBrowser.XbmcMetadata</Name>
+ </ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
diff --git a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs
index 77a543ad7..c2c64ea4d 100644
--- a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs
+++ b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs
@@ -25,7 +25,7 @@ namespace MediaBrowser.ServerApplication.Native
public static void OpenDashboardPage(string page, User loggedInUser, IServerConfigurationManager configurationManager, IServerApplicationHost appHost, ILogger logger)
{
var url = "http://localhost:" + configurationManager.Configuration.HttpServerPortNumber + "/" +
- appHost.WebApplicationName + "/dashboard/" + page;
+ appHost.WebApplicationName + "/web/" + page;
OpenUrl(url, logger);
}
@@ -87,18 +87,6 @@ namespace MediaBrowser.ServerApplication.Native
}
/// <summary>
- /// Opens the standard API documentation.
- /// </summary>
- /// <param name="configurationManager">The configuration manager.</param>
- /// <param name="appHost">The app host.</param>
- /// <param name="logger">The logger.</param>
- public static void OpenStandardApiDocumentation(IServerConfigurationManager configurationManager, IServerApplicationHost appHost, ILogger logger)
- {
- OpenUrl("http://localhost:" + configurationManager.Configuration.HttpServerPortNumber + "/" +
- appHost.WebApplicationName + "/metadata", logger);
- }
-
- /// <summary>
/// Opens the URL.
/// </summary>
/// <param name="url">The URL.</param>
diff --git a/MediaBrowser.ServerApplication/Native/NativeApp.cs b/MediaBrowser.ServerApplication/Native/NativeApp.cs
index 2388b610b..0e7dc50a9 100644
--- a/MediaBrowser.ServerApplication/Native/NativeApp.cs
+++ b/MediaBrowser.ServerApplication/Native/NativeApp.cs
@@ -1,4 +1,10 @@
-using System.Runtime.InteropServices;
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Updates;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Updates;
namespace MediaBrowser.ServerApplication.Native
{
@@ -84,5 +90,24 @@ namespace MediaBrowser.ServerApplication.Native
EXECUTION_STATE es = SetThreadExecutionState(EXECUTION_STATE.ES_SYSTEM_REQUIRED);
}
}
+
+ public static async Task<CheckForUpdateResult> CheckForApplicationUpdate(Version currentVersion,
+ PackageVersionClass updateLevel,
+ IInstallationManager installationManager,
+ CancellationToken cancellationToken,
+ IProgress<double> progress)
+ {
+ var availablePackages = await installationManager.GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
+
+ var version = installationManager.GetLatestCompatibleVersion(availablePackages, "MBServer", null, currentVersion, updateLevel);
+
+ var versionObject = version == null || string.IsNullOrWhiteSpace(version.versionStr) ? null : new Version(version.versionStr);
+
+ var isUpdateAvailable = versionObject != null && versionObject > currentVersion;
+
+ return versionObject != null ?
+ new CheckForUpdateResult { AvailableVersion = versionObject.ToString(), IsUpdateAvailable = isUpdateAvailable, Package = version } :
+ new CheckForUpdateResult { AvailableVersion = currentVersion.ToString(), IsUpdateAvailable = false };
+ }
}
}
diff --git a/MediaBrowser.ServerApplication/Native/RegisterServer.bat b/MediaBrowser.ServerApplication/Native/RegisterServer.bat
index d762dfaf7..350412344 100644
--- a/MediaBrowser.ServerApplication/Native/RegisterServer.bat
+++ b/MediaBrowser.ServerApplication/Native/RegisterServer.bat
@@ -1,7 +1,6 @@
rem %1 = http server port
rem %2 = http server url
rem %3 = udp server port
-rem %4 = tcp server port (web socket)
if [%1]==[] GOTO DONE
@@ -18,11 +17,6 @@ if [%3]==[] GOTO DONE
netsh advfirewall firewall delete rule name="Port %3" protocol=UDP localport=%3
netsh advfirewall firewall add rule name="Port %3" dir=in action=allow protocol=UDP localport=%3
-if [%4]==[] GOTO DONE
-
-netsh advfirewall firewall delete rule name="Port %4" protocol=TCP localport=%4
-netsh advfirewall firewall add rule name="Port %4" dir=in action=allow protocol=TCP localport=%4
-
:DONE
Exit \ No newline at end of file
diff --git a/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs b/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs
index d2e542536..e5989db3b 100644
--- a/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs
+++ b/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs
@@ -15,10 +15,9 @@ namespace MediaBrowser.ServerApplication.Native
/// </summary>
/// <param name="httpServerPort">The HTTP server port.</param>
/// <param name="httpServerUrlPrefix">The HTTP server URL prefix.</param>
- /// <param name="webSocketPort">The web socket port.</param>
/// <param name="udpPort">The UDP port.</param>
/// <param name="tempDirectory">The temp directory.</param>
- public static void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int webSocketPort, int udpPort, string tempDirectory)
+ public static void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int udpPort, string tempDirectory)
{
Directory.CreateDirectory(tempDirectory);
@@ -38,10 +37,9 @@ namespace MediaBrowser.ServerApplication.Native
{
FileName = tmpFile,
- Arguments = string.Format("{0} {1} {2} {3}", httpServerPort,
+ Arguments = string.Format("{0} {1} {2}", httpServerPort,
httpServerUrlPrefix,
- udpPort,
- webSocketPort),
+ udpPort),
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
diff --git a/MediaBrowser.ServerApplication/Networking/NetworkManager.cs b/MediaBrowser.ServerApplication/Networking/NetworkManager.cs
index e80c8ff3f..fc4d26363 100644
--- a/MediaBrowser.ServerApplication/Networking/NetworkManager.cs
+++ b/MediaBrowser.ServerApplication/Networking/NetworkManager.cs
@@ -1,11 +1,12 @@
-using System.Globalization;
-using System.IO;
-using MediaBrowser.Common.Implementations.Networking;
+using MediaBrowser.Common.Implementations.Networking;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using System;
using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
@@ -16,6 +17,11 @@ namespace MediaBrowser.ServerApplication.Networking
/// </summary>
public class NetworkManager : BaseNetworkManager, INetworkManager
{
+ public NetworkManager(ILogger logger)
+ : base(logger)
+ {
+ }
+
/// <summary>
/// Gets the network shares.
/// </summary>
diff --git a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs
index f5f9434e7..47a4be8e3 100644
--- a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs
+++ b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs
@@ -29,7 +29,6 @@ namespace MediaBrowser.ServerApplication
private System.Windows.Forms.ToolStripMenuItem cmdLogWindow;
private System.Windows.Forms.ToolStripMenuItem cmdCommunity;
private System.Windows.Forms.ToolStripMenuItem cmdApiDocs;
- private System.Windows.Forms.ToolStripMenuItem cmdStandardDocs;
private System.Windows.Forms.ToolStripMenuItem cmdSwagger;
private System.Windows.Forms.ToolStripMenuItem cmdGtihub;
@@ -90,7 +89,6 @@ namespace MediaBrowser.ServerApplication
cmdConfigure = new System.Windows.Forms.ToolStripMenuItem();
cmdBrowse = new System.Windows.Forms.ToolStripMenuItem();
cmdApiDocs = new System.Windows.Forms.ToolStripMenuItem();
- cmdStandardDocs = new System.Windows.Forms.ToolStripMenuItem();
cmdSwagger = new System.Windows.Forms.ToolStripMenuItem();
cmdGtihub = new System.Windows.Forms.ToolStripMenuItem();
@@ -169,17 +167,11 @@ namespace MediaBrowser.ServerApplication
// cmdApiDocs
//
cmdApiDocs.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- cmdStandardDocs,
cmdSwagger,
cmdGtihub});
cmdApiDocs.Name = "cmdApiDocs";
cmdApiDocs.Size = new System.Drawing.Size(208, 22);
//
- // cmdStandardDocs
- //
- cmdStandardDocs.Name = "cmdStandardDocs";
- cmdStandardDocs.Size = new System.Drawing.Size(136, 22);
- //
// cmdSwagger
//
cmdSwagger.Name = "cmdSwagger";
@@ -199,7 +191,6 @@ namespace MediaBrowser.ServerApplication
cmdLibraryExplorer.Click += cmdLibraryExplorer_Click;
cmdSwagger.Click += cmdSwagger_Click;
- cmdStandardDocs.Click += cmdStandardDocs_Click;
cmdGtihub.Click += cmdGtihub_Click;
LoadLogWindow(null, EventArgs.Empty);
@@ -224,7 +215,6 @@ namespace MediaBrowser.ServerApplication
cmdCommunity.Text = _localization.GetLocalizedString("LabelVisitCommunity");
cmdGtihub.Text = _localization.GetLocalizedString("LabelGithubWiki");
cmdSwagger.Text = _localization.GetLocalizedString("LabelSwagger");
- cmdStandardDocs.Text = _localization.GetLocalizedString("LabelStandard");
cmdApiDocs.Text = _localization.GetLocalizedString("LabelViewApiDocumentation");
cmdBrowse.Text = _localization.GetLocalizedString("LabelBrowseLibrary");
cmdConfigure.Text = _localization.GetLocalizedString("LabelConfigureMediaBrowser");
@@ -346,11 +336,6 @@ namespace MediaBrowser.ServerApplication
BrowserLauncher.OpenGithub(_logger);
}
- void cmdStandardDocs_Click(object sender, EventArgs e)
- {
- BrowserLauncher.OpenStandardApiDocumentation(_configurationManager, _appHost, _logger);
- }
-
void cmdSwagger_Click(object sender, EventArgs e)
{
BrowserLauncher.OpenSwagger(_configurationManager, _appHost, _logger);
diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config
index 87bd11bd4..8de487fb5 100644
--- a/MediaBrowser.ServerApplication/packages.config
+++ b/MediaBrowser.ServerApplication/packages.config
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="MediaBrowser.IsoMounting" version="3.0.68" targetFramework="net45" />
- <package id="NLog" version="3.0.0.0" targetFramework="net45" />
+ <package id="MediaBrowser.IsoMounting" version="3.0.69" targetFramework="net45" />
+ <package id="NLog" version="3.1.0.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Tests/MediaBrowser.Tests.csproj b/MediaBrowser.Tests/MediaBrowser.Tests.csproj
index d31615952..dc7393b01 100644
--- a/MediaBrowser.Tests/MediaBrowser.Tests.csproj
+++ b/MediaBrowser.Tests/MediaBrowser.Tests.csproj
@@ -55,6 +55,7 @@
<Compile Include="MediaEncoding\Subtitles\VttWriterTest.cs" />
<Compile Include="Providers\MovieDbProviderTests.cs" />
<Compile Include="Resolvers\MovieResolverTests.cs" />
+ <Compile Include="Resolvers\MusicResolverTests.cs" />
<Compile Include="Resolvers\TvUtilTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Server.Implementations\Library\ResolverHelperTests.cs" />
@@ -80,6 +81,10 @@
<Project>{2E781478-814D-4A48-9D80-BFF206441A65}</Project>
<Name>MediaBrowser.Server.Implementations</Name>
</ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj">
+ <Project>{23499896-b135-4527-8574-c26e926ea99e}</Project>
+ <Name>MediaBrowser.XbmcMetadata</Name>
+ </ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
diff --git a/MediaBrowser.Tests/MediaEncoding/Subtitles/SsaParserTests.cs b/MediaBrowser.Tests/MediaEncoding/Subtitles/SsaParserTests.cs
index 3c278ae41..d869146fd 100644
--- a/MediaBrowser.Tests/MediaEncoding/Subtitles/SsaParserTests.cs
+++ b/MediaBrowser.Tests/MediaEncoding/Subtitles/SsaParserTests.cs
@@ -39,7 +39,7 @@ namespace MediaBrowser.Tests.MediaEncoding.Subtitles {
}
};
- var sut = new SsaParser();
+ var sut = new AssParser();
var stream = File.OpenRead(@"MediaEncoding\Subtitles\TestSubtitles\data.ssa");
diff --git a/MediaBrowser.Tests/Providers/MovieDbProviderTests.cs b/MediaBrowser.Tests/Providers/MovieDbProviderTests.cs
index 8f5dcc034..545894b0d 100644
--- a/MediaBrowser.Tests/Providers/MovieDbProviderTests.cs
+++ b/MediaBrowser.Tests/Providers/MovieDbProviderTests.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Providers.Movies;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MediaBrowser.Tests.Providers {
@@ -9,24 +8,29 @@ namespace MediaBrowser.Tests.Providers {
public void TestNameMatches() {
var name = string.Empty;
int? year = null;
+
NameParser.ParseName("My Movie (2013)", out name, out year);
Assert.AreEqual("My Movie", name);
Assert.AreEqual(2013, year);
+
name = string.Empty;
year = null;
NameParser.ParseName("My Movie 2 (2013)", out name, out year);
Assert.AreEqual("My Movie 2", name);
Assert.AreEqual(2013, year);
+
name = string.Empty;
year = null;
NameParser.ParseName("My Movie 2001 (2013)", out name, out year);
Assert.AreEqual("My Movie 2001", name);
Assert.AreEqual(2013, year);
+
name = string.Empty;
year = null;
NameParser.ParseName("My Movie - 2 (2013)", out name, out year);
Assert.AreEqual("My Movie - 2", name);
Assert.AreEqual(2013, year);
+
name = string.Empty;
year = null;
NameParser.ParseName("curse.of.chucky.2013.stv.unrated.multi.1080p.bluray.x264-rough", out name, out year);
diff --git a/MediaBrowser.Tests/Resolvers/MovieResolverTests.cs b/MediaBrowser.Tests/Resolvers/MovieResolverTests.cs
index 768e4ee5c..af24609e8 100644
--- a/MediaBrowser.Tests/Resolvers/MovieResolverTests.cs
+++ b/MediaBrowser.Tests/Resolvers/MovieResolverTests.cs
@@ -38,6 +38,8 @@ namespace MediaBrowser.Tests.Resolvers
public void TestMultiPartFolders()
{
Assert.IsFalse(EntityResolutionHelper.IsMultiPartFolder(@"blah blah"));
+ Assert.IsFalse(EntityResolutionHelper.IsMultiPartFolder(@"d:\\music\weezer\\03 Pinkerton"));
+ Assert.IsFalse(EntityResolutionHelper.IsMultiPartFolder(@"d:\\music\\michael jackson\\Bad (2012 Remaster)"));
Assert.IsTrue(EntityResolutionHelper.IsMultiPartFolder(@"blah blah - cd1"));
Assert.IsTrue(EntityResolutionHelper.IsMultiPartFolder(@"blah blah - disc1"));
diff --git a/MediaBrowser.Tests/Resolvers/MusicResolverTests.cs b/MediaBrowser.Tests/Resolvers/MusicResolverTests.cs
new file mode 100644
index 000000000..201f25263
--- /dev/null
+++ b/MediaBrowser.Tests/Resolvers/MusicResolverTests.cs
@@ -0,0 +1,30 @@
+using MediaBrowser.Controller.Resolvers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace MediaBrowser.Tests.Resolvers
+{
+ [TestClass]
+ public class MusicResolverTests
+ {
+ [TestMethod]
+ public void TestMultiDiscAlbums()
+ {
+ Assert.IsFalse(EntityResolutionHelper.IsMultiDiscAlbumFolder(@"blah blah"));
+ Assert.IsFalse(EntityResolutionHelper.IsMultiDiscAlbumFolder(@"d:\\music\weezer\\03 Pinkerton"));
+ Assert.IsFalse(EntityResolutionHelper.IsMultiDiscAlbumFolder(@"d:\\music\\michael jackson\\Bad (2012 Remaster)"));
+
+ Assert.IsTrue(EntityResolutionHelper.IsMultiDiscAlbumFolder(@"cd1"));
+ Assert.IsTrue(EntityResolutionHelper.IsMultiDiscAlbumFolder(@"disc1"));
+ Assert.IsTrue(EntityResolutionHelper.IsMultiDiscAlbumFolder(@"disk1"));
+
+ // Add a space
+ Assert.IsTrue(EntityResolutionHelper.IsMultiDiscAlbumFolder(@"cd 1"));
+ Assert.IsTrue(EntityResolutionHelper.IsMultiDiscAlbumFolder(@"disc 1"));
+ Assert.IsTrue(EntityResolutionHelper.IsMultiDiscAlbumFolder(@"disk 1"));
+
+ Assert.IsTrue(EntityResolutionHelper.IsMultiDiscAlbumFolder(@"cd - 1"));
+ Assert.IsTrue(EntityResolutionHelper.IsMultiDiscAlbumFolder(@"disc- 1"));
+ Assert.IsTrue(EntityResolutionHelper.IsMultiDiscAlbumFolder(@"disk - 1"));
+ }
+ }
+}
diff --git a/MediaBrowser.Tests/Resolvers/TvUtilTests.cs b/MediaBrowser.Tests/Resolvers/TvUtilTests.cs
index 97e790776..5e6add528 100644
--- a/MediaBrowser.Tests/Resolvers/TvUtilTests.cs
+++ b/MediaBrowser.Tests/Resolvers/TvUtilTests.cs
@@ -9,6 +9,8 @@ namespace MediaBrowser.Tests.Resolvers
[TestMethod]
public void TestGetEpisodeNumberFromFile()
{
+ Assert.AreEqual(03, TVUtils.GetEpisodeNumberFromFile(@"Season 02\S02E03 blah.avi", true));
+
Assert.AreEqual(02, TVUtils.GetEpisodeNumberFromFile(@"Season 1\01x02 blah.avi", true));
Assert.AreEqual(02, TVUtils.GetEpisodeNumberFromFile(@"Season 1\S01x02 blah.avi", true));
Assert.AreEqual(02, TVUtils.GetEpisodeNumberFromFile(@"Season 1\S01E02 blah.avi", true));
@@ -31,6 +33,7 @@ namespace MediaBrowser.Tests.Resolvers
Assert.AreEqual(23, TVUtils.GetEpisodeNumberFromFile(@"Season 1\S01E23-E24-E26 - The Woman.mp4", true));
Assert.AreEqual(9, TVUtils.GetEpisodeNumberFromFile(@"Season 25\The Simpsons.S25E09.Steal this episode.mp4", true));
Assert.AreEqual(8, TVUtils.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons.S25E08.Steal this episode.mp4", false));
+ Assert.AreEqual(136, TVUtils.GetEpisodeNumberFromFile(@"Season 2\[HorribleSubs] Hunter X Hunter - 136 [720p].mkv",true));
//Four Digits seasons
Assert.AreEqual(02, TVUtils.GetEpisodeNumberFromFile(@"Season 2009\2009x02 blah.avi", true));
@@ -128,10 +131,20 @@ namespace MediaBrowser.Tests.Resolvers
Assert.AreEqual(null, TVUtils.GetEndingEpisodeNumberFromFile(@"Season 2\02 - blah 14 blah.avi"));
Assert.AreEqual(null, TVUtils.GetEndingEpisodeNumberFromFile(@"Season 1\02 - blah-02 a.avi"));
Assert.AreEqual(null, TVUtils.GetEndingEpisodeNumberFromFile(@"Season 2\02.avi"));
+
+ Assert.AreEqual(3, TVUtils.GetEndingEpisodeNumberFromFile(@"Season 1\02-03 - blah.avi"));
+ Assert.AreEqual(4, TVUtils.GetEndingEpisodeNumberFromFile(@"Season 2\02-04 - blah 14 blah.avi"));
+ Assert.AreEqual(5, TVUtils.GetEndingEpisodeNumberFromFile(@"Season 1\02-05 - blah-02 a.avi"));
+ Assert.AreEqual(4, TVUtils.GetEndingEpisodeNumberFromFile(@"Season 2\02-04.avi"));
+ Assert.AreEqual(null, TVUtils.GetEndingEpisodeNumberFromFile(@"Season 2\[HorribleSubs] Hunter X Hunter - 136 [720p].mkv"));
+
}
[TestMethod]
public void TestGetSeasonNumberFromPath() {
+
+ Assert.AreEqual(02, TVUtils.GetSeasonNumberFromEpisodeFile(@"\Show\Season 02\S02E03 blah.avi"));
+
Assert.AreEqual(1, TVUtils.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(1, TVUtils.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(1, TVUtils.GetSeasonNumberFromPath(@"\Drive\Season 1"));
@@ -153,6 +166,10 @@ namespace MediaBrowser.Tests.Resolvers
Assert.AreEqual(1, TVUtils.GetSeasonNumberFromPath(@"\Drive\Season 1"));
Assert.AreEqual(1, TVUtils.GetSeasonNumberFromPath(@"\Drive\Season 1"));
+ Assert.AreEqual(2, TVUtils.GetSeasonNumberFromPath(@"\Drive\Seinfeld\S02"));
+
+ Assert.AreEqual(2, TVUtils.GetSeasonNumberFromPath(@"\Drive\Seinfeld\2"));
+
//Four Digits seasons
Assert.AreEqual(2009, TVUtils.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
Assert.AreEqual(2009, TVUtils.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs
index 40a9d8ed6..2269d308e 100644
--- a/MediaBrowser.WebDashboard/Api/DashboardService.cs
+++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs
@@ -25,6 +25,7 @@ namespace MediaBrowser.WebDashboard.Api
/// Class GetDashboardConfigurationPages
/// </summary>
[Route("/dashboard/ConfigurationPages", "GET")]
+ [Route("/web/ConfigurationPages", "GET")]
public class GetDashboardConfigurationPages : IReturn<List<ConfigurationPageInfo>>
{
/// <summary>
@@ -38,6 +39,7 @@ namespace MediaBrowser.WebDashboard.Api
/// Class GetDashboardConfigurationPage
/// </summary>
[Route("/dashboard/ConfigurationPage", "GET")]
+ [Route("/web/ConfigurationPage", "GET")]
public class GetDashboardConfigurationPage
{
/// <summary>
@@ -50,6 +52,7 @@ namespace MediaBrowser.WebDashboard.Api
/// <summary>
/// Class GetDashboardResource
/// </summary>
+ [Route("/web/{ResourceName*}", "GET")]
[Route("/dashboard/{ResourceName*}", "GET")]
public class GetDashboardResource
{
@@ -218,6 +221,18 @@ namespace MediaBrowser.WebDashboard.Api
var contentType = MimeTypes.GetMimeType(path);
var isHtml = IsHtml(path);
+
+ if (isHtml && !_serverConfigurationManager.Configuration.IsStartupWizardCompleted)
+ {
+ if (path.IndexOf("wizard", StringComparison.OrdinalIgnoreCase) == -1)
+ {
+ Request.Response.Redirect("wizardstart.html");
+ return null;
+ }
+ }
+
+ path = path.Replace("scripts/jquery.mobile-1.4.3.min.map", "thirdparty/jquerymobile-1.4.3/jquery.mobile-1.4.3.min.map", StringComparison.OrdinalIgnoreCase);
+
var localizationCulture = GetLocalizationCulture();
// Don't cache if not configured to do so
@@ -400,7 +415,7 @@ namespace MediaBrowser.WebDashboard.Api
var files = new[]
{
- "thirdparty/jquerymobile-1.4.2/jquery.mobile-1.4.2.min.css",
+ "thirdparty/jquerymobile-1.4.3/jquery.mobile-1.4.3.min.css",
"css/all.css" + versionString
};
@@ -423,9 +438,7 @@ namespace MediaBrowser.WebDashboard.Api
var files = new[]
{
"scripts/all.js" + versionString,
- "thirdparty/jstree1.0/jquery.jstree.min.js",
- "thirdparty/jquery.unveil-custom.js",
- "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js"
+ "thirdparty/jstree1.0/jquery.jstree.min.js"
};
var tags = files.Select(s => string.Format("<script src=\"{0}\"></script>", s)).ToArray();
@@ -445,9 +458,17 @@ namespace MediaBrowser.WebDashboard.Api
var newLineBytes = Encoding.UTF8.GetBytes(Environment.NewLine);
// jQuery + jQuery mobile
- await AppendResource(memoryStream, "thirdparty/jquery-2.0.3.min.js", newLineBytes).ConfigureAwait(false);
- await AppendResource(memoryStream, "thirdparty/jquerymobile-1.4.2/jquery.mobile-1.4.2.min.js", newLineBytes).ConfigureAwait(false);
+ await AppendResource(memoryStream, "thirdparty/jquery-2.1.1.min.js", newLineBytes).ConfigureAwait(false);
+ await AppendResource(memoryStream, "thirdparty/jquerymobile-1.4.3/jquery.mobile-1.4.3.min.js", newLineBytes).ConfigureAwait(false);
+
+ await AppendResource(memoryStream, "thirdparty/jquery.unveil-custom.js", newLineBytes).ConfigureAwait(false);
+ // This script produces errors in older versions of safari
+ if ((Request.UserAgent ?? string.Empty).IndexOf("chrome/", StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ await AppendResource(memoryStream, "thirdparty/cast_sender.js", newLineBytes).ConfigureAwait(false);
+ }
+
await AppendLocalization(memoryStream).ConfigureAwait(false);
await memoryStream.WriteAsync(newLineBytes, 0, newLineBytes.Length).ConfigureAwait(false);
@@ -518,6 +539,8 @@ namespace MediaBrowser.WebDashboard.Api
"mediacontroller.js",
"chromecast.js",
"backdrops.js",
+ "sync.js",
+ "playlistmanager.js",
"mediaplayer.js",
"mediaplayer-video.js",
@@ -526,15 +549,10 @@ namespace MediaBrowser.WebDashboard.Api
"ratingdialog.js",
"aboutpage.js",
- "allusersettings.js",
"alphapicker.js",
"addpluginpage.js",
"advancedconfigurationpage.js",
- "advancedpaths.js",
- "advancedserversettings.js",
"metadataadvanced.js",
- "appsplayback.js",
- "appsweather.js",
"autoorganizetv.js",
"autoorganizelog.js",
"channels.js",
@@ -542,8 +560,8 @@ namespace MediaBrowser.WebDashboard.Api
"channelitems.js",
"channelsettings.js",
"dashboardgeneral.js",
- "dashboardinfo.js",
"dashboardpage.js",
+ "dashboardsync.js",
"directorybrowser.js",
"dlnaprofile.js",
"dlnaprofiles.js",
@@ -585,15 +603,13 @@ namespace MediaBrowser.WebDashboard.Api
"livetvstatus.js",
"livetvtimers.js",
- "localsettings.js",
-
"loginpage.js",
"logpage.js",
"medialibrarypage.js",
"metadataconfigurationpage.js",
"metadataimagespage.js",
"metadatasubtitles.js",
- "metadatachapters.js",
+ "metadataxbmc.js",
"moviegenres.js",
"moviecollections.js",
"movies.js",
@@ -618,12 +634,16 @@ namespace MediaBrowser.WebDashboard.Api
"notificationsetting.js",
"notificationsettings.js",
"playlist.js",
+ "playlists.js",
+ "playlistedit.js",
+
"plugincatalogpage.js",
"pluginspage.js",
"remotecontrol.js",
"scheduledtaskpage.js",
"scheduledtaskspage.js",
"search.js",
+ "serversecurity.js",
"songs.js",
"supporterkeypage.js",
"supporterpage.js",
@@ -642,7 +662,6 @@ namespace MediaBrowser.WebDashboard.Api
"userprofilespage.js",
"userparentalcontrol.js",
"wizardfinishpage.js",
- "wizardimagesettings.js",
"wizardservice.js",
"wizardstartpage.js",
"wizardsettings.js",
@@ -668,13 +687,12 @@ namespace MediaBrowser.WebDashboard.Api
{
"site.css",
"chromecast.css",
- "contextmenu.css",
"mediaplayer.css",
"mediaplayer-video.css",
"librarymenu.css",
"librarybrowser.css",
"detailtable.css",
- "posteritem.css",
+ "card.css",
"tileitem.css",
"metadataeditor.css",
"notifications.css",
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index 1ae22d49e..32cb88218 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -89,15 +89,6 @@
<EmbeddedResource Include="dashboard-ui\thirdparty\mediabrowser.apiclient.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
- <Content Include="dashboard-ui\advancedpaths.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\advancedserversettings.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\appsplayback.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\channelitems.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -113,9 +104,6 @@
<Content Include="dashboard-ui\css\chromecast.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\css\contextmenu.css">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\css\icons.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -161,9 +149,15 @@
<Content Include="dashboard-ui\css\images\clients\amazon.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\css\images\clients\chrome_companion.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\css\images\clients\mediaportal.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\css\images\clients\nuvue.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\css\images\clients\playstore.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -176,6 +170,9 @@
<Content Include="dashboard-ui\css\images\headersearch.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\css\images\icons\ellipsis-v.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\css\images\icons\remote.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -191,9 +188,6 @@
<Content Include="dashboard-ui\css\images\items\folders\settings.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\css\images\menu.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\css\images\icons\audiocd.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -278,9 +272,6 @@
<Content Include="dashboard-ui\css\images\media\play.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\css\images\media\tvflyout.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\css\librarymenu.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -296,10 +287,13 @@
<Content Include="dashboard-ui\css\nowplaying.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\css\card.css">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\dashboardgeneral.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\dashboardinfopage.html">
+ <Content Include="dashboard-ui\dashboardsync.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\dlnaprofile.html">
@@ -332,13 +326,16 @@
<Content Include="dashboard-ui\favorites.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\files\dummy.mp4">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\homelatest.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\librarypathmapping.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\metadatachapters.html">
+ <Content Include="dashboard-ui\metadataxbmc.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\mypreferencesdisplay.html">
@@ -353,6 +350,12 @@
<Content Include="dashboard-ui\notificationlist.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\playlistedit.html">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\playlists.html">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\reports.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -392,9 +395,6 @@
<Content Include="dashboard-ui\musicalbumartists.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\allusersettings.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\collections.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -464,21 +464,9 @@
<Content Include="dashboard-ui\css\images\items\searchhintsv2\tv.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\css\images\media\audioflyout.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\css\images\media\chapterflyout.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\css\images\media\qualityflyout.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\css\images\media\selected.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\css\images\media\subtitleflyout.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\css\images\rotten.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -548,9 +536,6 @@
<Content Include="dashboard-ui\css\pluginupdates.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\css\posteritem.css">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\css\remotecontrol.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -605,15 +590,6 @@
<Content Include="dashboard-ui\nowplaying.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\advancedpaths.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\scripts\advancedserversettings.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\scripts\appsplayback.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\scripts\backdrops.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -635,7 +611,7 @@
<Content Include="dashboard-ui\scripts\dashboardgeneral.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\dashboardinfo.js">
+ <Content Include="dashboard-ui\scripts\dashboardsync.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\dlnaprofile.js">
@@ -680,10 +656,7 @@
<Content Include="dashboard-ui\scripts\librarypathmapping.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\localsettings.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\scripts\metadatachapters.js">
+ <Content Include="dashboard-ui\scripts\metadataxbmc.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\mypreferencesdisplay.js">
@@ -698,6 +671,15 @@
<Content Include="dashboard-ui\scripts\notificationlist.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\scripts\playlistedit.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\scripts\playlistmanager.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\scripts\playlists.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\scripts\reports.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -785,6 +767,12 @@
<Content Include="dashboard-ui\scripts\livetvsuggested.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\scripts\serversecurity.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\scripts\sync.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\scripts\thememediaplayer.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -794,9 +782,6 @@
<Content Include="dashboard-ui\scripts\userparentalcontrol.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\wizardimagesettings.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\scripts\wizardservice.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -806,619 +791,628 @@
<Content Include="dashboard-ui\livetvseriestimers.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\serversecurity.html">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\cast_sender.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\thirdparty\jquery-2.0.3.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\thirdparty\jquery-2.1.1.min.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\thirdparty\jquery.unveil-custom.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\ajax-loader.gif">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\ajax-loader.gif">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\action-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\action-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\action-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\action-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\alert-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\alert-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\alert-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\alert-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-d-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-d-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-d-l-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-d-l-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-d-l-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-d-l-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-d-r-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-d-r-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-d-r-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-d-r-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-d-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-d-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-l-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-l-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-l-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-l-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-r-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-r-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-r-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-r-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-u-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-u-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-u-l-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-u-l-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-u-l-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-u-l-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-u-r-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-u-r-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-u-r-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-u-r-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\arrow-u-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\arrow-u-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\audio-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\audio-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\audio-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\audio-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\back-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\back-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\back-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\back-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\bars-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\bars-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\bars-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\bars-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\bullets-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\bullets-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\bullets-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\bullets-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\calendar-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\calendar-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\calendar-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\calendar-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\camera-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\camera-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\camera-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\camera-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-d-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\carat-d-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-d-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\carat-d-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-l-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\carat-l-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-l-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\carat-l-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-r-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\carat-r-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-r-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\carat-r-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-u-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\carat-u-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\carat-u-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\carat-u-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\check-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\check-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\check-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\check-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\clock-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\clock-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\clock-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\clock-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\cloud-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\cloud-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\cloud-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\cloud-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\comment-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\comment-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\comment-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\comment-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\delete-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\delete-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\delete-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\delete-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\edit-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\edit-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\edit-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\edit-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\eye-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\eye-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\eye-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\eye-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\forbidden-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\forbidden-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\forbidden-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\forbidden-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\forward-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\forward-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\forward-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\forward-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\gear-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\gear-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\gear-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\gear-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\grid-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\grid-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\grid-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\grid-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\heart-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\heart-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\heart-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\heart-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\home-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\home-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\home-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\home-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\info-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\info-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\info-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\info-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\location-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\location-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\location-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\location-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\lock-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\lock-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\lock-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\lock-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\mail-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\mail-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\mail-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\mail-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\minus-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\minus-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\minus-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\minus-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\navigation-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\navigation-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\navigation-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\navigation-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\phone-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\phone-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\phone-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\phone-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\plus-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\plus-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\plus-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\plus-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\power-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\power-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\power-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\power-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\recycle-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\recycle-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\recycle-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\recycle-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\refresh-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\refresh-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\refresh-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\refresh-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\search-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\search-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\search-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\search-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\shop-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\shop-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\shop-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\shop-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\star-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\star-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\star-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\star-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\tag-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\tag-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\tag-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\tag-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\user-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\user-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\user-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\user-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\video-black.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\video-black.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-png\video-white.png">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-png\video-white.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\action-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\action-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\action-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\action-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\alert-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\alert-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\alert-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\alert-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-d-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-d-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-d-l-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-d-l-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-d-l-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-d-l-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-d-r-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-d-r-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-d-r-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-d-r-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-d-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-d-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-l-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-l-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-l-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-l-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-r-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-r-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-r-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-r-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-u-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-u-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-u-l-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-u-l-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-u-l-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-u-l-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-u-r-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-u-r-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-u-r-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-u-r-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\arrow-u-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\arrow-u-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\audio-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\audio-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\audio-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\audio-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\back-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\back-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\back-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\back-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\bars-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\bars-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\bars-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\bars-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\bullets-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\bullets-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\bullets-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\bullets-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\calendar-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\calendar-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\calendar-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\calendar-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\camera-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\camera-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\camera-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\camera-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-d-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\carat-d-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-d-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\carat-d-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-l-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\carat-l-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-l-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\carat-l-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-r-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\carat-r-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-r-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\carat-r-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-u-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\carat-u-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\carat-u-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\carat-u-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\check-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\check-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\check-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\check-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\clock-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\clock-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\clock-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\clock-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\cloud-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\cloud-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\cloud-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\cloud-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\comment-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\comment-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\comment-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\comment-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\delete-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\delete-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\delete-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\delete-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\edit-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\edit-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\edit-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\edit-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\eye-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\eye-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\eye-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\eye-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\forbidden-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\forbidden-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\forbidden-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\forbidden-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\forward-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\forward-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\forward-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\forward-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\gear-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\gear-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\gear-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\gear-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\grid-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\grid-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\grid-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\grid-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\heart-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\heart-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\heart-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\heart-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\home-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\home-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\home-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\home-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\info-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\info-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\info-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\info-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\location-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\location-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\location-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\location-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\lock-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\lock-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\lock-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\lock-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\mail-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\mail-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\mail-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\mail-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\minus-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\minus-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\minus-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\minus-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\navigation-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\navigation-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\navigation-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\navigation-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\phone-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\phone-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\phone-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\phone-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\plus-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\plus-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\plus-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\plus-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\power-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\power-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\power-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\power-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\recycle-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\recycle-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\recycle-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\recycle-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\refresh-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\refresh-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\refresh-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\refresh-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\search-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\search-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\search-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\search-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\shop-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\shop-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\shop-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\shop-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\star-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\star-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\star-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\star-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\tag-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\tag-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\tag-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\tag-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\user-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\user-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\user-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\user-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\video-black.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\video-black.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\images\icons-svg\video-white.svg">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\images\icons-svg\video-white.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\jquery.mobile-1.4.2.min.css">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\jquery.mobile-1.4.3.min.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.2\jquery.mobile-1.4.2.min.js">
+ <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\jquery.mobile-1.4.3.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\thirdparty\jstree1.0\jquery.jstree.min.js">
@@ -1433,9 +1427,6 @@
<Content Include="dashboard-ui\userparentalcontrol.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\wizardimagesettings.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\wizardservice.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -1496,9 +1487,6 @@
<Content Include="dashboard-ui\musicvideos.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\allusersettings.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\scripts\alphapicker.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -1746,11 +1734,6 @@
</Content>
</ItemGroup>
<ItemGroup>
- <Content Include="dashboard-ui\appsweather.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- </ItemGroup>
- <ItemGroup>
<Content Include="dashboard-ui\useredit.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -1812,11 +1795,6 @@
</Content>
</ItemGroup>
<ItemGroup>
- <Content Include="dashboard-ui\scripts\appsweather.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- </ItemGroup>
- <ItemGroup>
<Content Include="dashboard-ui\scripts\pluginspage.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -2117,6 +2095,9 @@
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
+ <None Include="dashboard-ui\css\fonts\RobotoBold.woff">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
<None Include="dashboard-ui\css\fonts\OpenSans-ExtraBold.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@@ -2141,6 +2122,9 @@
<None Include="dashboard-ui\css\fonts\RobotoThin.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
+ <None Include="dashboard-ui\thirdparty\jquerymobile-1.4.3\jquery.mobile-1.4.3.min.map">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
<None Include="packages.config" />
<None Include="WebMarkupMin.Configuration.xsd">
<SubType>Designer</SubType>
@@ -2152,7 +2136,7 @@
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
- <Import Project="$(SolutionDir)\.nuget\nuget.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.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">
diff --git a/MediaBrowser.XbmcMetadata/Configuration/NfoOptions.cs b/MediaBrowser.XbmcMetadata/Configuration/NfoOptions.cs
new file mode 100644
index 000000000..d0e2dbc6d
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Configuration/NfoOptions.cs
@@ -0,0 +1,29 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Configuration;
+using System.Collections.Generic;
+
+namespace MediaBrowser.XbmcMetadata.Configuration
+{
+ public class ConfigurationFactory : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new[]
+ {
+ new ConfigurationStore
+ {
+ ConfigurationType = typeof(XbmcMetadataOptions),
+ Key = "xbmcmetadata"
+ }
+ };
+ }
+ }
+
+ public static class ConfigurationExtension
+ {
+ public static XbmcMetadataOptions GetNfoConfiguration(this IConfigurationManager manager)
+ {
+ return manager.GetConfiguration<XbmcMetadataOptions>("xbmcmetadata");
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/EntryPoint.cs b/MediaBrowser.XbmcMetadata/EntryPoint.cs
new file mode 100644
index 000000000..a7015e41f
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/EntryPoint.cs
@@ -0,0 +1,110 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Plugins;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.XbmcMetadata.Configuration;
+using System;
+using System.Linq;
+
+namespace MediaBrowser.XbmcMetadata
+{
+ public class EntryPoint : IServerEntryPoint
+ {
+ private readonly IUserDataManager _userDataManager;
+ private readonly ILogger _logger;
+ private readonly ILibraryManager _libraryManager;
+ private readonly IProviderManager _providerManager;
+ private readonly IConfigurationManager _config;
+
+ public EntryPoint(IUserDataManager userDataManager, ILibraryManager libraryManager, ILogger logger, IProviderManager providerManager, IConfigurationManager config)
+ {
+ _userDataManager = userDataManager;
+ _libraryManager = libraryManager;
+ _logger = logger;
+ _providerManager = providerManager;
+ _config = config;
+ }
+
+ public void Run()
+ {
+ _userDataManager.UserDataSaved += _userDataManager_UserDataSaved;
+ _libraryManager.ItemUpdated += _libraryManager_ItemUpdated;
+ }
+
+ void _libraryManager_ItemUpdated(object sender, ItemChangeEventArgs e)
+ {
+ // TODO: Need a more accurate check here to see if xbmc metadata saving is enabled.
+ // This is probably good enough, but no guarantee
+ var userId = _config.GetNfoConfiguration().UserId;
+ if (string.IsNullOrWhiteSpace(userId))
+ {
+ return;
+ }
+
+ if (e.UpdateReason == ItemUpdateType.ImageUpdate)
+ {
+ var person = e.Item as Person;
+
+ if (person != null)
+ {
+ var items = _libraryManager.RootFolder.RecursiveChildren;
+ items = person.GetTaggedItems(items).ToList();
+
+ foreach (var item in items)
+ {
+ SaveMetadataForItem(item, ItemUpdateType.MetadataEdit);
+ }
+ }
+ }
+ }
+
+ void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e)
+ {
+ var userId = _config.GetNfoConfiguration().UserId;
+ if (string.IsNullOrWhiteSpace(userId))
+ {
+ return;
+ }
+
+ if (e.SaveReason == UserDataSaveReason.PlaybackFinished || e.SaveReason == UserDataSaveReason.TogglePlayed)
+ {
+ var item = e.Item as BaseItem;
+
+ if (item != null)
+ {
+ if (!item.IsFolder && !(item is IItemByName))
+ {
+ SaveMetadataForItem(item, ItemUpdateType.MetadataEdit);
+ }
+ }
+ }
+ }
+
+ public void Dispose()
+ {
+ _userDataManager.UserDataSaved -= _userDataManager_UserDataSaved;
+ }
+
+ private async void SaveMetadataForItem(BaseItem item, ItemUpdateType updateReason)
+ {
+ var locationType = item.LocationType;
+ if (locationType == LocationType.Remote ||
+ locationType == LocationType.Virtual)
+ {
+ return;
+ }
+
+ try
+ {
+ await _providerManager.SaveMetadata(item, updateReason).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error saving metadata for {0}", ex, item.Path ?? item.Name);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs b/MediaBrowser.XbmcMetadata/Images/XbmcImageSaver.cs
index 93231e1e3..6071db6b5 100644
--- a/MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs
+++ b/MediaBrowser.XbmcMetadata/Images/XbmcImageSaver.cs
@@ -10,7 +10,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
-namespace MediaBrowser.Providers.Xbmc
+namespace MediaBrowser.XbmcMetadata.Images
{
public class XbmcImageSaver : IImageFileSaver
{
@@ -88,7 +88,7 @@ namespace MediaBrowser.Providers.Xbmc
if (item is Episode)
{
var seasonFolder = Path.GetDirectoryName(item.Path);
-
+
var imageFilename = Path.GetFileNameWithoutExtension(item.Path) + "-thumb" + extension;
return new[] { Path.Combine(seasonFolder, imageFilename) };
diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj
new file mode 100644
index 000000000..7116b4fd7
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.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>{23499896-B135-4527-8574-C26E926EA99E}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>MediaBrowser.XbmcMetadata</RootNamespace>
+ <AssemblyName>MediaBrowser.XbmcMetadata</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </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="System" />
+ <Reference Include="System.Core" />
+ <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="Configuration\NfoOptions.cs" />
+ <Compile Include="EntryPoint.cs" />
+ <Compile Include="Images\XbmcImageSaver.cs" />
+ <Compile Include="Parsers\BaseNfoParser.cs" />
+ <Compile Include="Parsers\EpisodeNfoParser.cs" />
+ <Compile Include="Parsers\MovieNfoParser.cs" />
+ <Compile Include="Parsers\SeasonNfoParser.cs" />
+ <Compile Include="Parsers\SeriesNfoParser.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Providers\AlbumNfoProvider.cs" />
+ <Compile Include="Providers\ArtistNfoProvider.cs" />
+ <Compile Include="Providers\BaseNfoProvider.cs" />
+ <Compile Include="Providers\BaseVideoNfoProvider.cs" />
+ <Compile Include="Providers\EpisodeNfoProvider.cs" />
+ <Compile Include="Providers\MovieNfoProvider.cs" />
+ <Compile Include="Providers\SeasonNfoProvider.cs" />
+ <Compile Include="Providers\SeriesNfoProvider.cs" />
+ <Compile Include="Savers\AlbumNfoSaver.cs" />
+ <Compile Include="Savers\ArtistNfoSaver.cs" />
+ <Compile Include="Savers\BaseNfoSaver.cs" />
+ <Compile Include="Savers\EpisodeNfoSaver.cs" />
+ <Compile Include="Savers\MovieNfoSaver.cs" />
+ <Compile Include="Savers\SeasonNfoSaver.cs" />
+ <Compile Include="Savers\SeriesNfoSaver.cs" />
+ </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/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
new file mode 100644
index 000000000..6e31b0178
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
@@ -0,0 +1,991 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.XbmcMetadata.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Xml;
+using MediaBrowser.XbmcMetadata.Savers;
+
+namespace MediaBrowser.XbmcMetadata.Parsers
+{
+ public class BaseNfoParser<T>
+ where T : BaseItem
+ {
+ /// <summary>
+ /// The logger
+ /// </summary>
+ protected ILogger Logger { get; private set; }
+
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+ private readonly IConfigurationManager _config;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BaseNfoParser{T}" /> class.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ /// <param name="config">The configuration.</param>
+ public BaseNfoParser(ILogger logger, IConfigurationManager config)
+ {
+ Logger = logger;
+ _config = config;
+ }
+
+ /// <summary>
+ /// Fetches metadata for an item from one xml file
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="metadataFile">The metadata file.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <exception cref="System.ArgumentNullException"></exception>
+ public void Fetch(T item, string metadataFile, CancellationToken cancellationToken)
+ {
+ if (item == null)
+ {
+ throw new ArgumentNullException();
+ }
+
+ if (string.IsNullOrEmpty(metadataFile))
+ {
+ throw new ArgumentNullException();
+ }
+
+ var settings = new XmlReaderSettings
+ {
+ CheckCharacters = false,
+ IgnoreProcessingInstructions = true,
+ IgnoreComments = true,
+ ValidationType = ValidationType.None
+ };
+
+ Fetch(item, metadataFile, settings, cancellationToken);
+ }
+
+ /// <summary>
+ /// Fetches the specified item.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="metadataFile">The metadata file.</param>
+ /// <param name="settings">The settings.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ private void Fetch(T item, string metadataFile, XmlReaderSettings settings, CancellationToken cancellationToken)
+ {
+ using (var streamReader = BaseNfoSaver.GetStreamReader(metadataFile))
+ {
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
+ {
+ reader.MoveToContent();
+
+ // Loop through each element
+ while (reader.Read())
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ FetchDataFromXmlNode(reader, item);
+ }
+ }
+ }
+ }
+ }
+
+ protected virtual void FetchDataFromXmlNode(XmlReader reader, T item)
+ {
+ switch (reader.Name)
+ {
+ // DateCreated
+ case "dateadded":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ DateTime added;
+ if (DateTime.TryParse(val, out added))
+ {
+ item.DateCreated = added.ToUniversalTime();
+ }
+ else
+ {
+ Logger.Warn("Invalid Added value found: " + val);
+ }
+ }
+ break;
+ }
+
+ case "title":
+ case "localtitle":
+ item.Name = reader.ReadElementContentAsString();
+ break;
+
+ case "criticrating":
+ {
+ var text = reader.ReadElementContentAsString();
+
+ var hasCriticRating = item as IHasCriticRating;
+
+ if (hasCriticRating != null && !string.IsNullOrEmpty(text))
+ {
+ float value;
+ if (float.TryParse(text, NumberStyles.Any, _usCulture, out value))
+ {
+ hasCriticRating.CriticRating = value;
+ }
+ }
+
+ break;
+ }
+
+ case "budget":
+ {
+ var text = reader.ReadElementContentAsString();
+ var hasBudget = item as IHasBudget;
+ if (hasBudget != null)
+ {
+ double value;
+ if (double.TryParse(text, NumberStyles.Any, _usCulture, out value))
+ {
+ hasBudget.Budget = value;
+ }
+ }
+
+ break;
+ }
+
+ case "revenue":
+ {
+ var text = reader.ReadElementContentAsString();
+ var hasBudget = item as IHasBudget;
+ if (hasBudget != null)
+ {
+ double value;
+ if (double.TryParse(text, NumberStyles.Any, _usCulture, out value))
+ {
+ hasBudget.Revenue = value;
+ }
+ }
+
+ break;
+ }
+
+ case "metascore":
+ {
+ var text = reader.ReadElementContentAsString();
+ var hasMetascore = item as IHasMetascore;
+ if (hasMetascore != null)
+ {
+ float value;
+ if (float.TryParse(text, NumberStyles.Any, _usCulture, out value))
+ {
+ hasMetascore.Metascore = value;
+ }
+ }
+
+ break;
+ }
+
+ case "awardsummary":
+ {
+ var text = reader.ReadElementContentAsString();
+ var hasAwards = item as IHasAwards;
+ if (hasAwards != null)
+ {
+ if (!string.IsNullOrWhiteSpace(text))
+ {
+ hasAwards.AwardSummary = text;
+ }
+ }
+
+ break;
+ }
+
+ case "sorttitle":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.ForcedSortName = val;
+ }
+ break;
+ }
+
+ case "outline":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ var hasShortOverview = item as IHasShortOverview;
+
+ if (hasShortOverview != null)
+ {
+ hasShortOverview.ShortOverview = val;
+ }
+ }
+ break;
+ }
+
+ case "biography":
+ case "plot":
+ case "review":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.Overview = val;
+ }
+
+ break;
+ }
+
+ case "criticratingsummary":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ var hasCriticRating = item as IHasCriticRating;
+
+ if (hasCriticRating != null)
+ {
+ hasCriticRating.CriticRatingSummary = val;
+ }
+ }
+
+ break;
+ }
+
+ case "language":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ var hasLanguage = item as IHasPreferredMetadataLanguage;
+ if (hasLanguage != null)
+ {
+ hasLanguage.PreferredMetadataLanguage = val;
+ }
+
+ break;
+ }
+
+ case "website":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.HomePageUrl = val;
+ }
+
+ break;
+ }
+
+ case "lockedfields":
+ {
+ var fields = new List<MetadataFields>();
+
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ var list = val.Split('|').Select(i =>
+ {
+ MetadataFields field;
+
+ if (Enum.TryParse<MetadataFields>(i, true, out field))
+ {
+ return (MetadataFields?)field;
+ }
+
+ return null;
+
+ }).Where(i => i.HasValue).Select(i => i.Value);
+
+ fields.AddRange(list);
+ }
+
+ item.LockedFields = fields;
+
+ break;
+ }
+
+ case "tagline":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ var hasTagline = item as IHasTaglines;
+ if (hasTagline != null)
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ hasTagline.AddTagline(val);
+ }
+ }
+ break;
+ }
+
+ case "country":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ var hasProductionLocations = item as IHasProductionLocations;
+ if (hasProductionLocations != null)
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ hasProductionLocations.AddProductionLocation(val);
+ }
+ }
+ break;
+ }
+
+ case "mpaa":
+ {
+ var rating = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(rating))
+ {
+ item.OfficialRating = rating;
+ }
+ break;
+ }
+
+ case "mpaadescription":
+ {
+ var rating = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(rating))
+ {
+ item.OfficialRatingDescription = rating;
+ }
+ break;
+ }
+
+ case "customrating":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.CustomRating = val;
+ }
+ break;
+ }
+
+ case "runtime":
+ {
+ var text = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(text))
+ {
+ int runtime;
+ if (int.TryParse(text.Split(' ')[0], NumberStyles.Integer, _usCulture, out runtime))
+ {
+ item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks;
+ }
+ }
+ break;
+ }
+
+ case "aspectratio":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ var hasAspectRatio = item as IHasAspectRatio;
+ if (!string.IsNullOrWhiteSpace(val) && hasAspectRatio != null)
+ {
+ hasAspectRatio.AspectRatio = val;
+ }
+ break;
+ }
+
+ case "lockdata":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.IsLocked = string.Equals("true", val, StringComparison.OrdinalIgnoreCase);
+ }
+ break;
+ }
+
+ case "studio":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.AddStudio(val);
+ }
+ break;
+ }
+
+ case "director":
+ {
+ foreach (var p in SplitNames(reader.ReadElementContentAsString()).Select(v => new PersonInfo { Name = v.Trim(), Type = PersonType.Director }))
+ {
+ if (string.IsNullOrWhiteSpace(p.Name))
+ {
+ continue;
+ }
+ item.AddPerson(p);
+ }
+ break;
+ }
+ case "credits":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ var parts = val.Split('/').Select(i => i.Trim())
+ .Where(i => !string.IsNullOrEmpty(i));
+
+ foreach (var p in parts.Select(v => new PersonInfo { Name = v.Trim(), Type = PersonType.Writer }))
+ {
+ if (string.IsNullOrWhiteSpace(p.Name))
+ {
+ continue;
+ }
+ item.AddPerson(p);
+ }
+ }
+ break;
+ }
+
+ case "writer":
+ {
+ foreach (var p in SplitNames(reader.ReadElementContentAsString()).Select(v => new PersonInfo { Name = v.Trim(), Type = PersonType.Writer }))
+ {
+ if (string.IsNullOrWhiteSpace(p.Name))
+ {
+ continue;
+ }
+ item.AddPerson(p);
+ }
+ break;
+ }
+
+ case "actor":
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ var person = GetPersonFromXmlNode(subtree);
+
+ item.AddPerson(person);
+ }
+ break;
+ }
+
+ case "trailer":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ var hasTrailer = item as IHasTrailers;
+ if (hasTrailer != null)
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ hasTrailer.AddTrailerUrl(val, false);
+ }
+ }
+ break;
+ }
+
+ case "displayorder":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ var hasDisplayOrder = item as IHasDisplayOrder;
+ if (hasDisplayOrder != null)
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ hasDisplayOrder.DisplayOrder = val;
+ }
+ }
+ break;
+ }
+
+ case "year":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int productionYear;
+ if (int.TryParse(val, out productionYear) && productionYear > 1850)
+ {
+ item.ProductionYear = productionYear;
+ }
+ }
+
+ break;
+ }
+
+ case "rating":
+ {
+
+ var rating = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(rating))
+ {
+ float val;
+ // All external meta is saving this as '.' for decimal I believe...but just to be sure
+ if (float.TryParse(rating.Replace(',', '.'), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out val))
+ {
+ item.CommunityRating = val;
+ }
+ }
+ break;
+ }
+
+ case "aired":
+ case "formed":
+ case "premiered":
+ case "releasedate":
+ {
+ var formatString = _config.GetNfoConfiguration().ReleaseDateFormat;
+
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ DateTime date;
+
+ if (DateTime.TryParseExact(val, formatString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out date) && date.Year > 1850)
+ {
+ item.PremiereDate = date.ToUniversalTime();
+ item.ProductionYear = date.Year;
+ }
+ }
+
+ break;
+ }
+
+ case "enddate":
+ {
+ var formatString = _config.GetNfoConfiguration().ReleaseDateFormat;
+
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ DateTime date;
+
+ if (DateTime.TryParseExact(val, formatString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out date) && date.Year > 1850)
+ {
+ item.EndDate = date.ToUniversalTime();
+ }
+ }
+
+ break;
+ }
+
+ case "tvdbid":
+ var tvdbId = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(tvdbId))
+ {
+ item.SetProviderId(MetadataProviders.Tvdb, tvdbId);
+ }
+ break;
+
+ case "votes":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int num;
+
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out num))
+ {
+ item.VoteCount = num;
+ }
+ }
+ break;
+ }
+ case "musicbrainzalbumid":
+ {
+ var mbz = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(mbz))
+ {
+ item.SetProviderId(MetadataProviders.MusicBrainzAlbum, mbz);
+ }
+ break;
+ }
+ case "musicbrainzalbumartistid":
+ {
+ var mbz = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(mbz))
+ {
+ item.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, mbz);
+ }
+ break;
+ }
+ case "musicbrainzartistid":
+ {
+ var mbz = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(mbz))
+ {
+ item.SetProviderId(MetadataProviders.MusicBrainzArtist, mbz);
+ }
+ break;
+ }
+ case "musicbrainzreleasegroupid":
+ {
+ var mbz = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(mbz))
+ {
+ item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, mbz);
+ }
+ break;
+ }
+ case "tvrageid":
+ {
+ var id = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(id))
+ {
+ item.SetProviderId(MetadataProviders.TvRage, id);
+ }
+ break;
+ }
+ case "audiodbartistid":
+ {
+ var id = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(id))
+ {
+ item.SetProviderId(MetadataProviders.AudioDbArtist, id);
+ }
+ break;
+ }
+ case "audiodbalbumid":
+ {
+ var id = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(id))
+ {
+ item.SetProviderId(MetadataProviders.AudioDbAlbum, id);
+ }
+ break;
+ }
+ case "rottentomatoesid":
+ var rtId = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(rtId))
+ {
+ item.SetProviderId(MetadataProviders.RottenTomatoes, rtId);
+ }
+ break;
+
+ case "tmdbid":
+ var tmdb = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(tmdb))
+ {
+ item.SetProviderId(MetadataProviders.Tmdb, tmdb);
+ }
+ break;
+
+ case "collectionnumber":
+ var tmdbCollection = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(tmdbCollection))
+ {
+ item.SetProviderId(MetadataProviders.TmdbCollection, tmdbCollection);
+ }
+ break;
+
+ case "tvcomid":
+ var TVcomId = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(TVcomId))
+ {
+ item.SetProviderId(MetadataProviders.Tvcom, TVcomId);
+ }
+ break;
+
+ case "zap2itid":
+ var zap2ItId = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(zap2ItId))
+ {
+ item.SetProviderId(MetadataProviders.Zap2It, zap2ItId);
+ }
+ break;
+
+ case "imdb_id":
+ case "imdbid":
+ var imDbId = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(imDbId))
+ {
+ item.SetProviderId(MetadataProviders.Imdb, imDbId);
+ }
+ break;
+
+ case "genre":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.AddGenre(val);
+ }
+ break;
+ }
+
+ case "style":
+ case "tag":
+ {
+ var val = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ var hasTags = item as IHasTags;
+ if (hasTags != null)
+ {
+ hasTags.AddTag(val);
+ }
+ }
+ break;
+ }
+
+ case "plotkeyword":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ var hasKeywords = item as IHasKeywords;
+ if (hasKeywords != null)
+ {
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ hasKeywords.AddKeyword(val);
+ }
+ }
+ break;
+ }
+
+ case "fileinfo":
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchFromFileInfoNode(subtree, item);
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+
+ private void FetchFromFileInfoNode(XmlReader reader, T item)
+ {
+ reader.MoveToContent();
+
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "streamdetails":
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchFromStreamDetailsNode(subtree, item);
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ }
+
+ private void FetchFromStreamDetailsNode(XmlReader reader, T item)
+ {
+ reader.MoveToContent();
+
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "video":
+ {
+ using (var subtree = reader.ReadSubtree())
+ {
+ FetchFromVideoNode(subtree, item);
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ }
+
+ private void FetchFromVideoNode(XmlReader reader, T item)
+ {
+ reader.MoveToContent();
+
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "format3d":
+ {
+ var video = item as Video;
+
+ if (video != null)
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (string.Equals("HSBS", val, StringComparison.CurrentCulture))
+ {
+ video.Video3DFormat = Video3DFormat.HalfSideBySide;
+ }
+ else if (string.Equals("HTAB", val, StringComparison.CurrentCulture))
+ {
+ video.Video3DFormat = Video3DFormat.HalfTopAndBottom;
+ }
+ else if (string.Equals("FTAB", val, StringComparison.CurrentCulture))
+ {
+ video.Video3DFormat = Video3DFormat.FullTopAndBottom;
+ }
+ else if (string.Equals("FSBS", val, StringComparison.CurrentCulture))
+ {
+ video.Video3DFormat = Video3DFormat.FullSideBySide;
+ }
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the persons from XML node.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <returns>IEnumerable{PersonInfo}.</returns>
+ private PersonInfo GetPersonFromXmlNode(XmlReader reader)
+ {
+ var name = string.Empty;
+ var type = PersonType.Actor; // If type is not specified assume actor
+ var role = string.Empty;
+ int? sortOrder = null;
+
+ reader.MoveToContent();
+
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ switch (reader.Name)
+ {
+ case "name":
+ name = reader.ReadElementContentAsString() ?? string.Empty;
+ break;
+
+ case "type":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ type = val;
+ }
+ break;
+ }
+
+ case "role":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ role = val;
+ }
+ break;
+ }
+ case "sortorder":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int intVal;
+ if (int.TryParse(val, NumberStyles.Integer, _usCulture, out intVal))
+ {
+ sortOrder = intVal;
+ }
+ }
+ break;
+ }
+
+ default:
+ reader.Skip();
+ break;
+ }
+ }
+ }
+
+ return new PersonInfo
+ {
+ Name = name.Trim(),
+ Role = role,
+ Type = type,
+ SortOrder = sortOrder
+ };
+ }
+
+ /// <summary>
+ /// Used to split names of comma or pipe delimeted genres and people
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>IEnumerable{System.String}.</returns>
+ private IEnumerable<string> SplitNames(string value)
+ {
+ value = value ?? string.Empty;
+
+ // Only split by comma if there is no pipe in the string
+ // We have to be careful to not split names like Matthew, Jr.
+ var separator = value.IndexOf('|') == -1 && value.IndexOf(';') == -1 ? new[] { ',' } : new[] { '|', ';' };
+
+ value = value.Trim().Trim(separator);
+
+ return string.IsNullOrWhiteSpace(value) ? new string[] { } : Split(value, separator, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ /// <summary>
+ /// Provides an additional overload for string.split
+ /// </summary>
+ /// <param name="val">The val.</param>
+ /// <param name="separators">The separators.</param>
+ /// <param name="options">The options.</param>
+ /// <returns>System.String[][].</returns>
+ private static string[] Split(string val, char[] separators, StringSplitOptions options)
+ {
+ return val.Split(separators, options);
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs
new file mode 100644
index 000000000..ba7b48b1f
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Parsers/EpisodeNfoParser.cs
@@ -0,0 +1,211 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Threading;
+using System.Xml;
+
+namespace MediaBrowser.XbmcMetadata.Parsers
+{
+ public class EpisodeNfoParser : BaseNfoParser<Episode>
+ {
+ private List<LocalImageInfo> _imagesFound;
+ private List<ChapterInfo> _chaptersFound;
+ private string _xmlPath;
+
+ public EpisodeNfoParser(ILogger logger, IConfigurationManager config) : base(logger, config)
+ {
+ }
+
+ public void Fetch(Episode item,
+ List<LocalImageInfo> images,
+ List<ChapterInfo> chapters,
+ string metadataFile,
+ CancellationToken cancellationToken)
+ {
+ _imagesFound = images;
+ _chaptersFound = chapters;
+ _xmlPath = metadataFile;
+
+ Fetch(item, metadataFile, cancellationToken);
+ }
+
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+ /// <summary>
+ /// Fetches the data from XML node.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="item">The item.</param>
+ protected override void FetchDataFromXmlNode(XmlReader reader, Episode item)
+ {
+ switch (reader.Name)
+ {
+ //case "Chapters":
+
+ // _chaptersFound.AddRange(FetchChaptersFromXmlNode(item, reader.ReadSubtree()));
+ // break;
+
+ case "season":
+ {
+ var number = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(number))
+ {
+ int num;
+
+ if (int.TryParse(number, out num))
+ {
+ item.ParentIndexNumber = num;
+ }
+ }
+ break;
+ }
+
+ case "episode":
+ {
+ var number = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(number))
+ {
+ int num;
+
+ if (int.TryParse(number, out num))
+ {
+ item.IndexNumber = num;
+ }
+ }
+ break;
+ }
+
+ case "episodenumberend":
+ {
+ var number = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(number))
+ {
+ int num;
+
+ if (int.TryParse(number, out num))
+ {
+ item.IndexNumberEnd = num;
+ }
+ }
+ break;
+ }
+
+ case "absolute_number":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int rval;
+
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
+ {
+ item.AbsoluteEpisodeNumber = rval;
+ }
+ }
+
+ break;
+ }
+ case "DVD_episodenumber":
+ {
+ var number = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(number))
+ {
+ float num;
+
+ if (float.TryParse(number, NumberStyles.Any, UsCulture, out num))
+ {
+ item.DvdEpisodeNumber = num;
+ }
+ }
+ break;
+ }
+
+ case "DVD_season":
+ {
+ var number = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(number))
+ {
+ float num;
+
+ if (float.TryParse(number, NumberStyles.Any, UsCulture, out num))
+ {
+ item.DvdSeasonNumber = Convert.ToInt32(num);
+ }
+ }
+ break;
+ }
+
+ case "airsbefore_episode":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int rval;
+
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
+ {
+ item.AirsBeforeEpisodeNumber = rval;
+ }
+ }
+
+ break;
+ }
+
+ case "airsafter_season":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int rval;
+
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
+ {
+ item.AirsAfterSeasonNumber = rval;
+ }
+ }
+
+ break;
+ }
+
+ case "airsbefore_season":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ int rval;
+
+ // int.TryParse is local aware, so it can be probamatic, force us culture
+ if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
+ {
+ item.AirsBeforeSeasonNumber = rval;
+ }
+ }
+
+ break;
+ }
+
+
+ default:
+ base.FetchDataFromXmlNode(reader, item);
+ break;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs
new file mode 100644
index 000000000..9b90b2bb3
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs
@@ -0,0 +1,97 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using System.Collections.Generic;
+using System.Threading;
+using System.Xml;
+
+namespace MediaBrowser.XbmcMetadata.Parsers
+{
+ class MovieNfoParser : BaseNfoParser<Video>
+ {
+ private List<ChapterInfo> _chaptersFound;
+
+ public MovieNfoParser(ILogger logger, IConfigurationManager config) : base(logger, config)
+ {
+ }
+
+ public void Fetch(Video item,
+ List<ChapterInfo> chapters,
+ string metadataFile,
+ CancellationToken cancellationToken)
+ {
+ _chaptersFound = chapters;
+
+ Fetch(item, metadataFile, cancellationToken);
+ }
+
+ /// <summary>
+ /// Fetches the data from XML node.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="item">The item.</param>
+ protected override void FetchDataFromXmlNode(XmlReader reader, Video item)
+ {
+ switch (reader.Name)
+ {
+ case "id":
+ var id = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(id))
+ {
+ item.SetProviderId(MetadataProviders.Imdb, id);
+ }
+ break;
+
+ case "set":
+ {
+ var val = reader.ReadElementContentAsString();
+ var movie = item as Movie;
+
+ if (!string.IsNullOrWhiteSpace(val) && movie != null)
+ {
+ movie.TmdbCollectionName = val;
+ }
+
+ break;
+ }
+
+ case "artist":
+ {
+ var val = reader.ReadElementContentAsString();
+ var movie = item as MusicVideo;
+
+ if (!string.IsNullOrWhiteSpace(val) && movie != null)
+ {
+ movie.Artist = val;
+ }
+
+ break;
+ }
+
+ case "album":
+ {
+ var val = reader.ReadElementContentAsString();
+ var movie = item as MusicVideo;
+
+ if (!string.IsNullOrWhiteSpace(val) && movie != null)
+ {
+ movie.Album = val;
+ }
+
+ break;
+ }
+
+ //case "chapter":
+
+ // _chaptersFound.AddRange(FetchChaptersFromXmlNode(item, reader.ReadSubtree()));
+ // break;
+
+ default:
+ base.FetchDataFromXmlNode(reader, item);
+ break;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs
new file mode 100644
index 000000000..14abb74c6
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Parsers/SeasonNfoParser.cs
@@ -0,0 +1,45 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Model.Logging;
+using System.Xml;
+
+namespace MediaBrowser.XbmcMetadata.Parsers
+{
+ public class SeasonNfoParser : BaseNfoParser<Season>
+ {
+ public SeasonNfoParser(ILogger logger, IConfigurationManager config) : base(logger, config)
+ {
+ }
+
+ /// <summary>
+ /// Fetches the data from XML node.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="item">The item.</param>
+ protected override void FetchDataFromXmlNode(XmlReader reader, Season item)
+ {
+ switch (reader.Name)
+ {
+ case "seasonnumber":
+ {
+ var number = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(number))
+ {
+ int num;
+
+ if (int.TryParse(number, out num))
+ {
+ item.IndexNumber = num;
+ }
+ }
+ break;
+ }
+
+ default:
+ base.FetchDataFromXmlNode(reader, item);
+ break;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs
new file mode 100644
index 000000000..d72a64b5b
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Parsers/SeriesNfoParser.cs
@@ -0,0 +1,93 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Xml;
+
+namespace MediaBrowser.XbmcMetadata.Parsers
+{
+ public class SeriesNfoParser : BaseNfoParser<Series>
+ {
+ public SeriesNfoParser(ILogger logger, IConfigurationManager config) : base(logger, config)
+ {
+ }
+
+ /// <summary>
+ /// Fetches the data from XML node.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <param name="item">The item.</param>
+ protected override void FetchDataFromXmlNode(XmlReader reader, Series item)
+ {
+ switch (reader.Name)
+ {
+ case "id":
+ string id = reader.ReadElementContentAsString();
+ if (!string.IsNullOrWhiteSpace(id))
+ {
+ item.SetProviderId(MetadataProviders.Tvdb, id);
+ }
+ break;
+
+ case "airs_dayofweek":
+ {
+ item.AirDays = TVUtils.GetAirDays(reader.ReadElementContentAsString());
+ break;
+ }
+
+ case "airs_time":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ item.AirTime = val;
+ }
+ break;
+ }
+
+ case "animeseriesindex":
+ {
+ var number = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(number))
+ {
+ int num;
+
+ if (int.TryParse(number, out num))
+ {
+ item.AnimeSeriesIndex = num;
+ }
+ }
+ break;
+ }
+
+ case "status":
+ {
+ var status = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(status))
+ {
+ SeriesStatus seriesStatus;
+ if (Enum.TryParse(status, true, out seriesStatus))
+ {
+ item.Status = seriesStatus;
+ }
+ else
+ {
+ Logger.Info("Unrecognized series status: " + status);
+ }
+ }
+
+ break;
+ }
+
+ default:
+ base.FetchDataFromXmlNode(reader, item);
+ break;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs b/MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..7df6e5967
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Properties/AssemblyInfo.cs
@@ -0,0 +1,34 @@
+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("MediaBrowser.XbmcMetadata")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MediaBrowser.XbmcMetadata")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[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("bbdf434b-65f1-4178-8ddf-067447df3e20")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")] \ No newline at end of file
diff --git a/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs
new file mode 100644
index 000000000..535fa28b8
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Providers/AlbumNfoProvider.cs
@@ -0,0 +1,34 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.XbmcMetadata.Parsers;
+using System.IO;
+using System.Threading;
+
+namespace MediaBrowser.XbmcMetadata.Providers
+{
+ public class AlbumNfoProvider : BaseNfoProvider<MusicAlbum>
+ {
+ private readonly ILogger _logger;
+ private readonly IConfigurationManager _config;
+
+ public AlbumNfoProvider(IFileSystem fileSystem, ILogger logger, IConfigurationManager config)
+ : base(fileSystem)
+ {
+ _logger = logger;
+ _config = config;
+ }
+
+ protected override void Fetch(LocalMetadataResult<MusicAlbum> result, string path, CancellationToken cancellationToken)
+ {
+ new BaseNfoParser<MusicAlbum>(_logger, _config).Fetch(result.Item, path, cancellationToken);
+ }
+
+ protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+ {
+ return directoryService.GetFile(Path.Combine(info.Path, "album.nfo"));
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs
new file mode 100644
index 000000000..f281c1048
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Providers/ArtistNfoProvider.cs
@@ -0,0 +1,34 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.XbmcMetadata.Parsers;
+using System.IO;
+using System.Threading;
+
+namespace MediaBrowser.XbmcMetadata.Providers
+{
+ public class ArtistNfoProvider : BaseNfoProvider<MusicArtist>
+ {
+ private readonly ILogger _logger;
+ private readonly IConfigurationManager _config;
+
+ public ArtistNfoProvider(IFileSystem fileSystem, ILogger logger, IConfigurationManager config)
+ : base(fileSystem)
+ {
+ _logger = logger;
+ _config = config;
+ }
+
+ protected override void Fetch(LocalMetadataResult<MusicArtist> result, string path, CancellationToken cancellationToken)
+ {
+ new BaseNfoParser<MusicArtist>(_logger, _config).Fetch(result.Item, path, cancellationToken);
+ }
+
+ protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+ {
+ return directoryService.GetFile(Path.Combine(info.Path, "artist.nfo"));
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs
new file mode 100644
index 000000000..47371ea04
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs
@@ -0,0 +1,89 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Logging;
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.XbmcMetadata.Providers
+{
+ public abstract class BaseNfoProvider<T> : ILocalMetadataProvider<T>, IHasChangeMonitor
+ where T : IHasMetadata, new()
+ {
+ protected IFileSystem FileSystem;
+
+ public async Task<LocalMetadataResult<T>> GetMetadata(ItemInfo info, CancellationToken cancellationToken)
+ {
+ var result = new LocalMetadataResult<T>();
+
+ var file = GetXmlFile(info, new DirectoryService(new NullLogger()));
+
+ if (file == null)
+ {
+ return result;
+ }
+
+ var path = file.FullName;
+
+ //await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
+
+ try
+ {
+ result.Item = new T();
+
+ Fetch(result, path, cancellationToken);
+ result.HasMetadata = true;
+ }
+ catch (FileNotFoundException)
+ {
+ result.HasMetadata = false;
+ }
+ catch (DirectoryNotFoundException)
+ {
+ result.HasMetadata = false;
+ }
+ //finally
+ //{
+ // XmlProviderUtils.XmlParsingResourcePool.Release();
+ //}
+
+ return result;
+ }
+
+ protected abstract void Fetch(LocalMetadataResult<T> result, string path, CancellationToken cancellationToken);
+
+ protected BaseNfoProvider(IFileSystem fileSystem)
+ {
+ FileSystem = fileSystem;
+ }
+
+ protected abstract FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService);
+
+ public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
+ {
+ var file = GetXmlFile(new ItemInfo { IsInMixedFolder = item.IsInMixedFolder, Path = item.Path }, directoryService);
+
+ if (file == null)
+ {
+ return false;
+ }
+
+ return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > date;
+ }
+
+ public string Name
+ {
+ get
+ {
+ return "Xbmc Nfo";
+ }
+ }
+ }
+
+ static class XmlProviderUtils
+ {
+ internal static readonly SemaphoreSlim XmlParsingResourcePool = new SemaphoreSlim(4, 4);
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs
new file mode 100644
index 000000000..c4edfb461
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Providers/BaseVideoNfoProvider.cs
@@ -0,0 +1,55 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.XbmcMetadata.Parsers;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+
+namespace MediaBrowser.XbmcMetadata.Providers
+{
+ public class BaseVideoNfoProvider<T> : BaseNfoProvider<T>
+ where T : Video, new ()
+ {
+ private readonly ILogger _logger;
+ private readonly IConfigurationManager _config;
+
+ public BaseVideoNfoProvider(IFileSystem fileSystem, ILogger logger, IConfigurationManager config)
+ : base(fileSystem)
+ {
+ _logger = logger;
+ _config = config;
+ }
+
+ protected override void Fetch(LocalMetadataResult<T> result, string path, CancellationToken cancellationToken)
+ {
+ var chapters = new List<ChapterInfo>();
+
+ new MovieNfoParser(_logger, _config).Fetch(result.Item, chapters, path, cancellationToken);
+
+ result.Chapters = chapters;
+ }
+
+ protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+ {
+ var path = GetMovieSavePath(info, FileSystem);
+
+ return directoryService.GetFile(path);
+ }
+
+ public static string GetMovieSavePath(ItemInfo item, IFileSystem fileSystem)
+ {
+ if (Directory.Exists(item.Path))
+ {
+ var path = item.Path;
+
+ return Path.Combine(path, fileSystem.GetFileNameWithoutExtension(path) + ".nfo");
+ }
+
+ return Path.ChangeExtension(item.Path, ".nfo");
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs
new file mode 100644
index 000000000..7899305e3
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Providers/EpisodeNfoProvider.cs
@@ -0,0 +1,44 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.XbmcMetadata.Parsers;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+
+namespace MediaBrowser.XbmcMetadata.Providers
+{
+ public class EpisodeNfoProvider : BaseNfoProvider<Episode>
+ {
+ private readonly ILogger _logger;
+ private readonly IConfigurationManager _config;
+
+ public EpisodeNfoProvider(IFileSystem fileSystem, ILogger logger, IConfigurationManager config)
+ : base(fileSystem)
+ {
+ _logger = logger;
+ _config = config;
+ }
+
+ protected override void Fetch(LocalMetadataResult<Episode> result, string path, CancellationToken cancellationToken)
+ {
+ var images = new List<LocalImageInfo>();
+ var chapters = new List<ChapterInfo>();
+
+ new EpisodeNfoParser(_logger, _config).Fetch(result.Item, images, chapters, path, cancellationToken);
+
+ result.Images = images;
+ result.Chapters = chapters;
+ }
+
+ protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+ {
+ var path = Path.ChangeExtension(info.Path, ".nfo");
+
+ return directoryService.GetFile(path);
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Providers/MovieNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/MovieNfoProvider.cs
new file mode 100644
index 000000000..bd17c8539
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Providers/MovieNfoProvider.cs
@@ -0,0 +1,45 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Model.Logging;
+
+namespace MediaBrowser.XbmcMetadata.Providers
+{
+ public class MovieNfoProvider : BaseVideoNfoProvider<Movie>
+ {
+ public MovieNfoProvider(IFileSystem fileSystem, ILogger logger, IConfigurationManager config) : base(fileSystem, logger, config)
+ {
+ }
+ }
+
+ public class MusicVideoNfoProvider : BaseVideoNfoProvider<MusicVideo>
+ {
+ public MusicVideoNfoProvider(IFileSystem fileSystem, ILogger logger, IConfigurationManager config) : base(fileSystem, logger, config)
+ {
+ }
+ }
+
+ public class AdultVideoNfoProvider : BaseVideoNfoProvider<AdultVideo>
+ {
+ public AdultVideoNfoProvider(IFileSystem fileSystem, ILogger logger, IConfigurationManager config) : base(fileSystem, logger, config)
+ {
+ }
+ }
+
+ public class VideoNfoProvider : BaseVideoNfoProvider<Video>
+ {
+ public VideoNfoProvider(IFileSystem fileSystem, ILogger logger, IConfigurationManager config) : base(fileSystem, logger, config)
+ {
+ }
+ }
+
+ public class TrailerNfoProvider : BaseVideoNfoProvider<Trailer>
+ {
+ public TrailerNfoProvider(IFileSystem fileSystem, ILogger logger, IConfigurationManager config)
+ : base(fileSystem, logger, config)
+ {
+ }
+ }
+
+} \ No newline at end of file
diff --git a/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs
new file mode 100644
index 000000000..7b68ed94b
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Providers/SeasonNfoProvider.cs
@@ -0,0 +1,35 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.XbmcMetadata.Parsers;
+using System.IO;
+using System.Threading;
+
+namespace MediaBrowser.XbmcMetadata.Providers
+{
+ public class SeasonNfoProvider : BaseNfoProvider<Season>
+ {
+ private readonly ILogger _logger;
+ private readonly IConfigurationManager _config;
+
+ public SeasonNfoProvider(IFileSystem fileSystem, ILogger logger, IConfigurationManager config)
+ : base(fileSystem)
+ {
+ _logger = logger;
+ _config = config;
+ }
+
+ protected override void Fetch(LocalMetadataResult<Season> result, string path, CancellationToken cancellationToken)
+ {
+ new SeasonNfoParser(_logger, _config).Fetch(result.Item, path, cancellationToken);
+ }
+
+ protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+ {
+ return directoryService.GetFile(Path.Combine(info.Path, "season.nfo"));
+ }
+ }
+}
+
diff --git a/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs
new file mode 100644
index 000000000..9db0cc8fc
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Providers/SeriesNfoProvider.cs
@@ -0,0 +1,34 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.XbmcMetadata.Parsers;
+using System.IO;
+using System.Threading;
+
+namespace MediaBrowser.XbmcMetadata.Providers
+{
+ public class SeriesNfoProvider : BaseNfoProvider<Series>
+ {
+ private readonly ILogger _logger;
+ private readonly IConfigurationManager _config;
+
+ public SeriesNfoProvider(IFileSystem fileSystem, ILogger logger, IConfigurationManager config)
+ : base(fileSystem)
+ {
+ _logger = logger;
+ _config = config;
+ }
+
+ protected override void Fetch(LocalMetadataResult<Series> result, string path, CancellationToken cancellationToken)
+ {
+ new SeriesNfoParser(_logger, _config).Fetch(result.Item, path, cancellationToken);
+ }
+
+ protected override FileSystemInfo GetXmlFile(ItemInfo info, IDirectoryService directoryService)
+ {
+ return directoryService.GetFile(Path.Combine(info.Path, "tvshow.nfo"));
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs
new file mode 100644
index 000000000..f9a6fc059
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs
@@ -0,0 +1,101 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Xml;
+
+namespace MediaBrowser.XbmcMetadata.Savers
+{
+ public class AlbumNfoSaver : BaseNfoSaver
+ {
+ public AlbumNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
+ {
+ }
+
+ public override string GetSavePath(IHasMetadata item)
+ {
+ return Path.Combine(item.Path, "album.nfo");
+ }
+
+ protected override string GetRootElementName(IHasMetadata item)
+ {
+ return "album";
+ }
+
+ public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ {
+ if (!item.SupportsLocalMetadata)
+ {
+ return false;
+ }
+
+ return item is MusicAlbum && updateType >= ItemUpdateType.MetadataDownload;
+ }
+
+ protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
+ {
+ var album = (MusicAlbum)item;
+
+ foreach (var artist in album.Artists)
+ {
+ writer.WriteElementString("artist", artist);
+ }
+
+ foreach (var artist in album.AlbumArtists)
+ {
+ writer.WriteElementString("albumartist", artist);
+ }
+
+ AddTracks(album.Tracks, writer);
+ }
+
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+ private void AddTracks(IEnumerable<Audio> tracks, XmlWriter writer)
+ {
+ foreach (var track in tracks.OrderBy(i => i.ParentIndexNumber ?? 0)
+ .ThenBy(i => i.IndexNumber ?? 0))
+ {
+ writer.WriteStartElement("track");
+
+ if (track.IndexNumber.HasValue)
+ {
+ writer.WriteElementString("position", track.IndexNumber.Value.ToString(UsCulture));
+ }
+
+ if (!string.IsNullOrEmpty(track.Name))
+ {
+ writer.WriteElementString("title", track.Name);
+ }
+
+ if (track.RunTimeTicks.HasValue)
+ {
+ var time = TimeSpan.FromTicks(track.RunTimeTicks.Value).ToString(@"mm\:ss");
+
+ writer.WriteElementString("duration", time);
+ }
+
+ writer.WriteEndElement();
+ }
+ }
+
+ protected override List<string> GetTagsUsed()
+ {
+ var list = new List<string>
+ {
+ "track",
+ "artist",
+ "albumartist"
+ };
+
+ return list;
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs
new file mode 100644
index 000000000..f4ffc35fb
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs
@@ -0,0 +1,94 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.XbmcMetadata.Configuration;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Xml;
+
+namespace MediaBrowser.XbmcMetadata.Savers
+{
+ public class ArtistNfoSaver : BaseNfoSaver
+ {
+ public ArtistNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
+ {
+ }
+
+ public override string GetSavePath(IHasMetadata item)
+ {
+ return Path.Combine(item.Path, "artist.nfo");
+ }
+
+ protected override string GetRootElementName(IHasMetadata item)
+ {
+ return "artist";
+ }
+
+ public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ {
+ if (!item.SupportsLocalMetadata)
+ {
+ return false;
+ }
+
+ return item is MusicArtist && updateType >= ItemUpdateType.MetadataDownload;
+ }
+
+ protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
+ {
+ var artist = (MusicArtist)item;
+
+ if (artist.EndDate.HasValue)
+ {
+ var formatString = ConfigurationManager.GetNfoConfiguration().ReleaseDateFormat;
+
+ writer.WriteElementString("disbanded", artist.EndDate.Value.ToString(formatString));
+ }
+
+ var albums = artist
+ .RecursiveChildren
+ .OfType<MusicAlbum>()
+ .ToList();
+
+ AddAlbums(albums, writer);
+ }
+
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+ private void AddAlbums(IEnumerable<MusicAlbum> albums, XmlWriter writer)
+ {
+ foreach (var album in albums)
+ {
+ writer.WriteStartElement("album");
+
+ if (!string.IsNullOrEmpty(album.Name))
+ {
+ writer.WriteElementString("title", album.Name);
+ }
+
+ if (album.ProductionYear.HasValue)
+ {
+ writer.WriteElementString("year", album.ProductionYear.Value.ToString(UsCulture));
+ }
+
+ writer.WriteEndElement();
+ }
+ }
+
+ protected override List<string> GetTagsUsed()
+ {
+ var list = new List<string>
+ {
+ "album",
+ "disbanded"
+ };
+
+ return list;
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
new file mode 100644
index 000000000..f795eb8b3
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
@@ -0,0 +1,1008 @@
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.XbmcMetadata.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Xml;
+
+namespace MediaBrowser.XbmcMetadata.Savers
+{
+ public abstract class BaseNfoSaver : IMetadataFileSaver
+ {
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+ private static readonly Dictionary<string, string> CommonTags = new[] {
+
+ "plot",
+ "customrating",
+ "lockdata",
+ "type",
+ "dateadded",
+ "title",
+ "rating",
+ "year",
+ "sorttitle",
+ "mpaa",
+ "mpaadescription",
+ "aspectratio",
+ "website",
+ "collectionnumber",
+ "tmdbid",
+ "rottentomatoesid",
+ "language",
+ "tvcomid",
+ "budget",
+ "revenue",
+ "tagline",
+ "studio",
+ "genre",
+ "tag",
+ "runtime",
+ "actor",
+ "criticratingsummary",
+ "criticrating",
+ "fileinfo",
+ "director",
+ "writer",
+ "trailer",
+ "premiered",
+ "releasedate",
+ "outline",
+ "id",
+ "votes",
+ "credits",
+ "originaltitle",
+ "watched",
+ "playcount",
+ "lastplayed",
+ "art",
+ "resume",
+ "biography",
+ "formed",
+ "review",
+ "style",
+ "imdbid",
+ "imdb_id",
+ "plotkeyword",
+ "country",
+ "audiodbalbumid",
+ "audiodbartistid",
+ "awardsummary",
+ "enddate",
+ "lockedfields",
+ "metascore",
+ "zap2itid",
+ "tvrageid",
+ "gamesdbid",
+
+ "musicbrainzartistid",
+ "musicbrainzalbumartistid",
+ "musicbrainzalbumid",
+ "musicbrainzreleasegroupid",
+ "tvdbid",
+ "collectionitem"
+
+ }.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
+
+ protected BaseNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger)
+ {
+ Logger = logger;
+ UserDataManager = userDataManager;
+ UserManager = userManager;
+ LibraryManager = libraryManager;
+ ConfigurationManager = configurationManager;
+ FileSystem = fileSystem;
+ }
+
+ protected IFileSystem FileSystem { get; private set; }
+ protected IServerConfigurationManager ConfigurationManager { get; private set; }
+ protected ILibraryManager LibraryManager { get; private set; }
+ protected IUserManager UserManager { get; private set; }
+ protected IUserDataManager UserDataManager { get; private set; }
+ protected ILogger Logger { get; private set; }
+
+ public string Name
+ {
+ get
+ {
+ return "Xbmc Nfo";
+ }
+ }
+
+ /// <summary>
+ /// Gets the save path.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>System.String.</returns>
+ public abstract string GetSavePath(IHasMetadata item);
+
+ /// <summary>
+ /// Gets the name of the root element.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>System.String.</returns>
+ protected abstract string GetRootElementName(IHasMetadata item);
+
+ /// <summary>
+ /// Determines whether [is enabled for] [the specified item].
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="updateType">Type of the update.</param>
+ /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
+ public abstract bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType);
+
+ protected virtual List<string> GetTagsUsed()
+ {
+ return new List<string>();
+ }
+
+ public void Save(IHasMetadata item, CancellationToken cancellationToken)
+ {
+ var path = GetSavePath(item);
+
+ using (var memoryStream = new MemoryStream())
+ {
+ Save(item, memoryStream, path);
+
+ memoryStream.Position = 0;
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ SaveToFile(memoryStream, path);
+ }
+ }
+
+ private void SaveToFile(Stream stream, string path)
+ {
+ var file = new FileInfo(path);
+
+ var wasHidden = false;
+
+ // This will fail if the file is hidden
+ if (file.Exists)
+ {
+ if ((file.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
+ {
+ file.Attributes &= ~FileAttributes.Hidden;
+
+ wasHidden = true;
+ }
+ }
+
+ using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
+ {
+ stream.CopyTo(filestream);
+ }
+
+ if (wasHidden)
+ {
+ file.Refresh();
+
+ // Add back the attribute
+ file.Attributes |= FileAttributes.Hidden;
+ }
+ }
+
+ private void Save(IHasMetadata item, Stream stream, string xmlPath)
+ {
+ var settings = new XmlWriterSettings
+ {
+ Indent = true,
+ Encoding = Encoding.UTF8,
+ CloseOutput = false
+ };
+
+ using (XmlWriter writer = XmlWriter.Create(stream, settings))
+ {
+ var root = GetRootElementName(item);
+
+ writer.WriteStartDocument(true);
+
+ writer.WriteStartElement(root);
+
+ var baseItem = item as BaseItem;
+
+ if (baseItem != null)
+ {
+ AddCommonNodes(baseItem, writer, LibraryManager, UserManager, UserDataManager, FileSystem, ConfigurationManager);
+ }
+
+ WriteCustomElements(item, writer);
+
+ var hasMediaSources = baseItem as IHasMediaSources;
+
+ if (hasMediaSources != null)
+ {
+ AddMediaInfo(hasMediaSources, writer);
+ }
+
+ var tagsUsed = GetTagsUsed();
+
+ try
+ {
+ AddCustomTags(xmlPath, tagsUsed, writer, Logger);
+ }
+ catch (FileNotFoundException)
+ {
+
+ }
+
+ writer.WriteEndElement();
+
+ writer.WriteEndDocument();
+ }
+ }
+
+ protected abstract void WriteCustomElements(IHasMetadata item, XmlWriter writer);
+
+ public static void AddMediaInfo<T>(T item, XmlWriter writer)
+ where T : IHasMediaSources
+ {
+ writer.WriteStartElement("fileinfo");
+ writer.WriteStartElement("streamdetails");
+
+ var mediaSource = item.GetMediaSources(false).First();
+
+ foreach (var stream in mediaSource.MediaStreams)
+ {
+ writer.WriteStartElement(stream.Type.ToString().ToLower());
+
+ if (!string.IsNullOrEmpty(stream.Codec))
+ {
+ writer.WriteElementString("codec", stream.Codec);
+ writer.WriteElementString("micodec", stream.Codec);
+ }
+
+ if (stream.BitRate.HasValue)
+ {
+ writer.WriteElementString("bitrate", stream.BitRate.Value.ToString(UsCulture));
+ }
+
+ if (stream.Width.HasValue)
+ {
+ writer.WriteElementString("width", stream.Width.Value.ToString(UsCulture));
+ }
+
+ if (stream.Height.HasValue)
+ {
+ writer.WriteElementString("height", stream.Height.Value.ToString(UsCulture));
+ }
+
+ if (!string.IsNullOrEmpty(stream.AspectRatio))
+ {
+ writer.WriteElementString("aspect", stream.AspectRatio);
+ writer.WriteElementString("aspectratio", stream.AspectRatio);
+ }
+
+ var framerate = stream.AverageFrameRate ?? stream.RealFrameRate;
+
+ if (framerate.HasValue)
+ {
+ writer.WriteElementString("framerate", framerate.Value.ToString(UsCulture));
+ }
+
+ if (!string.IsNullOrEmpty(stream.Language))
+ {
+ writer.WriteElementString("language", stream.Language);
+ }
+
+ var scanType = stream.IsInterlaced ? "interlaced" : "progressive";
+ if (!string.IsNullOrEmpty(scanType))
+ {
+ writer.WriteElementString("scantype", scanType);
+ }
+
+ if (stream.Channels.HasValue)
+ {
+ writer.WriteElementString("channels", stream.Channels.Value.ToString(UsCulture));
+ }
+
+ if (stream.SampleRate.HasValue)
+ {
+ writer.WriteElementString("samplingrate", stream.SampleRate.Value.ToString(UsCulture));
+ }
+
+ writer.WriteElementString("default", stream.IsDefault.ToString());
+ writer.WriteElementString("forced", stream.IsForced.ToString());
+
+ if (stream.Type == MediaStreamType.Video)
+ {
+ if (mediaSource.RunTimeTicks.HasValue)
+ {
+ var timespan = TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value);
+
+ writer.WriteElementString("duration", Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture));
+ writer.WriteElementString("durationinseconds", Convert.ToInt32(timespan.TotalSeconds).ToString(UsCulture));
+ }
+
+ var video = item as Video;
+
+ if (video != null)
+ {
+ //AddChapters(video, builder, itemRepository);
+
+ if (video.Video3DFormat.HasValue)
+ {
+ switch (video.Video3DFormat.Value)
+ {
+ case Video3DFormat.FullSideBySide:
+ writer.WriteElementString("format3d", "FSBS");
+ break;
+ case Video3DFormat.FullTopAndBottom:
+ writer.WriteElementString("format3d", "FTAB");
+ break;
+ case Video3DFormat.HalfSideBySide:
+ writer.WriteElementString("format3d", "HSBS");
+ break;
+ case Video3DFormat.HalfTopAndBottom:
+ writer.WriteElementString("format3d", "HTAB");
+ break;
+ }
+ }
+ }
+ }
+
+ writer.WriteEndElement();
+ }
+
+ writer.WriteEndElement();
+ writer.WriteEndElement();
+ }
+
+ /// <summary>
+ /// Adds the common nodes.
+ /// </summary>
+ /// <returns>Task.</returns>
+ public static void AddCommonNodes(BaseItem item, XmlWriter writer, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config)
+ {
+ var overview = (item.Overview ?? string.Empty)
+ .StripHtml()
+ .Replace("&quot;", "'");
+
+ var options = config.GetNfoConfiguration();
+
+ if (item is MusicArtist)
+ {
+ writer.WriteElementString("biography", overview);
+ }
+ else if (item is MusicAlbum)
+ {
+ writer.WriteElementString("review", overview);
+ }
+ else
+ {
+ writer.WriteElementString("plot", overview);
+ }
+
+ var hasShortOverview = item as IHasShortOverview;
+ if (hasShortOverview != null)
+ {
+ var outline = (hasShortOverview.ShortOverview ?? string.Empty)
+ .StripHtml()
+ .Replace("&quot;", "'");
+
+ writer.WriteElementString("outline", outline);
+ }
+ else
+ {
+ writer.WriteElementString("outline", overview);
+ }
+
+ if (!string.IsNullOrWhiteSpace(item.CustomRating))
+ {
+ writer.WriteElementString("customrating", item.CustomRating);
+ }
+
+ writer.WriteElementString("lockdata", item.IsLocked.ToString().ToLower());
+
+ if (item.LockedFields.Count > 0)
+ {
+ writer.WriteElementString("lockedfields", string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()));
+ }
+
+ if (!string.IsNullOrEmpty(item.DisplayMediaType))
+ {
+ writer.WriteElementString("type", item.DisplayMediaType);
+ }
+
+ writer.WriteElementString("dateadded", item.DateCreated.ToString("yyyy-MM-dd HH:mm:ss"));
+
+ writer.WriteElementString("title", item.Name ?? string.Empty);
+ writer.WriteElementString("originaltitle", item.Name ?? string.Empty);
+
+ var directors = item.People
+ .Where(i => IsPersonType(i, PersonType.Director))
+ .Select(i => i.Name)
+ .ToList();
+
+ foreach (var person in directors)
+ {
+ writer.WriteElementString("director", person);
+ }
+
+ var writers = item.People
+ .Where(i => IsPersonType(i, PersonType.Writer))
+ .Select(i => i.Name)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
+
+ foreach (var person in writers)
+ {
+ writer.WriteElementString("writer", person);
+ }
+
+ foreach (var person in writers)
+ {
+ writer.WriteElementString("credits", person);
+ }
+
+ var hasTrailer = item as IHasTrailers;
+ if (hasTrailer != null)
+ {
+ foreach (var trailer in hasTrailer.RemoteTrailers)
+ {
+ writer.WriteElementString("trailer", GetOutputTrailerUrl(trailer.Url));
+ }
+ }
+
+ if (item.CommunityRating.HasValue)
+ {
+ writer.WriteElementString("rating", item.CommunityRating.Value.ToString(UsCulture));
+ }
+
+ if (item.ProductionYear.HasValue)
+ {
+ writer.WriteElementString("year", item.ProductionYear.Value.ToString(UsCulture));
+ }
+
+ if (!string.IsNullOrEmpty(item.ForcedSortName))
+ {
+ writer.WriteElementString("sorttitle", item.ForcedSortName);
+ }
+
+ if (!string.IsNullOrEmpty(item.OfficialRating))
+ {
+ writer.WriteElementString("mpaa", item.OfficialRating);
+ }
+
+ if (!string.IsNullOrEmpty(item.OfficialRatingDescription))
+ {
+ writer.WriteElementString("mpaadescription", item.OfficialRatingDescription);
+ }
+
+ var hasAspectRatio = item as IHasAspectRatio;
+ if (hasAspectRatio != null)
+ {
+ if (!string.IsNullOrEmpty(hasAspectRatio.AspectRatio))
+ {
+ writer.WriteElementString("aspectratio", hasAspectRatio.AspectRatio);
+ }
+ }
+
+ if (!string.IsNullOrEmpty(item.HomePageUrl))
+ {
+ writer.WriteElementString("website", item.HomePageUrl);
+ }
+
+ var rt = item.GetProviderId(MetadataProviders.RottenTomatoes);
+
+ if (!string.IsNullOrEmpty(rt))
+ {
+ writer.WriteElementString("rottentomatoesid", rt);
+ }
+
+ var tmdbCollection = item.GetProviderId(MetadataProviders.TmdbCollection);
+
+ if (!string.IsNullOrEmpty(tmdbCollection))
+ {
+ writer.WriteElementString("collectionnumber", tmdbCollection);
+ }
+
+ var imdb = item.GetProviderId(MetadataProviders.Imdb);
+ if (!string.IsNullOrEmpty(imdb))
+ {
+ if (item is Series)
+ {
+ writer.WriteElementString("imdb_id", imdb);
+ }
+ else
+ {
+ writer.WriteElementString("imdbid", imdb);
+ }
+ }
+
+ // Series xml saver already saves this
+ if (!(item is Series))
+ {
+ var tvdb = item.GetProviderId(MetadataProviders.Tvdb);
+ if (!string.IsNullOrEmpty(tvdb))
+ {
+ writer.WriteElementString("tvdbid", tvdb);
+ }
+ }
+
+ var tmdb = item.GetProviderId(MetadataProviders.Tmdb);
+ if (!string.IsNullOrEmpty(tmdb))
+ {
+ writer.WriteElementString("tmdbid", tmdb);
+ }
+
+ var tvcom = item.GetProviderId(MetadataProviders.Tvcom);
+ if (!string.IsNullOrEmpty(tvcom))
+ {
+ writer.WriteElementString("tvcomid", tvcom);
+ }
+
+ var hasLanguage = item as IHasPreferredMetadataLanguage;
+ if (hasLanguage != null)
+ {
+ if (!string.IsNullOrEmpty(hasLanguage.PreferredMetadataLanguage))
+ {
+ writer.WriteElementString("language", hasLanguage.PreferredMetadataLanguage);
+ }
+ }
+
+ if (item.PremiereDate.HasValue && !(item is Episode))
+ {
+ var formatString = options.ReleaseDateFormat;
+
+ if (item is MusicArtist)
+ {
+ writer.WriteElementString("formed", item.PremiereDate.Value.ToString(formatString));
+ }
+ else
+ {
+ writer.WriteElementString("premiered", item.PremiereDate.Value.ToString(formatString));
+ writer.WriteElementString("releasedate", item.PremiereDate.Value.ToString(formatString));
+ }
+ }
+
+ if (item.EndDate.HasValue)
+ {
+ if (!(item is Episode))
+ {
+ var formatString = options.ReleaseDateFormat;
+
+ writer.WriteElementString("enddate", item.EndDate.Value.ToString(formatString));
+ }
+ }
+
+ var hasCriticRating = item as IHasCriticRating;
+
+ if (hasCriticRating != null)
+ {
+ if (hasCriticRating.CriticRating.HasValue)
+ {
+ writer.WriteElementString("criticrating", hasCriticRating.CriticRating.Value.ToString(UsCulture));
+ }
+
+ if (!string.IsNullOrEmpty(hasCriticRating.CriticRatingSummary))
+ {
+ writer.WriteElementString("criticratingsummary", hasCriticRating.CriticRatingSummary);
+ }
+ }
+
+ var hasDisplayOrder = item as IHasDisplayOrder;
+
+ if (hasDisplayOrder != null)
+ {
+ if (!string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder))
+ {
+ writer.WriteElementString("displayorder", hasDisplayOrder.DisplayOrder);
+ }
+ }
+
+ if (item.VoteCount.HasValue)
+ {
+ writer.WriteElementString("votes", item.VoteCount.Value.ToString(UsCulture));
+ }
+
+ var hasBudget = item as IHasBudget;
+ if (hasBudget != null)
+ {
+ if (hasBudget.Budget.HasValue)
+ {
+ writer.WriteElementString("budget", hasBudget.Budget.Value.ToString(UsCulture));
+ }
+
+ if (hasBudget.Revenue.HasValue)
+ {
+ writer.WriteElementString("revenue", hasBudget.Revenue.Value.ToString(UsCulture));
+ }
+ }
+
+ var hasMetascore = item as IHasMetascore;
+ if (hasMetascore != null && hasMetascore.Metascore.HasValue)
+ {
+ writer.WriteElementString("metascore", hasMetascore.Metascore.Value.ToString(UsCulture));
+ }
+
+ // Use original runtime here, actual file runtime later in MediaInfo
+ var runTimeTicks = item.RunTimeTicks;
+
+ if (runTimeTicks.HasValue)
+ {
+ var timespan = TimeSpan.FromTicks(runTimeTicks.Value);
+
+ writer.WriteElementString("runtime", Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture));
+ }
+
+ var hasTaglines = item as IHasTaglines;
+ if (hasTaglines != null)
+ {
+ foreach (var tagline in hasTaglines.Taglines)
+ {
+ writer.WriteElementString("tagline", tagline);
+ }
+ }
+
+ var hasProductionLocations = item as IHasProductionLocations;
+ if (hasProductionLocations != null)
+ {
+ foreach (var country in hasProductionLocations.ProductionLocations)
+ {
+ writer.WriteElementString("country", country);
+ }
+ }
+
+ foreach (var genre in item.Genres)
+ {
+ writer.WriteElementString("genre", genre);
+ }
+
+ foreach (var studio in item.Studios)
+ {
+ writer.WriteElementString("studio", studio);
+ }
+
+ var hasTags = item as IHasTags;
+ if (hasTags != null)
+ {
+ foreach (var tag in hasTags.Tags)
+ {
+ if (item is MusicAlbum || item is MusicArtist)
+ {
+ writer.WriteElementString("style", tag);
+ }
+ else
+ {
+ writer.WriteElementString("tag", tag);
+ }
+ }
+ }
+
+ var hasKeywords = item as IHasKeywords;
+ if (hasKeywords != null)
+ {
+ foreach (var tag in hasKeywords.Keywords)
+ {
+ writer.WriteElementString("plotkeyword", tag);
+ }
+ }
+
+ var hasAwards = item as IHasAwards;
+ if (hasAwards != null && !string.IsNullOrEmpty(hasAwards.AwardSummary))
+ {
+ writer.WriteElementString("awardsummary", hasAwards.AwardSummary);
+ }
+
+ var externalId = item.GetProviderId(MetadataProviders.AudioDbArtist);
+
+ if (!string.IsNullOrEmpty(externalId))
+ {
+ writer.WriteElementString("audiodbartistid", externalId);
+ }
+
+ externalId = item.GetProviderId(MetadataProviders.AudioDbAlbum);
+
+ if (!string.IsNullOrEmpty(externalId))
+ {
+ writer.WriteElementString("audiodbalbumid", externalId);
+ }
+
+ externalId = item.GetProviderId(MetadataProviders.Zap2It);
+
+ if (!string.IsNullOrEmpty(externalId))
+ {
+ writer.WriteElementString("zap2itid", externalId);
+ }
+
+ externalId = item.GetProviderId(MetadataProviders.MusicBrainzAlbum);
+
+ if (!string.IsNullOrEmpty(externalId))
+ {
+ writer.WriteElementString("musicbrainzalbumid", externalId);
+ }
+
+ externalId = item.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist);
+
+ if (!string.IsNullOrEmpty(externalId))
+ {
+ writer.WriteElementString("musicbrainzalbumartistid", externalId);
+ }
+
+ externalId = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
+
+ if (!string.IsNullOrEmpty(externalId))
+ {
+ writer.WriteElementString("musicbrainzartistid", externalId);
+ }
+
+ externalId = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
+
+ if (!string.IsNullOrEmpty(externalId))
+ {
+ writer.WriteElementString("musicbrainzreleasegroupid", externalId);
+ }
+
+ externalId = item.GetProviderId(MetadataProviders.Gamesdb);
+ if (!string.IsNullOrEmpty(externalId))
+ {
+ writer.WriteElementString("gamesdbid", externalId);
+ }
+
+ externalId = item.GetProviderId(MetadataProviders.TvRage);
+ if (!string.IsNullOrEmpty(externalId))
+ {
+ writer.WriteElementString("tvrageid", externalId);
+ }
+
+ if (options.SaveImagePathsInNfo)
+ {
+ AddImages(item, writer, fileSystem, config);
+ }
+
+ AddUserData(item, writer, userManager, userDataRepo, options);
+
+ AddActors(item, writer, libraryManager, fileSystem, config);
+
+ var folder = item as BoxSet;
+ if (folder != null)
+ {
+ AddCollectionItems(folder, writer);
+ }
+ }
+
+ public static void AddChapters(Video item, XmlWriter writer, IItemRepository repository)
+ {
+ var chapters = repository.GetChapters(item.Id);
+
+ foreach (var chapter in chapters)
+ {
+ writer.WriteStartElement("chapter");
+ writer.WriteElementString("name", chapter.Name);
+
+ var time = TimeSpan.FromTicks(chapter.StartPositionTicks);
+ var ms = Convert.ToInt64(time.TotalMilliseconds);
+
+ writer.WriteElementString("startpositionms", ms.ToString(UsCulture));
+ writer.WriteEndElement();
+ }
+ }
+
+ private static void AddCollectionItems(Folder item, XmlWriter writer)
+ {
+ var items = item.LinkedChildren
+ .Where(i => i.Type == LinkedChildType.Manual && !string.IsNullOrWhiteSpace(i.ItemName))
+ .ToList();
+
+ foreach (var link in items)
+ {
+ writer.WriteStartElement("collectionitem");
+
+ writer.WriteElementString("name", link.ItemName);
+ writer.WriteElementString("type", link.ItemType);
+
+ if (link.ItemYear.HasValue)
+ {
+ writer.WriteElementString("year", link.ItemYear.Value.ToString(UsCulture));
+ }
+
+ writer.WriteEndElement();
+ }
+ }
+
+ /// <summary>
+ /// Gets the output trailer URL.
+ /// </summary>
+ /// <param name="url">The URL.</param>
+ /// <returns>System.String.</returns>
+ private static string GetOutputTrailerUrl(string url)
+ {
+ // This is what xbmc expects
+
+ return url.Replace("http://www.youtube.com/watch?v=",
+ "plugin://plugin.video.youtube/?action=play_video&videoid=",
+ StringComparison.OrdinalIgnoreCase);
+ }
+
+ private static void AddImages(BaseItem item, XmlWriter writer, IFileSystem fileSystem, IServerConfigurationManager config)
+ {
+ writer.WriteStartElement("art");
+
+ var poster = item.PrimaryImagePath;
+
+ if (!string.IsNullOrEmpty(poster))
+ {
+ writer.WriteElementString("poster", GetPathToSave(item.PrimaryImagePath, fileSystem, config));
+ }
+
+ foreach (var backdrop in item.GetImages(ImageType.Backdrop))
+ {
+ writer.WriteElementString("fanart", GetPathToSave(backdrop.Path, fileSystem, config));
+ }
+
+ writer.WriteEndElement();
+ }
+
+ private static void AddUserData(BaseItem item, XmlWriter writer, IUserManager userManager, IUserDataManager userDataRepo, XbmcMetadataOptions options)
+ {
+ var userId = options.UserId;
+ if (string.IsNullOrWhiteSpace(userId))
+ {
+ return;
+ }
+
+ var user = userManager.GetUserById(new Guid(userId));
+
+ if (user == null)
+ {
+ return;
+ }
+
+ if (item.IsFolder)
+ {
+ return;
+ }
+
+ var userdata = userDataRepo.GetUserData(user.Id, item.GetUserDataKey());
+
+ writer.WriteElementString("playcount", userdata.PlayCount.ToString(UsCulture));
+ writer.WriteElementString("watched", userdata.Played.ToString().ToLower());
+
+ if (userdata.LastPlayedDate.HasValue)
+ {
+ writer.WriteElementString("lastplayed", userdata.LastPlayedDate.Value.ToString("yyyy-MM-dd HH:mm:ss").ToLower());
+ }
+
+ writer.WriteStartElement("resume");
+
+ var runTimeTicks = item.RunTimeTicks ?? 0;
+
+ writer.WriteElementString("position", TimeSpan.FromTicks(userdata.PlaybackPositionTicks).TotalSeconds.ToString(UsCulture));
+ writer.WriteElementString("total", TimeSpan.FromTicks(runTimeTicks).TotalSeconds.ToString(UsCulture));
+
+ writer.WriteEndElement();
+ }
+
+ private static void AddActors(BaseItem item, XmlWriter writer, ILibraryManager libraryManager, IFileSystem fileSystem, IServerConfigurationManager config)
+ {
+ var actors = item.People
+ .Where(i => !IsPersonType(i, PersonType.Director) && !IsPersonType(i, PersonType.Writer))
+ .ToList();
+
+ foreach (var person in actors)
+ {
+ writer.WriteStartElement("actor");
+
+ if (!string.IsNullOrWhiteSpace(person.Name))
+ {
+ writer.WriteElementString("name", person.Name);
+ }
+
+ if (!string.IsNullOrWhiteSpace(person.Role))
+ {
+ writer.WriteElementString("role", person.Role);
+ }
+
+ if (!string.IsNullOrWhiteSpace(person.Type))
+ {
+ writer.WriteElementString("type", person.Type);
+ }
+
+ if (person.SortOrder.HasValue)
+ {
+ writer.WriteElementString("sortorder", person.SortOrder.Value.ToString(UsCulture));
+ }
+
+ try
+ {
+ var personEntity = libraryManager.GetPerson(person.Name);
+
+ if (!string.IsNullOrEmpty(personEntity.PrimaryImagePath))
+ {
+ writer.WriteElementString("thumb", GetPathToSave(personEntity.PrimaryImagePath, fileSystem, config));
+ }
+ }
+ catch (Exception)
+ {
+ // Already logged in core
+ }
+
+ writer.WriteEndElement();
+ }
+ }
+
+ private static string GetPathToSave(string path, IFileSystem fileSystem, IServerConfigurationManager config)
+ {
+ foreach (var map in config.Configuration.PathSubstitutions)
+ {
+ path = fileSystem.SubstitutePath(path, map.From, map.To);
+ }
+
+ return path;
+ }
+
+ private static bool IsPersonType(PersonInfo person, string type)
+ {
+ return string.Equals(person.Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(person.Role, type, StringComparison.OrdinalIgnoreCase);
+ }
+
+ private static void AddCustomTags(string path, List<string> xmlTagsUsed, XmlWriter writer, ILogger logger)
+ {
+ var settings = new XmlReaderSettings
+ {
+ CheckCharacters = false,
+ IgnoreProcessingInstructions = true,
+ IgnoreComments = true,
+ ValidationType = ValidationType.None
+ };
+
+ using (var streamReader = GetStreamReader(path))
+ {
+ // Use XmlReader for best performance
+ using (var reader = XmlReader.Create(streamReader, settings))
+ {
+ try
+ {
+ reader.MoveToContent();
+ }
+ catch (Exception ex)
+ {
+ logger.ErrorException("Error reading existing xml tags from {0}.", ex, path);
+ return;
+ }
+
+ // Loop through each element
+ while (reader.Read())
+ {
+ if (reader.NodeType == XmlNodeType.Element)
+ {
+ var name = reader.Name;
+
+ if (!CommonTags.ContainsKey(name) && !xmlTagsUsed.Contains(name, StringComparer.OrdinalIgnoreCase))
+ {
+ writer.WriteNode(reader, false);
+ }
+ else
+ {
+ reader.Skip();
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ public static StreamReader GetStreamReader(string path)
+ {
+ return new StreamReader(path, Encoding.UTF8);
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs
new file mode 100644
index 000000000..f5dc0558b
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs
@@ -0,0 +1,122 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.XbmcMetadata.Configuration;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Xml;
+
+namespace MediaBrowser.XbmcMetadata.Savers
+{
+ public class EpisodeNfoSaver : BaseNfoSaver
+ {
+ public EpisodeNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
+ {
+ }
+
+ public override string GetSavePath(IHasMetadata item)
+ {
+ return GetMovieSavePath(item);
+ }
+
+ public static string GetMovieSavePath(IHasMetadata item)
+ {
+ return Path.ChangeExtension(item.Path, ".nfo");
+ }
+
+ protected override string GetRootElementName(IHasMetadata item)
+ {
+ return "episodedetails";
+ }
+
+ public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ {
+ if (!item.SupportsLocalMetadata)
+ {
+ return false;
+ }
+
+ return item is Episode && updateType >= ItemUpdateType.MetadataDownload;
+ }
+
+ protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
+ {
+ var episode = (Episode)item;
+
+ if (episode.IndexNumber.HasValue)
+ {
+ writer.WriteElementString("episode", episode.IndexNumber.Value.ToString(UsCulture));
+ }
+
+ if (episode.IndexNumberEnd.HasValue)
+ {
+ writer.WriteElementString("episodenumberend", episode.IndexNumberEnd.Value.ToString(UsCulture));
+ }
+
+ if (episode.ParentIndexNumber.HasValue)
+ {
+ writer.WriteElementString("season", episode.ParentIndexNumber.Value.ToString(UsCulture));
+ }
+
+ if (episode.PremiereDate.HasValue)
+ {
+ var formatString = ConfigurationManager.GetNfoConfiguration().ReleaseDateFormat;
+
+ writer.WriteElementString("aired", episode.PremiereDate.Value.ToString(formatString));
+ }
+
+ if (episode.AirsAfterSeasonNumber.HasValue)
+ {
+ writer.WriteElementString("airsafter_season", episode.AirsAfterSeasonNumber.Value.ToString(UsCulture));
+ }
+ if (episode.AirsBeforeEpisodeNumber.HasValue)
+ {
+ writer.WriteElementString("airsbefore_episode", episode.AirsBeforeEpisodeNumber.Value.ToString(UsCulture));
+ }
+ if (episode.AirsBeforeSeasonNumber.HasValue)
+ {
+ writer.WriteElementString("airsbefore_season", episode.AirsBeforeSeasonNumber.Value.ToString(UsCulture));
+ }
+
+ if (episode.DvdEpisodeNumber.HasValue)
+ {
+ writer.WriteElementString("DVD_episodenumber", episode.DvdEpisodeNumber.Value.ToString(UsCulture));
+ }
+
+ if (episode.DvdSeasonNumber.HasValue)
+ {
+ writer.WriteElementString("DVD_season", episode.DvdSeasonNumber.Value.ToString(UsCulture));
+ }
+
+ if (episode.AbsoluteEpisodeNumber.HasValue)
+ {
+ writer.WriteElementString("absolute_number", episode.AbsoluteEpisodeNumber.Value.ToString(UsCulture));
+ }
+ }
+
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+ protected override List<string> GetTagsUsed()
+ {
+ var list = new List<string>
+ {
+ "aired",
+ "season",
+ "episode",
+ "episodenumberend",
+ "airsafter_season",
+ "airsbefore_episode",
+ "airsbefore_season",
+ "DVD_episodenumber",
+ "DVD_season",
+ "absolute_number"
+ };
+
+ return list;
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs
new file mode 100644
index 000000000..210c743bf
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs
@@ -0,0 +1,113 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Xml;
+
+namespace MediaBrowser.XbmcMetadata.Savers
+{
+ public class MovieNfoSaver : BaseNfoSaver
+ {
+ public MovieNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
+ {
+ }
+
+ public override string GetSavePath(IHasMetadata item)
+ {
+ return GetMovieSavePath(item, FileSystem);
+ }
+
+ public static string GetMovieSavePath(IHasMetadata item, IFileSystem fileSystem)
+ {
+ var video = (Video)item;
+
+ if (video.VideoType == VideoType.Dvd || video.VideoType == VideoType.BluRay || video.VideoType == VideoType.HdDvd)
+ {
+ var path = item.ContainingFolderPath;
+
+ return Path.Combine(path, fileSystem.GetFileNameWithoutExtension(path) + ".nfo");
+ }
+
+ return Path.ChangeExtension(item.Path, ".nfo");
+ }
+
+ protected override string GetRootElementName(IHasMetadata item)
+ {
+ return item is MusicVideo ? "musicvideo" : "movie";
+ }
+
+ public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ {
+ if (!item.SupportsLocalMetadata)
+ {
+ return false;
+ }
+
+ var video = item as Video;
+
+ // Check parent for null to avoid running this against things like video backdrops
+ if (video != null && !(item is Episode) && !video.IsOwnedItem)
+ {
+ return updateType >= ItemUpdateType.MetadataDownload;
+ }
+
+ return false;
+ }
+
+ protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
+ {
+ var imdb = item.GetProviderId(MetadataProviders.Imdb);
+
+ if (!string.IsNullOrEmpty(imdb))
+ {
+ writer.WriteElementString("id", imdb);
+ }
+
+ var musicVideo = item as MusicVideo;
+
+ if (musicVideo != null)
+ {
+ if (!string.IsNullOrEmpty(musicVideo.Artist))
+ {
+ writer.WriteElementString("artist", musicVideo.Artist);
+ }
+ if (!string.IsNullOrEmpty(musicVideo.Album))
+ {
+ writer.WriteElementString("album", musicVideo.Album);
+ }
+ }
+
+ var movie = item as Movie;
+
+ if (movie != null)
+ {
+ if (!string.IsNullOrEmpty(movie.TmdbCollectionName))
+ {
+ writer.WriteElementString("set", movie.TmdbCollectionName);
+ }
+ }
+ }
+
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+ protected override List<string> GetTagsUsed()
+ {
+ var list = new List<string>
+ {
+ "album",
+ "artist",
+ "set",
+ "id"
+ };
+
+ return list;
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs
new file mode 100644
index 000000000..715337a01
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs
@@ -0,0 +1,64 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Logging;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Xml;
+
+namespace MediaBrowser.XbmcMetadata.Savers
+{
+ public class SeasonNfoSaver : BaseNfoSaver
+ {
+ public SeasonNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
+ {
+ }
+
+ public override string GetSavePath(IHasMetadata item)
+ {
+ return Path.Combine(item.Path, "season.nfo");
+ }
+
+ protected override string GetRootElementName(IHasMetadata item)
+ {
+ return "season";
+ }
+
+ public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ {
+ if (!item.SupportsLocalMetadata)
+ {
+ return false;
+ }
+
+ if (!(item is Season))
+ {
+ return false;
+ }
+
+ return updateType >= ItemUpdateType.MetadataDownload || (updateType >= ItemUpdateType.MetadataImport && File.Exists(GetSavePath(item)));
+ }
+
+ protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
+ {
+ var season = (Season)item;
+
+ if (season.IndexNumber.HasValue)
+ {
+ writer.WriteElementString("seasonnumber", season.IndexNumber.Value.ToString(CultureInfo.InvariantCulture));
+ }
+ }
+
+ protected override List<string> GetTagsUsed()
+ {
+ var list = base.GetTagsUsed();
+
+ list.Add("seasonnumber");
+
+ return list;
+ }
+ }
+}
diff --git a/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs
new file mode 100644
index 000000000..8a67b0418
--- /dev/null
+++ b/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs
@@ -0,0 +1,113 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Xml;
+
+namespace MediaBrowser.XbmcMetadata.Savers
+{
+ public class SeriesNfoSaver : BaseNfoSaver
+ {
+ public SeriesNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager, ILogger logger) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager, logger)
+ {
+ }
+
+ public override string GetSavePath(IHasMetadata item)
+ {
+ return Path.Combine(item.Path, "tvshow.nfo");
+ }
+
+ protected override string GetRootElementName(IHasMetadata item)
+ {
+ return "tvshow";
+ }
+
+ public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType)
+ {
+ if (!item.SupportsLocalMetadata)
+ {
+ return false;
+ }
+
+ return item is Series && updateType >= ItemUpdateType.MetadataDownload;
+ }
+
+ protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer)
+ {
+ var series = (Series)item;
+
+ var tvdb = item.GetProviderId(MetadataProviders.Tvdb);
+
+ if (!string.IsNullOrEmpty(tvdb))
+ {
+ writer.WriteElementString("id", tvdb);
+
+ writer.WriteStartElement("episodeguide");
+
+ var language = item.GetPreferredMetadataLanguage();
+ language = string.IsNullOrEmpty(language)
+ ? "en"
+ : language;
+
+ writer.WriteStartElement("url");
+ writer.WriteAttributeString("cache", string.Format("{0}.xml", tvdb));
+ writer.WriteString(string.Format("http://www.thetvdb.com/api/1D62F2F90030C444/series/{0}/all/{1}.zip", tvdb, language));
+ writer.WriteEndElement();
+
+ writer.WriteEndElement();
+ }
+
+ writer.WriteElementString("season", "-1");
+ writer.WriteElementString("episode", "-1");
+
+ if (series.Status.HasValue)
+ {
+ writer.WriteElementString("status", series.Status.Value.ToString());
+ }
+
+ if (!string.IsNullOrEmpty(series.AirTime))
+ {
+ writer.WriteElementString("airs_time", series.AirTime);
+ }
+
+ if (series.AirDays.Count == 7)
+ {
+ writer.WriteElementString("airs_dayofweek", "Daily");
+ }
+ else if (series.AirDays.Count > 0)
+ {
+ writer.WriteElementString("airs_dayofweek", series.AirDays[0].ToString());
+ }
+
+ if (series.AnimeSeriesIndex.HasValue)
+ {
+ writer.WriteElementString("animeseriesindex", series.AnimeSeriesIndex.Value.ToString(CultureInfo.InvariantCulture));
+ }
+ }
+
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+ protected override List<string> GetTagsUsed()
+ {
+ var list = new List<string>
+ {
+ "id",
+ "episodeguide",
+ "season",
+ "episode",
+ "status",
+ "airs_time",
+ "airs_dayofweek",
+ "animeseriesindex"
+ };
+
+ return list;
+ }
+ }
+}
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index 1b132e07f..cc9198349 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -1,18 +1,8 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
-VisualStudioVersion = 12.0.21005.1
+VisualStudioVersion = 12.0.30723.0
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Controller", "MediaBrowser.Controller\MediaBrowser.Controller.csproj", "{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Api", "MediaBrowser.Api\MediaBrowser.Api.csproj", "{4FD51AC5-2C16-4308-A993-C3A84F3B4582}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Common", "MediaBrowser.Common\MediaBrowser.Common.csproj", "{9142EEFA-7570-41E1-BFCC-468BB571AF2F}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Model", "MediaBrowser.Model\MediaBrowser.Model.csproj", "{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.WebDashboard", "MediaBrowser.WebDashboard\MediaBrowser.WebDashboard.csproj", "{5624B7B5-B5A7-41D8-9F10-CC5611109619}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{F0E0E64C-2A6F-4E35-9533-D53AC07C2CD1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8C5D6ABC-D277-407B-8061-3AA04251D539}"
@@ -27,6 +17,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget (2)", ".nuget (2)",
.nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Controller", "MediaBrowser.Controller\MediaBrowser.Controller.csproj", "{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Api", "MediaBrowser.Api\MediaBrowser.Api.csproj", "{4FD51AC5-2C16-4308-A993-C3A84F3B4582}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Common", "MediaBrowser.Common\MediaBrowser.Common.csproj", "{9142EEFA-7570-41E1-BFCC-468BB571AF2F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Model", "MediaBrowser.Model\MediaBrowser.Model.csproj", "{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.WebDashboard", "MediaBrowser.WebDashboard\MediaBrowser.WebDashboard.csproj", "{5624B7B5-B5A7-41D8-9F10-CC5611109619}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Common.Implementations", "MediaBrowser.Common.Implementations\MediaBrowser.Common.Implementations.csproj", "{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Server.Implementations", "MediaBrowser.Server.Implementations\MediaBrowser.Server.Implementations.csproj", "{2E781478-814D-4A48-9D80-BFF206441A65}"
@@ -47,13 +47,27 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSubtitlesHandler", "OpenSubtitlesHandler\OpenSubtitlesHandler.csproj", "{4A4402D4-E910-443B-B8FC-2C18286A2CA0}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.XbmcMetadata", "MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj", "{23499896-B135-4527-8574-C26E926EA99E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.LocalMetadata", "MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj", "{7EF9F3E0-697D-42F3-A08F-19DEB5F84392}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug_Ubuntu|Any CPU = Debug_Ubuntu|Any CPU
+ Debug_Ubuntu|Mixed Platforms = Debug_Ubuntu|Mixed Platforms
+ Debug_Ubuntu|Win32 = Debug_Ubuntu|Win32
+ Debug_Ubuntu|x64 = Debug_Ubuntu|x64
+ Debug_Ubuntu|x86 = Debug_Ubuntu|x86
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
+ Release_Ubuntu|Any CPU = Release_Ubuntu|Any CPU
+ Release_Ubuntu|Mixed Platforms = Release_Ubuntu|Mixed Platforms
+ Release_Ubuntu|Win32 = Release_Ubuntu|Win32
+ Release_Ubuntu|x64 = Release_Ubuntu|x64
+ Release_Ubuntu|x86 = Release_Ubuntu|x86
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|Win32 = Release|Win32
@@ -61,6 +75,13 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -69,6 +90,13 @@ Global
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x64.ActiveCfg = Debug|Any CPU
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x86.ActiveCfg = Debug|Any CPU
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x86.Build.0 = Debug|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release_Ubuntu|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release_Ubuntu|Any CPU.Build.0 = Release Mono|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release Mono|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release_Ubuntu|Mixed Platforms.Build.0 = Release Mono|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release_Ubuntu|Win32.ActiveCfg = Release Mono|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release_Ubuntu|x64.ActiveCfg = Release Mono|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release_Ubuntu|x86.ActiveCfg = Release Mono|Any CPU
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.Build.0 = Release|Any CPU
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -77,6 +105,13 @@ Global
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x64.ActiveCfg = Release|Any CPU
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.ActiveCfg = Release|Any CPU
{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.Build.0 = Release|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -85,6 +120,13 @@ Global
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x64.ActiveCfg = Debug|Any CPU
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.ActiveCfg = Debug|Any CPU
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.Build.0 = Debug|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release_Ubuntu|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release_Ubuntu|Any CPU.Build.0 = Release Mono|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release Mono|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release_Ubuntu|Mixed Platforms.Build.0 = Release Mono|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release_Ubuntu|Win32.ActiveCfg = Release Mono|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release_Ubuntu|x64.ActiveCfg = Release Mono|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release_Ubuntu|x86.ActiveCfg = Release Mono|Any CPU
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.Build.0 = Release|Any CPU
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -93,6 +135,13 @@ Global
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|x64.ActiveCfg = Release|Any CPU
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|x86.ActiveCfg = Release|Any CPU
{4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|x86.Build.0 = Release|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -101,6 +150,13 @@ Global
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x64.ActiveCfg = Debug|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x86.ActiveCfg = Debug|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x86.Build.0 = Debug|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release_Ubuntu|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release_Ubuntu|Any CPU.Build.0 = Release Mono|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release Mono|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release_Ubuntu|Mixed Platforms.Build.0 = Release Mono|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release_Ubuntu|Win32.ActiveCfg = Release Mono|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release_Ubuntu|x64.ActiveCfg = Release Mono|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release_Ubuntu|x86.ActiveCfg = Release Mono|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.Build.0 = Release|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -109,6 +165,13 @@ Global
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|x64.ActiveCfg = Release|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|x86.ActiveCfg = Release|Any CPU
{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|x86.Build.0 = Release|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -117,6 +180,13 @@ Global
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|x64.ActiveCfg = Debug|Any CPU
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|x86.ActiveCfg = Debug|Any CPU
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|x86.Build.0 = Debug|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release_Ubuntu|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release_Ubuntu|Any CPU.Build.0 = Release Mono|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release Mono|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release_Ubuntu|Mixed Platforms.Build.0 = Release Mono|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release_Ubuntu|Win32.ActiveCfg = Release Mono|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release_Ubuntu|x64.ActiveCfg = Release Mono|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release_Ubuntu|x86.ActiveCfg = Release Mono|Any CPU
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.Build.0 = Release|Any CPU
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -125,6 +195,13 @@ Global
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x64.ActiveCfg = Release|Any CPU
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x86.ActiveCfg = Release|Any CPU
{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x86.Build.0 = Release|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -133,6 +210,13 @@ Global
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|x64.ActiveCfg = Debug|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|x86.ActiveCfg = Debug|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|x86.Build.0 = Debug|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release_Ubuntu|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release_Ubuntu|Any CPU.Build.0 = Release Mono|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release Mono|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release_Ubuntu|Mixed Platforms.Build.0 = Release Mono|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release_Ubuntu|Win32.ActiveCfg = Release Mono|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release_Ubuntu|x64.ActiveCfg = Release Mono|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release_Ubuntu|x86.ActiveCfg = Release Mono|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.Build.0 = Release|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -141,6 +225,13 @@ Global
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x64.ActiveCfg = Release|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.ActiveCfg = Release|Any CPU
{5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.Build.0 = Release|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -148,6 +239,13 @@ Global
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug|Win32.ActiveCfg = Debug|Any CPU
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug|x64.ActiveCfg = Debug|Any CPU
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release_Ubuntu|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release_Ubuntu|Any CPU.Build.0 = Release Mono|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release Mono|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release_Ubuntu|Mixed Platforms.Build.0 = Release Mono|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release_Ubuntu|Win32.ActiveCfg = Release Mono|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release_Ubuntu|x64.ActiveCfg = Release Mono|Any CPU
+ {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release_Ubuntu|x86.ActiveCfg = Release Mono|Any CPU
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|Any CPU.Build.0 = Release|Any CPU
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -155,6 +253,13 @@ Global
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|Win32.ActiveCfg = Release|Any CPU
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|x64.ActiveCfg = Release|Any CPU
{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|x86.ActiveCfg = Release|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -162,6 +267,13 @@ Global
{2E781478-814D-4A48-9D80-BFF206441A65}.Debug|Win32.ActiveCfg = Debug|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x64.ActiveCfg = Debug|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Release_Ubuntu|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Release_Ubuntu|Any CPU.Build.0 = Release Mono|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release Mono|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Release_Ubuntu|Mixed Platforms.Build.0 = Release Mono|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Release_Ubuntu|Win32.ActiveCfg = Release Mono|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Release_Ubuntu|x64.ActiveCfg = Release Mono|Any CPU
+ {2E781478-814D-4A48-9D80-BFF206441A65}.Release_Ubuntu|x86.ActiveCfg = Release Mono|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.Build.0 = Release|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -169,6 +281,13 @@ Global
{2E781478-814D-4A48-9D80-BFF206441A65}.Release|Win32.ActiveCfg = Release|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Release|x64.ActiveCfg = Release|Any CPU
{2E781478-814D-4A48-9D80-BFF206441A65}.Release|x86.ActiveCfg = Release|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{657B5410-7C3B-4806-9753-D254102CE537}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{657B5410-7C3B-4806-9753-D254102CE537}.Debug|Any CPU.Build.0 = Debug|Any CPU
{657B5410-7C3B-4806-9753-D254102CE537}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -176,6 +295,13 @@ Global
{657B5410-7C3B-4806-9753-D254102CE537}.Debug|Win32.ActiveCfg = Debug|Any CPU
{657B5410-7C3B-4806-9753-D254102CE537}.Debug|x64.ActiveCfg = Debug|Any CPU
{657B5410-7C3B-4806-9753-D254102CE537}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Release_Ubuntu|Any CPU.ActiveCfg = Release|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Release_Ubuntu|Any CPU.Build.0 = Release|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Release_Ubuntu|Mixed Platforms.Build.0 = Release|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Release_Ubuntu|Win32.ActiveCfg = Release|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Release_Ubuntu|x64.ActiveCfg = Release|Any CPU
+ {657B5410-7C3B-4806-9753-D254102CE537}.Release_Ubuntu|x86.ActiveCfg = Release|Any CPU
{657B5410-7C3B-4806-9753-D254102CE537}.Release|Any CPU.ActiveCfg = Release|Any CPU
{657B5410-7C3B-4806-9753-D254102CE537}.Release|Any CPU.Build.0 = Release|Any CPU
{657B5410-7C3B-4806-9753-D254102CE537}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -183,6 +309,13 @@ Global
{657B5410-7C3B-4806-9753-D254102CE537}.Release|Win32.ActiveCfg = Release|Any CPU
{657B5410-7C3B-4806-9753-D254102CE537}.Release|x64.ActiveCfg = Release|Any CPU
{657B5410-7C3B-4806-9753-D254102CE537}.Release|x86.ActiveCfg = Release|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -190,6 +323,13 @@ Global
{E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug|Win32.ActiveCfg = Debug|Any CPU
{E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug|x64.ActiveCfg = Debug|Any CPU
{E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release_Ubuntu|Any CPU.ActiveCfg = Release|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release_Ubuntu|Any CPU.Build.0 = Release|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release_Ubuntu|Mixed Platforms.Build.0 = Release|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release_Ubuntu|Win32.ActiveCfg = Release|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release_Ubuntu|x64.ActiveCfg = Release|Any CPU
+ {E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release_Ubuntu|x86.ActiveCfg = Release|Any CPU
{E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release|Any CPU.Build.0 = Release|Any CPU
{E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -197,6 +337,13 @@ Global
{E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release|Win32.ActiveCfg = Release|Any CPU
{E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release|x64.ActiveCfg = Release|Any CPU
{E22BFD35-0FCD-4A85-978A-C22DCD73A081}.Release|x86.ActiveCfg = Release|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -204,6 +351,13 @@ Global
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Win32.ActiveCfg = Debug|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|x64.ActiveCfg = Debug|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release_Ubuntu|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release_Ubuntu|Any CPU.Build.0 = Release Mono|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release Mono|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release_Ubuntu|Mixed Platforms.Build.0 = Release Mono|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release_Ubuntu|Win32.ActiveCfg = Release Mono|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release_Ubuntu|x64.ActiveCfg = Release Mono|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release_Ubuntu|x86.ActiveCfg = Release Mono|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.Build.0 = Release|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -211,6 +365,13 @@ Global
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Win32.ActiveCfg = Release|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x64.ActiveCfg = Release|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.ActiveCfg = Release|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -218,6 +379,13 @@ Global
{D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug|Win32.ActiveCfg = Debug|Any CPU
{D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug|x64.ActiveCfg = Debug|Any CPU
{D729ADB1-1C01-428D-B680-8EFACD687B2A}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release_Ubuntu|Any CPU.ActiveCfg = Release|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release_Ubuntu|Any CPU.Build.0 = Release|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release_Ubuntu|Mixed Platforms.Build.0 = Release|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release_Ubuntu|Win32.ActiveCfg = Release|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release_Ubuntu|x64.ActiveCfg = Release|Any CPU
+ {D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release_Ubuntu|x86.ActiveCfg = Release|Any CPU
{D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release|Any CPU.Build.0 = Release|Any CPU
{D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -225,6 +393,15 @@ Global
{D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release|Win32.ActiveCfg = Release|Any CPU
{D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release|x64.ActiveCfg = Release|Any CPU
{D729ADB1-1C01-428D-B680-8EFACD687B2A}.Release|x86.ActiveCfg = Release|Any CPU
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|x86
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|x86
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug_Ubuntu|Win32.ActiveCfg = Debug|x86
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug_Ubuntu|Win32.Build.0 = Debug|x86
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug_Ubuntu|x86.ActiveCfg = Debug|x86
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug_Ubuntu|x86.Build.0 = Debug|x86
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug|Any CPU.ActiveCfg = Debug|x86
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug|Any CPU.Build.0 = Debug|x86
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -232,6 +409,15 @@ Global
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug|Win32.ActiveCfg = Debug|Any CPU
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug|x64.ActiveCfg = Debug|Any CPU
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release_Ubuntu|Any CPU.ActiveCfg = Release|Any CPU
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release_Ubuntu|Any CPU.Build.0 = Release|Any CPU
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release|x86
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release_Ubuntu|Mixed Platforms.Build.0 = Release|x86
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release_Ubuntu|Win32.ActiveCfg = Release|x86
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release_Ubuntu|Win32.Build.0 = Release|x86
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release_Ubuntu|x64.ActiveCfg = Release|Any CPU
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release_Ubuntu|x86.ActiveCfg = Release|x86
+ {94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release_Ubuntu|x86.Build.0 = Release|x86
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release|Any CPU.ActiveCfg = Release|x86
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release|Any CPU.Build.0 = Release|x86
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -239,6 +425,13 @@ Global
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release|Win32.ActiveCfg = Release|Any CPU
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release|x64.ActiveCfg = Release|Any CPU
{94ADE4D3-B7EC-45CD-A200-CC469433072B}.Release|x86.ActiveCfg = Release|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -246,6 +439,13 @@ Global
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|Win32.ActiveCfg = Debug|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|x64.ActiveCfg = Debug|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release_Ubuntu|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release_Ubuntu|Any CPU.Build.0 = Release Mono|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release Mono|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release_Ubuntu|Mixed Platforms.Build.0 = Release Mono|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release_Ubuntu|Win32.ActiveCfg = Release Mono|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release_Ubuntu|x64.ActiveCfg = Release Mono|Any CPU
+ {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release_Ubuntu|x86.ActiveCfg = Release Mono|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Any CPU.Build.0 = Release|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -253,6 +453,13 @@ Global
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Win32.ActiveCfg = Release|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x64.ActiveCfg = Release|Any CPU
{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x86.ActiveCfg = Release|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -260,6 +467,13 @@ Global
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Win32.ActiveCfg = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x64.ActiveCfg = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release_Ubuntu|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release_Ubuntu|Any CPU.Build.0 = Release Mono|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release Mono|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release_Ubuntu|Mixed Platforms.Build.0 = Release Mono|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release_Ubuntu|Win32.ActiveCfg = Release Mono|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release_Ubuntu|x64.ActiveCfg = Release Mono|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release_Ubuntu|x86.ActiveCfg = Release Mono|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.Build.0 = Release|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -267,6 +481,13 @@ Global
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Win32.ActiveCfg = Release|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|x64.ActiveCfg = Release|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|x86.ActiveCfg = Release|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@@ -274,6 +495,13 @@ Global
{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Win32.ActiveCfg = Debug|Any CPU
{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|x64.ActiveCfg = Debug|Any CPU
{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release_Ubuntu|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release_Ubuntu|Any CPU.Build.0 = Release Mono|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release Mono|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release_Ubuntu|Mixed Platforms.Build.0 = Release Mono|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release_Ubuntu|Win32.ActiveCfg = Release Mono|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release_Ubuntu|x64.ActiveCfg = Release Mono|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release_Ubuntu|x86.ActiveCfg = Release Mono|Any CPU
{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.Build.0 = Release|Any CPU
{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -281,6 +509,62 @@ Global
{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Win32.ActiveCfg = Release|Any CPU
{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x64.ActiveCfg = Release|Any CPU
{4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x86.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release_Ubuntu|Any CPU.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release_Ubuntu|Any CPU.Build.0 = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release_Ubuntu|Mixed Platforms.Build.0 = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release_Ubuntu|Win32.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release_Ubuntu|x64.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release_Ubuntu|x86.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|Win32.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|x64.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|x86.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug_Ubuntu|Any CPU.ActiveCfg = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug_Ubuntu|Any CPU.Build.0 = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug_Ubuntu|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug_Ubuntu|Mixed Platforms.Build.0 = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug_Ubuntu|Win32.ActiveCfg = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug_Ubuntu|x64.ActiveCfg = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug_Ubuntu|x86.ActiveCfg = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Win32.ActiveCfg = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release_Ubuntu|Any CPU.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release_Ubuntu|Any CPU.Build.0 = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release_Ubuntu|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release_Ubuntu|Mixed Platforms.Build.0 = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release_Ubuntu|Win32.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release_Ubuntu|x64.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release_Ubuntu|x86.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Win32.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x64.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.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 507a66f6f..11ccc3075 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.410</version>
+ <version>3.0.429</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,9 +12,9 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.410" />
- <dependency id="NLog" version="2.1.0" />
- <dependency id="SimpleInjector" version="2.5.0" />
+ <dependency id="MediaBrowser.Common" version="3.0.429" />
+ <dependency id="NLog" version="3.1.0.0" />
+ <dependency id="SimpleInjector" version="2.5.2" />
<dependency id="sharpcompress" version="0.10.2" />
</dependencies>
</metadata>
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index 9d2aa3ffe..b91274593 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
-<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
+<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
- <version>3.0.410</version>
+ <version>3.0.429</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,10 +12,10 @@
<description>Contains common model objects and interfaces used by all Media Browser solutions.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
- <group targetFramework=".NETFramework4.5"/>
- <group targetFramework=".NETFramework3.5"/>
+ <group targetFramework=".NETFramework4.5" />
+ <group targetFramework=".NETFramework3.5" />
<group targetFramework=".NETPortable0.0-net45+sl4+wp71+win8">
- <dependency id="Microsoft.Bcl.Async" version="1.0.16" />
+ <dependency id="Microsoft.Bcl.Async" version="1.0.168" />
</group>
</dependencies>
</metadata>
diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec
new file mode 100644
index 000000000..9280656b1
--- /dev/null
+++ b/Nuget/MediaBrowser.Model.Signed.nuspec
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
+ <metadata>
+ <id>MediaBrowser.Model.Signed</id>
+ <version>3.0.429</version>
+ <title>MediaBrowser.Model - Signed Edition</title>
+ <authors>Media Browser Team</authors>
+ <owners>ebr,Luke,scottisafool</owners>
+ <projectUrl>https://github.com/MediaBrowser/MediaBrowser</projectUrl>
+ <iconUrl>http://www.mb3admin.com/images/mb3icons1-1.png</iconUrl>
+ <requireLicenseAcceptance>false</requireLicenseAcceptance>
+ <description>Contains common model objects and interfaces used by all Media Browser solutions.</description>
+ <copyright>Copyright © Media Browser 2013</copyright>
+ <dependencies>
+ <group targetFramework=".NETFramework4.5"/>
+ <group targetFramework=".NETFramework3.5"/>
+ <group targetFramework=".NETPortable0.0-net45+sl4+wp71+win8"/>
+ </dependencies>
+ </metadata>
+ <files>
+ <file src="dllssigned\net45\MediaBrowser.Model.dll" target="lib\net45\MediaBrowser.Model.dll" />
+ </files>
+</package> \ No newline at end of file
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index 4ebea620d..a44bc2eab 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.410</version>
+ <version>3.0.429</version>
<title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
- <dependency id="MediaBrowser.Common" version="3.0.410" />
+ <dependency id="MediaBrowser.Common" version="3.0.429" />
</dependencies>
</metadata>
<files>
diff --git a/OpenSubtitlesHandler/OpenSubtitlesHandler.csproj b/OpenSubtitlesHandler/OpenSubtitlesHandler.csproj
index d1257d058..6180b8009 100644
--- a/OpenSubtitlesHandler/OpenSubtitlesHandler.csproj
+++ b/OpenSubtitlesHandler/OpenSubtitlesHandler.csproj
@@ -11,6 +11,7 @@
<AssemblyName>OpenSubtitlesHandler</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -126,4 +127,4 @@
<Target Name="AfterBuild">
</Target>
-->
-</Project> \ No newline at end of file
+</Project>
diff --git a/README.md b/README.md
index 7db6e79dd..84b097997 100644
--- a/README.md
+++ b/README.md
@@ -9,16 +9,16 @@ We have several client apps released and in production:
- [Android](https://play.google.com/store/apps/details?id=com.mb.android "Android")
- Html5
-- [iOS](https://itunes.apple.com/us/app/media-browser-for-ios/id705058087 "iOS")
+- [iPad](https://itunes.apple.com/us/app/media-browser-client/id879475585 "iPad")
+- [iPhone](https://itunes.apple.com/us/app/media-browser-for-ios/id705058087?mt=8 "iPhone")
- [Media Portal](http://www.team-mediaportal.com/ "Media Portal")
- [Roku](http://www.roku.com/channels/#!details/34503/media-browser "Roku")
- Windows 7/8 Desktop
- Windows Media Center
- [Windows Phone](http://www.windowsphone.com/s?appid=f4971ed9-f651-4bf6-84bb-94fd98613b86 "Windows Phone")
- [Windows 8](http://apps.microsoft.com/windows/en-us/app/media-browser/ad55a2f0-9897-47bd-8944-bed3aefd5d06 "Windows 8.1")
-- [Xbmc](http://addons.xbmc.org/show/plugin.video.xbmb3c "Xbmc")
+- [Xbmc](http://mediabrowser.tv/download/ "Xbmc")
-#### [Now with 60+ active contributors!](https://github.com/MediaBrowser/MediaBrowser/blob/master/CONTRIBUTORS.md "Now with 60+ active contributors!")
## New Users ##
@@ -33,7 +33,7 @@ If you're a new user looking to install Media Browser Server, please head over t
## Visit our community: ##
-http://mediabrowser3.com/community
+http://mediabrowser.tv/community
## Images