aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Api/ApiEntryPoint.cs36
-rw-r--r--MediaBrowser.Api/ChannelService.cs2
-rw-r--r--MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs19
-rw-r--r--MediaBrowser.Api/DefaultTheme/Models.cs2
-rw-r--r--MediaBrowser.Api/DisplayPreferencesService.cs12
-rw-r--r--MediaBrowser.Api/Images/ImageByNameService.cs90
-rw-r--r--MediaBrowser.Api/Images/ImageService.cs6
-rw-r--r--MediaBrowser.Api/ItemLookupService.cs27
-rw-r--r--MediaBrowser.Api/LocalizationService.cs8
-rw-r--r--MediaBrowser.Api/PackageService.cs4
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs4
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs4
-rw-r--r--MediaBrowser.Api/Playback/Hls/VideoHlsService.cs4
-rw-r--r--MediaBrowser.Api/Playback/Progressive/VideoService.cs14
-rw-r--r--MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs18
-rw-r--r--MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs53
-rw-r--r--MediaBrowser.Api/SearchService.cs12
-rw-r--r--MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs2
-rw-r--r--MediaBrowser.Api/UserLibrary/ItemsService.cs3
-rw-r--r--MediaBrowser.Api/UserLibrary/UserLibraryService.cs4
-rw-r--r--MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs2
-rw-r--r--MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs4
-rw-r--r--MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs4
-rw-r--r--MediaBrowser.Common.Implementations/BaseApplicationHost.cs1
-rw-r--r--MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs18
-rw-r--r--MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj3
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs32
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs30
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs6
-rw-r--r--MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs (renamed from MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerTask.cs)0
-rw-r--r--MediaBrowser.Common.Implementations/Security/MBRegistration.cs7
-rw-r--r--MediaBrowser.Common.Implementations/Security/RegRecord.cs11
-rw-r--r--MediaBrowser.Common.Implementations/Updates/InstallationManager.cs12
-rw-r--r--MediaBrowser.Common/IApplicationHost.cs15
-rw-r--r--MediaBrowser.Common/IDependencyContainer.cs15
-rw-r--r--MediaBrowser.Common/MediaBrowser.Common.csproj6
-rw-r--r--MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs98
-rw-r--r--MediaBrowser.Common/Net/HttpRequestOptions.cs17
-rw-r--r--MediaBrowser.Common/Net/IWebSocketConnection.cs12
-rw-r--r--MediaBrowser.Common/Net/WebSocketMessageInfo.cs16
-rw-r--r--MediaBrowser.Common/Plugins/BasePlugin.cs2
-rw-r--r--MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs16
-rw-r--r--MediaBrowser.Common/ScheduledTasks/IHasKey.cs7
-rw-r--r--MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs19
-rw-r--r--MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs10
-rw-r--r--MediaBrowser.Common/ScheduledTasks/ITaskManager.cs7
-rw-r--r--MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs2
-rw-r--r--MediaBrowser.Common/Updates/IInstallationManager.cs4
-rw-r--r--MediaBrowser.Common/Updates/InstallationEventArgs.cs6
-rw-r--r--MediaBrowser.Common/Updates/InstallationFailedEventArgs.cs9
-rw-r--r--MediaBrowser.Controller/Channels/ChannelAudioItem.cs2
-rw-r--r--MediaBrowser.Controller/Channels/ChannelCategoryItem.cs2
-rw-r--r--MediaBrowser.Controller/Channels/ChannelInfo.cs30
-rw-r--r--MediaBrowser.Controller/Channels/ChannelItemInfo.cs41
-rw-r--r--MediaBrowser.Controller/Channels/ChannelItemResult.cs12
-rw-r--r--MediaBrowser.Controller/Channels/ChannelItemType.cs9
-rw-r--r--MediaBrowser.Controller/Channels/ChannelMediaContentType.cs17
-rw-r--r--MediaBrowser.Controller/Channels/ChannelMediaInfo.cs26
-rw-r--r--MediaBrowser.Controller/Channels/ChannelMediaType.cs9
-rw-r--r--MediaBrowser.Controller/Channels/ChannelSearchInfo.cs7
-rw-r--r--MediaBrowser.Controller/Channels/ChannelVideoItem.cs2
-rw-r--r--MediaBrowser.Controller/Channels/IChannel.cs45
-rw-r--r--MediaBrowser.Controller/Channels/IChannelFactory.cs9
-rw-r--r--MediaBrowser.Controller/Channels/IChannelItem.cs9
-rw-r--r--MediaBrowser.Controller/Channels/IChannelManager.cs3
-rw-r--r--MediaBrowser.Controller/Channels/IChannelMediaItem.cs9
-rw-r--r--MediaBrowser.Controller/Channels/InternalChannelItemQuery.cs11
-rw-r--r--MediaBrowser.Controller/Chapters/ChapterResponse.cs19
-rw-r--r--MediaBrowser.Controller/Chapters/ChapterSearchRequest.cs29
-rw-r--r--MediaBrowser.Controller/Chapters/IChapterProvider.cs39
-rw-r--r--MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs7
-rw-r--r--MediaBrowser.Controller/Dlna/ControlRequest.cs14
-rw-r--r--MediaBrowser.Controller/Dlna/ControlResponse.cs18
-rw-r--r--MediaBrowser.Controller/Drawing/IImageProcessor.cs24
-rw-r--r--MediaBrowser.Controller/Drawing/ImageProcessorExtensions.cs25
-rw-r--r--MediaBrowser.Controller/Entities/TV/Episode.cs8
-rw-r--r--MediaBrowser.Controller/Library/IIntroProvider.cs16
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs16
-rw-r--r--MediaBrowser.Controller/Library/IMetadataFileSaver.cs14
-rw-r--r--MediaBrowser.Controller/Library/IMetadataSaver.cs10
-rw-r--r--MediaBrowser.Controller/Library/IUserManager.cs4
-rw-r--r--MediaBrowser.Controller/Library/IntroInfo.cs19
-rw-r--r--MediaBrowser.Controller/Library/LibraryManagerExtensions.cs22
-rw-r--r--MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs9
-rw-r--r--MediaBrowser.Controller/Library/PlaybackStopEventArgs.cs11
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs9
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvException.cs7
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvServiceStatusInfo.cs56
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvTunerInfo.cs61
-rw-r--r--MediaBrowser.Controller/LiveTv/RecordingStatusChangedEventArgs.cs (renamed from MediaBrowser.Controller/LiveTv/EventArgs.cs)0
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj29
-rw-r--r--MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs4
-rw-r--r--MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs2
-rw-r--r--MediaBrowser.Controller/Providers/DirectoryService.cs20
-rw-r--r--MediaBrowser.Controller/Providers/VideoContentType.cs19
-rw-r--r--MediaBrowser.Controller/Security/IEncryptionManager.cs20
-rw-r--r--MediaBrowser.Controller/Session/ISessionController.cs8
-rw-r--r--MediaBrowser.Controller/Subtitles/ISubtitleManager.cs50
-rw-r--r--MediaBrowser.Controller/Subtitles/ISubtitleProvider.cs39
-rw-r--r--MediaBrowser.Controller/Subtitles/SubtitleResponse.cs11
-rw-r--r--MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs29
-rw-r--r--MediaBrowser.Dlna/Didl/DidlBuilder.cs10
-rw-r--r--MediaBrowser.Dlna/MediaBrowser.Dlna.csproj8
-rw-r--r--MediaBrowser.Dlna/PlayTo/Device.cs4
-rw-r--r--MediaBrowser.Dlna/PlayTo/DeviceEventArgs.cs28
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlayToController.cs (renamed from MediaBrowser.Dlna/PlayTo/DlnaController.cs)36
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlaybackProgressEventArgs.cs9
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlaybackStartEventArgs.cs9
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlaybackStoppedEventArgs.cs9
-rw-r--r--MediaBrowser.Dlna/PlayTo/TRANSPORTSTATE.cs11
-rw-r--r--MediaBrowser.Dlna/PlayTo/uParser.cs5
-rw-r--r--MediaBrowser.Dlna/PlayTo/uParserObject.cs9
-rw-r--r--MediaBrowser.Dlna/Profiles/DefaultProfile.cs4
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Default.xml4
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml4
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml4
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml4
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml4
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml4
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml4
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml4
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml4
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml4
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml4
-rw-r--r--MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml4
-rw-r--r--MediaBrowser.Dlna/Ssdp/SsdpHandler.cs2
-rw-r--r--MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj15
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs9
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs17
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs61
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs69
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SubtitleTrackInfo.cs22
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs26
-rw-r--r--MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj311
-rw-r--r--MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj304
-rw-r--r--MediaBrowser.Model/ApiClient/GeneralCommandEventArgs.cs23
-rw-r--r--MediaBrowser.Model/ApiClient/IApiClient.cs64
-rw-r--r--MediaBrowser.Model/ApiClient/IServerEvents.cs57
-rw-r--r--MediaBrowser.Model/ApiClient/ServerEventArgs.cs177
-rw-r--r--MediaBrowser.Model/ApiClient/SessionUpdatesEventArgs.cs13
-rw-r--r--MediaBrowser.Model/Channels/ChannelItemQuery.cs48
-rw-r--r--MediaBrowser.Model/Channels/ChannelQuery.cs48
-rw-r--r--MediaBrowser.Model/Chapters/RemoteChapterInfo.cs18
-rw-r--r--MediaBrowser.Model/Chapters/RemoteChapterResult.cs42
-rw-r--r--MediaBrowser.Model/Configuration/EncodingQuality.cs10
-rw-r--r--MediaBrowser.Model/Configuration/ImageOption.cs29
-rw-r--r--MediaBrowser.Model/Configuration/ImageSavingConvention.cs8
-rw-r--r--MediaBrowser.Model/Configuration/LiveTvOptions.cs7
-rw-r--r--MediaBrowser.Model/Configuration/MetadataOptions.cs47
-rw-r--r--MediaBrowser.Model/Configuration/MetadataPlugin.cs45
-rw-r--r--MediaBrowser.Model/Configuration/MetadataPluginSummary.cs32
-rw-r--r--MediaBrowser.Model/Configuration/MetadataPluginType.cs15
-rw-r--r--MediaBrowser.Model/Configuration/NotificationOption.cs54
-rw-r--r--MediaBrowser.Model/Configuration/NotificationOptions.cs90
-rw-r--r--MediaBrowser.Model/Configuration/NotificationType.cs20
-rw-r--r--MediaBrowser.Model/Configuration/PathSubstitution.cs8
-rw-r--r--MediaBrowser.Model/Configuration/SendToUserType.cs9
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs31
-rw-r--r--MediaBrowser.Model/Configuration/SubtitleOptions.cs21
-rw-r--r--MediaBrowser.Model/Configuration/TvFileOrganizationOptions.cs (renamed from MediaBrowser.Model/Configuration/AutoOrganize.cs)0
-rw-r--r--MediaBrowser.Model/Configuration/UnratedItem.cs16
-rw-r--r--MediaBrowser.Model/Configuration/UserConfiguration.cs14
-rw-r--r--MediaBrowser.Model/Dlna/AudioOptions.cs33
-rw-r--r--MediaBrowser.Model/Dlna/CodecProfile.cs61
-rw-r--r--MediaBrowser.Model/Dlna/CodecType.cs9
-rw-r--r--MediaBrowser.Model/Dlna/ConditionProcessor.cs4
-rw-r--r--MediaBrowser.Model/Dlna/ContainerProfile.cs8
-rw-r--r--MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs91
-rw-r--r--MediaBrowser.Model/Dlna/DeviceIdentification.cs23
-rw-r--r--MediaBrowser.Model/Dlna/DeviceProfile.cs205
-rw-r--r--MediaBrowser.Model/Dlna/DeviceProfileInfo.cs6
-rw-r--r--MediaBrowser.Model/Dlna/DeviceProfileType.cs8
-rw-r--r--MediaBrowser.Model/Dlna/DirectPlayProfile.cs38
-rw-r--r--MediaBrowser.Model/Dlna/DlnaFlags.cs21
-rw-r--r--MediaBrowser.Model/Dlna/DlnaMaps.cs25
-rw-r--r--MediaBrowser.Model/Dlna/DlnaProfileType.cs9
-rw-r--r--MediaBrowser.Model/Dlna/Filter.cs7
-rw-r--r--MediaBrowser.Model/Dlna/HeaderMatchType.cs9
-rw-r--r--MediaBrowser.Model/Dlna/HttpHeaderInfo.cs16
-rw-r--r--MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs17
-rw-r--r--MediaBrowser.Model/Dlna/ProfileCondition.cs24
-rw-r--r--MediaBrowser.Model/Dlna/ProfileConditionType.cs10
-rw-r--r--MediaBrowser.Model/Dlna/ProfileConditionValue.cs19
-rw-r--r--MediaBrowser.Model/Dlna/ResponseProfile.cs24
-rw-r--r--MediaBrowser.Model/Dlna/SearchCriteria.cs9
-rw-r--r--MediaBrowser.Model/Dlna/SearchType.cs11
-rw-r--r--MediaBrowser.Model/Dlna/StreamBuilder.cs359
-rw-r--r--MediaBrowser.Model/Dlna/StreamInfo.cs130
-rw-r--r--MediaBrowser.Model/Dlna/TranscodeSeekInfo.cs8
-rw-r--r--MediaBrowser.Model/Dlna/TranscodingProfile.cs14
-rw-r--r--MediaBrowser.Model/Dlna/VideoOptions.cs17
-rw-r--r--MediaBrowser.Model/Dlna/XmlAttribute.cs13
-rw-r--r--MediaBrowser.Model/Drawing/DrawingUtils.cs122
-rw-r--r--MediaBrowser.Model/Drawing/ImageSize.cs83
-rw-r--r--MediaBrowser.Model/Dto/BaseItemDto.cs26
-rw-r--r--MediaBrowser.Model/Dto/BaseItemPerson.cs13
-rw-r--r--MediaBrowser.Model/Dto/ChapterInfoDto.cs4
-rw-r--r--MediaBrowser.Model/Dto/IItemDto.cs6
-rw-r--r--MediaBrowser.Model/Dto/ImageInfo.cs2
-rw-r--r--MediaBrowser.Model/Dto/ImageOptions.cs2
-rw-r--r--MediaBrowser.Model/Dto/ItemByNameCounts.cs2
-rw-r--r--MediaBrowser.Model/Dto/MediaSourceInfo.cs86
-rw-r--r--MediaBrowser.Model/Dto/MediaVersionInfo.cs42
-rw-r--r--MediaBrowser.Model/Dto/RatingType.cs8
-rw-r--r--MediaBrowser.Model/Dto/RecommendationDto.cs15
-rw-r--r--MediaBrowser.Model/Dto/RecommendationType.cs17
-rw-r--r--MediaBrowser.Model/Dto/StreamOptions.cs112
-rw-r--r--MediaBrowser.Model/Dto/StudioDto.cs4
-rw-r--r--MediaBrowser.Model/Dto/SubtitleDownloadOptions.cs17
-rw-r--r--MediaBrowser.Model/Dto/UserDto.cs4
-rw-r--r--MediaBrowser.Model/Dto/VideoStreamOptions.cs99
-rw-r--r--MediaBrowser.Model/Entities/BaseItemInfo.cs39
-rw-r--r--MediaBrowser.Model/Entities/DisplayPreferences.cs38
-rw-r--r--MediaBrowser.Model/Entities/EmptyRequestResult.cs (renamed from MediaBrowser.Model/Entities/RequestResult.cs)0
-rw-r--r--MediaBrowser.Model/Entities/IHasProviderIds.cs101
-rw-r--r--MediaBrowser.Model/Entities/IsoType.cs17
-rw-r--r--MediaBrowser.Model/Entities/LibraryUpdateInfo.cs20
-rw-r--r--MediaBrowser.Model/Entities/MediaInfo.cs26
-rw-r--r--MediaBrowser.Model/Entities/MediaStream.cs62
-rw-r--r--MediaBrowser.Model/Entities/MediaStreamType.cs25
-rw-r--r--MediaBrowser.Model/Entities/MediaUrl.cs6
-rw-r--r--MediaBrowser.Model/Entities/PackageReviewInfo.cs4
-rw-r--r--MediaBrowser.Model/Entities/ProviderIdsExtensions.cs103
-rw-r--r--MediaBrowser.Model/Entities/ScrollDirection.cs17
-rw-r--r--MediaBrowser.Model/Entities/SortOrder.cs17
-rw-r--r--MediaBrowser.Model/Entities/VideoSize.cs8
-rw-r--r--MediaBrowser.Model/Entities/VideoType.cs15
-rw-r--r--MediaBrowser.Model/Events/GenericEventArgs.cs (renamed from MediaBrowser.Common/Events/GenericEventArgs.cs)2
-rw-r--r--MediaBrowser.Model/FileOrganization/EpisodeFileOrganizationRequest.cs17
-rw-r--r--MediaBrowser.Model/FileOrganization/FileOrganizationResult.cs14
-rw-r--r--MediaBrowser.Model/FileOrganization/FileOrganizationResultQuery.cs (renamed from MediaBrowser.Model/FileOrganization/FileOrganizationQuery.cs)15
-rw-r--r--MediaBrowser.Model/FileOrganization/FileOrganizerType.cs9
-rw-r--r--MediaBrowser.Model/FileOrganization/FileSortingStatus.cs9
-rw-r--r--MediaBrowser.Model/Globalization/CountryInfo.cs6
-rw-r--r--MediaBrowser.Model/Globalization/LocalizatonOption.cs8
-rw-r--r--MediaBrowser.Model/IO/FileSystemEntryInfo.cs23
-rw-r--r--MediaBrowser.Model/IO/FileSystemEntryType.cs25
-rw-r--r--MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs108
-rw-r--r--MediaBrowser.Model/LiveTv/ChannelInfoDto.cs4
-rw-r--r--MediaBrowser.Model/LiveTv/DayPattern.cs9
-rw-r--r--MediaBrowser.Model/LiveTv/GuideInfo.cs19
-rw-r--r--MediaBrowser.Model/LiveTv/LiveTvInfo.cs49
-rw-r--r--MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs139
-rw-r--r--MediaBrowser.Model/LiveTv/LiveTvServiceStatus.cs8
-rw-r--r--MediaBrowser.Model/LiveTv/LiveTvTunerInfoDto.cs66
-rw-r--r--MediaBrowser.Model/LiveTv/LiveTvTunerStatus.cs10
-rw-r--r--MediaBrowser.Model/LiveTv/ProgramAudio.cs11
-rw-r--r--MediaBrowser.Model/LiveTv/ProgramInfoDto.cs15
-rw-r--r--MediaBrowser.Model/LiveTv/ProgramQuery.cs27
-rw-r--r--MediaBrowser.Model/LiveTv/RecommendedProgramQuery.cs29
-rw-r--r--MediaBrowser.Model/LiveTv/RecordingGroupQuery.cs11
-rw-r--r--MediaBrowser.Model/LiveTv/RecordingInfoDto.cs6
-rw-r--r--MediaBrowser.Model/LiveTv/RecordingQuery.cs43
-rw-r--r--MediaBrowser.Model/LiveTv/RecordingStatus.cs7
-rw-r--r--MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs4
-rw-r--r--MediaBrowser.Model/LiveTv/SeriesTimerQuery.cs19
-rw-r--r--MediaBrowser.Model/LiveTv/TimerInfoDto.cs108
-rw-r--r--MediaBrowser.Model/LiveTv/TimerQuery.cs17
-rw-r--r--MediaBrowser.Model/MediaBrowser.Model.csproj101
-rw-r--r--MediaBrowser.Model/MediaInfo/AudioCodec.cs8
-rw-r--r--MediaBrowser.Model/MediaInfo/BlurayDiscInfo.cs7
-rw-r--r--MediaBrowser.Model/MediaInfo/Container.cs8
-rw-r--r--MediaBrowser.Model/MediaInfo/SubtitleFormat.cs7
-rw-r--r--MediaBrowser.Model/MediaInfo/TransportStreamTimestamp.cs9
-rw-r--r--MediaBrowser.Model/MediaInfo/VideoCodec.cs12
-rw-r--r--MediaBrowser.Model/News/NewsChannel.cs12
-rw-r--r--MediaBrowser.Model/News/NewsItem.cs16
-rw-r--r--MediaBrowser.Model/News/NewsQuery.cs9
-rw-r--r--MediaBrowser.Model/Notifications/Notification.cs70
-rw-r--r--MediaBrowser.Model/Notifications/NotificationRequest.cs42
-rw-r--r--MediaBrowser.Model/Notifications/NotificationServiceInfo.cs8
-rw-r--r--MediaBrowser.Model/Notifications/NotificationTypeInfo.cs28
-rw-r--r--MediaBrowser.Model/Plugins/BasePluginConfiguration.cs24
-rw-r--r--MediaBrowser.Model/Plugins/PluginInfo.cs20
-rw-r--r--MediaBrowser.Model/Providers/ExternalIdInfo.cs15
-rw-r--r--MediaBrowser.Model/Providers/ExternalUrl.cs17
-rw-r--r--MediaBrowser.Model/Providers/RemoteImageQuery.cs15
-rw-r--r--MediaBrowser.Model/Providers/RemoteImageResult.cs12
-rw-r--r--MediaBrowser.Model/Providers/RemoteSubtitleInfo.cs19
-rw-r--r--MediaBrowser.Model/Querying/AllThemeMediaResult.cs (renamed from MediaBrowser.Model/Querying/ThemeSongsResult.cs)17
-rw-r--r--MediaBrowser.Model/Querying/EpisodeQuery.cs20
-rw-r--r--MediaBrowser.Model/Querying/ItemFilter.cs4
-rw-r--r--MediaBrowser.Model/Querying/NextUpQuery.cs34
-rw-r--r--MediaBrowser.Model/Querying/SeasonQuery.cs22
-rw-r--r--MediaBrowser.Model/Querying/SimilarItemsByNameQuery.cs29
-rw-r--r--MediaBrowser.Model/Querying/SimilarItemsQuery.cs27
-rw-r--r--MediaBrowser.Model/Querying/ThemeMediaResult.cs15
-rw-r--r--MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs35
-rw-r--r--MediaBrowser.Model/Search/SearchHint.cs6
-rw-r--r--MediaBrowser.Model/Session/ClientCapabilities.cs16
-rw-r--r--MediaBrowser.Model/Session/GeneralCommand.cs35
-rw-r--r--MediaBrowser.Model/Session/GeneralCommandType.cs38
-rw-r--r--MediaBrowser.Model/Session/PlayCommand.cs29
-rw-r--r--MediaBrowser.Model/Session/PlayMethod.cs9
-rw-r--r--MediaBrowser.Model/Session/PlayRequest.cs27
-rw-r--r--MediaBrowser.Model/Session/PlaybackProgressInfo.cs (renamed from MediaBrowser.Model/Session/PlaybackReports.cs)63
-rw-r--r--MediaBrowser.Model/Session/PlaybackStartInfo.cs21
-rw-r--r--MediaBrowser.Model/Session/PlaybackStopInfo.cs40
-rw-r--r--MediaBrowser.Model/Session/PlayerStateInfo.cs59
-rw-r--r--MediaBrowser.Model/Session/PlaystateCommand.cs13
-rw-r--r--MediaBrowser.Model/Session/PlaystateRequest.cs15
-rw-r--r--MediaBrowser.Model/Session/SessionInfoDto.cs88
-rw-r--r--MediaBrowser.Model/Session/SessionUserInfo.cs19
-rw-r--r--MediaBrowser.Model/Tasks/TaskInfo.cs2
-rw-r--r--MediaBrowser.Model/Tasks/TaskResult.cs2
-rw-r--r--MediaBrowser.Model/Themes/AppTheme.cs7
-rw-r--r--MediaBrowser.Model/Themes/AppThemeInfo.cs9
-rw-r--r--MediaBrowser.Model/Updates/InstallationInfo.cs2
-rw-r--r--MediaBrowser.Model/Updates/PackageVersionInfo.cs4
-rw-r--r--MediaBrowser.Model/Web/QueryStringDictionary.cs63
-rw-r--r--MediaBrowser.Mono.sln14
-rw-r--r--MediaBrowser.Mono.userprefs2
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj7
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs16
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs67
-rw-r--r--MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs160
-rw-r--r--MediaBrowser.Providers/Movies/MovieDbProvider.cs2
-rw-r--r--MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs277
-rw-r--r--MediaBrowser.Providers/Subtitles/SubtitleManager.cs143
-rw-r--r--MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelManager.cs164
-rw-r--r--MediaBrowser.Server.Implementations/Collections/CollectionManager.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs27
-rw-r--r--MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs31
-rw-r--r--MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs12
-rw-r--r--MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Dto/DtoService.cs34
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs10
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs (renamed from MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifier.cs)126
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs21
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/DelReceiveWebRequest.cs6
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/GetSwaggerResource.cs17
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs2
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/ServerLogFactory.cs46
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs46
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SwaggerService.cs14
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/ItemResolver.cs (renamed from MediaBrowser.Server.Implementations/Library/Resolvers/BaseItemResolver.cs)0
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserManager.cs1
-rw-r--r--MediaBrowser.Server.Implementations/Library/Validators/BoxSetPostScanTask.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/Validators/CountHelpers.cs171
-rw-r--r--MediaBrowser.Server.Implementations/Library/Validators/PeoplePostScanTask.cs44
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs14
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/da.json30
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json2
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json2
-rw-r--r--MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs48
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ar.json107
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ca.json113
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/cs.json109
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/da.json715
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/de.json117
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/el.json167
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/en_GB.json107
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/en_US.json107
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/es.json103
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/es_MX.json107
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/fr.json199
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/he.json105
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/it.json105
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/kk.json103
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ms.json107
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/nb.json107
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/nl.json117
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json113
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json159
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ru.json181
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/server.json137
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/sv.json111
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json105
-rw-r--r--MediaBrowser.Server.Implementations/Localization/countries.json1
-rw-r--r--MediaBrowser.Server.Implementations/Localization/cultures.json1
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj15
-rw-r--r--MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs7
-rw-r--r--MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs18
-rw-r--r--MediaBrowser.Server.Implementations/Roku/RokuSessionController.cs10
-rw-r--r--MediaBrowser.Server.Implementations/Security/EncryptionManager.cs36
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionManager.cs69
-rw-r--r--MediaBrowser.Server.Implementations/Session/WebSocketController.cs12
-rw-r--r--MediaBrowser.Server.Implementations/Sorting/IsPlayedComparer.cs58
-rw-r--r--MediaBrowser.Server.Implementations/Sorting/IsUnplayedComparer.cs51
-rw-r--r--MediaBrowser.Server.Mono/Native/NativeApp.cs5
-rw-r--r--MediaBrowser.ServerApplication/ApplicationHost.cs27
-rw-r--r--MediaBrowser.ServerApplication/EntryPoints/KeepServerAwake.cs57
-rw-r--r--MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs81
-rw-r--r--MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs135
-rw-r--r--MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs2
-rw-r--r--MediaBrowser.ServerApplication/MainStartup.cs3
-rw-r--r--MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj1
-rw-r--r--MediaBrowser.ServerApplication/Native/BrowserLauncher.cs2
-rw-r--r--MediaBrowser.ServerApplication/Native/NativeApp.cs29
-rw-r--r--MediaBrowser.Tests/MediaBrowser.Tests.csproj18
-rw-r--r--MediaBrowser.Tests/MediaEncoding/Subtitles/SrtParserTests.cs108
-rw-r--r--MediaBrowser.Tests/MediaEncoding/Subtitles/SsaParserTests.cs59
-rw-r--r--MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/data.ssa23
-rw-r--r--MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/expected.vtt32
-rw-r--r--MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/unit.srt44
-rw-r--r--MediaBrowser.Tests/MediaEncoding/Subtitles/VttWriterTest.cs103
-rw-r--r--MediaBrowser.WebDashboard/Api/DashboardService.cs4
-rw-r--r--MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj70
-rw-r--r--MediaBrowser.sln16
-rw-r--r--Nuget/MediaBrowser.Common.Internal.nuspec6
-rw-r--r--Nuget/MediaBrowser.Common.nuspec2
-rw-r--r--Nuget/MediaBrowser.Server.Core.nuspec4
-rw-r--r--OpenSubtitlesHandler/Console/OSHConsole.cs92
-rw-r--r--OpenSubtitlesHandler/Interfaces/IMethodResponse.cs62
-rw-r--r--OpenSubtitlesHandler/Interfaces/MethodResponseAttr.cs40
-rw-r--r--OpenSubtitlesHandler/Languages/DetectLanguageResult.cs31
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseAddComment.cs32
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseAddRequest.cs35
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseAutoUpdate.cs60
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash.cs37
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash2.cs37
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseCheckSubHash.cs38
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseDetectLanguage.cs37
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseError.cs36
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseGetAvailableTranslations.cs37
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseGetComments.cs41
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseGetSubLanguages.cs39
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseGetTranslation.cs37
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovie.cs37
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovieHash.cs38
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseLogIn.cs40
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseMovieDetails.cs73
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseMovieSearch.cs43
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseNoOperation.cs53
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongImdbMovie.cs33
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongMovieHash.cs34
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseSearchToMail.cs32
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseServerInfo.cs132
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleDownload.cs44
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleSearch.cs46
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitlesVote.cs44
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseTryUploadSubtitles.cs40
-rw-r--r--OpenSubtitlesHandler/MethodResponses/MethodResponseUploadSubtitles.cs39
-rw-r--r--OpenSubtitlesHandler/Methods Implemeted.txt39
-rw-r--r--OpenSubtitlesHandler/MovieHasher.cs59
-rw-r--r--OpenSubtitlesHandler/Movies/CheckMovieHash2Data.cs42
-rw-r--r--OpenSubtitlesHandler/Movies/CheckMovieHash2Result.cs37
-rw-r--r--OpenSubtitlesHandler/Movies/CheckMovieHashResult.cs42
-rw-r--r--OpenSubtitlesHandler/Movies/InsertMovieHashParameters.cs38
-rw-r--r--OpenSubtitlesHandler/Movies/MovieSearchResult.cs41
-rw-r--r--OpenSubtitlesHandler/Movies/SearchToMailMovieParameter.cs30
-rw-r--r--OpenSubtitlesHandler/OpenSubtitles.cs2731
-rw-r--r--OpenSubtitlesHandler/OpenSubtitlesHandler.csproj129
-rw-r--r--OpenSubtitlesHandler/OtherTypes/GetAvailableTranslationsResult.cs39
-rw-r--r--OpenSubtitlesHandler/OtherTypes/GetCommentsResult.cs37
-rw-r--r--OpenSubtitlesHandler/Properties/AssemblyInfo.cs36
-rw-r--r--OpenSubtitlesHandler/Readme.txt20
-rw-r--r--OpenSubtitlesHandler/SubtitleTypes/CheckSubHashResult.cs31
-rw-r--r--OpenSubtitlesHandler/SubtitleTypes/SubtitleDownloadResult.cs44
-rw-r--r--OpenSubtitlesHandler/SubtitleTypes/SubtitleLanguage.cs39
-rw-r--r--OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchParameters.cs80
-rw-r--r--OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchResult.cs137
-rw-r--r--OpenSubtitlesHandler/SubtitleTypes/TryUploadSubtitlesParameters.cs48
-rw-r--r--OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleInfoParameter.cs46
-rw-r--r--OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleParameters.cs53
-rw-r--r--OpenSubtitlesHandler/Utilities.cs247
-rw-r--r--OpenSubtitlesHandler/XML-RPC/Docs/XML-RPC.txt225
-rw-r--r--OpenSubtitlesHandler/XML-RPC/Enums/XmlRpcValueType.cs25
-rw-r--r--OpenSubtitlesHandler/XML-RPC/Types/XmlRpcMethodCall.cs63
-rw-r--r--OpenSubtitlesHandler/XML-RPC/Values/IXmlRpcValue.cs37
-rw-r--r--OpenSubtitlesHandler/XML-RPC/Values/XmlRpcStructMember.cs44
-rw-r--r--OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueArray.cs121
-rw-r--r--OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueBasic.cs100
-rw-r--r--OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueStruct.cs43
-rw-r--r--OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs323
-rw-r--r--README.md2
468 files changed, 16572 insertions, 4019 deletions
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs
index f35ade432..9b04ec011 100644
--- a/MediaBrowser.Api/ApiEntryPoint.cs
+++ b/MediaBrowser.Api/ApiEntryPoint.cs
@@ -71,8 +71,7 @@ namespace MediaBrowser.Api
/// </summary>
private void DeleteEncodedMediaCache()
{
- foreach (var file in Directory.EnumerateFiles(_appPaths.TranscodingTempPath)
- .Where(i => EntityResolutionHelper.VideoFileExtensions.Contains(Path.GetExtension(i)))
+ foreach (var file in Directory.EnumerateFiles(_appPaths.TranscodingTempPath, "*", SearchOption.AllDirectories)
.ToList())
{
File.Delete(file);
@@ -116,11 +115,10 @@ namespace MediaBrowser.Api
/// <param name="path">The path.</param>
/// <param name="type">The type.</param>
/// <param name="process">The process.</param>
- /// <param name="isVideo">if set to <c>true</c> [is video].</param>
/// <param name="startTimeTicks">The start time ticks.</param>
/// <param name="sourcePath">The source path.</param>
/// <param name="deviceId">The device id.</param>
- public void OnTranscodeBeginning(string path, TranscodingJobType type, Process process, bool isVideo, long? startTimeTicks, string sourcePath, string deviceId)
+ public void OnTranscodeBeginning(string path, TranscodingJobType type, Process process, long? startTimeTicks, string sourcePath, string deviceId)
{
lock (_activeTranscodingJobs)
{
@@ -130,7 +128,6 @@ namespace MediaBrowser.Api
Path = path,
Process = process,
ActiveRequestCount = 1,
- IsVideo = isVideo,
StartTimeTicks = startTimeTicks,
SourcePath = sourcePath,
DeviceId = deviceId
@@ -261,7 +258,7 @@ namespace MediaBrowser.Api
{
// This is really only needed for HLS.
// Progressive streams can stop on their own reliably
- jobs.AddRange(_activeTranscodingJobs.Where(i => isVideo == i.IsVideo && string.Equals(deviceId, i.DeviceId, StringComparison.OrdinalIgnoreCase)));
+ jobs.AddRange(_activeTranscodingJobs.Where(i => string.Equals(deviceId, i.DeviceId, StringComparison.OrdinalIgnoreCase)));
}
foreach (var job in jobs)
@@ -325,37 +322,15 @@ namespace MediaBrowser.Api
}
}
- // Determine if it exited successfully
- var hasExitedSuccessfully = false;
-
- try
- {
- hasExitedSuccessfully = process.ExitCode == 0;
- }
- catch (InvalidOperationException)
- {
-
- }
- catch (NotSupportedException)
- {
-
- }
-
// Dispose the process
process.Dispose();
- // If it didn't complete successfully cleanup the partial files
- // Also don't cache output from resume points
- // Also don't cache video
- if (!hasExitedSuccessfully || job.StartTimeTicks.HasValue || job.IsVideo)
- {
- DeletePartialStreamFiles(job.Path, job.Type, 0, 1500);
- }
+ DeletePartialStreamFiles(job.Path, job.Type, 0, 1500);
}
private async void DeletePartialStreamFiles(string path, TranscodingJobType jobType, int retryCount, int delayMs)
{
- if (retryCount >= 5)
+ if (retryCount >= 10)
{
return;
}
@@ -455,7 +430,6 @@ namespace MediaBrowser.Api
/// <value>The kill timer.</value>
public Timer KillTimer { get; set; }
- public bool IsVideo { get; set; }
public long? StartTimeTicks { get; set; }
public string SourcePath { get; set; }
public string DeviceId { get; set; }
diff --git a/MediaBrowser.Api/ChannelService.cs b/MediaBrowser.Api/ChannelService.cs
index a0795c14d..9fa4eec4a 100644
--- a/MediaBrowser.Api/ChannelService.cs
+++ b/MediaBrowser.Api/ChannelService.cs
@@ -67,7 +67,7 @@ namespace MediaBrowser.Api
[ApiMember(Name = "SortOrder", Description = "Sort Order - Ascending,Descending", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public SortOrder? SortOrder { get; set; }
- [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsRecentlyAdded, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Filters { get; set; }
[ApiMember(Name = "SortBy", Description = "Optional. Specify one or more sort orders, comma delimeted. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
diff --git a/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs b/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs
index c9c4cbc43..6acecd342 100644
--- a/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs
+++ b/MediaBrowser.Api/DefaultTheme/DefaultThemeService.cs
@@ -24,6 +24,8 @@ namespace MediaBrowser.Api.DefaultTheme
[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")]
@@ -49,6 +51,8 @@ namespace MediaBrowser.Api.DefaultTheme
[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")]
@@ -71,6 +75,8 @@ namespace MediaBrowser.Api.DefaultTheme
[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")]
@@ -224,7 +230,7 @@ namespace MediaBrowser.Api.DefaultTheme
{
var user = _userManager.GetUserById(request.UserId);
- var items = user.RootFolder.GetRecursiveChildren(user, i => i is Game || i is GameSystem)
+ 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();
@@ -280,7 +286,7 @@ namespace MediaBrowser.Api.DefaultTheme
var user = _userManager.GetUserById(request.UserId);
- var series = user.RootFolder.GetRecursiveChildren(user)
+ var series = GetAllLibraryItems(user.Id, _userManager, _libraryManager, request.ParentId)
.OfType<Series>()
.ToList();
@@ -403,7 +409,8 @@ namespace MediaBrowser.Api.DefaultTheme
{
var user = _userManager.GetUserById(request.UserId);
- var items = user.RootFolder.GetRecursiveChildren(user, i => i is Movie || i is Trailer || i is BoxSet)
+ 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();
@@ -556,7 +563,7 @@ namespace MediaBrowser.Api.DefaultTheme
// Avoid implicitly captured closure
var currentUserId1 = user.Id;
-
+
view.LatestMovies = movies
.OrderByDescending(i => i.DateCreated)
.Where(i => !_userDataManager.GetUserData(currentUserId1, i.GetUserDataKey()).Played)
@@ -622,9 +629,9 @@ namespace MediaBrowser.Api.DefaultTheme
{
var tag = _imageProcessor.GetImageCacheTag(item, imageType);
- if (tag.HasValue)
+ if (tag != null)
{
- stub.ImageTag = tag.Value;
+ stub.ImageTag = tag;
}
}
catch (Exception ex)
diff --git a/MediaBrowser.Api/DefaultTheme/Models.cs b/MediaBrowser.Api/DefaultTheme/Models.cs
index f261a9aff..6cc7af499 100644
--- a/MediaBrowser.Api/DefaultTheme/Models.cs
+++ b/MediaBrowser.Api/DefaultTheme/Models.cs
@@ -9,7 +9,7 @@ namespace MediaBrowser.Api.DefaultTheme
{
public string Name { get; set; }
public string Id { get; set; }
- public Guid ImageTag { get; set; }
+ public string ImageTag { get; set; }
public ImageType ImageType { get; set; }
}
diff --git a/MediaBrowser.Api/DisplayPreferencesService.cs b/MediaBrowser.Api/DisplayPreferencesService.cs
index 4060b42b4..206f5bf7b 100644
--- a/MediaBrowser.Api/DisplayPreferencesService.cs
+++ b/MediaBrowser.Api/DisplayPreferencesService.cs
@@ -1,5 +1,4 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Serialization;
using ServiceStack;
@@ -77,14 +76,7 @@ namespace MediaBrowser.Api
/// <param name="request">The request.</param>
public object Get(GetDisplayPreferences request)
{
- Guid displayPreferencesId;
-
- if (!Guid.TryParse(request.Id, out displayPreferencesId))
- {
- displayPreferencesId = request.Id.GetMD5();
- }
-
- var result = _displayPreferencesManager.GetDisplayPreferences(displayPreferencesId, request.UserId, request.Client);
+ var result = _displayPreferencesManager.GetDisplayPreferences(request.Id, request.UserId, request.Client);
return ToOptimizedSerializedResultUsingCache(result);
}
diff --git a/MediaBrowser.Api/Images/ImageByNameService.cs b/MediaBrowser.Api/Images/ImageByNameService.cs
index 44a69f6de..6dda2ae7a 100644
--- a/MediaBrowser.Api/Images/ImageByNameService.cs
+++ b/MediaBrowser.Api/Images/ImageByNameService.cs
@@ -1,8 +1,10 @@
using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using ServiceStack;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -70,6 +72,32 @@ namespace MediaBrowser.Api.Images
public string Theme { get; set; }
}
+ [Route("/Images/MediaInfo", "GET")]
+ [Api(Description = "Gets all media info image by name")]
+ public class GetMediaInfoImages : IReturn<List<ImageByNameInfo>>
+ {
+ }
+
+ [Route("/Images/Ratings", "GET")]
+ [Api(Description = "Gets all rating images by name")]
+ public class GetRatingImages : IReturn<List<ImageByNameInfo>>
+ {
+ }
+
+ [Route("/Images/General", "GET")]
+ [Api(Description = "Gets all general images by name")]
+ public class GetGeneralImages : IReturn<List<ImageByNameInfo>>
+ {
+ }
+
+ public class ImageByNameInfo
+ {
+ public string Name { get; set; }
+ public string Theme { get; set; }
+ public long FileLength { get; set; }
+ public string Format { get; set; }
+ }
+
/// <summary>
/// Class ImageByNameService
/// </summary>
@@ -89,6 +117,60 @@ namespace MediaBrowser.Api.Images
_appPaths = appPaths;
}
+ public object Get(GetMediaInfoImages request)
+ {
+ return ToOptimizedResult(GetImageList(_appPaths.MediaInfoImagesPath));
+ }
+
+ public object Get(GetRatingImages request)
+ {
+ return ToOptimizedResult(GetImageList(_appPaths.RatingsPath));
+ }
+
+ public object Get(GetGeneralImages request)
+ {
+ return ToOptimizedResult(GetImageList(_appPaths.GeneralPath));
+ }
+
+ private List<ImageByNameInfo> GetImageList(string path)
+ {
+ try
+ {
+ return new DirectoryInfo(path)
+ .GetFiles("*", SearchOption.AllDirectories)
+ .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.Ordinal))
+ .Select(i => new ImageByNameInfo
+ {
+ Name = Path.GetFileNameWithoutExtension(i.FullName),
+ FileLength = i.Length,
+ Theme = GetThemeName(i.FullName, path),
+ Format = i.Extension.ToLower().TrimStart('.')
+ })
+ .OrderBy(i => i.Name)
+ .ToList();
+ }
+ catch (DirectoryNotFoundException)
+ {
+ return new List<ImageByNameInfo>();
+ }
+ }
+
+ private string GetThemeName(string path, string rootImagePath)
+ {
+ var parentName = Path.GetDirectoryName(path);
+
+ if (string.Equals(parentName, rootImagePath, StringComparison.OrdinalIgnoreCase))
+ {
+ return null;
+ }
+
+ parentName = Path.GetFileName(parentName);
+
+ return string.Equals(parentName, "all", StringComparison.OrdinalIgnoreCase) ?
+ null :
+ parentName;
+ }
+
/// <summary>
/// Gets the specified request.
/// </summary>
@@ -118,7 +200,8 @@ namespace MediaBrowser.Api.Images
if (Directory.Exists(themeFolder))
{
- var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(themeFolder, request.Name + i))
+ var path = BaseItem.SupportedImageExtensions
+ .Select(i => Path.Combine(themeFolder, request.Name + i))
.FirstOrDefault(File.Exists);
if (!string.IsNullOrEmpty(path))
@@ -134,7 +217,8 @@ namespace MediaBrowser.Api.Images
// Avoid implicitly captured closure
var currentRequest = request;
- var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(allFolder, currentRequest.Name + i))
+ var path = BaseItem.SupportedImageExtensions
+ .Select(i => Path.Combine(allFolder, currentRequest.Name + i))
.FirstOrDefault(File.Exists);
if (!string.IsNullOrEmpty(path))
@@ -175,7 +259,7 @@ namespace MediaBrowser.Api.Images
var path = BaseItem.SupportedImageExtensions.Select(i => Path.Combine(allFolder, currentRequest.Name + i))
.FirstOrDefault(File.Exists);
-
+
if (!string.IsNullOrEmpty(path))
{
return ToStaticFileResult(path);
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs
index a5bb291ae..a760819d6 100644
--- a/MediaBrowser.Api/Images/ImageService.cs
+++ b/MediaBrowser.Api/Images/ImageService.cs
@@ -1,5 +1,4 @@
-using System.Globalization;
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
@@ -14,6 +13,7 @@ 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;
@@ -548,7 +548,7 @@ namespace MediaBrowser.Api.Images
var contentType = GetMimeType(request.Format, imageInfo.Path);
- var cacheGuid = _imageProcessor.GetImageCacheTag(item, request.Type, imageInfo.Path, originalFileImageDateModified, supportedImageEnhancers);
+ var cacheGuid = new Guid(_imageProcessor.GetImageCacheTag(item, request.Type, imageInfo.Path, originalFileImageDateModified, supportedImageEnhancers));
TimeSpan? cacheDuration = null;
diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs
index b600c3b46..86fdd6da8 100644
--- a/MediaBrowser.Api/ItemLookupService.cs
+++ b/MediaBrowser.Api/ItemLookupService.cs
@@ -1,13 +1,13 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller;
-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.Providers;
+using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using ServiceStack;
@@ -32,6 +32,16 @@ namespace MediaBrowser.Api
public string Id { get; set; }
}
+ [Route("/Items/{Id}/RemoteSearch/Subtitles/{Language}", "GET")]
+ public class SearchRemoteSubtitles : IReturn<List<RemoteSubtitleInfo>>
+ {
+ [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Id { get; set; }
+
+ [ApiMember(Name = "Language", Description = "Language", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string Language { get; set; }
+ }
+
[Route("/Items/RemoteSearch/Movie", "POST")]
[Api(Description = "Gets external id infos for an item")]
public class GetMovieRemoteSearchResults : RemoteSearchQuery<MovieInfo>, IReturn<List<RemoteSearchResult>>
@@ -107,19 +117,28 @@ namespace MediaBrowser.Api
public class ItemLookupService : BaseApiService
{
- private readonly IDtoService _dtoService;
private readonly IProviderManager _providerManager;
private readonly IServerApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem;
private readonly ILibraryManager _libraryManager;
+ private readonly ISubtitleManager _subtitleManager;
- public ItemLookupService(IDtoService dtoService, IProviderManager providerManager, IServerApplicationPaths appPaths, IFileSystem fileSystem, ILibraryManager libraryManager)
+ public ItemLookupService(IProviderManager providerManager, IServerApplicationPaths appPaths, IFileSystem fileSystem, ILibraryManager libraryManager, ISubtitleManager subtitleManager)
{
- _dtoService = dtoService;
_providerManager = providerManager;
_appPaths = appPaths;
_fileSystem = fileSystem;
_libraryManager = libraryManager;
+ _subtitleManager = subtitleManager;
+ }
+
+ public object Get(SearchRemoteSubtitles request)
+ {
+ var video = (Video)_libraryManager.GetItemById(request.Id);
+
+ var response = _subtitleManager.SearchSubtitles(video, request.Language, CancellationToken.None).Result;
+
+ return ToOptimizedResult(response);
}
public object Get(GetExternalIdInfos request)
diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs
index be86090ac..d3c47dfa1 100644
--- a/MediaBrowser.Api/LocalizationService.cs
+++ b/MediaBrowser.Api/LocalizationService.cs
@@ -67,14 +67,14 @@ namespace MediaBrowser.Api
{
var result = _localization.GetParentalRatings().ToList();
- return ToOptimizedSerializedResultUsingCache(result);
+ return ToOptimizedResult(result);
}
public object Get(GetLocalizationOptions request)
{
var result = _localization.GetLocalizationOptions().ToList();
- return ToOptimizedSerializedResultUsingCache(result);
+ return ToOptimizedResult(result);
}
/// <summary>
@@ -86,7 +86,7 @@ namespace MediaBrowser.Api
{
var result = _localization.GetCountries().ToList();
- return ToOptimizedSerializedResultUsingCache(result);
+ return ToOptimizedResult(result);
}
/// <summary>
@@ -98,7 +98,7 @@ namespace MediaBrowser.Api
{
var result = _localization.GetCultures().ToList();
- return ToOptimizedSerializedResultUsingCache(result);
+ return ToOptimizedResult(result);
}
}
diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs
index 948a67f16..0a8f0d83f 100644
--- a/MediaBrowser.Api/PackageService.cs
+++ b/MediaBrowser.Api/PackageService.cs
@@ -112,7 +112,7 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", Description = "Installation Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid Id { get; set; }
+ public string Id { get; set; }
}
/// <summary>
@@ -221,7 +221,7 @@ namespace MediaBrowser.Api
/// <param name="request">The request.</param>
public void Delete(CancelPackageInstallation request)
{
- var info = _installationManager.CurrentInstallations.FirstOrDefault(i => i.Item1.Id == request.Id);
+ var info = _installationManager.CurrentInstallations.FirstOrDefault(i => string.Equals(i.Item1.Id, request.Id));
if (info != null)
{
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index ab20ab730..23209b59c 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -542,7 +542,7 @@ namespace MediaBrowser.Api.Playback
var maxWidthParam = request.MaxWidth.Value.ToString(UsCulture);
return isH264Output ?
- string.Format("{3} -vf \"{0}scale=min(iw\\,{1}):trunc(ow/a/2)*2{2}\"", yadifParam, maxWidthParam, assSubtitleParam, copyTsParam) :
+ string.Format("{3} -vf \"{0}scale=min(iw\\,{1}):trunc(ow/dar/2)*2{2}\"", yadifParam, maxWidthParam, assSubtitleParam, copyTsParam) :
string.Format("{3} -vf \"{0}scale=min(iw\\,{1}):-1{2}\"", yadifParam, maxWidthParam, assSubtitleParam, copyTsParam);
}
@@ -903,7 +903,7 @@ namespace MediaBrowser.Api.Playback
EnableRaisingEvents = true
};
- ApiEntryPoint.Instance.OnTranscodeBeginning(outputPath, TranscodingJobType, process, state.IsInputVideo, state.Request.StartTimeTicks, state.MediaPath, state.Request.DeviceId);
+ ApiEntryPoint.Instance.OnTranscodeBeginning(outputPath, TranscodingJobType, process, state.Request.StartTimeTicks, state.MediaPath, state.Request.DeviceId);
var commandLineLogMessage = process.StartInfo.FileName + " " + process.StartInfo.Arguments;
Logger.Info(commandLineLogMessage);
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index c86550404..fd93ef685 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -273,9 +273,7 @@ namespace MediaBrowser.Api.Playback.Hls
const string keyFrameArg = " -force_key_frames expr:if(isnan(prev_forced_t),gte(t,.1),gte(t,prev_forced_t+5))";
- var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsExternal &&
- (state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 ||
- state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1);
+ var hasGraphicalSubs = state.SubtitleStream != null && state.SubtitleStream.IsGraphicalSubtitleStream;
var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264", true) + keyFrameArg;
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index efd98616f..77ac95815 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -168,9 +168,7 @@ namespace MediaBrowser.Api.Playback.Hls
" -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 hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsExternal &&
- (state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 ||
- state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1);
+ var hasGraphicalSubs = state.SubtitleStream != null && state.SubtitleStream.IsGraphicalSubtitleStream;
var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264", true) + keyFrameArg;
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index d61e8d73a..d7061ae75 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -131,24 +131,22 @@ namespace MediaBrowser.Api.Playback.Progressive
{
var args = "-vcodec " + codec;
- // See if we can save come cpu cycles by avoiding encoding
- if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
+ if (state.EnableMpegtsM2TsMode)
{
- return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf h264_mp4toannexb" : args;
+ args += " -mpegts_m2ts_mode 1";
}
- if (state.EnableMpegtsM2TsMode)
+ // See if we can save come cpu cycles by avoiding encoding
+ if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
{
- args += " -mpegts_m2ts_mode 1";
+ 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))";
args += keyFrameArg;
- var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsExternal &&
- (state.SubtitleStream.Codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 ||
- state.SubtitleStream.Codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1);
+ var hasGraphicalSubs = state.SubtitleStream != null && state.SubtitleStream.IsGraphicalSubtitleStream;
var request = state.VideoRequest;
diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
index 80080fbb3..aaf14ce71 100644
--- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
+++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
@@ -20,7 +20,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid Id { get; set; }
+ public string Id { get; set; }
}
/// <summary>
@@ -44,7 +44,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
+ public string Id { get; set; }
}
/// <summary>
@@ -58,7 +58,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid Id { get; set; }
+ public string Id { get; set; }
}
/// <summary>
@@ -72,7 +72,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// </summary>
/// <value>The task id.</value>
[ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
+ public string Id { get; set; }
}
/// <summary>
@@ -145,7 +145,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <exception cref="MediaBrowser.Common.Extensions.ResourceNotFoundException">Task not found</exception>
public object Get(GetScheduledTask request)
{
- var task = TaskManager.ScheduledTasks.FirstOrDefault(i => i.Id == request.Id);
+ var task = TaskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
if (task == null)
{
@@ -164,7 +164,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <exception cref="MediaBrowser.Common.Extensions.ResourceNotFoundException">Task not found</exception>
public void Post(StartScheduledTask request)
{
- var task = TaskManager.ScheduledTasks.FirstOrDefault(i => i.Id == request.Id);
+ var task = TaskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
if (task == null)
{
@@ -181,7 +181,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <exception cref="MediaBrowser.Common.Extensions.ResourceNotFoundException">Task not found</exception>
public void Delete(StopScheduledTask request)
{
- var task = TaskManager.ScheduledTasks.FirstOrDefault(i => i.Id == request.Id);
+ var task = TaskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, request.Id));
if (task == null)
{
@@ -201,9 +201,9 @@ namespace MediaBrowser.Api.ScheduledTasks
// 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);
- var id = new Guid(pathInfo.GetArgumentValue<string>(1));
+ var id = pathInfo.GetArgumentValue<string>(1);
- var task = TaskManager.ScheduledTasks.FirstOrDefault(i => i.Id == id);
+ var task = TaskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, id));
if (task == null)
{
diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
index 0d3f5dfcd..0d61c2ce1 100644
--- a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
+++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Tasks;
using System.Collections.Generic;
@@ -11,7 +12,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <summary>
/// Class ScheduledTasksWebSocketListener
/// </summary>
- public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<TaskInfo>, object>
+ public class ScheduledTasksWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<TaskInfo>, WebSocketListenerState>
{
/// <summary>
/// Gets or sets the task manager.
@@ -37,39 +38,47 @@ namespace MediaBrowser.Api.ScheduledTasks
: base(logger)
{
TaskManager = taskManager;
+
+ TaskManager.TaskExecuting += TaskManager_TaskExecuting;
+ TaskManager.TaskCompleted += TaskManager_TaskCompleted;
+ }
+
+ void TaskManager_TaskCompleted(object sender, TaskCompletionEventArgs e)
+ {
+ SendData(true);
+ e.Task.TaskProgress -= Argument_TaskProgress;
}
- private bool _lastResponseHadTasksRunning = true;
+ void TaskManager_TaskExecuting(object sender, GenericEventArgs<IScheduledTaskWorker> e)
+ {
+ SendData(true);
+ e.Argument.TaskProgress += Argument_TaskProgress;
+ }
+
+ void Argument_TaskProgress(object sender, GenericEventArgs<double> e)
+ {
+ SendData(false);
+ }
/// <summary>
/// Gets the data to send.
/// </summary>
/// <param name="state">The state.</param>
/// <returns>Task{IEnumerable{TaskInfo}}.</returns>
- protected override Task<IEnumerable<TaskInfo>> GetDataToSend(object state)
+ protected override Task<IEnumerable<TaskInfo>> GetDataToSend(WebSocketListenerState state)
{
- var tasks = TaskManager.ScheduledTasks.ToList();
-
- var anyRunning = tasks.Any(i => i.State != TaskState.Idle);
-
- if (anyRunning)
- {
- _lastResponseHadTasksRunning = true;
- }
- else
- {
- if (!_lastResponseHadTasksRunning)
- {
- return Task.FromResult<IEnumerable<TaskInfo>>(null);
- }
-
- _lastResponseHadTasksRunning = false;
- }
-
- return Task.FromResult(tasks
+ return Task.FromResult(TaskManager.ScheduledTasks
.OrderBy(i => i.Name)
.Select(ScheduledTaskHelpers.GetTaskInfo)
.Where(i => !i.IsHidden));
}
+
+ protected override bool SendOnTimer
+ {
+ get
+ {
+ return false;
+ }
+ }
}
}
diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs
index 662c728e4..db646344a 100644
--- a/MediaBrowser.Api/SearchService.cs
+++ b/MediaBrowser.Api/SearchService.cs
@@ -171,9 +171,9 @@ namespace MediaBrowser.Api
var primaryImageTag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
- if (primaryImageTag.HasValue)
+ if (primaryImageTag != null)
{
- result.PrimaryImageTag = primaryImageTag.Value;
+ result.PrimaryImageTag = primaryImageTag;
}
SetThumbImageInfo(result, item);
@@ -250,9 +250,9 @@ namespace MediaBrowser.Api
{
var tag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Thumb);
- if (tag.HasValue)
+ if (tag != null)
{
- hint.ThumbImageTag = tag.Value;
+ hint.ThumbImageTag = tag;
hint.ThumbImageItemId = itemWithImage.Id.ToString("N");
}
}
@@ -271,9 +271,9 @@ namespace MediaBrowser.Api
{
var tag = _imageProcessor.GetImageCacheTag(itemWithImage, ImageType.Backdrop);
- if (tag.HasValue)
+ if (tag != null)
{
- hint.BackdropImageTag = tag.Value;
+ hint.BackdropImageTag = tag;
hint.BackdropImageItemId = itemWithImage.Id.ToString("N");
}
}
diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
index f1fe904f3..cc76ee95f 100644
--- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
+++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs
@@ -69,7 +69,7 @@ namespace MediaBrowser.Api.UserLibrary
/// Filters to apply to the results
/// </summary>
/// <value>The filters.</value>
- [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsRecentlyAdded, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
+ [ApiMember(Name = "Filters", Description = "Optional. Specify additional filters to apply. This allows multiple, comma delimeted. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
public string Filters { get; set; }
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs
index 1cd819197..c7f36e6ac 100644
--- a/MediaBrowser.Api/UserLibrary/ItemsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs
@@ -521,6 +521,9 @@ namespace MediaBrowser.Api.UserLibrary
case ItemFilter.IsNotFolder:
return items.Where(item => !item.IsFolder);
+
+ case ItemFilter.IsRecentlyAdded:
+ return items.Where(item => (DateTime.UtcNow - item.DateCreated).TotalDays <= 10);
}
return items;
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
index d145dd054..008730ef6 100644
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
@@ -1,5 +1,4 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
@@ -8,7 +7,6 @@ using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session;
using ServiceStack;
using System;
diff --git a/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs b/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs
index 7fbea2f40..46dabb042 100644
--- a/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs
+++ b/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs
@@ -133,7 +133,7 @@ namespace MediaBrowser.Api.WebSocket
/// <summary>
/// Class LogFileWebSocketState
/// </summary>
- public class LogFileWebSocketState
+ public class LogFileWebSocketState : WebSocketListenerState
{
/// <summary>
/// Gets or sets the last log file path.
diff --git a/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs
index 721d8976b..a16ea863f 100644
--- a/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs
+++ b/MediaBrowser.Api/WebSocket/SessionInfoWebSocketListener.cs
@@ -11,7 +11,7 @@ namespace MediaBrowser.Api.WebSocket
/// <summary>
/// Class SessionInfoWebSocketListener
/// </summary>
- class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfoDto>, object>
+ class SessionInfoWebSocketListener : BasePeriodicWebSocketListener<IEnumerable<SessionInfoDto>, WebSocketListenerState>
{
/// <summary>
/// Gets the name.
@@ -43,7 +43,7 @@ namespace MediaBrowser.Api.WebSocket
/// </summary>
/// <param name="state">The state.</param>
/// <returns>Task{SystemInfo}.</returns>
- protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(object state)
+ protected override Task<IEnumerable<SessionInfoDto>> GetDataToSend(WebSocketListenerState state)
{
return Task.FromResult(_sessionManager.Sessions.Where(i => i.IsActive).Select(_sessionManager.GetSessionInfoDto));
}
diff --git a/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs b/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs
index 62e642c92..2940bcef0 100644
--- a/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs
+++ b/MediaBrowser.Api/WebSocket/SystemInfoWebSocketListener.cs
@@ -9,7 +9,7 @@ namespace MediaBrowser.Api.WebSocket
/// <summary>
/// Class SystemInfoWebSocketListener
/// </summary>
- public class SystemInfoWebSocketListener : BasePeriodicWebSocketListener<SystemInfo, object>
+ public class SystemInfoWebSocketListener : BasePeriodicWebSocketListener<SystemInfo, WebSocketListenerState>
{
/// <summary>
/// Gets the name.
@@ -41,7 +41,7 @@ namespace MediaBrowser.Api.WebSocket
/// </summary>
/// <param name="state">The state.</param>
/// <returns>Task{SystemInfo}.</returns>
- protected override Task<SystemInfo> GetDataToSend(object state)
+ protected override Task<SystemInfo> GetDataToSend(WebSocketListenerState state)
{
return Task.FromResult(_appHost.GetSystemInfo());
}
diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
index 4946241fd..e488fd9bf 100644
--- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
+++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs
@@ -13,6 +13,7 @@ using MediaBrowser.Common.Progress;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Common.Security;
using MediaBrowser.Common.Updates;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
index 69533ef9d..0a9f0ff8a 100644
--- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
+++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
@@ -114,9 +114,7 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
request.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None;
- request.CachePolicy = options.CachePolicy == Net.HttpRequestCachePolicy.None ?
- new RequestCachePolicy(RequestCacheLevel.BypassCache) :
- new RequestCachePolicy(RequestCacheLevel.Revalidate);
+ request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
request.ConnectionGroupName = GetHostFromUrl(options.Url);
request.KeepAlive = true;
@@ -124,6 +122,11 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
request.Pipelined = true;
request.Timeout = 20000;
+ if (!string.IsNullOrEmpty(options.Host))
+ {
+ request.Host = options.Host;
+ }
+
#if !__MonoCS__
// This is a hack to prevent KeepAlive from getting disabled internally by the HttpWebRequest
// May need to remove this for mono
@@ -230,12 +233,15 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
var httpWebRequest = GetRequest(options, httpMethod, options.EnableHttpCompression);
- if (!string.IsNullOrEmpty(options.RequestContent) || string.Equals(httpMethod, "post", StringComparison.OrdinalIgnoreCase))
+ if (options.RequestContentBytes != null ||
+ !string.IsNullOrEmpty(options.RequestContent) ||
+ string.Equals(httpMethod, "post", StringComparison.OrdinalIgnoreCase))
{
- var content = options.RequestContent ?? string.Empty;
- var bytes = Encoding.UTF8.GetBytes(content);
+ var bytes = options.RequestContentBytes ??
+ Encoding.UTF8.GetBytes(options.RequestContent ?? string.Empty);
httpWebRequest.ContentType = options.RequestContentType ?? "application/x-www-form-urlencoded";
+
httpWebRequest.ContentLength = bytes.Length;
httpWebRequest.GetRequestStream().Write(bytes, 0, bytes.Length);
}
diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
index f6f800f4a..fcb66d0bd 100644
--- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
+++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
@@ -95,11 +95,12 @@
<Compile Include="ScheduledTasks\Tasks\DeleteCacheFileTask.cs" />
<Compile Include="ScheduledTasks\Tasks\DeleteLogFileTask.cs" />
<Compile Include="ScheduledTasks\Tasks\PluginUpdateTask.cs" />
- <Compile Include="ScheduledTasks\Tasks\ReloadLoggerTask.cs" />
+ <Compile Include="ScheduledTasks\Tasks\ReloadLoggerFileTask.cs" />
<Compile Include="ScheduledTasks\Tasks\SystemUpdateTask.cs" />
<Compile Include="Security\MBLicenseFile.cs" />
<Compile Include="Security\MBRegistration.cs" />
<Compile Include="Security\PluginSecurityManager.cs" />
+ <Compile Include="Security\RegRecord.cs" />
<Compile Include="Serialization\JsonSerializer.cs" />
<Compile Include="Serialization\XmlSerializer.cs" />
<Compile Include="Updates\InstallationManager.cs" />
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
index 8f3f9b0a6..68222d843 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
@@ -1,6 +1,8 @@
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Tasks;
@@ -18,6 +20,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// </summary>
public class ScheduledTaskWorker : IScheduledTaskWorker
{
+ public event EventHandler<GenericEventArgs<double>> TaskProgress;
+
/// <summary>
/// Gets or sets the scheduled task.
/// </summary>
@@ -269,22 +273,22 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// <summary>
/// The _id
/// </summary>
- private Guid? _id;
+ private string _id;
/// <summary>
/// Gets the unique id.
/// </summary>
/// <value>The unique id.</value>
- public Guid Id
+ public string Id
{
get
{
- if (!_id.HasValue)
+ if (_id == null)
{
- _id = ScheduledTask.GetType().FullName.GetMD5();
+ _id = ScheduledTask.GetType().FullName.GetMD5().ToString("N");
}
- return _id.Value;
+ return _id;
}
}
@@ -344,13 +348,13 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
throw new InvalidOperationException("Cannot execute a Task that is already running");
}
+ var progress = new Progress<double>();
+
CurrentCancellationTokenSource = new CancellationTokenSource();
Logger.Info("Executing {0}", Name);
- ((TaskManager)TaskManager).OnTaskExecuting(ScheduledTask);
-
- var progress = new Progress<double>();
+ ((TaskManager)TaskManager).OnTaskExecuting(this);
progress.ProgressChanged += progress_ProgressChanged;
@@ -412,6 +416,12 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
void progress_ProgressChanged(object sender, double e)
{
CurrentProgress = e;
+
+ EventHelper.FireEventIfNotNull(TaskProgress, this, new GenericEventArgs<double>
+ {
+ Argument = e
+
+ }, Logger);
}
/// <summary>
@@ -464,7 +474,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// <value>The history file path.</value>
private string GetHistoryFilePath()
{
- return Path.Combine(GetScheduledTasksDataDirectory(), Id + ".js");
+ return Path.Combine(GetScheduledTasksDataDirectory(), new Guid(Id) + ".js");
}
/// <summary>
@@ -473,7 +483,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// <returns>System.String.</returns>
private string GetConfigurationFilePath()
{
- return Path.Combine(GetScheduledTasksConfigurationDirectory(), Id + ".js");
+ return Path.Combine(GetScheduledTasksConfigurationDirectory(), new Guid(Id) + ".js");
}
/// <summary>
@@ -546,7 +556,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
LastExecutionResult = result;
- ((TaskManager) TaskManager).OnTaskCompleted(ScheduledTask, result);
+ ((TaskManager)TaskManager).OnTaskCompleted(this, result);
}
/// <summary>
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs
index 6605432fa..5aec39b89 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Tasks;
@@ -16,8 +17,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// </summary>
public class TaskManager : ITaskManager
{
- public event EventHandler<EventArgs> TaskExecuting;
- public event EventHandler<GenericEventArgs<TaskResult>> TaskCompleted;
+ public event EventHandler<GenericEventArgs<IScheduledTaskWorker>> TaskExecuting;
+ public event EventHandler<TaskCompletionEventArgs> TaskCompleted;
/// <summary>
/// Gets the list of Scheduled Tasks
@@ -124,7 +125,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
// If it's idle just execute immediately
if (task.State == TaskState.Idle)
{
- ((ScheduledTaskWorker)task).Execute();
+ Execute(task);
return;
}
@@ -148,7 +149,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
{
var myTasks = ScheduledTasks.ToList();
- myTasks.AddRange(tasks.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger)));
+ var list = tasks.ToList();
+ myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger)));
ScheduledTasks = myTasks.ToArray();
}
@@ -188,9 +190,13 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// Called when [task executing].
/// </summary>
/// <param name="task">The task.</param>
- internal void OnTaskExecuting(IScheduledTask task)
+ internal void OnTaskExecuting(IScheduledTaskWorker task)
{
- EventHelper.QueueEventIfNotNull(TaskExecuting, task, EventArgs.Empty, Logger);
+ EventHelper.QueueEventIfNotNull(TaskExecuting, this, new GenericEventArgs<IScheduledTaskWorker>
+ {
+ Argument = task
+
+ }, Logger);
}
/// <summary>
@@ -198,9 +204,15 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
/// </summary>
/// <param name="task">The task.</param>
/// <param name="result">The result.</param>
- internal void OnTaskCompleted(IScheduledTask task, TaskResult result)
+ internal void OnTaskCompleted(IScheduledTaskWorker task, TaskResult result)
{
- EventHelper.QueueEventIfNotNull(TaskCompleted, task, new GenericEventArgs<TaskResult> { Argument = result }, Logger);
+ EventHelper.QueueEventIfNotNull(TaskCompleted, task, new TaskCompletionEventArgs
+ {
+ Result = result,
+ Task = task
+
+ }, Logger);
+
ExecuteQueuedTasks();
}
@@ -218,7 +230,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
if (scheduledTask.State == TaskState.Idle)
{
- ((ScheduledTaskWorker)scheduledTask).Execute();
+ Execute(scheduledTask);
_taskQueue.Remove(type);
}
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
index a5b8de554..dbeedfed5 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
@@ -25,7 +25,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
-
+
/// <summary>
/// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
/// </summary>
@@ -74,9 +74,11 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
progress.Report(90);
+ minDateModified = DateTime.UtcNow.AddDays(-3);
+
try
{
- DeleteCacheFilesFromDirectory(cancellationToken, ApplicationPaths.TempDirectory, DateTime.MaxValue, progress);
+ DeleteCacheFilesFromDirectory(cancellationToken, ApplicationPaths.TempDirectory, minDateModified, progress);
}
catch (DirectoryNotFoundException)
{
diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerTask.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs
index 78f60632f..78f60632f 100644
--- a/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerTask.cs
+++ b/MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerFileTask.cs
diff --git a/MediaBrowser.Common.Implementations/Security/MBRegistration.cs b/MediaBrowser.Common.Implementations/Security/MBRegistration.cs
index 1d64b5ea1..ca000df19 100644
--- a/MediaBrowser.Common.Implementations/Security/MBRegistration.cs
+++ b/MediaBrowser.Common.Implementations/Security/MBRegistration.cs
@@ -94,11 +94,4 @@ namespace MediaBrowser.Common.Implementations.Security
return new MBRegistrationRecord { IsRegistered = reg.registered, ExpirationDate = reg.expDate, RegChecked = true };
}
}
-
- class RegRecord
- {
- public string featId { get; set; }
- public bool registered { get; set; }
- public DateTime expDate { get; set; }
- }
}
diff --git a/MediaBrowser.Common.Implementations/Security/RegRecord.cs b/MediaBrowser.Common.Implementations/Security/RegRecord.cs
new file mode 100644
index 000000000..f4e4337bf
--- /dev/null
+++ b/MediaBrowser.Common.Implementations/Security/RegRecord.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace MediaBrowser.Common.Implementations.Security
+{
+ class RegRecord
+ {
+ public string featId { get; set; }
+ public bool registered { get; set; }
+ public DateTime expDate { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
index 18462ba9b..fe484840a 100644
--- a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
+++ b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Progress;
using MediaBrowser.Common.Security;
using MediaBrowser.Common.Updates;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Updates;
@@ -328,14 +329,14 @@ namespace MediaBrowser.Common.Implementations.Updates
if (withAutoUpdateEnabled)
{
plugins = plugins
- .Where(p => p.Configuration.EnableAutoUpdate)
+ .Where(p => _config.CommonConfiguration.EnableAutoUpdate)
.ToList();
}
// Figure out what needs to be installed
var packages = plugins.Select(p =>
{
- var latestPluginInfo = GetLatestCompatibleVersion(catalog, p.Name, p.Id.ToString(), applicationVersion, p.Configuration.UpdateClass);
+ 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;
@@ -367,7 +368,7 @@ namespace MediaBrowser.Common.Implementations.Updates
var installationInfo = new InstallationInfo
{
- Id = Guid.NewGuid(),
+ Id = Guid.NewGuid().ToString("N"),
Name = package.name,
AssemblyGuid = package.guid,
UpdateClass = package.classification,
@@ -510,13 +511,14 @@ namespace MediaBrowser.Common.Implementations.Updates
cancellationToken.ThrowIfCancellationRequested();
// Validate with a checksum
- if (package.checksum != Guid.Empty) // support for legacy uploads for now
+ var packageChecksum = string.IsNullOrWhiteSpace(package.checksum) ? Guid.Empty : new Guid(package.checksum);
+ if (packageChecksum != Guid.Empty) // support for legacy uploads for now
{
using (var crypto = new MD5CryptoServiceProvider())
using (var stream = new BufferedStream(File.OpenRead(tempFile), 100000))
{
var check = Guid.Parse(BitConverter.ToString(crypto.ComputeHash(stream)).Replace("-", String.Empty));
- if (check != package.checksum)
+ if (check != packageChecksum)
{
throw new ApplicationException(string.Format("Download validation failed for {0}. Probably corrupted during transfer.", package.name));
}
diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs
index ecd099711..709a8e927 100644
--- a/MediaBrowser.Common/IApplicationHost.cs
+++ b/MediaBrowser.Common/IApplicationHost.cs
@@ -1,5 +1,5 @@
-using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Plugins;
+using MediaBrowser.Common.Plugins;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Updates;
using System;
using System.Collections.Generic;
@@ -152,15 +152,4 @@ namespace MediaBrowser.Common
/// <returns>System.Object.</returns>
object CreateInstance(Type type);
}
-
- public interface IDependencyContainer
- {
- void RegisterSingleInstance<T>(T obj, bool manageLifetime = true)
- where T : class;
-
- void RegisterSingleInstance<T>(Func<T> func)
- where T : class;
-
- void Register(Type typeInterface, Type typeImplementation);
- }
}
diff --git a/MediaBrowser.Common/IDependencyContainer.cs b/MediaBrowser.Common/IDependencyContainer.cs
new file mode 100644
index 000000000..423c1740a
--- /dev/null
+++ b/MediaBrowser.Common/IDependencyContainer.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace MediaBrowser.Common
+{
+ public interface IDependencyContainer
+ {
+ void RegisterSingleInstance<T>(T obj, bool manageLifetime = true)
+ where T : class;
+
+ void RegisterSingleInstance<T>(Func<T> func)
+ where T : class;
+
+ void Register(Type typeInterface, Type typeImplementation);
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj
index 5e0d3aa24..2e7db5c35 100644
--- a/MediaBrowser.Common/MediaBrowser.Common.csproj
+++ b/MediaBrowser.Common/MediaBrowser.Common.csproj
@@ -59,8 +59,8 @@
<Compile Include="Constants\Constants.cs" />
<Compile Include="Events\EventHelper.cs" />
<Compile Include="Extensions\BaseExtensions.cs" />
- <Compile Include="Events\GenericEventArgs.cs" />
<Compile Include="Extensions\ResourceNotFoundException.cs" />
+ <Compile Include="IDependencyContainer.cs" />
<Compile Include="IO\FileSystemRepository.cs" />
<Compile Include="IO\IFileSystem.cs" />
<Compile Include="IO\ProgressStream.cs" />
@@ -79,9 +79,12 @@
<Compile Include="Net\IWebSocketServer.cs" />
<Compile Include="Net\MimeTypes.cs" />
<Compile Include="Net\WebSocketConnectEventArgs.cs" />
+ <Compile Include="Net\WebSocketMessageInfo.cs" />
<Compile Include="Plugins\IDependencyModule.cs" />
<Compile Include="Plugins\IPlugin.cs" />
<Compile Include="Progress\ActionableProgress.cs" />
+ <Compile Include="ScheduledTasks\IConfigurableScheduledTask.cs" />
+ <Compile Include="ScheduledTasks\IHasKey.cs" />
<Compile Include="ScheduledTasks\IScheduledTask.cs" />
<Compile Include="ScheduledTasks\IScheduledTaskWorker.cs" />
<Compile Include="ScheduledTasks\ITaskManager.cs" />
@@ -99,6 +102,7 @@
<Compile Include="Security\ISecurityManager.cs" />
<Compile Include="Updates\IInstallationManager.cs" />
<Compile Include="Updates\InstallationEventArgs.cs" />
+ <Compile Include="Updates\InstallationFailedEventArgs.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
diff --git a/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs
index 33d3f368b..a2af3707b 100644
--- a/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs
+++ b/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs
@@ -15,7 +15,7 @@ namespace MediaBrowser.Common.Net
/// <typeparam name="TReturnDataType">The type of the T return data type.</typeparam>
/// <typeparam name="TStateType">The type of the T state type.</typeparam>
public abstract class BasePeriodicWebSocketListener<TReturnDataType, TStateType> : IWebSocketListener, IDisposable
- where TStateType : class, new()
+ where TStateType : WebSocketListenerState, new()
where TReturnDataType : class
{
/// <summary>
@@ -83,7 +83,15 @@ namespace MediaBrowser.Common.Net
}
protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
+
+ protected virtual bool SendOnTimer
+ {
+ get
+ {
+ return true;
+ }
+ }
+
/// <summary>
/// Starts sending messages over a web socket
/// </summary>
@@ -99,9 +107,15 @@ namespace MediaBrowser.Common.Net
Logger.Info("{1} Begin transmitting over websocket to {0}", message.Connection.RemoteEndPoint, GetType().Name);
- var timer = new Timer(TimerCallback, message.Connection, Timeout.Infinite, Timeout.Infinite);
+ var timer = SendOnTimer ?
+ new Timer(TimerCallback, message.Connection, Timeout.Infinite, Timeout.Infinite) :
+ null;
- var state = new TStateType();
+ var state = new TStateType
+ {
+ IntervalMs = periodMs,
+ InitialDelayMs = dueTimeMs
+ };
var semaphore = new SemaphoreSlim(1, 1);
@@ -110,14 +124,17 @@ namespace MediaBrowser.Common.Net
ActiveConnections.Add(new Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim>(message.Connection, cancellationTokenSource, timer, state, semaphore));
}
- timer.Change(TimeSpan.FromMilliseconds(dueTimeMs), TimeSpan.FromMilliseconds(periodMs));
+ if (timer != null)
+ {
+ timer.Change(TimeSpan.FromMilliseconds(dueTimeMs), TimeSpan.FromMilliseconds(periodMs));
+ }
}
/// <summary>
/// Timers the callback.
/// </summary>
/// <param name="state">The state.</param>
- private async void TimerCallback(object state)
+ private void TimerCallback(object state)
{
var connection = (IWebSocketConnection)state;
@@ -139,11 +156,50 @@ namespace MediaBrowser.Common.Net
return;
}
+ SendData(tuple);
+ }
+
+ protected void SendData(bool force)
+ {
+ List<Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim>> tuples;
+
+ lock (ActiveConnections)
+ {
+ tuples = ActiveConnections
+ .Where(c =>
+ {
+ if (c.Item1.State == WebSocketState.Open && !c.Item2.IsCancellationRequested)
+ {
+ var state = c.Item4;
+
+ if (force || (DateTime.UtcNow - state.DateLastSendUtc).TotalMilliseconds >= state.IntervalMs)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ })
+ .ToList();
+ }
+
+ foreach (var tuple in tuples)
+ {
+ SendData(tuple);
+ }
+ }
+
+ private async void SendData(Tuple<IWebSocketConnection, CancellationTokenSource, Timer, TStateType, SemaphoreSlim> tuple)
+ {
+ var connection = tuple.Item1;
+
try
{
await tuple.Item5.WaitAsync(tuple.Item2.Token).ConfigureAwait(false);
- var data = await GetDataToSend(tuple.Item4).ConfigureAwait(false);
+ var state = tuple.Item4;
+
+ var data = await GetDataToSend(state).ConfigureAwait(false);
if (data != null)
{
@@ -153,6 +209,8 @@ namespace MediaBrowser.Common.Net
Data = data
}, tuple.Item2.Token).ConfigureAwait(false);
+
+ state.DateLastSendUtc = DateTime.UtcNow;
}
tuple.Item5.Release();
@@ -196,13 +254,18 @@ namespace MediaBrowser.Common.Net
{
Logger.Info("{1} stop transmitting over websocket to {0}", connection.Item1.RemoteEndPoint, GetType().Name);
- try
- {
- connection.Item3.Dispose();
- }
- catch (ObjectDisposedException)
+ var timer = connection.Item3;
+
+ if (timer != null)
{
+ try
+ {
+ timer.Dispose();
+ }
+ catch (ObjectDisposedException)
+ {
+ }
}
try
@@ -212,7 +275,7 @@ namespace MediaBrowser.Common.Net
}
catch (ObjectDisposedException)
{
-
+
}
try
@@ -223,7 +286,7 @@ namespace MediaBrowser.Common.Net
{
}
-
+
ActiveConnections.Remove(connection);
}
@@ -253,4 +316,11 @@ namespace MediaBrowser.Common.Net
Dispose(true);
}
}
+
+ public class WebSocketListenerState
+ {
+ public DateTime DateLastSendUtc { get; set; }
+ public long InitialDelayMs { get; set; }
+ public long IntervalMs { get; set; }
+ }
}
diff --git a/MediaBrowser.Common/Net/HttpRequestOptions.cs b/MediaBrowser.Common/Net/HttpRequestOptions.cs
index c7277eba8..192264eed 100644
--- a/MediaBrowser.Common/Net/HttpRequestOptions.cs
+++ b/MediaBrowser.Common/Net/HttpRequestOptions.cs
@@ -53,6 +53,12 @@ namespace MediaBrowser.Common.Net
}
/// <summary>
+ /// Gets or sets the host.
+ /// </summary>
+ /// <value>The host.</value>
+ public string Host { get; set; }
+
+ /// <summary>
/// Gets or sets the progress.
/// </summary>
/// <value>The progress.</value>
@@ -69,14 +75,13 @@ namespace MediaBrowser.Common.Net
public string RequestContentType { get; set; }
public string RequestContent { get; set; }
+ public byte[] RequestContentBytes { get; set; }
public bool BufferContent { get; set; }
public bool LogRequest { get; set; }
public bool LogErrorResponseBody { get; set; }
-
- public HttpRequestCachePolicy CachePolicy { get; set; }
private string GetHeaderValue(string name)
{
@@ -95,17 +100,9 @@ namespace MediaBrowser.Common.Net
EnableHttpCompression = true;
BufferContent = true;
- CachePolicy = HttpRequestCachePolicy.None;
-
RequestHeaders = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
LogRequest = true;
}
}
-
- public enum HttpRequestCachePolicy
- {
- None = 1,
- Validate = 2
- }
}
diff --git a/MediaBrowser.Common/Net/IWebSocketConnection.cs b/MediaBrowser.Common/Net/IWebSocketConnection.cs
index 482da131e..514a52d96 100644
--- a/MediaBrowser.Common/Net/IWebSocketConnection.cs
+++ b/MediaBrowser.Common/Net/IWebSocketConnection.cs
@@ -65,16 +65,4 @@ namespace MediaBrowser.Common.Net
/// <exception cref="System.ArgumentNullException">buffer</exception>
Task SendAsync(byte[] buffer, WebSocketMessageType type, CancellationToken cancellationToken);
}
-
- /// <summary>
- /// Class WebSocketMessageInfo
- /// </summary>
- public class WebSocketMessageInfo : WebSocketMessage<string>
- {
- /// <summary>
- /// Gets or sets the connection.
- /// </summary>
- /// <value>The connection.</value>
- public IWebSocketConnection Connection { get; set; }
- }
} \ No newline at end of file
diff --git a/MediaBrowser.Common/Net/WebSocketMessageInfo.cs b/MediaBrowser.Common/Net/WebSocketMessageInfo.cs
new file mode 100644
index 000000000..c1f935a7b
--- /dev/null
+++ b/MediaBrowser.Common/Net/WebSocketMessageInfo.cs
@@ -0,0 +1,16 @@
+using MediaBrowser.Model.Net;
+
+namespace MediaBrowser.Common.Net
+{
+ /// <summary>
+ /// Class WebSocketMessageInfo
+ /// </summary>
+ public class WebSocketMessageInfo : WebSocketMessage<string>
+ {
+ /// <summary>
+ /// Gets or sets the connection.
+ /// </summary>
+ /// <value>The connection.</value>
+ public IWebSocketConnection Connection { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs
index aa1369c4e..6bbd69f04 100644
--- a/MediaBrowser.Common/Plugins/BasePlugin.cs
+++ b/MediaBrowser.Common/Plugins/BasePlugin.cs
@@ -305,8 +305,6 @@ namespace MediaBrowser.Common.Plugins
ConfigurationDateLastModified = ConfigurationDateLastModified,
Description = Description,
Id = Id.ToString("N"),
- EnableAutoUpdate = Configuration.EnableAutoUpdate,
- UpdateClass = Configuration.UpdateClass,
ConfigurationFileName = ConfigurationFileName
};
diff --git a/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs
new file mode 100644
index 000000000..fc6963070
--- /dev/null
+++ b/MediaBrowser.Common/ScheduledTasks/IConfigurableScheduledTask.cs
@@ -0,0 +1,16 @@
+namespace MediaBrowser.Common.ScheduledTasks
+{
+ public interface IConfigurableScheduledTask
+ {
+ /// <summary>
+ /// Gets a value indicating whether this instance is hidden.
+ /// </summary>
+ /// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
+ bool IsHidden { get; }
+ /// <summary>
+ /// Gets a value indicating whether this instance is enabled.
+ /// </summary>
+ /// <value><c>true</c> if this instance is enabled; otherwise, <c>false</c>.</value>
+ bool IsEnabled { get; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Common/ScheduledTasks/IHasKey.cs b/MediaBrowser.Common/ScheduledTasks/IHasKey.cs
new file mode 100644
index 000000000..5736cb616
--- /dev/null
+++ b/MediaBrowser.Common/ScheduledTasks/IHasKey.cs
@@ -0,0 +1,7 @@
+namespace MediaBrowser.Common.ScheduledTasks
+{
+ public interface IHasKey
+ {
+ string Key { get; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs
index e150f7f4e..351e96c7d 100644
--- a/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs
+++ b/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs
@@ -42,23 +42,4 @@ namespace MediaBrowser.Common.ScheduledTasks
/// <returns>IEnumerable{BaseTaskTrigger}.</returns>
IEnumerable<ITaskTrigger> GetDefaultTriggers();
}
-
- public interface IConfigurableScheduledTask
- {
- /// <summary>
- /// Gets a value indicating whether this instance is hidden.
- /// </summary>
- /// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
- bool IsHidden { get; }
- /// <summary>
- /// Gets a value indicating whether this instance is enabled.
- /// </summary>
- /// <value><c>true</c> if this instance is enabled; otherwise, <c>false</c>.</value>
- bool IsEnabled { get; }
- }
-
- public interface IHasKey
- {
- string Key { get; }
- }
}
diff --git a/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs b/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs
index 2fa76472d..f50bd9e76 100644
--- a/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs
+++ b/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Tasks;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.Tasks;
using System;
using System.Collections.Generic;
@@ -10,6 +11,11 @@ namespace MediaBrowser.Common.ScheduledTasks
public interface IScheduledTaskWorker : IDisposable
{
/// <summary>
+ /// Occurs when [task progress].
+ /// </summary>
+ event EventHandler<GenericEventArgs<double>> TaskProgress;
+
+ /// <summary>
/// Gets or sets the scheduled task.
/// </summary>
/// <value>The scheduled task.</value>
@@ -62,6 +68,6 @@ namespace MediaBrowser.Common.ScheduledTasks
/// Gets the unique id.
/// </summary>
/// <value>The unique id.</value>
- Guid Id { get; }
+ string Id { get; }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs b/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs
index 394872783..01dc355c3 100644
--- a/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs
+++ b/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs
@@ -1,5 +1,4 @@
-using MediaBrowser.Common.Events;
-using MediaBrowser.Model.Tasks;
+using MediaBrowser.Model.Events;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -50,7 +49,7 @@ namespace MediaBrowser.Common.ScheduledTasks
void Cancel(IScheduledTaskWorker task);
Task Execute(IScheduledTaskWorker task);
- event EventHandler<EventArgs> TaskExecuting;
- event EventHandler<GenericEventArgs<TaskResult>> TaskCompleted;
+ event EventHandler<GenericEventArgs<IScheduledTaskWorker>> TaskExecuting;
+ event EventHandler<TaskCompletionEventArgs> TaskCompleted;
}
} \ No newline at end of file
diff --git a/MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs b/MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs
index 8aab6b50d..2974806d0 100644
--- a/MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs
+++ b/MediaBrowser.Common/ScheduledTasks/TaskCompletionEventArgs.cs
@@ -5,7 +5,7 @@ namespace MediaBrowser.Common.ScheduledTasks
{
public class TaskCompletionEventArgs : EventArgs
{
- public IScheduledTask Task { get; set; }
+ public IScheduledTaskWorker Task { get; set; }
public TaskResult Result { get; set; }
}
diff --git a/MediaBrowser.Common/Updates/IInstallationManager.cs b/MediaBrowser.Common/Updates/IInstallationManager.cs
index f162f8dc8..592613c54 100644
--- a/MediaBrowser.Common/Updates/IInstallationManager.cs
+++ b/MediaBrowser.Common/Updates/IInstallationManager.cs
@@ -1,5 +1,5 @@
-using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Plugins;
+using MediaBrowser.Common.Plugins;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Updates;
using System;
using System.Collections.Concurrent;
diff --git a/MediaBrowser.Common/Updates/InstallationEventArgs.cs b/MediaBrowser.Common/Updates/InstallationEventArgs.cs
index 2c3a805de..9dc8ead83 100644
--- a/MediaBrowser.Common/Updates/InstallationEventArgs.cs
+++ b/MediaBrowser.Common/Updates/InstallationEventArgs.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Model.Updates;
-using System;
namespace MediaBrowser.Common.Updates
{
@@ -9,9 +8,4 @@ namespace MediaBrowser.Common.Updates
public PackageVersionInfo PackageVersionInfo { get; set; }
}
-
- public class InstallationFailedEventArgs : InstallationEventArgs
- {
- public Exception Exception { get; set; }
- }
}
diff --git a/MediaBrowser.Common/Updates/InstallationFailedEventArgs.cs b/MediaBrowser.Common/Updates/InstallationFailedEventArgs.cs
new file mode 100644
index 000000000..69dc1ee98
--- /dev/null
+++ b/MediaBrowser.Common/Updates/InstallationFailedEventArgs.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace MediaBrowser.Common.Updates
+{
+ public class InstallationFailedEventArgs : InstallationEventArgs
+ {
+ public Exception Exception { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
index a0999593f..72a996b19 100644
--- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
@@ -8,6 +8,8 @@ namespace MediaBrowser.Controller.Channels
{
public string ExternalId { get; set; }
+ public string ChannelId { get; set; }
+
public ChannelItemType ChannelItemType { get; set; }
public bool IsInfiniteStream { get; set; }
diff --git a/MediaBrowser.Controller/Channels/ChannelCategoryItem.cs b/MediaBrowser.Controller/Channels/ChannelCategoryItem.cs
index 67f0ec65f..b20dcf620 100644
--- a/MediaBrowser.Controller/Channels/ChannelCategoryItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelCategoryItem.cs
@@ -7,6 +7,8 @@ namespace MediaBrowser.Controller.Channels
{
public string ExternalId { get; set; }
+ public string ChannelId { get; set; }
+
public ChannelItemType ChannelItemType { get; set; }
public string OriginalImageUrl { get; set; }
diff --git a/MediaBrowser.Controller/Channels/ChannelInfo.cs b/MediaBrowser.Controller/Channels/ChannelInfo.cs
new file mode 100644
index 000000000..fd3a169a2
--- /dev/null
+++ b/MediaBrowser.Controller/Channels/ChannelInfo.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Channels
+{
+ public class ChannelInfo
+ {
+ /// <summary>
+ /// Gets the home page URL.
+ /// </summary>
+ /// <value>The home page URL.</value>
+ public string HomePageUrl { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance can search.
+ /// </summary>
+ /// <value><c>true</c> if this instance can search; otherwise, <c>false</c>.</value>
+ public bool CanSearch { get; set; }
+
+ public List<ChannelMediaType> MediaTypes { get; set; }
+
+ public List<ChannelMediaContentType> ContentTypes { get; set; }
+
+ public ChannelInfo()
+ {
+ MediaTypes = new List<ChannelMediaType>();
+ ContentTypes = new List<ChannelMediaContentType>();
+ }
+ }
+
+}
diff --git a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
index 104204eb0..7bb8d15fc 100644
--- a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
+++ b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
@@ -52,45 +52,4 @@ namespace MediaBrowser.Controller.Channels
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}
-
- public enum ChannelItemType
- {
- Media = 0,
-
- Category = 1
- }
-
- public enum ChannelMediaType
- {
- Audio = 0,
-
- Video = 1
- }
-
- public enum ChannelMediaContentType
- {
- Clip = 0,
-
- Podcast = 1,
-
- Trailer = 2,
-
- Movie = 3,
-
- Episode = 4,
-
- Song = 5
- }
-
- public class ChannelMediaInfo
- {
- public string Path { get; set; }
-
- public Dictionary<string, string> RequiredHttpHeaders { get; set; }
-
- public ChannelMediaInfo()
- {
- RequiredHttpHeaders = new Dictionary<string, string>();
- }
- }
}
diff --git a/MediaBrowser.Controller/Channels/ChannelItemResult.cs b/MediaBrowser.Controller/Channels/ChannelItemResult.cs
new file mode 100644
index 000000000..c6d33996e
--- /dev/null
+++ b/MediaBrowser.Controller/Channels/ChannelItemResult.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Channels
+{
+ public class ChannelItemResult
+ {
+ public List<ChannelItemInfo> Items { get; set; }
+
+ public TimeSpan CacheLength { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Channels/ChannelItemType.cs b/MediaBrowser.Controller/Channels/ChannelItemType.cs
new file mode 100644
index 000000000..ba9d7f414
--- /dev/null
+++ b/MediaBrowser.Controller/Channels/ChannelItemType.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Controller.Channels
+{
+ public enum ChannelItemType
+ {
+ Media = 0,
+
+ Category = 1
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Channels/ChannelMediaContentType.cs b/MediaBrowser.Controller/Channels/ChannelMediaContentType.cs
new file mode 100644
index 000000000..2aad8e0d9
--- /dev/null
+++ b/MediaBrowser.Controller/Channels/ChannelMediaContentType.cs
@@ -0,0 +1,17 @@
+namespace MediaBrowser.Controller.Channels
+{
+ public enum ChannelMediaContentType
+ {
+ Clip = 0,
+
+ Podcast = 1,
+
+ Trailer = 2,
+
+ Movie = 3,
+
+ Episode = 4,
+
+ Song = 5
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
new file mode 100644
index 000000000..8105bf43c
--- /dev/null
+++ b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Channels
+{
+ public class ChannelMediaInfo
+ {
+ public string Path { get; set; }
+
+ public Dictionary<string, string> RequiredHttpHeaders { get; set; }
+
+ public string Container { get; set; }
+ public string AudioCodec { get; set; }
+ public string VideoCodec { get; set; }
+
+ public int? AudioBitrate { get; set; }
+ public int? VideoBitrate { get; set; }
+ public int? Width { get; set; }
+ public int? Height { get; set; }
+ public int? AudioChannels { get; set; }
+
+ public ChannelMediaInfo()
+ {
+ RequiredHttpHeaders = new Dictionary<string, string>();
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Channels/ChannelMediaType.cs b/MediaBrowser.Controller/Channels/ChannelMediaType.cs
new file mode 100644
index 000000000..a03e27498
--- /dev/null
+++ b/MediaBrowser.Controller/Channels/ChannelMediaType.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Controller.Channels
+{
+ public enum ChannelMediaType
+ {
+ Audio = 0,
+
+ Video = 1
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Channels/ChannelSearchInfo.cs b/MediaBrowser.Controller/Channels/ChannelSearchInfo.cs
new file mode 100644
index 000000000..bf7461327
--- /dev/null
+++ b/MediaBrowser.Controller/Channels/ChannelSearchInfo.cs
@@ -0,0 +1,7 @@
+namespace MediaBrowser.Controller.Channels
+{
+ public class ChannelSearchInfo
+ {
+ public string SearchTerm { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
index 0bf05f965..0d2bd933b 100644
--- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
@@ -10,6 +10,8 @@ namespace MediaBrowser.Controller.Channels
{
public string ExternalId { get; set; }
+ public string ChannelId { get; set; }
+
public ChannelItemType ChannelItemType { get; set; }
public bool IsInfiniteStream { get; set; }
diff --git a/MediaBrowser.Controller/Channels/IChannel.cs b/MediaBrowser.Controller/Channels/IChannel.cs
index 0c4be8630..bd0bd64ea 100644
--- a/MediaBrowser.Controller/Channels/IChannel.cs
+++ b/MediaBrowser.Controller/Channels/IChannel.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
-using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -60,48 +59,4 @@ namespace MediaBrowser.Controller.Channels
/// <returns>IEnumerable{ImageType}.</returns>
IEnumerable<ImageType> GetSupportedChannelImages();
}
-
- public class ChannelInfo
- {
- /// <summary>
- /// Gets the home page URL.
- /// </summary>
- /// <value>The home page URL.</value>
- public string HomePageUrl { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance can search.
- /// </summary>
- /// <value><c>true</c> if this instance can search; otherwise, <c>false</c>.</value>
- public bool CanSearch { get; set; }
-
- public List<ChannelMediaType> MediaTypes { get; set; }
-
- public List<ChannelMediaContentType> ContentTypes { get; set; }
-
- public ChannelInfo()
- {
- MediaTypes = new List<ChannelMediaType>();
- ContentTypes = new List<ChannelMediaContentType>();
- }
- }
-
- public class ChannelSearchInfo
- {
- public string SearchTerm { get; set; }
- }
-
- public class InternalChannelItemQuery
- {
- public string CategoryId { get; set; }
-
- public User User { get; set; }
- }
-
- public class ChannelItemResult
- {
- public List<ChannelItemInfo> Items { get; set; }
-
- public TimeSpan CacheLength { get; set; }
- }
}
diff --git a/MediaBrowser.Controller/Channels/IChannelFactory.cs b/MediaBrowser.Controller/Channels/IChannelFactory.cs
new file mode 100644
index 000000000..e275227ff
--- /dev/null
+++ b/MediaBrowser.Controller/Channels/IChannelFactory.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Channels
+{
+ public interface IChannelFactory
+ {
+ IEnumerable<IChannel> GetChannels();
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Channels/IChannelItem.cs b/MediaBrowser.Controller/Channels/IChannelItem.cs
index a05ef8e29..fc088b888 100644
--- a/MediaBrowser.Controller/Channels/IChannelItem.cs
+++ b/MediaBrowser.Controller/Channels/IChannelItem.cs
@@ -4,17 +4,12 @@ namespace MediaBrowser.Controller.Channels
{
public interface IChannelItem : IHasImages
{
+ string ChannelId { get; set; }
+
string ExternalId { get; set; }
ChannelItemType ChannelItemType { get; set; }
string OriginalImageUrl { get; set; }
}
-
- public interface IChannelMediaItem : IChannelItem
- {
- bool IsInfiniteStream { get; set; }
-
- ChannelMediaContentType ContentType { get; set; }
- }
}
diff --git a/MediaBrowser.Controller/Channels/IChannelManager.cs b/MediaBrowser.Controller/Channels/IChannelManager.cs
index b34e77415..05f9afcf0 100644
--- a/MediaBrowser.Controller/Channels/IChannelManager.cs
+++ b/MediaBrowser.Controller/Channels/IChannelManager.cs
@@ -13,7 +13,8 @@ namespace MediaBrowser.Controller.Channels
/// Adds the parts.
/// </summary>
/// <param name="channels">The channels.</param>
- void AddParts(IEnumerable<IChannel> channels);
+ /// <param name="factories">The factories.</param>
+ void AddParts(IEnumerable<IChannel> channels, IEnumerable<IChannelFactory> factories);
/// <summary>
/// Gets the channels.
diff --git a/MediaBrowser.Controller/Channels/IChannelMediaItem.cs b/MediaBrowser.Controller/Channels/IChannelMediaItem.cs
new file mode 100644
index 000000000..3a2c076e0
--- /dev/null
+++ b/MediaBrowser.Controller/Channels/IChannelMediaItem.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Controller.Channels
+{
+ public interface IChannelMediaItem : IChannelItem
+ {
+ bool IsInfiniteStream { get; set; }
+
+ ChannelMediaContentType ContentType { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Channels/InternalChannelItemQuery.cs b/MediaBrowser.Controller/Channels/InternalChannelItemQuery.cs
new file mode 100644
index 000000000..21100ebdd
--- /dev/null
+++ b/MediaBrowser.Controller/Channels/InternalChannelItemQuery.cs
@@ -0,0 +1,11 @@
+using MediaBrowser.Controller.Entities;
+
+namespace MediaBrowser.Controller.Channels
+{
+ public class InternalChannelItemQuery
+ {
+ public string CategoryId { get; set; }
+
+ public User User { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Chapters/ChapterResponse.cs b/MediaBrowser.Controller/Chapters/ChapterResponse.cs
new file mode 100644
index 000000000..3c1b8ed07
--- /dev/null
+++ b/MediaBrowser.Controller/Chapters/ChapterResponse.cs
@@ -0,0 +1,19 @@
+using MediaBrowser.Model.Chapters;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Chapters
+{
+ public class ChapterResponse
+ {
+ /// <summary>
+ /// Gets or sets the chapters.
+ /// </summary>
+ /// <value>The chapters.</value>
+ public List<RemoteChapterInfo> Chapters { get; set; }
+
+ public ChapterResponse()
+ {
+ Chapters = new List<RemoteChapterInfo>();
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Chapters/ChapterSearchRequest.cs b/MediaBrowser.Controller/Chapters/ChapterSearchRequest.cs
new file mode 100644
index 000000000..9a53d68ea
--- /dev/null
+++ b/MediaBrowser.Controller/Chapters/ChapterSearchRequest.cs
@@ -0,0 +1,29 @@
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Chapters
+{
+ public class ChapterSearchRequest : IHasProviderIds
+ {
+ public string Language { get; set; }
+
+ public VideoContentType ContentType { get; set; }
+
+ public string MediaPath { get; set; }
+ public string SeriesName { get; set; }
+ public string Name { get; set; }
+ public int? IndexNumber { get; set; }
+ public int? IndexNumberEnd { get; set; }
+ public int? ParentIndexNumber { get; set; }
+ public int? ProductionYear { get; set; }
+ public long? RuntimeTicks { get; set; }
+ public Dictionary<string, string> ProviderIds { get; set; }
+
+ public ChapterSearchRequest()
+ {
+ ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Chapters/IChapterProvider.cs b/MediaBrowser.Controller/Chapters/IChapterProvider.cs
new file mode 100644
index 000000000..a7505347b
--- /dev/null
+++ b/MediaBrowser.Controller/Chapters/IChapterProvider.cs
@@ -0,0 +1,39 @@
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Chapters;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Chapters
+{
+ public interface IChapterProvider
+ {
+ /// <summary>
+ /// Gets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ string Name { get; }
+
+ /// <summary>
+ /// Gets the supported media types.
+ /// </summary>
+ /// <value>The supported media types.</value>
+ IEnumerable<VideoContentType> SupportedMediaTypes { get; }
+
+ /// <summary>
+ /// Searches the specified request.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{IEnumerable{RemoteChapterResult}}.</returns>
+ Task<IEnumerable<RemoteChapterResult>> Search(ChapterSearchRequest request, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the chapters.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{ChapterResponse}.</returns>
+ Task<ChapterResponse> GetChapters(string id, CancellationToken cancellationToken);
+ }
+}
diff --git a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs b/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs
index 810376f6c..6a2343a00 100644
--- a/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs
+++ b/MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs
@@ -1,5 +1,7 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Events;
+using System;
namespace MediaBrowser.Controller.Configuration
{
@@ -9,6 +11,11 @@ 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>
diff --git a/MediaBrowser.Controller/Dlna/ControlRequest.cs b/MediaBrowser.Controller/Dlna/ControlRequest.cs
index 1bb5ddf8a..7020cc0d9 100644
--- a/MediaBrowser.Controller/Dlna/ControlRequest.cs
+++ b/MediaBrowser.Controller/Dlna/ControlRequest.cs
@@ -17,18 +17,4 @@ namespace MediaBrowser.Controller.Dlna
Headers = new Dictionary<string, string>();
}
}
-
- public class ControlResponse
- {
- public IDictionary<string, string> Headers { get; set; }
-
- public string Xml { get; set; }
-
- public bool IsSuccessful { get; set; }
-
- public ControlResponse()
- {
- Headers = new Dictionary<string, string>();
- }
- }
}
diff --git a/MediaBrowser.Controller/Dlna/ControlResponse.cs b/MediaBrowser.Controller/Dlna/ControlResponse.cs
new file mode 100644
index 000000000..8d19a8109
--- /dev/null
+++ b/MediaBrowser.Controller/Dlna/ControlResponse.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Dlna
+{
+ public class ControlResponse
+ {
+ public IDictionary<string, string> Headers { get; set; }
+
+ public string Xml { get; set; }
+
+ public bool IsSuccessful { get; set; }
+
+ public ControlResponse()
+ {
+ Headers = new Dictionary<string, string>();
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
index ad5e622fc..9c42e0581 100644
--- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs
+++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
@@ -55,7 +55,7 @@ namespace MediaBrowser.Controller.Drawing
/// <param name="item">The item.</param>
/// <param name="image">The image.</param>
/// <returns>Guid.</returns>
- Guid GetImageCacheTag(IHasImages item, ItemImageInfo image);
+ string GetImageCacheTag(IHasImages item, ItemImageInfo image);
/// <summary>
/// Gets the image cache tag.
@@ -66,7 +66,7 @@ namespace MediaBrowser.Controller.Drawing
/// <param name="dateModified">The date modified.</param>
/// <param name="imageEnhancers">The image enhancers.</param>
/// <returns>Guid.</returns>
- Guid GetImageCacheTag(IHasImages item, ImageType imageType, string originalImagePath, DateTime dateModified,
+ string GetImageCacheTag(IHasImages item, ImageType imageType, string originalImagePath, DateTime dateModified,
List<IImageEnhancer> imageEnhancers);
/// <summary>
@@ -86,24 +86,4 @@ namespace MediaBrowser.Controller.Drawing
/// <returns>Task{System.String}.</returns>
Task<string> GetEnhancedImage(IHasImages item, ImageType imageType, int imageIndex);
}
-
- public static class ImageProcessorExtensions
- {
- public static Guid? GetImageCacheTag(this IImageProcessor processor, IHasImages item, ImageType imageType)
- {
- return processor.GetImageCacheTag(item, imageType, 0);
- }
-
- public static Guid? GetImageCacheTag(this IImageProcessor processor, IHasImages item, ImageType imageType, int imageIndex)
- {
- var imageInfo = item.GetImageInfo(imageType, imageIndex);
-
- if (imageInfo == null)
- {
- return null;
- }
-
- return processor.GetImageCacheTag(item, imageInfo);
- }
- }
}
diff --git a/MediaBrowser.Controller/Drawing/ImageProcessorExtensions.cs b/MediaBrowser.Controller/Drawing/ImageProcessorExtensions.cs
new file mode 100644
index 000000000..c5601c49f
--- /dev/null
+++ b/MediaBrowser.Controller/Drawing/ImageProcessorExtensions.cs
@@ -0,0 +1,25 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Controller.Drawing
+{
+ public static class ImageProcessorExtensions
+ {
+ public static string GetImageCacheTag(this IImageProcessor processor, IHasImages item, ImageType imageType)
+ {
+ return processor.GetImageCacheTag(item, imageType, 0);
+ }
+
+ public static string GetImageCacheTag(this IImageProcessor processor, IHasImages item, ImageType imageType, int imageIndex)
+ {
+ var imageInfo = item.GetImageInfo(imageType, imageIndex);
+
+ if (imageInfo == null)
+ {
+ return null;
+ }
+
+ return processor.GetImageCacheTag(item, imageInfo);
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs
index 503d1513c..be761ef66 100644
--- a/MediaBrowser.Controller/Entities/TV/Episode.cs
+++ b/MediaBrowser.Controller/Entities/TV/Episode.cs
@@ -305,13 +305,7 @@ namespace MediaBrowser.Controller.Entities.TV
if (!ParentIndexNumber.HasValue && !string.IsNullOrEmpty(Path))
{
- ParentIndexNumber = TVUtils.GetSeasonNumberFromPath(Path);
-
- // If a change was made record it
- if (ParentIndexNumber.HasValue)
- {
- hasChanges = true;
- }
+ ParentIndexNumber = TVUtils.GetSeasonNumberFromEpisodeFile(Path);
}
// If a change was made record it
diff --git a/MediaBrowser.Controller/Library/IIntroProvider.cs b/MediaBrowser.Controller/Library/IIntroProvider.cs
index 224ca2271..a83d3c5eb 100644
--- a/MediaBrowser.Controller/Library/IIntroProvider.cs
+++ b/MediaBrowser.Controller/Library/IIntroProvider.cs
@@ -1,5 +1,4 @@
using MediaBrowser.Controller.Entities;
-using System;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Library
@@ -23,19 +22,4 @@ namespace MediaBrowser.Controller.Library
/// <returns>IEnumerable{System.String}.</returns>
IEnumerable<string> GetAllIntroFiles();
}
-
- public class IntroInfo
- {
- /// <summary>
- /// Gets or sets the path.
- /// </summary>
- /// <value>The path.</value>
- public string Path { get; set; }
-
- /// <summary>
- /// Gets or sets the item id.
- /// </summary>
- /// <value>The item id.</value>
- public Guid? ItemId { get; set; }
- }
}
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index 7529f1e0d..69dea5e74 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -333,20 +333,4 @@ namespace MediaBrowser.Controller.Library
/// <returns>IEnumerable{BaseItem}.</returns>
IEnumerable<BaseItem> ReplaceVideosWithPrimaryVersions(IEnumerable<BaseItem> items);
}
-
- public static class LibraryManagerExtensions
- {
- public static Task DeleteItem(this ILibraryManager manager, BaseItem item)
- {
- return manager.DeleteItem(item, new DeleteOptions
- {
- DeleteFileLocation = true
- });
- }
-
- public static BaseItem GetItemById(this ILibraryManager manager, string id)
- {
- return manager.GetItemById(new Guid(id));
- }
- }
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Library/IMetadataFileSaver.cs b/MediaBrowser.Controller/Library/IMetadataFileSaver.cs
new file mode 100644
index 000000000..0883da48f
--- /dev/null
+++ b/MediaBrowser.Controller/Library/IMetadataFileSaver.cs
@@ -0,0 +1,14 @@
+using MediaBrowser.Controller.Entities;
+
+namespace MediaBrowser.Controller.Library
+{
+ public interface IMetadataFileSaver : IMetadataSaver
+ {
+ /// <summary>
+ /// Gets the save path.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>System.String.</returns>
+ string GetSavePath(IHasMetadata item);
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Library/IMetadataSaver.cs b/MediaBrowser.Controller/Library/IMetadataSaver.cs
index cfee9d206..ce8feb4c6 100644
--- a/MediaBrowser.Controller/Library/IMetadataSaver.cs
+++ b/MediaBrowser.Controller/Library/IMetadataSaver.cs
@@ -31,14 +31,4 @@ namespace MediaBrowser.Controller.Library
/// <returns>Task.</returns>
void Save(IHasMetadata item, CancellationToken cancellationToken);
}
-
- public interface IMetadataFileSaver : IMetadataSaver
- {
- /// <summary>
- /// Gets the save path.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns>System.String.</returns>
- string GetSavePath(IHasMetadata item);
- }
}
diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs
index c3b0748cf..0a0174b6d 100644
--- a/MediaBrowser.Controller/Library/IUserManager.cs
+++ b/MediaBrowser.Controller/Library/IUserManager.cs
@@ -1,5 +1,5 @@
-using MediaBrowser.Common.Events;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Events;
using System;
using System.Collections.Generic;
using System.Threading;
diff --git a/MediaBrowser.Controller/Library/IntroInfo.cs b/MediaBrowser.Controller/Library/IntroInfo.cs
new file mode 100644
index 000000000..d0e61d0f0
--- /dev/null
+++ b/MediaBrowser.Controller/Library/IntroInfo.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace MediaBrowser.Controller.Library
+{
+ public class IntroInfo
+ {
+ /// <summary>
+ /// Gets or sets the path.
+ /// </summary>
+ /// <value>The path.</value>
+ public string Path { get; set; }
+
+ /// <summary>
+ /// Gets or sets the item id.
+ /// </summary>
+ /// <value>The item id.</value>
+ public Guid? ItemId { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Library/LibraryManagerExtensions.cs b/MediaBrowser.Controller/Library/LibraryManagerExtensions.cs
new file mode 100644
index 000000000..dd1c9c07a
--- /dev/null
+++ b/MediaBrowser.Controller/Library/LibraryManagerExtensions.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Threading.Tasks;
+using MediaBrowser.Controller.Entities;
+
+namespace MediaBrowser.Controller.Library
+{
+ public static class LibraryManagerExtensions
+ {
+ public static Task DeleteItem(this ILibraryManager manager, BaseItem item)
+ {
+ return manager.DeleteItem(item, new DeleteOptions
+ {
+ DeleteFileLocation = true
+ });
+ }
+
+ public static BaseItem GetItemById(this ILibraryManager manager, string id)
+ {
+ return manager.GetItemById(new Guid(id));
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
index 7482607ff..7b7b625bf 100644
--- a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
+++ b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
@@ -24,13 +24,4 @@ namespace MediaBrowser.Controller.Library
Users = new List<User>();
}
}
-
- public class PlaybackStopEventArgs : PlaybackProgressEventArgs
- {
- /// <summary>
- /// Gets or sets a value indicating whether [played to completion].
- /// </summary>
- /// <value><c>true</c> if [played to completion]; otherwise, <c>false</c>.</value>
- public bool PlayedToCompletion { get; set; }
- }
}
diff --git a/MediaBrowser.Controller/Library/PlaybackStopEventArgs.cs b/MediaBrowser.Controller/Library/PlaybackStopEventArgs.cs
new file mode 100644
index 000000000..b0f6799fc
--- /dev/null
+++ b/MediaBrowser.Controller/Library/PlaybackStopEventArgs.cs
@@ -0,0 +1,11 @@
+namespace MediaBrowser.Controller.Library
+{
+ public class PlaybackStopEventArgs : PlaybackProgressEventArgs
+ {
+ /// <summary>
+ /// Gets or sets a value indicating whether [played to completion].
+ /// </summary>
+ /// <value><c>true</c> if [played to completion]; otherwise, <c>false</c>.</value>
+ public bool PlayedToCompletion { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs b/MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs
new file mode 100644
index 000000000..682150d35
--- /dev/null
+++ b/MediaBrowser.Controller/LiveTv/LiveTvConflictException.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Controller.LiveTv
+{
+ /// <summary>
+ /// Class LiveTvConflictException.
+ /// </summary>
+ public class LiveTvConflictException : LiveTvException
+ {
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvException.cs b/MediaBrowser.Controller/LiveTv/LiveTvException.cs
index 0a68180ca..b0a6f75b1 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvException.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvException.cs
@@ -8,11 +8,4 @@ namespace MediaBrowser.Controller.LiveTv
public class LiveTvException : Exception
{
}
-
- /// <summary>
- /// Class LiveTvConflictException.
- /// </summary>
- public class LiveTvConflictException : LiveTvException
- {
- }
}
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvServiceStatusInfo.cs b/MediaBrowser.Controller/LiveTv/LiveTvServiceStatusInfo.cs
index da6b8ab17..0cb064aba 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvServiceStatusInfo.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvServiceStatusInfo.cs
@@ -40,60 +40,4 @@ namespace MediaBrowser.Controller.LiveTv
Tuners = new List<LiveTvTunerInfo>();
}
}
-
- public class LiveTvTunerInfo
- {
- /// <summary>
- /// Gets or sets the type of the source.
- /// </summary>
- /// <value>The type of the source.</value>
- public string SourceType { get; set; }
-
- /// <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; }
-
- /// <summary>
- /// Gets or sets the status.
- /// </summary>
- /// <value>The status.</value>
- public LiveTvTunerStatus Status { get; set; }
-
- /// <summary>
- /// Gets or sets the channel identifier.
- /// </summary>
- /// <value>The channel identifier.</value>
- public string ChannelId { get; set; }
-
- /// <summary>
- /// Gets or sets the recording identifier.
- /// </summary>
- /// <value>The recording identifier.</value>
- public string RecordingId { get; set; }
-
- /// <summary>
- /// Gets or sets the name of the program.
- /// </summary>
- /// <value>The name of the program.</value>
- public string ProgramName { get; set; }
-
- /// <summary>
- /// Gets or sets the clients.
- /// </summary>
- /// <value>The clients.</value>
- public List<string> Clients { get; set; }
-
- public LiveTvTunerInfo()
- {
- Clients = new List<string>();
- }
- }
}
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvTunerInfo.cs b/MediaBrowser.Controller/LiveTv/LiveTvTunerInfo.cs
new file mode 100644
index 000000000..cdf2f0ef5
--- /dev/null
+++ b/MediaBrowser.Controller/LiveTv/LiveTvTunerInfo.cs
@@ -0,0 +1,61 @@
+using System.Collections.Generic;
+using MediaBrowser.Model.LiveTv;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+ public class LiveTvTunerInfo
+ {
+ /// <summary>
+ /// Gets or sets the type of the source.
+ /// </summary>
+ /// <value>The type of the source.</value>
+ public string SourceType { get; set; }
+
+ /// <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; }
+
+ /// <summary>
+ /// Gets or sets the status.
+ /// </summary>
+ /// <value>The status.</value>
+ public LiveTvTunerStatus Status { get; set; }
+
+ /// <summary>
+ /// Gets or sets the channel identifier.
+ /// </summary>
+ /// <value>The channel identifier.</value>
+ public string ChannelId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the recording identifier.
+ /// </summary>
+ /// <value>The recording identifier.</value>
+ public string RecordingId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the program.
+ /// </summary>
+ /// <value>The name of the program.</value>
+ public string ProgramName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the clients.
+ /// </summary>
+ /// <value>The clients.</value>
+ public List<string> Clients { get; set; }
+
+ public LiveTvTunerInfo()
+ {
+ Clients = new List<string>();
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/LiveTv/EventArgs.cs b/MediaBrowser.Controller/LiveTv/RecordingStatusChangedEventArgs.cs
index 90ea329fe..90ea329fe 100644
--- a/MediaBrowser.Controller/LiveTv/EventArgs.cs
+++ b/MediaBrowser.Controller/LiveTv/RecordingStatusChangedEventArgs.cs
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index b54ad2272..97158c112 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -69,16 +69,30 @@
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="Channels\ChannelCategoryItem.cs" />
+ <Compile Include="Channels\ChannelInfo.cs" />
<Compile Include="Channels\ChannelItemInfo.cs" />
+ <Compile Include="Channels\ChannelItemResult.cs" />
+ <Compile Include="Channels\ChannelItemType.cs" />
+ <Compile Include="Channels\ChannelMediaContentType.cs" />
+ <Compile Include="Channels\ChannelMediaInfo.cs" />
+ <Compile Include="Channels\ChannelMediaType.cs" />
+ <Compile Include="Channels\ChannelSearchInfo.cs" />
<Compile Include="Channels\IChannel.cs" />
+ <Compile Include="Channels\IChannelFactory.cs" />
<Compile Include="Channels\IChannelManager.cs" />
<Compile Include="Channels\IChannelItem.cs" />
<Compile Include="Channels\ChannelAudioItem.cs" />
<Compile Include="Channels\ChannelVideoItem.cs" />
<Compile Include="Channels\Channel.cs" />
+ <Compile Include="Channels\IChannelMediaItem.cs" />
+ <Compile Include="Channels\InternalChannelItemQuery.cs" />
+ <Compile Include="Chapters\ChapterSearchRequest.cs" />
+ <Compile Include="Chapters\IChapterProvider.cs" />
+ <Compile Include="Chapters\ChapterResponse.cs" />
<Compile Include="Collections\CollectionCreationOptions.cs" />
<Compile Include="Collections\ICollectionManager.cs" />
<Compile Include="Dlna\ControlRequest.cs" />
+ <Compile Include="Dlna\ControlResponse.cs" />
<Compile Include="Dlna\DlnaIconResponse.cs" />
<Compile Include="Dlna\EventSubscriptionResponse.cs" />
<Compile Include="Dlna\IContentDirectory.cs" />
@@ -87,6 +101,7 @@
<Compile Include="Drawing\IImageProcessor.cs" />
<Compile Include="Drawing\ImageFormat.cs" />
<Compile Include="Drawing\ImageProcessingOptions.cs" />
+ <Compile Include="Drawing\ImageProcessorExtensions.cs" />
<Compile Include="Dto\IDtoService.cs" />
<Compile Include="Entities\AdultVideo.cs" />
<Compile Include="Entities\Audio\IHasAlbumArtist.cs" />
@@ -131,12 +146,16 @@
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
<Compile Include="Library\DeleteOptions.cs" />
<Compile Include="Library\ILibraryPostScanTask.cs" />
+ <Compile Include="Library\IMetadataFileSaver.cs" />
<Compile Include="Library\IMetadataSaver.cs" />
<Compile Include="Library\IMusicManager.cs" />
+ <Compile Include="Library\IntroInfo.cs" />
<Compile Include="Library\ItemUpdateType.cs" />
<Compile Include="Library\IUserDataManager.cs" />
+ <Compile Include="Library\LibraryManagerExtensions.cs" />
+ <Compile Include="Library\PlaybackStopEventArgs.cs" />
<Compile Include="Library\UserDataSaveEventArgs.cs" />
- <Compile Include="LiveTv\EventArgs.cs" />
+ <Compile Include="LiveTv\RecordingStatusChangedEventArgs.cs" />
<Compile Include="LiveTv\ILiveTvRecording.cs" />
<Compile Include="LiveTv\LiveStreamInfo.cs" />
<Compile Include="LiveTv\LiveTvAudioRecording.cs" />
@@ -144,8 +163,10 @@
<Compile Include="LiveTv\ChannelInfo.cs" />
<Compile Include="LiveTv\ILiveTvManager.cs" />
<Compile Include="LiveTv\ILiveTvService.cs" />
+ <Compile Include="LiveTv\LiveTvConflictException.cs" />
<Compile Include="LiveTv\LiveTvException.cs" />
<Compile Include="LiveTv\LiveTvServiceStatusInfo.cs" />
+ <Compile Include="LiveTv\LiveTvTunerInfo.cs" />
<Compile Include="LiveTv\StreamResponseInfo.cs" />
<Compile Include="LiveTv\LiveTvProgram.cs" />
<Compile Include="LiveTv\LiveTvVideoRecording.cs" />
@@ -190,6 +211,10 @@
<Compile Include="Providers\IMetadataProvider.cs" />
<Compile Include="Providers\IMetadataService.cs" />
<Compile Include="Providers\IRemoteMetadataProvider.cs" />
+ <Compile Include="Providers\VideoContentType.cs" />
+ <Compile Include="Security\IEncryptionManager.cs" />
+ <Compile Include="Subtitles\ISubtitleManager.cs" />
+ <Compile Include="Subtitles\ISubtitleProvider.cs" />
<Compile Include="Providers\ItemLookupInfo.cs" />
<Compile Include="Providers\MetadataRefreshOptions.cs" />
<Compile Include="Providers\NameParser.cs" />
@@ -265,6 +290,8 @@
<Compile Include="Sorting\IUserBaseItemComparer.cs" />
<Compile Include="Providers\BaseItemXmlParser.cs" />
<Compile Include="Sorting\SortExtensions.cs" />
+ <Compile Include="Subtitles\SubtitleResponse.cs" />
+ <Compile Include="Subtitles\SubtitleSearchRequest.cs" />
<Compile Include="Themes\IAppThemeManager.cs" />
<Compile Include="Themes\InternalThemeImage.cs" />
</ItemGroup>
diff --git a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
index 521bf7a81..6a37626b7 100644
--- a/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
+++ b/MediaBrowser.Controller/MediaEncoding/MediaEncoderHelpers.cs
@@ -187,7 +187,9 @@ namespace MediaBrowser.Controller.MediaEncoding
}
else if (string.Equals(streamInfo.codec_type, "video", StringComparison.OrdinalIgnoreCase))
{
- stream.Type = MediaStreamType.Video;
+ stream.Type = (streamInfo.codec_name ?? string.Empty).IndexOf("mjpeg", StringComparison.OrdinalIgnoreCase) != -1
+ ? MediaStreamType.EmbeddedImage
+ : MediaStreamType.Video;
stream.Width = streamInfo.width;
stream.Height = streamInfo.height;
diff --git a/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs b/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs
index 4e56932ec..84fedebce 100644
--- a/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs
@@ -34,6 +34,6 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="userId">The user id.</param>
/// <param name="client">The client.</param>
/// <returns>Task{DisplayPreferences}.</returns>
- DisplayPreferences GetDisplayPreferences(Guid displayPreferencesId, Guid userId, string client);
+ DisplayPreferences GetDisplayPreferences(string displayPreferencesId, Guid userId, string client);
}
}
diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs
index 9d41b6d25..6f70df435 100644
--- a/MediaBrowser.Controller/Providers/DirectoryService.cs
+++ b/MediaBrowser.Controller/Providers/DirectoryService.cs
@@ -11,6 +11,7 @@ namespace MediaBrowser.Controller.Providers
{
List<FileSystemInfo> GetFileSystemEntries(string path);
IEnumerable<FileSystemInfo> GetFiles(string path);
+ IEnumerable<FileSystemInfo> GetFiles(string path, bool clearCache);
FileSystemInfo GetFile(string path);
}
@@ -27,8 +28,20 @@ namespace MediaBrowser.Controller.Providers
public List<FileSystemInfo> GetFileSystemEntries(string path)
{
+ return GetFileSystemEntries(path, false);
+ }
+
+ private List<FileSystemInfo> GetFileSystemEntries(string path, bool clearCache)
+ {
List<FileSystemInfo> entries;
+ if (clearCache)
+ {
+ List<FileSystemInfo> removed;
+
+ _cache.TryRemove(path, out removed);
+ }
+
if (!_cache.TryGetValue(path, out entries))
{
//_logger.Debug("Getting files for " + path);
@@ -50,7 +63,12 @@ namespace MediaBrowser.Controller.Providers
public IEnumerable<FileSystemInfo> GetFiles(string path)
{
- return GetFileSystemEntries(path).Where(i => (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory);
+ return GetFiles(path, false);
+ }
+
+ public IEnumerable<FileSystemInfo> GetFiles(string path, bool clearCache)
+ {
+ return GetFileSystemEntries(path, clearCache).Where(i => (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory);
}
public FileSystemInfo GetFile(string path)
diff --git a/MediaBrowser.Controller/Providers/VideoContentType.cs b/MediaBrowser.Controller/Providers/VideoContentType.cs
new file mode 100644
index 000000000..903c77612
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/VideoContentType.cs
@@ -0,0 +1,19 @@
+
+namespace MediaBrowser.Controller.Providers
+{
+ /// <summary>
+ /// Enum VideoContentType
+ /// </summary>
+ public enum VideoContentType
+ {
+ /// <summary>
+ /// The episode
+ /// </summary>
+ Episode = 0,
+
+ /// <summary>
+ /// The movie
+ /// </summary>
+ Movie = 1
+ }
+}
diff --git a/MediaBrowser.Controller/Security/IEncryptionManager.cs b/MediaBrowser.Controller/Security/IEncryptionManager.cs
new file mode 100644
index 000000000..bb4f77d83
--- /dev/null
+++ b/MediaBrowser.Controller/Security/IEncryptionManager.cs
@@ -0,0 +1,20 @@
+
+namespace MediaBrowser.Controller.Security
+{
+ public interface IEncryptionManager
+ {
+ /// <summary>
+ /// Encrypts the string.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>System.String.</returns>
+ string EncryptString(string value);
+
+ /// <summary>
+ /// Decrypts the string.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>System.String.</returns>
+ string DecryptString(string value);
+ }
+}
diff --git a/MediaBrowser.Controller/Session/ISessionController.cs b/MediaBrowser.Controller/Session/ISessionController.cs
index d4612acb5..9c818284d 100644
--- a/MediaBrowser.Controller/Session/ISessionController.cs
+++ b/MediaBrowser.Controller/Session/ISessionController.cs
@@ -20,14 +20,6 @@ namespace MediaBrowser.Controller.Session
bool IsSessionActive { get; }
/// <summary>
- /// Sends the message command.
- /// </summary>
- /// <param name="command">The command.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- Task SendMessageCommand(MessageCommand command, CancellationToken cancellationToken);
-
- /// <summary>
/// Sends the play command.
/// </summary>
/// <param name="command">The command.</param>
diff --git a/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs
new file mode 100644
index 000000000..8b0ef223c
--- /dev/null
+++ b/MediaBrowser.Controller/Subtitles/ISubtitleManager.cs
@@ -0,0 +1,50 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Providers;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Subtitles
+{
+ public interface ISubtitleManager
+ {
+ /// <summary>
+ /// Adds the parts.
+ /// </summary>
+ /// <param name="subtitleProviders">The subtitle providers.</param>
+ void AddParts(IEnumerable<ISubtitleProvider> subtitleProviders);
+
+ /// <summary>
+ /// Searches the subtitles.
+ /// </summary>
+ /// <param name="video">The video.</param>
+ /// <param name="language">The language.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{IEnumerable{RemoteSubtitleInfo}}.</returns>
+ Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(Video video,
+ string language,
+ CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Searches the subtitles.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{IEnumerable{RemoteSubtitleInfo}}.</returns>
+ Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(SubtitleSearchRequest request,
+ CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Downloads the subtitles.
+ /// </summary>
+ /// <param name="video">The video.</param>
+ /// <param name="subtitleId">The subtitle identifier.</param>
+ /// <param name="providerName">Name of the provider.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task DownloadSubtitles(Video video,
+ string subtitleId,
+ string providerName,
+ CancellationToken cancellationToken);
+ }
+}
diff --git a/MediaBrowser.Controller/Subtitles/ISubtitleProvider.cs b/MediaBrowser.Controller/Subtitles/ISubtitleProvider.cs
new file mode 100644
index 000000000..dceea0cc6
--- /dev/null
+++ b/MediaBrowser.Controller/Subtitles/ISubtitleProvider.cs
@@ -0,0 +1,39 @@
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Providers;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Subtitles
+{
+ public interface ISubtitleProvider
+ {
+ /// <summary>
+ /// Gets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ string Name { get; }
+
+ /// <summary>
+ /// Gets the supported media types.
+ /// </summary>
+ /// <value>The supported media types.</value>
+ IEnumerable<VideoContentType> SupportedMediaTypes { get; }
+
+ /// <summary>
+ /// Searches the subtitles.
+ /// </summary>
+ /// <param name="request">The request.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{IEnumerable{RemoteSubtitleInfo}}.</returns>
+ Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Gets the subtitles.
+ /// </summary>
+ /// <param name="id">The identifier.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task{SubtitleResponse}.</returns>
+ Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken);
+ }
+}
diff --git a/MediaBrowser.Controller/Subtitles/SubtitleResponse.cs b/MediaBrowser.Controller/Subtitles/SubtitleResponse.cs
new file mode 100644
index 000000000..69e92c1f5
--- /dev/null
+++ b/MediaBrowser.Controller/Subtitles/SubtitleResponse.cs
@@ -0,0 +1,11 @@
+using System.IO;
+
+namespace MediaBrowser.Controller.Subtitles
+{
+ public class SubtitleResponse
+ {
+ public string Language { get; set; }
+ public string Format { get; set; }
+ public Stream Stream { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs b/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs
new file mode 100644
index 000000000..e83387129
--- /dev/null
+++ b/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs
@@ -0,0 +1,29 @@
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Subtitles
+{
+ public class SubtitleSearchRequest : IHasProviderIds
+ {
+ public string Language { get; set; }
+
+ public VideoContentType ContentType { get; set; }
+
+ public string MediaPath { get; set; }
+ public string SeriesName { get; set; }
+ public string Name { get; set; }
+ public int? IndexNumber { get; set; }
+ public int? IndexNumberEnd { get; set; }
+ public int? ParentIndexNumber { get; set; }
+ public int? ProductionYear { get; set; }
+ public long? RuntimeTicks { get; set; }
+ public Dictionary<string, string> ProviderIds { get; set; }
+
+ public SubtitleSearchRequest()
+ {
+ ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
index b5129fdb4..1cd4a4cbd 100644
--- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs
+++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
@@ -414,11 +414,11 @@ namespace MediaBrowser.Dlna.Didl
{
classType = "object.container.album.musicAlbum";
}
- if (item is MusicArtist)
+ else if (item is MusicArtist)
{
classType = "object.container.person.musicArtist";
}
- if (item is Series || item is Season || item is BoxSet || item is CollectionFolder)
+ else if (item is Series || item is Season || item is BoxSet)
{
classType = "object.container.album.videoAlbum";
}
@@ -623,9 +623,7 @@ namespace MediaBrowser.Dlna.Didl
try
{
- var guid = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
-
- tag = guid.HasValue ? guid.Value.ToString("N") : null;
+ tag = _imageProcessor.GetImageCacheTag(item, ImageType.Primary);
}
catch
{
@@ -712,7 +710,7 @@ namespace MediaBrowser.Dlna.Didl
Height = height.Value,
Width = width.Value
- }, maxWidth: maxWidth, maxHeight: maxHeight);
+ }, null, null, maxWidth, maxHeight);
width = Convert.ToInt32(newSize.Width);
height = Convert.ToInt32(newSize.Height);
diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
index fa609843b..d39bcbefe 100644
--- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
+++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj
@@ -59,18 +59,22 @@
<Compile Include="PlayTo\Device.cs">
<SubType>Code</SubType>
</Compile>
- <Compile Include="PlayTo\DeviceEventArgs.cs" />
+ <Compile Include="PlayTo\PlaybackStartEventArgs.cs" />
<Compile Include="PlayTo\DeviceInfo.cs" />
<Compile Include="Common\DeviceService.cs" />
<Compile Include="Didl\DidlBuilder.cs" />
- <Compile Include="PlayTo\DlnaController.cs" />
+ <Compile Include="PlayTo\PlayToController.cs" />
<Compile Include="PlayTo\Extensions.cs" />
+ <Compile Include="PlayTo\PlaybackProgressEventArgs.cs" />
+ <Compile Include="PlayTo\PlaybackStoppedEventArgs.cs" />
<Compile Include="PlayTo\PlaylistItem.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="PlayTo\PlaylistItemFactory.cs" />
<Compile Include="PlayTo\PlayToManager.cs" />
<Compile Include="Common\ServiceAction.cs" />
+ <Compile Include="PlayTo\TRANSPORTSTATE.cs" />
+ <Compile Include="PlayTo\uParserObject.cs" />
<Compile Include="Profiles\Foobar2000Profile.cs" />
<Compile Include="Profiles\Windows81Profile.cs" />
<Compile Include="Profiles\WindowsMediaCenterProfile.cs" />
diff --git a/MediaBrowser.Dlna/PlayTo/Device.cs b/MediaBrowser.Dlna/PlayTo/Device.cs
index 1c7ed13b6..3e5e877cd 100644
--- a/MediaBrowser.Dlna/PlayTo/Device.cs
+++ b/MediaBrowser.Dlna/PlayTo/Device.cs
@@ -77,6 +77,8 @@ namespace MediaBrowser.Dlna.PlayTo
private readonly ILogger _logger;
private readonly IServerConfigurationManager _config;
+ public DateTime DateLastActivity { get; private set; }
+
public Device(DeviceInfo deviceProperties, IHttpClient httpClient, ILogger logger, IServerConfigurationManager config)
{
Properties = deviceProperties;
@@ -386,6 +388,8 @@ namespace MediaBrowser.Dlna.PlayTo
{
var transportState = await GetTransportInfo().ConfigureAwait(false);
+ DateLastActivity = DateTime.UtcNow;
+
if (transportState.HasValue)
{
// If we're not playing anything no need to get additional data
diff --git a/MediaBrowser.Dlna/PlayTo/DeviceEventArgs.cs b/MediaBrowser.Dlna/PlayTo/DeviceEventArgs.cs
deleted file mode 100644
index 67230c189..000000000
--- a/MediaBrowser.Dlna/PlayTo/DeviceEventArgs.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-
-namespace MediaBrowser.Dlna.PlayTo
-{
- public class PlaybackStartEventArgs : EventArgs
- {
- public uBaseObject MediaInfo { get; set; }
- }
-
- public class PlaybackProgressEventArgs : EventArgs
- {
- public uBaseObject MediaInfo { get; set; }
- }
-
- public class PlaybackStoppedEventArgs : EventArgs
- {
- public uBaseObject MediaInfo { get; set; }
- }
-
- public enum TRANSPORTSTATE
- {
- STOPPED,
- PLAYING,
- TRANSITIONING,
- PAUSED_PLAYBACK,
- PAUSED
- }
-}
diff --git a/MediaBrowser.Dlna/PlayTo/DlnaController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
index fb5e0bf34..ab342d635 100644
--- a/MediaBrowser.Dlna/PlayTo/DlnaController.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
@@ -51,6 +51,8 @@ namespace MediaBrowser.Dlna.PlayTo
}
}
+ private Timer _updateTimer;
+
public PlayToController(SessionInfo session, ISessionManager sessionManager, IItemRepository itemRepository, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IDtoService dtoService, IImageProcessor imageProcessor, SsdpHandler ssdpHandler, string serverAddress)
{
_session = session;
@@ -75,6 +77,24 @@ namespace MediaBrowser.Dlna.PlayTo
_device.Start();
_ssdpHandler.MessageReceived += _SsdpHandler_MessageReceived;
+
+ _updateTimer = new Timer(updateTimer_Elapsed, null, 60000, 60000);
+ }
+
+ private async void updateTimer_Elapsed(object state)
+ {
+ if (DateTime.UtcNow >= _device.DateLastActivity.AddSeconds(60))
+ {
+ try
+ {
+ // Session is inactive, mark it for Disposal and don't start the elapsed timer.
+ await _sessionManager.ReportSessionEnded(_session.Id).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error in ReportSessionEnded", ex);
+ }
+ }
}
private string GetServerAddress()
@@ -335,11 +355,6 @@ namespace MediaBrowser.Dlna.PlayTo
return Task.FromResult(true);
}
- public Task SendMessageCommand(MessageCommand command, CancellationToken cancellationToken)
- {
- return Task.FromResult(true);
- }
-
#endregion
#region Playlist
@@ -571,10 +586,21 @@ namespace MediaBrowser.Dlna.PlayTo
_device.PlaybackStopped -= _device_PlaybackStopped;
_ssdpHandler.MessageReceived -= _SsdpHandler_MessageReceived;
+ DisposeUpdateTimer();
+
_device.Dispose();
}
}
+ private void DisposeUpdateTimer()
+ {
+ if (_updateTimer != null)
+ {
+ _updateTimer.Dispose();
+ _updateTimer = null;
+ }
+ }
+
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Dlna/PlayTo/PlaybackProgressEventArgs.cs b/MediaBrowser.Dlna/PlayTo/PlaybackProgressEventArgs.cs
new file mode 100644
index 000000000..104697166
--- /dev/null
+++ b/MediaBrowser.Dlna/PlayTo/PlaybackProgressEventArgs.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace MediaBrowser.Dlna.PlayTo
+{
+ public class PlaybackProgressEventArgs : EventArgs
+ {
+ public uBaseObject MediaInfo { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Dlna/PlayTo/PlaybackStartEventArgs.cs b/MediaBrowser.Dlna/PlayTo/PlaybackStartEventArgs.cs
new file mode 100644
index 000000000..772eba55b
--- /dev/null
+++ b/MediaBrowser.Dlna/PlayTo/PlaybackStartEventArgs.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace MediaBrowser.Dlna.PlayTo
+{
+ public class PlaybackStartEventArgs : EventArgs
+ {
+ public uBaseObject MediaInfo { get; set; }
+ }
+}
diff --git a/MediaBrowser.Dlna/PlayTo/PlaybackStoppedEventArgs.cs b/MediaBrowser.Dlna/PlayTo/PlaybackStoppedEventArgs.cs
new file mode 100644
index 000000000..aac08cd6f
--- /dev/null
+++ b/MediaBrowser.Dlna/PlayTo/PlaybackStoppedEventArgs.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace MediaBrowser.Dlna.PlayTo
+{
+ public class PlaybackStoppedEventArgs : EventArgs
+ {
+ public uBaseObject MediaInfo { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Dlna/PlayTo/TRANSPORTSTATE.cs b/MediaBrowser.Dlna/PlayTo/TRANSPORTSTATE.cs
new file mode 100644
index 000000000..d58c4413c
--- /dev/null
+++ b/MediaBrowser.Dlna/PlayTo/TRANSPORTSTATE.cs
@@ -0,0 +1,11 @@
+namespace MediaBrowser.Dlna.PlayTo
+{
+ public enum TRANSPORTSTATE
+ {
+ STOPPED,
+ PLAYING,
+ TRANSITIONING,
+ PAUSED_PLAYBACK,
+ PAUSED
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Dlna/PlayTo/uParser.cs b/MediaBrowser.Dlna/PlayTo/uParser.cs
index a9ebd4fb0..838ddfc31 100644
--- a/MediaBrowser.Dlna/PlayTo/uParser.cs
+++ b/MediaBrowser.Dlna/PlayTo/uParser.cs
@@ -44,9 +44,4 @@ namespace MediaBrowser.Dlna.PlayTo
return UpnpContainer.Create(uItem.Element);
}
}
-
- public class uParserObject
- {
- public XElement Element { get; set; }
- }
}
diff --git a/MediaBrowser.Dlna/PlayTo/uParserObject.cs b/MediaBrowser.Dlna/PlayTo/uParserObject.cs
new file mode 100644
index 000000000..265ef7f8d
--- /dev/null
+++ b/MediaBrowser.Dlna/PlayTo/uParserObject.cs
@@ -0,0 +1,9 @@
+using System.Xml.Linq;
+
+namespace MediaBrowser.Dlna.PlayTo
+{
+ public class uParserObject
+ {
+ public XElement Element { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
index 9283f4ba4..409c646d9 100644
--- a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
+++ b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs
@@ -19,8 +19,8 @@ namespace MediaBrowser.Dlna.Profiles
ModelDescription = "Media Browser";
ModelName = "Media Browser";
ModelNumber = "Media Browser";
- ModelUrl = "http://mediabrowser3.com/";
- ManufacturerUrl = "http://mediabrowser3.com/";
+ ModelUrl = "http://mediabrowser.tv/";
+ ManufacturerUrl = "http://mediabrowser.tv/";
AlbumArtPn = "JPEG_SM";
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Default.xml b/MediaBrowser.Dlna/Profiles/Xml/Default.xml
index f556e8504..f6b52a727 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Default.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Default.xml
@@ -3,11 +3,11 @@
<Name>Generic Device</Name>
<FriendlyName>Media Browser</FriendlyName>
<Manufacturer>Media Browser</Manufacturer>
- <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
<ModelName>Media Browser</ModelName>
<ModelDescription>Media Browser</ModelDescription>
<ModelNumber>Media Browser</ModelNumber>
- <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
index 56a55ba02..22df1501d 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
@@ -8,11 +8,11 @@
</Identification>
<FriendlyName>Media Browser</FriendlyName>
<Manufacturer>Media Browser</Manufacturer>
- <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
<ModelName>Media Browser</ModelName>
<ModelDescription>Media Browser</ModelDescription>
<ModelNumber>Media Browser</ModelNumber>
- <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
index f449d5dee..49d45687f 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
@@ -9,11 +9,11 @@
</Identification>
<FriendlyName>Media Browser</FriendlyName>
<Manufacturer>Media Browser</Manufacturer>
- <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
<ModelName>Media Browser</ModelName>
<ModelDescription>Media Browser</ModelDescription>
<ModelNumber>Media Browser</ModelNumber>
- <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
index 9c2fb22e8..5476159f0 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
@@ -7,11 +7,11 @@
</Identification>
<FriendlyName>Media Browser</FriendlyName>
<Manufacturer>Media Browser</Manufacturer>
- <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
<ModelName>Media Browser</ModelName>
<ModelDescription>Media Browser</ModelDescription>
<ModelNumber>Media Browser</ModelNumber>
- <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
index bc661d439..2a54860b6 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
@@ -10,11 +10,11 @@
</Identification>
<FriendlyName>Media Browser</FriendlyName>
<Manufacturer>Media Browser</Manufacturer>
- <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
<ModelName>Media Browser</ModelName>
<ModelDescription>Media Browser</ModelDescription>
<ModelNumber>Media Browser</ModelNumber>
- <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
index 7b281abd1..a35f9b413 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
@@ -9,11 +9,11 @@
</Identification>
<FriendlyName>Media Browser</FriendlyName>
<Manufacturer>Media Browser</Manufacturer>
- <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
<ModelName>Media Browser</ModelName>
<ModelDescription>Media Browser</ModelDescription>
<ModelNumber>Media Browser</ModelNumber>
- <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<EnableAlbumArtInDidl>true</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
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 352299e0f..3a7e99eaa 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
@@ -9,11 +9,11 @@
</Identification>
<FriendlyName>Media Browser</FriendlyName>
<Manufacturer>Microsoft Corporation</Manufacturer>
- <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
<ModelName>Windows Media Player Sharing</ModelName>
<ModelDescription>Media Browser</ModelDescription>
<ModelNumber>3.0</ModelNumber>
- <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
index af35b5f1a..61b5d1a05 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
@@ -11,11 +11,11 @@
</Identification>
<FriendlyName>Media Browser</FriendlyName>
<Manufacturer>Microsoft Corporation</Manufacturer>
- <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
<ModelName>Windows Media Player Sharing</ModelName>
<ModelDescription>Media Browser</ModelDescription>
<ModelNumber>3.0</ModelNumber>
- <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
index f870ac1b4..04768020c 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
@@ -10,11 +10,11 @@
</Identification>
<FriendlyName>Media Browser</FriendlyName>
<Manufacturer>Media Browser</Manufacturer>
- <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
<ModelName>Media Browser</ModelName>
<ModelDescription>Media Browser</ModelDescription>
<ModelNumber>Media Browser</ModelNumber>
- <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
index 3605003e1..5c28c4e38 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
@@ -10,11 +10,11 @@
</Identification>
<FriendlyName>Media Browser</FriendlyName>
<Manufacturer>Media Browser</Manufacturer>
- <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
<ModelName>Media Browser</ModelName>
<ModelDescription>Media Browser</ModelDescription>
<ModelNumber>Media Browser</ModelNumber>
- <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
<IgnoreTranscodeByteRangeRequests>true</IgnoreTranscodeByteRangeRequests>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
index bbe2d5bcf..fc8d7692d 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
@@ -8,11 +8,11 @@
</Identification>
<FriendlyName>Media Browser</FriendlyName>
<Manufacturer>Media Browser</Manufacturer>
- <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
<ModelName>Media Browser</ModelName>
<ModelDescription>Media Browser</ModelDescription>
<ModelNumber>Media Browser</ModelNumber>
- <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio,Photo,Video</SupportedMediaTypes>
diff --git a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
index 0b7e10c01..1d1b2375e 100644
--- a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
+++ b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
@@ -9,11 +9,11 @@
</Identification>
<FriendlyName>Media Browser</FriendlyName>
<Manufacturer>Media Browser</Manufacturer>
- <ManufacturerUrl>http://mediabrowser3.com/</ManufacturerUrl>
+ <ManufacturerUrl>http://mediabrowser.tv/</ManufacturerUrl>
<ModelName>Media Browser</ModelName>
<ModelDescription>Media Browser</ModelDescription>
<ModelNumber>Media Browser</ModelNumber>
- <ModelUrl>http://mediabrowser3.com/</ModelUrl>
+ <ModelUrl>http://mediabrowser.tv/</ModelUrl>
<IgnoreTranscodeByteRangeRequests>false</IgnoreTranscodeByteRangeRequests>
<EnableAlbumArtInDidl>false</EnableAlbumArtInDidl>
<SupportedMediaTypes>Audio</SupportedMediaTypes>
diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
index 8366e6fb9..083ec8c82 100644
--- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
+++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
@@ -147,7 +147,7 @@ namespace MediaBrowser.Dlna.Ssdp
SendDatagram(header, values, endpoint, null);
- _logger.Info("{1} - Responded to a {0} request to {2}", d.Type, endpoint, d.Address.ToString());
+ _logger.Debug("{1} - Responded to a {0} request to {2}", d.Type, endpoint, d.Address.ToString());
}
}
}
diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
index e129468d3..2343d9718 100644
--- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
+++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
@@ -61,6 +61,12 @@
<Compile Include="Encoder\InternalEncodingTaskFactory.cs" />
<Compile Include="Encoder\MediaEncoder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Subtitles\ISubtitleParser.cs" />
+ <Compile Include="Subtitles\ISubtitleWriter.cs" />
+ <Compile Include="Subtitles\SrtParser.cs" />
+ <Compile Include="Subtitles\SsaParser.cs" />
+ <Compile Include="Subtitles\SubtitleTrackInfo.cs" />
+ <Compile Include="Subtitles\VttWriter.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj">
@@ -79,14 +85,9 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
+ <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
- <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
- <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
- <PropertyGroup>
- <ErrorText>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=322105. The missing file is {0}.</ErrorText>
- </PropertyGroup>
- <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
- </Target>
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
<!-- 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/Subtitles/ISubtitleParser.cs b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs
new file mode 100644
index 000000000..b983bc5d4
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleParser.cs
@@ -0,0 +1,9 @@
+using System.IO;
+
+namespace MediaBrowser.MediaEncoding.Subtitles
+{
+ public interface ISubtitleParser
+ {
+ SubtitleTrackInfo Parse(Stream stream);
+ }
+}
diff --git a/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs
new file mode 100644
index 000000000..9cbd09e7b
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Subtitles/ISubtitleWriter.cs
@@ -0,0 +1,17 @@
+using System.IO;
+
+namespace MediaBrowser.MediaEncoding.Subtitles
+{
+ /// <summary>
+ /// Interface ISubtitleWriter
+ /// </summary>
+ public interface ISubtitleWriter
+ {
+ /// <summary>
+ /// Writes the specified information.
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <param name="stream">The stream.</param>
+ void Write(SubtitleTrackInfo info, Stream stream);
+ }
+}
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs
new file mode 100644
index 000000000..09bc52df4
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Subtitles/SrtParser.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text.RegularExpressions;
+
+namespace MediaBrowser.MediaEncoding.Subtitles
+{
+ public class SrtParser : ISubtitleParser
+ {
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+ public SubtitleTrackInfo Parse(Stream stream) {
+ var trackInfo = new SubtitleTrackInfo();
+ using ( var reader = new StreamReader(stream))
+ {
+ string line;
+ while ((line = reader.ReadLine()) != null)
+ {
+ if (string.IsNullOrWhiteSpace(line))
+ {
+ continue;
+ }
+ var subEvent = new SubtitleTrackEvent {Id = line};
+ line = reader.ReadLine();
+ var time = Regex.Split(line, @"[\t ]*-->[\t ]*");
+ subEvent.StartPositionTicks = GetTicks(time[0]);
+ var endTime = time[1];
+ var idx = endTime.IndexOf(" ", StringComparison.Ordinal);
+ if (idx > 0)
+ endTime = endTime.Substring(0, idx);
+ subEvent.EndPositionTicks = GetTicks(endTime);
+ var multiline = new List<string>();
+ while ((line = reader.ReadLine()) != null)
+ {
+ if (string.IsNullOrEmpty(line))
+ {
+ break;
+ }
+ multiline.Add(line);
+ }
+ 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);
+ subEvent.Text = Regex.Replace(subEvent.Text, "&lt;(\\/?(font|b|u|i|s))((\\s+(\\w|\\w[\\w\\-]*\\w)(\\s*=\\s*(?:\\\".*?\\\"|'.*?'|[^'\\\">\\s]+))?)+\\s*|\\s*)(\\/?)&gt;", "<$1$3$7>", RegexOptions.IgnoreCase);
+ subEvent.Text = Regex.Replace(subEvent.Text, @"\\N", "<br />",RegexOptions.IgnoreCase);
+ trackInfo.TrackEvents.Add(subEvent);
+ }
+ }
+ return trackInfo;
+ }
+
+ long GetTicks(string time) {
+ TimeSpan span;
+ return TimeSpan.TryParseExact(time, @"hh\:mm\:ss\.fff", _usCulture, out span)
+ ? span.Ticks
+ : (TimeSpan.TryParseExact(time, @"hh\:mm\:ss\,fff", _usCulture, out span)
+ ? span.Ticks : 0);
+ }
+ }
+}
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs
new file mode 100644
index 000000000..996ef1c4e
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace MediaBrowser.MediaEncoding.Subtitles
+{
+ public class SsaParser : ISubtitleParser
+ {
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
+ public SubtitleTrackInfo Parse(Stream stream)
+ {
+ 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)
+ {
+ 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);
+ subEvent.Text = Regex.Replace(subEvent.Text, @"\\N", "<br />", 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/SubtitleTrackInfo.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleTrackInfo.cs
new file mode 100644
index 000000000..67d70ed6e
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleTrackInfo.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.MediaEncoding.Subtitles
+{
+ public class SubtitleTrackInfo
+ {
+ public List<SubtitleTrackEvent> TrackEvents { get; set; }
+
+ public SubtitleTrackInfo()
+ {
+ TrackEvents = new List<SubtitleTrackEvent>();
+ }
+ }
+
+ public class SubtitleTrackEvent
+ {
+ public string Id { get; set; }
+ public string Text { get; set; }
+ public long StartPositionTicks { get; set; }
+ public long EndPositionTicks { get; set; }
+ }
+}
diff --git a/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs
new file mode 100644
index 000000000..dc750fb6b
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Subtitles/VttWriter.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.MediaEncoding.Subtitles
+{
+ public class VttWriter : ISubtitleWriter
+ {
+ public void Write(SubtitleTrackInfo info, Stream stream) {
+ using (var writer = new StreamWriter(stream))
+ {
+ writer.WriteLine("WEBVTT");
+ writer.WriteLine(string.Empty);
+ foreach (var trackEvent in info.TrackEvents)
+ {
+ writer.WriteLine(@"{0:hh\:mm\:ss\.fff} --> {1:hh\:mm\:ss\.fff}", TimeSpan.FromTicks(trackEvent.StartPositionTicks), TimeSpan.FromTicks(trackEvent.EndPositionTicks));
+ writer.WriteLine(trackEvent.Text);
+ writer.WriteLine(string.Empty);
+ }
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
index f6c8f6135..ef59f8878 100644
--- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
+++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
@@ -62,6 +62,9 @@
<Compile Include="..\MediaBrowser.Model\ApiClient\ApiClientExtensions.cs">
<Link>ApiClient\ApiClientExtensions.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\ApiClient\GeneralCommandEventArgs.cs">
+ <Link>ApiClient\GeneralCommandEventArgs.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\ApiClient\HttpResponseEventArgs.cs">
<Link>ApiClient\HttpResponseEventArgs.cs</Link>
</Compile>
@@ -71,14 +74,20 @@
<Compile Include="..\MediaBrowser.Model\ApiClient\IServerEvents.cs">
<Link>ApiClient\IServerEvents.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\ApiClient\ServerEventArgs.cs">
- <Link>ApiClient\ServerEventArgs.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\ApiClient\SessionUpdatesEventArgs.cs">
+ <Link>ApiClient\SessionUpdatesEventArgs.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Channels\ChannelItemQuery.cs">
+ <Link>Channels\ChannelItemQuery.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Channels\ChannelQuery.cs">
<Link>Channels\ChannelQuery.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\AutoOrganize.cs">
- <Link>Configuration\AutoOrganize.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Chapters\RemoteChapterInfo.cs">
+ <Link>Chapters\RemoteChapterInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Chapters\RemoteChapterResult.cs">
+ <Link>Chapters\RemoteChapterResult.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\BaseApplicationConfiguration.cs">
<Link>Configuration\BaseApplicationConfiguration.cs</Link>
@@ -86,30 +95,78 @@
<Compile Include="..\MediaBrowser.Model\Configuration\DlnaOptions.cs">
<Link>Configuration\DlnaOptions.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\EncodingQuality.cs">
+ <Link>Configuration\EncodingQuality.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\ImageOption.cs">
+ <Link>Configuration\ImageOption.cs</Link>
+ </Compile>
+ <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>
<Compile Include="..\MediaBrowser.Model\Configuration\MetadataPlugin.cs">
<Link>Configuration\MetadataPlugin.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\MetadataPluginSummary.cs">
+ <Link>Configuration\MetadataPluginSummary.cs</Link>
+ </Compile>
+ <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>
+ <Compile Include="..\MediaBrowser.Model\Configuration\UnratedItem.cs">
+ <Link>Configuration\UnratedItem.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\UserConfiguration.cs">
<Link>Configuration\UserConfiguration.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\AudioOptions.cs">
+ <Link>Dlna\AudioOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\CodecProfile.cs">
<Link>Dlna\CodecProfile.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\CodecType.cs">
+ <Link>Dlna\CodecType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\ConditionProcessor.cs">
<Link>Dlna\ConditionProcessor.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\ContainerProfile.cs">
<Link>Dlna\ContainerProfile.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\ContentFeatureBuilder.cs">
+ <Link>Dlna\ContentFeatureBuilder.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\DeviceIdentification.cs">
<Link>Dlna\DeviceIdentification.cs</Link>
</Compile>
@@ -119,30 +176,57 @@
<Compile Include="..\MediaBrowser.Model\Dlna\DeviceProfileInfo.cs">
<Link>Dlna\DeviceProfileInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\DeviceProfileType.cs">
+ <Link>Dlna\DeviceProfileType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\DirectPlayProfile.cs">
<Link>Dlna\DirectPlayProfile.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\DlnaFlags.cs">
+ <Link>Dlna\DlnaFlags.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\DlnaMaps.cs">
<Link>Dlna\DlnaMaps.cs</Link>
</Compile>
+ <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>
+ <Compile Include="..\MediaBrowser.Model\Dlna\HttpHeaderInfo.cs">
+ <Link>Dlna\HttpHeaderInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\MediaFormatProfile.cs">
<Link>Dlna\MediaFormatProfile.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\MediaFormatProfileResolver.cs">
<Link>Dlna\MediaFormatProfileResolver.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\ProfileCondition.cs">
+ <Link>Dlna\ProfileCondition.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\ProfileConditionType.cs">
+ <Link>Dlna\ProfileConditionType.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\ProfileConditionValue.cs">
+ <Link>Dlna\ProfileConditionValue.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\ResponseProfile.cs">
<Link>Dlna\ResponseProfile.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\SearchCriteria.cs">
<Link>Dlna\SearchCriteria.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\SearchType.cs">
+ <Link>Dlna\SearchType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\SortCriteria.cs">
<Link>Dlna\SortCriteria.cs</Link>
</Compile>
@@ -152,15 +236,27 @@
<Compile Include="..\MediaBrowser.Model\Dlna\StreamInfo.cs">
<Link>Dlna\StreamInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\TranscodeSeekInfo.cs">
+ <Link>Dlna\TranscodeSeekInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\TranscodingProfile.cs">
<Link>Dlna\TranscodingProfile.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\VideoOptions.cs">
+ <Link>Dlna\VideoOptions.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\XmlAttribute.cs">
+ <Link>Dlna\XmlAttribute.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Drawing\DrawingUtils.cs">
<Link>Drawing\DrawingUtils.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Drawing\ImageOutputFormat.cs">
<Link>Drawing\ImageOutputFormat.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Drawing\ImageSize.cs">
+ <Link>Drawing\ImageSize.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\BaseItemDto.cs">
<Link>Dto\BaseItemDto.cs</Link>
</Compile>
@@ -191,39 +287,60 @@
<Compile Include="..\MediaBrowser.Model\Dto\ItemIndex.cs">
<Link>Dto\ItemIndex.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Dto\MediaVersionInfo.cs">
- <Link>Dto\MediaVersionInfo.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Dto\MediaSourceInfo.cs">
+ <Link>Dto\MediaSourceInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Dto\RatingType.cs">
+ <Link>Dto\RatingType.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Dto\RecommendationDto.cs">
<Link>Dto\RecommendationDto.cs</Link>
</Compile>
+ <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>
+ <Compile Include="..\MediaBrowser.Model\Dto\SubtitleDownloadOptions.cs">
+ <Link>Dto\SubtitleDownloadOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\UserDto.cs">
<Link>Dto\UserDto.cs</Link>
</Compile>
<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>
<Compile Include="..\MediaBrowser.Model\Entities\ChapterInfo.cs">
<Link>Entities\ChapterInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\CollectionType.cs">
+ <Link>Entities\CollectionType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\DisplayPreferences.cs">
<Link>Entities\DisplayPreferences.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\EmptyRequestResult.cs">
+ <Link>Entities\EmptyRequestResult.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\IHasProviderIds.cs">
<Link>Entities\IHasProviderIds.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Entities\ImageType.cs">
<Link>Entities\ImageType.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\IsoType.cs">
+ <Link>Entities\IsoType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\ItemReview.cs">
<Link>Entities\ItemReview.cs</Link>
</Compile>
@@ -236,9 +353,15 @@
<Compile Include="..\MediaBrowser.Model\Entities\MBRegistrationRecord.cs">
<Link>Entities\MBRegistrationRecord.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\MediaInfo.cs">
+ <Link>Entities\MediaInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\MediaStream.cs">
<Link>Entities\MediaStream.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\MediaStreamType.cs">
+ <Link>Entities\MediaStreamType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\MediaType.cs">
<Link>Entities\MediaType.cs</Link>
</Compile>
@@ -251,6 +374,9 @@
<Compile Include="..\MediaBrowser.Model\Entities\MetadataProviders.cs">
<Link>Entities\MetadataProviders.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\PackageReviewInfo.cs">
+ <Link>Entities\PackageReviewInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\ParentalRating.cs">
<Link>Entities\ParentalRating.cs</Link>
</Compile>
@@ -260,27 +386,51 @@
<Compile Include="..\MediaBrowser.Model\Entities\PluginSecurityInfo.cs">
<Link>Entities\PluginSecurityInfo.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Entities\RequestResult.cs">
- <Link>Entities\RequestResult.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Entities\ProviderIdsExtensions.cs">
+ <Link>Entities\ProviderIdsExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\ScrollDirection.cs">
+ <Link>Entities\ScrollDirection.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Entities\SeriesStatus.cs">
<Link>Entities\SeriesStatus.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\SortOrder.cs">
+ <Link>Entities\SortOrder.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\UserDataSaveReason.cs">
+ <Link>Entities\UserDataSaveReason.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\Video3DFormat.cs">
<Link>Entities\Video3DFormat.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\VideoSize.cs">
+ <Link>Entities\VideoSize.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\VideoType.cs">
<Link>Entities\VideoType.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Entities\VirtualFolderInfo.cs">
<Link>Entities\VirtualFolderInfo.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\FileOrganization\FileOrganizationQuery.cs">
- <Link>FileOrganization\FileOrganizationQuery.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Events\GenericEventArgs.cs">
+ <Link>Events\GenericEventArgs.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\FileOrganization\EpisodeFileOrganizationRequest.cs">
+ <Link>FileOrganization\EpisodeFileOrganizationRequest.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\FileOrganization\FileOrganizationResult.cs">
<Link>FileOrganization\FileOrganizationResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\FileOrganization\FileOrganizationResultQuery.cs">
+ <Link>FileOrganization\FileOrganizationResultQuery.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\FileOrganization\FileOrganizerType.cs">
+ <Link>FileOrganization\FileOrganizerType.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\FileOrganization\FileSortingStatus.cs">
+ <Link>FileOrganization\FileSortingStatus.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Games\GameSystem.cs">
<Link>Games\GameSystem.cs</Link>
</Compile>
@@ -290,15 +440,33 @@
<Compile Include="..\MediaBrowser.Model\Globalization\CultureDto.cs">
<Link>Globalization\CultureDto.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Globalization\LocalizatonOption.cs">
+ <Link>Globalization\LocalizatonOption.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\IO\FileSystemEntryInfo.cs">
<Link>IO\FileSystemEntryInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\IO\FileSystemEntryType.cs">
+ <Link>IO\FileSystemEntryType.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\IO\IIsoManager.cs">
+ <Link>IO\IIsoManager.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\IO\IIsoMount.cs">
+ <Link>IO\IIsoMount.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\IO\IIsoMounter.cs">
+ <Link>IO\IIsoMounter.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\IO\IZipClient.cs">
<Link>IO\IZipClient.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Library\PlayAccess.cs">
<Link>Library\PlayAccess.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\BaseTimerInfoDto.cs">
+ <Link>LiveTv\BaseTimerInfoDto.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelInfoDto.cs">
<Link>LiveTv\ChannelInfoDto.cs</Link>
</Compile>
@@ -308,18 +476,45 @@
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelType.cs">
<Link>LiveTv\ChannelType.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\DayPattern.cs">
+ <Link>LiveTv\DayPattern.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\GuideInfo.cs">
+ <Link>LiveTv\GuideInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvInfo.cs">
+ <Link>LiveTv\LiveTvInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvServiceInfo.cs">
<Link>LiveTv\LiveTvServiceInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvServiceStatus.cs">
+ <Link>LiveTv\LiveTvServiceStatus.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvTunerInfoDto.cs">
+ <Link>LiveTv\LiveTvTunerInfoDto.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvTunerStatus.cs">
+ <Link>LiveTv\LiveTvTunerStatus.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\ProgramAudio.cs">
+ <Link>LiveTv\ProgramAudio.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\ProgramInfoDto.cs">
<Link>LiveTv\ProgramInfoDto.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\ProgramQuery.cs">
<Link>LiveTv\ProgramQuery.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\RecommendedProgramQuery.cs">
+ <Link>LiveTv\RecommendedProgramQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingGroupDto.cs">
<Link>LiveTv\RecordingGroupDto.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\RecordingGroupQuery.cs">
+ <Link>LiveTv\RecordingGroupQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingInfoDto.cs">
<Link>LiveTv\RecordingInfoDto.cs</Link>
</Compile>
@@ -332,9 +527,15 @@
<Compile Include="..\MediaBrowser.Model\LiveTv\SeriesTimerInfoDto.cs">
<Link>LiveTv\SeriesTimerInfoDto.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\SeriesTimerQuery.cs">
+ <Link>LiveTv\SeriesTimerQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\TimerInfoDto.cs">
<Link>LiveTv\TimerInfoDto.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\TimerQuery.cs">
+ <Link>LiveTv\TimerQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Logging\ILogger.cs">
<Link>Logging\ILogger.cs</Link>
</Compile>
@@ -347,12 +548,27 @@
<Compile Include="..\MediaBrowser.Model\Logging\NullLogger.cs">
<Link>Logging\NullLogger.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\MediaInfo\AudioCodec.cs">
+ <Link>MediaInfo\AudioCodec.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\MediaInfo\BlurayDiscInfo.cs">
<Link>MediaInfo\BlurayDiscInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\MediaInfo\Container.cs">
+ <Link>MediaInfo\Container.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\MediaInfo\IBlurayExaminer.cs">
<Link>MediaInfo\IBlurayExaminer.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\MediaInfo\SubtitleFormat.cs">
+ <Link>MediaInfo\SubtitleFormat.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\MediaInfo\TransportStreamTimestamp.cs">
+ <Link>MediaInfo\TransportStreamTimestamp.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\MediaInfo\VideoCodec.cs">
+ <Link>MediaInfo\VideoCodec.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Net\HttpException.cs">
<Link>Net\HttpException.cs</Link>
</Compile>
@@ -371,9 +587,15 @@
<Compile Include="..\MediaBrowser.Model\Net\WebSocketState.cs">
<Link>Net\WebSocketState.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\News\NewsChannel.cs">
+ <Link>News\NewsChannel.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\News\NewsItem.cs">
<Link>News\NewsItem.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\News\NewsQuery.cs">
+ <Link>News\NewsQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Notifications\Notification.cs">
<Link>Notifications\Notification.cs</Link>
</Compile>
@@ -383,12 +605,21 @@
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationQuery.cs">
<Link>Notifications\NotificationQuery.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\NotificationRequest.cs">
+ <Link>Notifications\NotificationRequest.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationResult.cs">
<Link>Notifications\NotificationResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\NotificationServiceInfo.cs">
+ <Link>Notifications\NotificationServiceInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationsSummary.cs">
<Link>Notifications\NotificationsSummary.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\NotificationTypeInfo.cs">
+ <Link>Notifications\NotificationTypeInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Plugins\BasePluginConfiguration.cs">
<Link>Plugins\BasePluginConfiguration.cs</Link>
</Compile>
@@ -398,18 +629,30 @@
<Compile Include="..\MediaBrowser.Model\Providers\ExternalIdInfo.cs">
<Link>Providers\ExternalIdInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Providers\ExternalUrl.cs">
+ <Link>Providers\ExternalUrl.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Providers\ImageProviderInfo.cs">
<Link>Providers\ImageProviderInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Providers\RemoteImageInfo.cs">
<Link>Providers\RemoteImageInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Providers\RemoteImageQuery.cs">
+ <Link>Providers\RemoteImageQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Providers\RemoteImageResult.cs">
<Link>Providers\RemoteImageResult.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Providers\RemoteSearchResult.cs">
<Link>Providers\RemoteSearchResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Providers\RemoteSubtitleInfo.cs">
+ <Link>Providers\RemoteSubtitleInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Querying\AllThemeMediaResult.cs">
+ <Link>Querying\AllThemeMediaResult.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Querying\ArtistsQuery.cs">
<Link>Querying\ArtistsQuery.cs</Link>
</Compile>
@@ -446,14 +689,23 @@
<Compile Include="..\MediaBrowser.Model\Querying\QueryResult.cs">
<Link>Querying\QueryResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Querying\SeasonQuery.cs">
+ <Link>Querying\SeasonQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Querying\SessionQuery.cs">
<Link>Querying\SessionQuery.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Querying\SimilarItemsByNameQuery.cs">
+ <Link>Querying\SimilarItemsByNameQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Querying\SimilarItemsQuery.cs">
<Link>Querying\SimilarItemsQuery.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Querying\ThemeSongsResult.cs">
- <Link>Querying\ThemeSongsResult.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Querying\ThemeMediaResult.cs">
+ <Link>Querying\ThemeMediaResult.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Querying\UpcomingEpisodesQuery.cs">
+ <Link>Querying\UpcomingEpisodesQuery.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Querying\UserQuery.cs">
<Link>Querying\UserQuery.cs</Link>
@@ -476,14 +728,35 @@
<Compile Include="..\MediaBrowser.Model\Session\BrowseRequest.cs">
<Link>Session\BrowseRequest.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\ClientCapabilities.cs">
+ <Link>Session\ClientCapabilities.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Session\GeneralCommand.cs">
<Link>Session\GeneralCommand.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\GeneralCommandType.cs">
+ <Link>Session\GeneralCommandType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Session\MessageCommand.cs">
<Link>Session\MessageCommand.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Session\PlaybackReports.cs">
- <Link>Session\PlaybackReports.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Session\PlaybackProgressInfo.cs">
+ <Link>Session\PlaybackProgressInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\PlaybackStartInfo.cs">
+ <Link>Session\PlaybackStartInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\PlaybackStopInfo.cs">
+ <Link>Session\PlaybackStopInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\PlayCommand.cs">
+ <Link>Session\PlayCommand.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\PlayerStateInfo.cs">
+ <Link>Session\PlayerStateInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\PlayMethod.cs">
+ <Link>Session\PlayMethod.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Session\PlayRequest.cs">
<Link>Session\PlayRequest.cs</Link>
@@ -491,12 +764,18 @@
<Compile Include="..\MediaBrowser.Model\Session\PlaystateCommand.cs">
<Link>Session\PlaystateCommand.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\PlaystateRequest.cs">
+ <Link>Session\PlaystateRequest.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Session\SessionCapabilities.cs">
<Link>Session\SessionCapabilities.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Session\SessionInfoDto.cs">
<Link>Session\SessionInfoDto.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\SessionUserInfo.cs">
+ <Link>Session\SessionUserInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Session\UserDataChangeInfo.cs">
<Link>Session\UserDataChangeInfo.cs</Link>
</Compile>
@@ -524,6 +803,9 @@
<Compile Include="..\MediaBrowser.Model\Themes\AppTheme.cs">
<Link>Themes\AppTheme.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Themes\AppThemeInfo.cs">
+ <Link>Themes\AppThemeInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Themes\ThemeImage.cs">
<Link>Themes\ThemeImage.cs</Link>
</Compile>
@@ -565,6 +847,7 @@
<ItemGroup>
<Content Include="FodyWeavers.xml" />
</ItemGroup>
+ <ItemGroup />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>if $(ConfigurationName) == Release (
diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
index 9845cb6b2..38ca64019 100644
--- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
+++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
@@ -52,20 +52,29 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\MediaBrowser.Model\ApiClient\GeneralCommandEventArgs.cs">
+ <Link>ApiClient\GeneralCommandEventArgs.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\ApiClient\HttpResponseEventArgs.cs">
<Link>ApiClient\HttpResponseEventArgs.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\ApiClient\IServerEvents.cs">
<Link>ApiClient\IServerEvents.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\ApiClient\ServerEventArgs.cs">
- <Link>ApiClient\ServerEventArgs.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\ApiClient\SessionUpdatesEventArgs.cs">
+ <Link>ApiClient\SessionUpdatesEventArgs.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Channels\ChannelItemQuery.cs">
+ <Link>Channels\ChannelItemQuery.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Channels\ChannelQuery.cs">
<Link>Channels\ChannelQuery.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Configuration\AutoOrganize.cs">
- <Link>Configuration\AutoOrganize.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Chapters\RemoteChapterInfo.cs">
+ <Link>Chapters\RemoteChapterInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Chapters\RemoteChapterResult.cs">
+ <Link>Chapters\RemoteChapterResult.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\BaseApplicationConfiguration.cs">
<Link>Configuration\BaseApplicationConfiguration.cs</Link>
@@ -73,30 +82,78 @@
<Compile Include="..\MediaBrowser.Model\Configuration\DlnaOptions.cs">
<Link>Configuration\DlnaOptions.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\EncodingQuality.cs">
+ <Link>Configuration\EncodingQuality.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\ImageOption.cs">
+ <Link>Configuration\ImageOption.cs</Link>
+ </Compile>
+ <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>
<Compile Include="..\MediaBrowser.Model\Configuration\MetadataPlugin.cs">
<Link>Configuration\MetadataPlugin.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\MetadataPluginSummary.cs">
+ <Link>Configuration\MetadataPluginSummary.cs</Link>
+ </Compile>
+ <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>
+ <Compile Include="..\MediaBrowser.Model\Configuration\UnratedItem.cs">
+ <Link>Configuration\UnratedItem.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\UserConfiguration.cs">
<Link>Configuration\UserConfiguration.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\AudioOptions.cs">
+ <Link>Dlna\AudioOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\CodecProfile.cs">
<Link>Dlna\CodecProfile.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\CodecType.cs">
+ <Link>Dlna\CodecType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\ConditionProcessor.cs">
<Link>Dlna\ConditionProcessor.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\ContainerProfile.cs">
<Link>Dlna\ContainerProfile.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\ContentFeatureBuilder.cs">
+ <Link>Dlna\ContentFeatureBuilder.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\DeviceIdentification.cs">
<Link>Dlna\DeviceIdentification.cs</Link>
</Compile>
@@ -106,30 +163,57 @@
<Compile Include="..\MediaBrowser.Model\Dlna\DeviceProfileInfo.cs">
<Link>Dlna\DeviceProfileInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\DeviceProfileType.cs">
+ <Link>Dlna\DeviceProfileType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\DirectPlayProfile.cs">
<Link>Dlna\DirectPlayProfile.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\DlnaFlags.cs">
+ <Link>Dlna\DlnaFlags.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\DlnaMaps.cs">
<Link>Dlna\DlnaMaps.cs</Link>
</Compile>
+ <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>
+ <Compile Include="..\MediaBrowser.Model\Dlna\HttpHeaderInfo.cs">
+ <Link>Dlna\HttpHeaderInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\MediaFormatProfile.cs">
<Link>Dlna\MediaFormatProfile.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\MediaFormatProfileResolver.cs">
<Link>Dlna\MediaFormatProfileResolver.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\ProfileCondition.cs">
+ <Link>Dlna\ProfileCondition.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\ProfileConditionType.cs">
+ <Link>Dlna\ProfileConditionType.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\ProfileConditionValue.cs">
+ <Link>Dlna\ProfileConditionValue.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\ResponseProfile.cs">
<Link>Dlna\ResponseProfile.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\SearchCriteria.cs">
<Link>Dlna\SearchCriteria.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\SearchType.cs">
+ <Link>Dlna\SearchType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\SortCriteria.cs">
<Link>Dlna\SortCriteria.cs</Link>
</Compile>
@@ -139,15 +223,27 @@
<Compile Include="..\MediaBrowser.Model\Dlna\StreamInfo.cs">
<Link>Dlna\StreamInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\TranscodeSeekInfo.cs">
+ <Link>Dlna\TranscodeSeekInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dlna\TranscodingProfile.cs">
<Link>Dlna\TranscodingProfile.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\VideoOptions.cs">
+ <Link>Dlna\VideoOptions.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Dlna\XmlAttribute.cs">
+ <Link>Dlna\XmlAttribute.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Drawing\DrawingUtils.cs">
<Link>Drawing\DrawingUtils.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Drawing\ImageOutputFormat.cs">
<Link>Drawing\ImageOutputFormat.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Drawing\ImageSize.cs">
+ <Link>Drawing\ImageSize.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\BaseItemDto.cs">
<Link>Dto\BaseItemDto.cs</Link>
</Compile>
@@ -178,39 +274,60 @@
<Compile Include="..\MediaBrowser.Model\Dto\ItemIndex.cs">
<Link>Dto\ItemIndex.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Dto\MediaVersionInfo.cs">
- <Link>Dto\MediaVersionInfo.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Dto\MediaSourceInfo.cs">
+ <Link>Dto\MediaSourceInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Dto\RatingType.cs">
+ <Link>Dto\RatingType.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Dto\RecommendationDto.cs">
<Link>Dto\RecommendationDto.cs</Link>
</Compile>
+ <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>
+ <Compile Include="..\MediaBrowser.Model\Dto\SubtitleDownloadOptions.cs">
+ <Link>Dto\SubtitleDownloadOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\UserDto.cs">
<Link>Dto\UserDto.cs</Link>
</Compile>
<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>
<Compile Include="..\MediaBrowser.Model\Entities\ChapterInfo.cs">
<Link>Entities\ChapterInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\CollectionType.cs">
+ <Link>Entities\CollectionType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\DisplayPreferences.cs">
<Link>Entities\DisplayPreferences.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\EmptyRequestResult.cs">
+ <Link>Entities\EmptyRequestResult.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\IHasProviderIds.cs">
<Link>Entities\IHasProviderIds.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Entities\ImageType.cs">
<Link>Entities\ImageType.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\IsoType.cs">
+ <Link>Entities\IsoType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\ItemReview.cs">
<Link>Entities\ItemReview.cs</Link>
</Compile>
@@ -223,9 +340,15 @@
<Compile Include="..\MediaBrowser.Model\Entities\MBRegistrationRecord.cs">
<Link>Entities\MBRegistrationRecord.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\MediaInfo.cs">
+ <Link>Entities\MediaInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\MediaStream.cs">
<Link>Entities\MediaStream.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\MediaStreamType.cs">
+ <Link>Entities\MediaStreamType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\MediaType.cs">
<Link>Entities\MediaType.cs</Link>
</Compile>
@@ -238,6 +361,9 @@
<Compile Include="..\MediaBrowser.Model\Entities\MetadataProviders.cs">
<Link>Entities\MetadataProviders.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\PackageReviewInfo.cs">
+ <Link>Entities\PackageReviewInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\ParentalRating.cs">
<Link>Entities\ParentalRating.cs</Link>
</Compile>
@@ -247,27 +373,51 @@
<Compile Include="..\MediaBrowser.Model\Entities\PluginSecurityInfo.cs">
<Link>Entities\PluginSecurityInfo.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Entities\RequestResult.cs">
- <Link>Entities\RequestResult.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Entities\ProviderIdsExtensions.cs">
+ <Link>Entities\ProviderIdsExtensions.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\ScrollDirection.cs">
+ <Link>Entities\ScrollDirection.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Entities\SeriesStatus.cs">
<Link>Entities\SeriesStatus.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\SortOrder.cs">
+ <Link>Entities\SortOrder.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\UserDataSaveReason.cs">
+ <Link>Entities\UserDataSaveReason.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\Video3DFormat.cs">
<Link>Entities\Video3DFormat.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Entities\VideoSize.cs">
+ <Link>Entities\VideoSize.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\VideoType.cs">
<Link>Entities\VideoType.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Entities\VirtualFolderInfo.cs">
<Link>Entities\VirtualFolderInfo.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\FileOrganization\FileOrganizationQuery.cs">
- <Link>FileOrganization\FileOrganizationQuery.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Events\GenericEventArgs.cs">
+ <Link>Events\GenericEventArgs.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\FileOrganization\EpisodeFileOrganizationRequest.cs">
+ <Link>FileOrganization\EpisodeFileOrganizationRequest.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\FileOrganization\FileOrganizationResult.cs">
<Link>FileOrganization\FileOrganizationResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\FileOrganization\FileOrganizationResultQuery.cs">
+ <Link>FileOrganization\FileOrganizationResultQuery.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\FileOrganization\FileOrganizerType.cs">
+ <Link>FileOrganization\FileOrganizerType.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\FileOrganization\FileSortingStatus.cs">
+ <Link>FileOrganization\FileSortingStatus.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Games\GameSystem.cs">
<Link>Games\GameSystem.cs</Link>
</Compile>
@@ -277,15 +427,27 @@
<Compile Include="..\MediaBrowser.Model\Globalization\CultureDto.cs">
<Link>Globalization\CultureDto.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Globalization\LocalizatonOption.cs">
+ <Link>Globalization\LocalizatonOption.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\IO\FileSystemEntryInfo.cs">
<Link>IO\FileSystemEntryInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\IO\FileSystemEntryType.cs">
+ <Link>IO\FileSystemEntryType.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\IO\IIsoMount.cs">
+ <Link>IO\IIsoMount.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\IO\IZipClient.cs">
<Link>IO\IZipClient.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Library\PlayAccess.cs">
<Link>Library\PlayAccess.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\BaseTimerInfoDto.cs">
+ <Link>LiveTv\BaseTimerInfoDto.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelInfoDto.cs">
<Link>LiveTv\ChannelInfoDto.cs</Link>
</Compile>
@@ -295,18 +457,45 @@
<Compile Include="..\MediaBrowser.Model\LiveTv\ChannelType.cs">
<Link>LiveTv\ChannelType.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\DayPattern.cs">
+ <Link>LiveTv\DayPattern.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\GuideInfo.cs">
+ <Link>LiveTv\GuideInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvInfo.cs">
+ <Link>LiveTv\LiveTvInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvServiceInfo.cs">
<Link>LiveTv\LiveTvServiceInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvServiceStatus.cs">
+ <Link>LiveTv\LiveTvServiceStatus.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvTunerInfoDto.cs">
+ <Link>LiveTv\LiveTvTunerInfoDto.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\LiveTvTunerStatus.cs">
+ <Link>LiveTv\LiveTvTunerStatus.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\ProgramAudio.cs">
+ <Link>LiveTv\ProgramAudio.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\ProgramInfoDto.cs">
<Link>LiveTv\ProgramInfoDto.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\ProgramQuery.cs">
<Link>LiveTv\ProgramQuery.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\RecommendedProgramQuery.cs">
+ <Link>LiveTv\RecommendedProgramQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingGroupDto.cs">
<Link>LiveTv\RecordingGroupDto.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\RecordingGroupQuery.cs">
+ <Link>LiveTv\RecordingGroupQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\RecordingInfoDto.cs">
<Link>LiveTv\RecordingInfoDto.cs</Link>
</Compile>
@@ -319,9 +508,15 @@
<Compile Include="..\MediaBrowser.Model\LiveTv\SeriesTimerInfoDto.cs">
<Link>LiveTv\SeriesTimerInfoDto.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\SeriesTimerQuery.cs">
+ <Link>LiveTv\SeriesTimerQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\LiveTv\TimerInfoDto.cs">
<Link>LiveTv\TimerInfoDto.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\LiveTv\TimerQuery.cs">
+ <Link>LiveTv\TimerQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Logging\ILogger.cs">
<Link>Logging\ILogger.cs</Link>
</Compile>
@@ -334,12 +529,27 @@
<Compile Include="..\MediaBrowser.Model\Logging\NullLogger.cs">
<Link>Logging\NullLogger.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\MediaInfo\AudioCodec.cs">
+ <Link>MediaInfo\AudioCodec.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\MediaInfo\BlurayDiscInfo.cs">
<Link>MediaInfo\BlurayDiscInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\MediaInfo\Container.cs">
+ <Link>MediaInfo\Container.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\MediaInfo\IBlurayExaminer.cs">
<Link>MediaInfo\IBlurayExaminer.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\MediaInfo\SubtitleFormat.cs">
+ <Link>MediaInfo\SubtitleFormat.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\MediaInfo\TransportStreamTimestamp.cs">
+ <Link>MediaInfo\TransportStreamTimestamp.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\MediaInfo\VideoCodec.cs">
+ <Link>MediaInfo\VideoCodec.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Net\HttpException.cs">
<Link>Net\HttpException.cs</Link>
</Compile>
@@ -358,9 +568,15 @@
<Compile Include="..\MediaBrowser.Model\Net\WebSocketState.cs">
<Link>Net\WebSocketState.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\News\NewsChannel.cs">
+ <Link>News\NewsChannel.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\News\NewsItem.cs">
<Link>News\NewsItem.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\News\NewsQuery.cs">
+ <Link>News\NewsQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Notifications\Notification.cs">
<Link>Notifications\Notification.cs</Link>
</Compile>
@@ -370,12 +586,21 @@
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationQuery.cs">
<Link>Notifications\NotificationQuery.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\NotificationRequest.cs">
+ <Link>Notifications\NotificationRequest.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationResult.cs">
<Link>Notifications\NotificationResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\NotificationServiceInfo.cs">
+ <Link>Notifications\NotificationServiceInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Notifications\NotificationsSummary.cs">
<Link>Notifications\NotificationsSummary.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Notifications\NotificationTypeInfo.cs">
+ <Link>Notifications\NotificationTypeInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Plugins\BasePluginConfiguration.cs">
<Link>Plugins\BasePluginConfiguration.cs</Link>
</Compile>
@@ -385,18 +610,30 @@
<Compile Include="..\MediaBrowser.Model\Providers\ExternalIdInfo.cs">
<Link>Providers\ExternalIdInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Providers\ExternalUrl.cs">
+ <Link>Providers\ExternalUrl.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Providers\ImageProviderInfo.cs">
<Link>Providers\ImageProviderInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Providers\RemoteImageInfo.cs">
<Link>Providers\RemoteImageInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Providers\RemoteImageQuery.cs">
+ <Link>Providers\RemoteImageQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Providers\RemoteImageResult.cs">
<Link>Providers\RemoteImageResult.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Providers\RemoteSearchResult.cs">
<Link>Providers\RemoteSearchResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Providers\RemoteSubtitleInfo.cs">
+ <Link>Providers\RemoteSubtitleInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Querying\AllThemeMediaResult.cs">
+ <Link>Querying\AllThemeMediaResult.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Querying\ArtistsQuery.cs">
<Link>Querying\ArtistsQuery.cs</Link>
</Compile>
@@ -433,14 +670,23 @@
<Compile Include="..\MediaBrowser.Model\Querying\QueryResult.cs">
<Link>Querying\QueryResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Querying\SeasonQuery.cs">
+ <Link>Querying\SeasonQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Querying\SessionQuery.cs">
<Link>Querying\SessionQuery.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Querying\SimilarItemsByNameQuery.cs">
+ <Link>Querying\SimilarItemsByNameQuery.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Querying\SimilarItemsQuery.cs">
<Link>Querying\SimilarItemsQuery.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Querying\ThemeSongsResult.cs">
- <Link>Querying\ThemeSongsResult.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Querying\ThemeMediaResult.cs">
+ <Link>Querying\ThemeMediaResult.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Querying\UpcomingEpisodesQuery.cs">
+ <Link>Querying\UpcomingEpisodesQuery.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Querying\UserQuery.cs">
<Link>Querying\UserQuery.cs</Link>
@@ -463,14 +709,35 @@
<Compile Include="..\MediaBrowser.Model\Session\BrowseRequest.cs">
<Link>Session\BrowseRequest.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\ClientCapabilities.cs">
+ <Link>Session\ClientCapabilities.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Session\GeneralCommand.cs">
<Link>Session\GeneralCommand.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\GeneralCommandType.cs">
+ <Link>Session\GeneralCommandType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Session\MessageCommand.cs">
<Link>Session\MessageCommand.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Session\PlaybackReports.cs">
- <Link>Session\PlaybackReports.cs</Link>
+ <Compile Include="..\MediaBrowser.Model\Session\PlaybackProgressInfo.cs">
+ <Link>Session\PlaybackProgressInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\PlaybackStartInfo.cs">
+ <Link>Session\PlaybackStartInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\PlaybackStopInfo.cs">
+ <Link>Session\PlaybackStopInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\PlayCommand.cs">
+ <Link>Session\PlayCommand.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\PlayerStateInfo.cs">
+ <Link>Session\PlayerStateInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\PlayMethod.cs">
+ <Link>Session\PlayMethod.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Session\PlayRequest.cs">
<Link>Session\PlayRequest.cs</Link>
@@ -478,12 +745,18 @@
<Compile Include="..\MediaBrowser.Model\Session\PlaystateCommand.cs">
<Link>Session\PlaystateCommand.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\PlaystateRequest.cs">
+ <Link>Session\PlaystateRequest.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Session\SessionCapabilities.cs">
<Link>Session\SessionCapabilities.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Session\SessionInfoDto.cs">
<Link>Session\SessionInfoDto.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Session\SessionUserInfo.cs">
+ <Link>Session\SessionUserInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Session\UserDataChangeInfo.cs">
<Link>Session\UserDataChangeInfo.cs</Link>
</Compile>
@@ -511,6 +784,9 @@
<Compile Include="..\MediaBrowser.Model\Themes\AppTheme.cs">
<Link>Themes\AppTheme.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Themes\AppThemeInfo.cs">
+ <Link>Themes\AppThemeInfo.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Themes\ThemeImage.cs">
<Link>Themes\ThemeImage.cs</Link>
</Compile>
diff --git a/MediaBrowser.Model/ApiClient/GeneralCommandEventArgs.cs b/MediaBrowser.Model/ApiClient/GeneralCommandEventArgs.cs
new file mode 100644
index 000000000..ce518a7cc
--- /dev/null
+++ b/MediaBrowser.Model/ApiClient/GeneralCommandEventArgs.cs
@@ -0,0 +1,23 @@
+using MediaBrowser.Model.Session;
+using System;
+
+namespace MediaBrowser.Model.ApiClient
+{
+ /// <summary>
+ /// Class SystemCommandEventArgs
+ /// </summary>
+ public class GeneralCommandEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Gets or sets the command.
+ /// </summary>
+ /// <value>The command.</value>
+ public GeneralCommand Command { get; set; }
+
+ /// <summary>
+ /// Gets or sets the type of the known command.
+ /// </summary>
+ /// <value>The type of the known command.</value>
+ public GeneralCommandType? KnownCommandType { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs
index dd1603d01..e12a6cf2b 100644
--- a/MediaBrowser.Model/ApiClient/IApiClient.cs
+++ b/MediaBrowser.Model/ApiClient/IApiClient.cs
@@ -138,7 +138,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="notificationIdList">The notification id list.</param>
/// <param name="isRead">if set to <c>true</c> [is read].</param>
/// <returns>Task.</returns>
- Task MarkNotificationsRead(string userId, IEnumerable<Guid> notificationIdList, bool isRead);
+ Task MarkNotificationsRead(string userId, IEnumerable<string> notificationIdList, bool isRead);
/// <summary>
/// Gets the notifications summary.
@@ -447,7 +447,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="id">The id.</param>
/// <returns>Task{TaskInfo}.</returns>
/// <exception cref="ArgumentNullException">id</exception>
- Task<TaskInfo> GetScheduledTaskAsync(Guid id);
+ Task<TaskInfo> GetScheduledTaskAsync(string id);
/// <summary>
/// Gets a user by id
@@ -582,6 +582,38 @@ namespace MediaBrowser.Model.ApiClient
Task SendCommandAsync(string sessionId, GeneralCommand command);
/// <summary>
+ /// Sends the string.
+ /// </summary>
+ /// <param name="sessionId">The session identifier.</param>
+ /// <param name="text">The text.</param>
+ /// <returns>Task.</returns>
+ Task SendString(string sessionId, string text);
+
+ /// <summary>
+ /// Sets the volume.
+ /// </summary>
+ /// <param name="sessionId">The session identifier.</param>
+ /// <param name="volume">The volume.</param>
+ /// <returns>Task.</returns>
+ Task SetVolume(string sessionId, int volume);
+
+ /// <summary>
+ /// Sets the index of the audio stream.
+ /// </summary>
+ /// <param name="sessionId">The session identifier.</param>
+ /// <param name="index">The index.</param>
+ /// <returns>Task.</returns>
+ Task SetAudioStreamIndex(string sessionId, int index);
+
+ /// <summary>
+ /// Sets the index of the subtitle stream.
+ /// </summary>
+ /// <param name="sessionId">The session identifier.</param>
+ /// <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>
/// <param name="sessionId">The session id.</param>
@@ -632,7 +664,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="triggers">The triggers.</param>
/// <returns>Task{RequestResult}.</returns>
/// <exception cref="ArgumentNullException">id</exception>
- Task UpdateScheduledTaskTriggersAsync(Guid id, TaskTriggerInfo[] triggers);
+ Task UpdateScheduledTaskTriggersAsync(string id, TaskTriggerInfo[] triggers);
/// <summary>
/// Gets the display preferences.
@@ -760,7 +792,7 @@ namespace MediaBrowser.Model.ApiClient
/// </summary>
/// <param name="options">The options.</param>
/// <returns>System.String.</returns>
- string GetSubtitleUrl(SubtitleOptions options);
+ string GetSubtitleUrl(SubtitleDownloadOptions options);
/// <summary>
/// Gets an image url that can be used to download an image from the api
@@ -893,30 +925,6 @@ namespace MediaBrowser.Model.ApiClient
string GetThumbImageUrl(BaseItemDto item, ImageOptions options);
/// <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>
/// Gets the live tv information asynchronous.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
diff --git a/MediaBrowser.Model/ApiClient/IServerEvents.cs b/MediaBrowser.Model/ApiClient/IServerEvents.cs
index e13f3cc2c..62d8fdff3 100644
--- a/MediaBrowser.Model/ApiClient/IServerEvents.cs
+++ b/MediaBrowser.Model/ApiClient/IServerEvents.cs
@@ -1,4 +1,11 @@
-using System;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Events;
+using MediaBrowser.Model.Plugins;
+using MediaBrowser.Model.Session;
+using MediaBrowser.Model.Tasks;
+using MediaBrowser.Model.Updates;
+using System;
namespace MediaBrowser.Model.ApiClient
{
@@ -10,59 +17,55 @@ namespace MediaBrowser.Model.ApiClient
/// <summary>
/// Occurs when [user deleted].
/// </summary>
- event EventHandler<UserDeletedEventArgs> UserDeleted;
- /// <summary>
- /// Occurs when [scheduled task started].
- /// </summary>
- event EventHandler<ScheduledTaskStartedEventArgs> ScheduledTaskStarted;
+ event EventHandler<GenericEventArgs<string>> UserDeleted;
/// <summary>
/// Occurs when [scheduled task ended].
/// </summary>
- event EventHandler<ScheduledTaskEndedEventArgs> ScheduledTaskEnded;
+ event EventHandler<GenericEventArgs<TaskResult>> ScheduledTaskEnded;
/// <summary>
/// Occurs when [package installing].
/// </summary>
- event EventHandler<PackageInstallationEventArgs> PackageInstalling;
+ event EventHandler<GenericEventArgs<InstallationInfo>> PackageInstalling;
/// <summary>
/// Occurs when [package installation failed].
/// </summary>
- event EventHandler<PackageInstallationEventArgs> PackageInstallationFailed;
+ event EventHandler<GenericEventArgs<InstallationInfo>> PackageInstallationFailed;
/// <summary>
/// Occurs when [package installation completed].
/// </summary>
- event EventHandler<PackageInstallationEventArgs> PackageInstallationCompleted;
+ event EventHandler<GenericEventArgs<InstallationInfo>> PackageInstallationCompleted;
/// <summary>
/// Occurs when [package installation cancelled].
/// </summary>
- event EventHandler<PackageInstallationEventArgs> PackageInstallationCancelled;
+ event EventHandler<GenericEventArgs<InstallationInfo>> PackageInstallationCancelled;
/// <summary>
/// Occurs when [user updated].
/// </summary>
- event EventHandler<UserUpdatedEventArgs> UserUpdated;
+ event EventHandler<GenericEventArgs<UserDto>> UserUpdated;
/// <summary>
/// Occurs when [plugin uninstalled].
/// </summary>
- event EventHandler<PluginUninstallEventArgs> PluginUninstalled;
+ event EventHandler<GenericEventArgs<PluginInfo>> PluginUninstalled;
/// <summary>
/// Occurs when [library changed].
/// </summary>
- event EventHandler<LibraryChangedEventArgs> LibraryChanged;
+ event EventHandler<GenericEventArgs<LibraryUpdateInfo>> LibraryChanged;
/// <summary>
/// Occurs when [browse command].
/// </summary>
- event EventHandler<BrowseRequestEventArgs> BrowseCommand;
+ event EventHandler<GenericEventArgs<BrowseRequest>> BrowseCommand;
/// <summary>
/// Occurs when [play command].
/// </summary>
- event EventHandler<PlayRequestEventArgs> PlayCommand;
+ event EventHandler<GenericEventArgs<PlayRequest>> PlayCommand;
/// <summary>
/// Occurs when [playstate command].
/// </summary>
- event EventHandler<PlaystateRequestEventArgs> PlaystateCommand;
+ event EventHandler<GenericEventArgs<PlaystateRequest>> PlaystateCommand;
/// <summary>
/// Occurs when [message command].
/// </summary>
- event EventHandler<MessageCommandEventArgs> MessageCommand;
+ event EventHandler<GenericEventArgs<MessageCommand>> MessageCommand;
/// <summary>
/// Occurs when [system command].
/// </summary>
@@ -88,6 +91,22 @@ namespace MediaBrowser.Model.ApiClient
/// </summary>
event EventHandler<EventArgs> ServerShuttingDown;
/// <summary>
+ /// Occurs when [send text command].
+ /// </summary>
+ event EventHandler<GenericEventArgs<string>> SendStringCommand;
+ /// <summary>
+ /// Occurs when [set volume command].
+ /// </summary>
+ event EventHandler<GenericEventArgs<int>> SetVolumeCommand;
+ /// <summary>
+ /// Occurs when [set audio stream index command].
+ /// </summary>
+ event EventHandler<GenericEventArgs<int>> SetAudioStreamIndexCommand;
+ /// <summary>
+ /// Occurs when [set video stream index command].
+ /// </summary>
+ event EventHandler<GenericEventArgs<int>> SetSubtitleStreamIndexCommand;
+ /// <summary>
/// Occurs when [sessions updated].
/// </summary>
event EventHandler<SessionUpdatesEventArgs> SessionsUpdated;
@@ -98,7 +117,7 @@ namespace MediaBrowser.Model.ApiClient
/// <summary>
/// Occurs when [user data changed].
/// </summary>
- event EventHandler<UserDataChangedEventArgs> UserDataChanged;
+ event EventHandler<GenericEventArgs<UserDataChangeInfo>> UserDataChanged;
/// <summary>
/// Occurs when [connected].
/// </summary>
diff --git a/MediaBrowser.Model/ApiClient/ServerEventArgs.cs b/MediaBrowser.Model/ApiClient/ServerEventArgs.cs
deleted file mode 100644
index 6637edd74..000000000
--- a/MediaBrowser.Model/ApiClient/ServerEventArgs.cs
+++ /dev/null
@@ -1,177 +0,0 @@
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Plugins;
-using MediaBrowser.Model.Session;
-using MediaBrowser.Model.Tasks;
-using MediaBrowser.Model.Updates;
-using System;
-
-namespace MediaBrowser.Model.ApiClient
-{
- /// <summary>
- /// Class UserDeletedEventArgs
- /// </summary>
- public class UserDeletedEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- public string Id { get; set; }
- }
-
- public class UserDataChangedEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the user.
- /// </summary>
- /// <value>The user.</value>
- public UserDataChangeInfo ChangeInfo { get; set; }
- }
-
- /// <summary>
- /// Class UserUpdatedEventArgs
- /// </summary>
- public class UserUpdatedEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the user.
- /// </summary>
- /// <value>The user.</value>
- public UserDto User { get; set; }
- }
-
- /// <summary>
- /// Class ScheduledTaskStartedEventArgs
- /// </summary>
- public class ScheduledTaskStartedEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
- }
-
- /// <summary>
- /// Class ScheduledTaskEndedEventArgs
- /// </summary>
- public class ScheduledTaskEndedEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the result.
- /// </summary>
- /// <value>The result.</value>
- public TaskResult Result { get; set; }
- }
-
- /// <summary>
- /// Class PackageInstallationEventArgs
- /// </summary>
- public class PackageInstallationEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the installation info.
- /// </summary>
- /// <value>The installation info.</value>
- public InstallationInfo InstallationInfo { get; set; }
- }
-
- /// <summary>
- /// Class PluginUninstallEventArgs
- /// </summary>
- public class PluginUninstallEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the plugin info.
- /// </summary>
- /// <value>The plugin info.</value>
- public PluginInfo PluginInfo { get; set; }
- }
-
- /// <summary>
- /// Class LibraryChangedEventArgs
- /// </summary>
- public class LibraryChangedEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the update info.
- /// </summary>
- /// <value>The update info.</value>
- public LibraryUpdateInfo UpdateInfo { get; set; }
- }
-
- /// <summary>
- /// Class BrowseRequestEventArgs
- /// </summary>
- public class BrowseRequestEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the request.
- /// </summary>
- /// <value>The request.</value>
- public BrowseRequest Request { get; set; }
- }
-
- /// <summary>
- /// Class PlayRequestEventArgs
- /// </summary>
- public class PlayRequestEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the request.
- /// </summary>
- /// <value>The request.</value>
- public PlayRequest Request { get; set; }
- }
-
- /// <summary>
- /// Class PlaystateRequestEventArgs
- /// </summary>
- public class PlaystateRequestEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the request.
- /// </summary>
- /// <value>The request.</value>
- public PlaystateRequest Request { get; set; }
- }
-
- /// <summary>
- /// Class MessageCommandEventArgs
- /// </summary>
- public class MessageCommandEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the request.
- /// </summary>
- /// <value>The request.</value>
- public MessageCommand Request { get; set; }
- }
-
- /// <summary>
- /// Class SystemCommandEventArgs
- /// </summary>
- public class GeneralCommandEventArgs : EventArgs
- {
- /// <summary>
- /// Gets or sets the command.
- /// </summary>
- /// <value>The command.</value>
- public GeneralCommand Command { get; set; }
-
- /// <summary>
- /// Gets or sets the type of the known command.
- /// </summary>
- /// <value>The type of the known command.</value>
- public GeneralCommandType? KnownCommandType { get; set; }
- }
-
- /// <summary>
- /// Class SessionUpdatesEventArgs
- /// </summary>
- public class SessionUpdatesEventArgs : EventArgs
- {
- public SessionInfoDto[] Sessions { get; set; }
- }
-}
diff --git a/MediaBrowser.Model/ApiClient/SessionUpdatesEventArgs.cs b/MediaBrowser.Model/ApiClient/SessionUpdatesEventArgs.cs
new file mode 100644
index 000000000..483ee45d0
--- /dev/null
+++ b/MediaBrowser.Model/ApiClient/SessionUpdatesEventArgs.cs
@@ -0,0 +1,13 @@
+using System;
+using MediaBrowser.Model.Session;
+
+namespace MediaBrowser.Model.ApiClient
+{
+ /// <summary>
+ /// Class SessionUpdatesEventArgs
+ /// </summary>
+ public class SessionUpdatesEventArgs : EventArgs
+ {
+ public SessionInfoDto[] Sessions { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Channels/ChannelItemQuery.cs b/MediaBrowser.Model/Channels/ChannelItemQuery.cs
new file mode 100644
index 000000000..2da955e88
--- /dev/null
+++ b/MediaBrowser.Model/Channels/ChannelItemQuery.cs
@@ -0,0 +1,48 @@
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Querying;
+
+namespace MediaBrowser.Model.Channels
+{
+ public class ChannelItemQuery
+ {
+ /// <summary>
+ /// Gets or sets the channel identifier.
+ /// </summary>
+ /// <value>The channel identifier.</value>
+ public string ChannelId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the category identifier.
+ /// </summary>
+ /// <value>The category identifier.</value>
+ public string CategoryId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the user identifier.
+ /// </summary>
+ /// <value>The user identifier.</value>
+ 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>
+ public int? StartIndex { get; set; }
+
+ /// <summary>
+ /// The maximum number of items to return
+ /// </summary>
+ /// <value>The limit.</value>
+ public int? Limit { get; set; }
+
+ public SortOrder? SortOrder { get; set; }
+ public string[] SortBy { get; set; }
+ public ItemFilter[] Filters { get; set; }
+
+ public ChannelItemQuery()
+ {
+ Filters = new ItemFilter[] { };
+ SortBy = new string[] { };
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Channels/ChannelQuery.cs b/MediaBrowser.Model/Channels/ChannelQuery.cs
index e09769b00..7c3f76fda 100644
--- a/MediaBrowser.Model/Channels/ChannelQuery.cs
+++ b/MediaBrowser.Model/Channels/ChannelQuery.cs
@@ -1,7 +1,4 @@
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Querying;
-
-namespace MediaBrowser.Model.Channels
+namespace MediaBrowser.Model.Channels
{
public class ChannelQuery
{
@@ -23,47 +20,4 @@ namespace MediaBrowser.Model.Channels
/// <value>The limit.</value>
public int? Limit { get; set; }
}
-
- public class ChannelItemQuery
- {
- /// <summary>
- /// Gets or sets the channel identifier.
- /// </summary>
- /// <value>The channel identifier.</value>
- public string ChannelId { get; set; }
-
- /// <summary>
- /// Gets or sets the category identifier.
- /// </summary>
- /// <value>The category identifier.</value>
- public string CategoryId { get; set; }
-
- /// <summary>
- /// Gets or sets the user identifier.
- /// </summary>
- /// <value>The user identifier.</value>
- 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>
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return
- /// </summary>
- /// <value>The limit.</value>
- public int? Limit { get; set; }
-
- public SortOrder? SortOrder { get; set; }
- public string[] SortBy { get; set; }
- public ItemFilter[] Filters { get; set; }
-
- public ChannelItemQuery()
- {
- Filters = new ItemFilter[] { };
- SortBy = new string[] { };
- }
- }
}
diff --git a/MediaBrowser.Model/Chapters/RemoteChapterInfo.cs b/MediaBrowser.Model/Chapters/RemoteChapterInfo.cs
new file mode 100644
index 000000000..f2674c842
--- /dev/null
+++ b/MediaBrowser.Model/Chapters/RemoteChapterInfo.cs
@@ -0,0 +1,18 @@
+
+namespace MediaBrowser.Model.Chapters
+{
+ public class RemoteChapterInfo
+ {
+ /// <summary>
+ /// Gets or sets the start position ticks.
+ /// </summary>
+ /// <value>The start position ticks.</value>
+ public long StartPositionTicks { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Chapters/RemoteChapterResult.cs b/MediaBrowser.Model/Chapters/RemoteChapterResult.cs
new file mode 100644
index 000000000..3f627c8df
--- /dev/null
+++ b/MediaBrowser.Model/Chapters/RemoteChapterResult.cs
@@ -0,0 +1,42 @@
+
+namespace MediaBrowser.Model.Chapters
+{
+ public class RemoteChapterResult
+ {
+ /// <summary>
+ /// Gets or sets the identifier.
+ /// </summary>
+ /// <value>The identifier.</value>
+ public string Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the run time ticks.
+ /// </summary>
+ /// <value>The run time ticks.</value>
+ public long? RunTimeTicks { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the community rating.
+ /// </summary>
+ /// <value>The community rating.</value>
+ public float? CommunityRating { get; set; }
+
+ /// <summary>
+ /// Gets or sets the chapter count.
+ /// </summary>
+ /// <value>The chapter count.</value>
+ public int? ChapterCount { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the three letter iso language.
+ /// </summary>
+ /// <value>The name of the three letter iso language.</value>
+ public string ThreeLetterISOLanguageName { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Configuration/EncodingQuality.cs b/MediaBrowser.Model/Configuration/EncodingQuality.cs
new file mode 100644
index 000000000..ba5a1f279
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/EncodingQuality.cs
@@ -0,0 +1,10 @@
+namespace MediaBrowser.Model.Configuration
+{
+ public enum EncodingQuality
+ {
+ Auto,
+ HighSpeed,
+ HighQuality,
+ MaxQuality
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/ImageOption.cs b/MediaBrowser.Model/Configuration/ImageOption.cs
new file mode 100644
index 000000000..ade0af83e
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/ImageOption.cs
@@ -0,0 +1,29 @@
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Model.Configuration
+{
+ public class ImageOption
+ {
+ /// <summary>
+ /// Gets or sets the type.
+ /// </summary>
+ /// <value>The type.</value>
+ public ImageType Type { get; set; }
+ /// <summary>
+ /// Gets or sets the limit.
+ /// </summary>
+ /// <value>The limit.</value>
+ public int Limit { get; set; }
+
+ /// <summary>
+ /// Gets or sets the minimum width.
+ /// </summary>
+ /// <value>The minimum width.</value>
+ public int MinWidth { get; set; }
+
+ public ImageOption()
+ {
+ Limit = 1;
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/ImageSavingConvention.cs b/MediaBrowser.Model/Configuration/ImageSavingConvention.cs
new file mode 100644
index 000000000..611678e67
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/ImageSavingConvention.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Model.Configuration
+{
+ public enum ImageSavingConvention
+ {
+ Legacy,
+ Compatible
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/LiveTvOptions.cs b/MediaBrowser.Model/Configuration/LiveTvOptions.cs
new file mode 100644
index 000000000..ae8aeb200
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/LiveTvOptions.cs
@@ -0,0 +1,7 @@
+namespace MediaBrowser.Model.Configuration
+{
+ public class LiveTvOptions
+ {
+ public int? GuideDays { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/MetadataOptions.cs b/MediaBrowser.Model/Configuration/MetadataOptions.cs
index d666f6cce..fdfbbf4f4 100644
--- a/MediaBrowser.Model/Configuration/MetadataOptions.cs
+++ b/MediaBrowser.Model/Configuration/MetadataOptions.cs
@@ -30,7 +30,7 @@ namespace MediaBrowser.Model.Configuration
public MetadataOptions(int backdropLimit, int minBackdropWidth)
{
- var imageOptions = new List<ImageOption>
+ List<ImageOption> imageOptions = new List<ImageOption>
{
new ImageOption
{
@@ -52,14 +52,30 @@ namespace MediaBrowser.Model.Configuration
public int GetLimit(ImageType type)
{
- var option = ImageOptions.FirstOrDefault(i => i.Type == type);
+ ImageOption option = null;
+ foreach (ImageOption i in ImageOptions)
+ {
+ if (i.Type == type)
+ {
+ option = i;
+ break;
+ }
+ }
return option == null ? 1 : option.Limit;
}
public int GetMinWidth(ImageType type)
{
- var option = ImageOptions.FirstOrDefault(i => i.Type == type);
+ ImageOption option = null;
+ foreach (ImageOption i in ImageOptions)
+ {
+ if (i.Type == type)
+ {
+ option = i;
+ break;
+ }
+ }
return option == null ? 0 : option.MinWidth;
}
@@ -74,29 +90,4 @@ namespace MediaBrowser.Model.Configuration
return !DisabledMetadataSavers.Contains(name, StringComparer.OrdinalIgnoreCase);
}
}
-
- public class ImageOption
- {
- /// <summary>
- /// Gets or sets the type.
- /// </summary>
- /// <value>The type.</value>
- public ImageType Type { get; set; }
- /// <summary>
- /// Gets or sets the limit.
- /// </summary>
- /// <value>The limit.</value>
- public int Limit { get; set; }
-
- /// <summary>
- /// Gets or sets the minimum width.
- /// </summary>
- /// <value>The minimum width.</value>
- public int MinWidth { get; set; }
-
- public ImageOption()
- {
- Limit = 1;
- }
- }
}
diff --git a/MediaBrowser.Model/Configuration/MetadataPlugin.cs b/MediaBrowser.Model/Configuration/MetadataPlugin.cs
index b019cf71a..f3e0ce106 100644
--- a/MediaBrowser.Model/Configuration/MetadataPlugin.cs
+++ b/MediaBrowser.Model/Configuration/MetadataPlugin.cs
@@ -1,7 +1,4 @@
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
-
-namespace MediaBrowser.Model.Configuration
+namespace MediaBrowser.Model.Configuration
{
public class MetadataPlugin
{
@@ -17,44 +14,4 @@ namespace MediaBrowser.Model.Configuration
/// <value>The type.</value>
public MetadataPluginType Type { get; set; }
}
-
- public class MetadataPluginSummary
- {
- /// <summary>
- /// Gets or sets the type of the item.
- /// </summary>
- /// <value>The type of the item.</value>
- public string ItemType { get; set; }
-
- /// <summary>
- /// Gets or sets the plugins.
- /// </summary>
- /// <value>The plugins.</value>
- public List<MetadataPlugin> Plugins { get; set; }
-
- /// <summary>
- /// Gets or sets the supported image types.
- /// </summary>
- /// <value>The supported image types.</value>
- public List<ImageType> SupportedImageTypes { get; set; }
-
- public MetadataPluginSummary()
- {
- SupportedImageTypes = new List<ImageType>();
- Plugins = new List<MetadataPlugin>();
- }
- }
-
- /// <summary>
- /// Enum MetadataPluginType
- /// </summary>
- public enum MetadataPluginType
- {
- LocalImageProvider,
- ImageFetcher,
- ImageSaver,
- LocalMetadataProvider,
- MetadataFetcher,
- MetadataSaver
- }
}
diff --git a/MediaBrowser.Model/Configuration/MetadataPluginSummary.cs b/MediaBrowser.Model/Configuration/MetadataPluginSummary.cs
new file mode 100644
index 000000000..90b3933eb
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/MetadataPluginSummary.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Model.Configuration
+{
+ public class MetadataPluginSummary
+ {
+ /// <summary>
+ /// Gets or sets the type of the item.
+ /// </summary>
+ /// <value>The type of the item.</value>
+ public string ItemType { get; set; }
+
+ /// <summary>
+ /// Gets or sets the plugins.
+ /// </summary>
+ /// <value>The plugins.</value>
+ public List<MetadataPlugin> Plugins { get; set; }
+
+ /// <summary>
+ /// Gets or sets the supported image types.
+ /// </summary>
+ /// <value>The supported image types.</value>
+ public List<ImageType> SupportedImageTypes { get; set; }
+
+ public MetadataPluginSummary()
+ {
+ SupportedImageTypes = new List<ImageType>();
+ Plugins = new List<MetadataPlugin>();
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/MetadataPluginType.cs b/MediaBrowser.Model/Configuration/MetadataPluginType.cs
new file mode 100644
index 000000000..95ca3b2e6
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/MetadataPluginType.cs
@@ -0,0 +1,15 @@
+namespace MediaBrowser.Model.Configuration
+{
+ /// <summary>
+ /// Enum MetadataPluginType
+ /// </summary>
+ public enum MetadataPluginType
+ {
+ LocalImageProvider,
+ ImageFetcher,
+ ImageSaver,
+ LocalMetadataProvider,
+ MetadataFetcher,
+ MetadataSaver
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/NotificationOption.cs b/MediaBrowser.Model/Configuration/NotificationOption.cs
new file mode 100644
index 000000000..5fcf3550c
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/NotificationOption.cs
@@ -0,0 +1,54 @@
+namespace MediaBrowser.Model.Configuration
+{
+ public class NotificationOption
+ {
+ public string Type { get; set; }
+
+ /// <summary>
+ /// User Ids to not monitor (it's opt out)
+ /// </summary>
+ public string[] DisabledMonitorUsers { get; set; }
+
+ /// <summary>
+ /// User Ids to send to (if SendToUserMode == Custom)
+ /// </summary>
+ public string[] SendToUsers { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this <see cref="NotificationOption"/> is enabled.
+ /// </summary>
+ /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
+ public bool Enabled { get; set; }
+
+ /// <summary>
+ /// Gets or sets the title format string.
+ /// </summary>
+ /// <value>The title format string.</value>
+ public string Title { get; set; }
+
+ /// <summary>
+ /// Gets or sets the description.
+ /// </summary>
+ /// <value>The description.</value>
+ public string Description { get; set; }
+
+ /// <summary>
+ /// Gets or sets the disabled services.
+ /// </summary>
+ /// <value>The disabled services.</value>
+ public string[] DisabledServices { get; set; }
+
+ /// <summary>
+ /// Gets or sets the send to user mode.
+ /// </summary>
+ /// <value>The send to user mode.</value>
+ public SendToUserType SendToUserMode { get; set; }
+
+ public NotificationOption()
+ {
+ DisabledServices = new string[] { };
+ DisabledMonitorUsers = new string[] { };
+ SendToUsers = new string[] { };
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/NotificationOptions.cs b/MediaBrowser.Model/Configuration/NotificationOptions.cs
index fedc1c2f8..d6517e895 100644
--- a/MediaBrowser.Model/Configuration/NotificationOptions.cs
+++ b/MediaBrowser.Model/Configuration/NotificationOptions.cs
@@ -70,19 +70,23 @@ namespace MediaBrowser.Model.Configuration
public NotificationOption GetOptions(string type)
{
- return Options.FirstOrDefault(i => string.Equals(type, i.Type, StringComparison.OrdinalIgnoreCase));
+ foreach (NotificationOption i in Options)
+ {
+ if (string.Equals(type, i.Type, StringComparison.OrdinalIgnoreCase)) return i;
+ }
+ return null;
}
public bool IsEnabled(string type)
{
- var opt = GetOptions(type);
+ NotificationOption opt = GetOptions(type);
return opt != null && opt.Enabled;
}
public bool IsServiceEnabled(string service, string notificationType)
{
- var opt = GetOptions(notificationType);
+ NotificationOption opt = GetOptions(notificationType);
return opt == null ||
!opt.DisabledServices.Contains(service, StringComparer.OrdinalIgnoreCase);
@@ -90,7 +94,7 @@ namespace MediaBrowser.Model.Configuration
public bool IsEnabledToMonitorUser(string type, string userId)
{
- var opt = GetOptions(type);
+ NotificationOption opt = GetOptions(type);
return opt != null && opt.Enabled &&
!opt.DisabledMonitorUsers.Contains(userId, StringComparer.OrdinalIgnoreCase);
@@ -98,7 +102,7 @@ namespace MediaBrowser.Model.Configuration
public bool IsEnabledToSendToUser(string type, string userId, UserConfiguration userConfig)
{
- var opt = GetOptions(type);
+ NotificationOption opt = GetOptions(type);
if (opt != null && opt.Enabled)
{
@@ -118,80 +122,4 @@ namespace MediaBrowser.Model.Configuration
return false;
}
}
-
- public class NotificationOption
- {
- public string Type { get; set; }
-
- /// <summary>
- /// User Ids to not monitor (it's opt out)
- /// </summary>
- public string[] DisabledMonitorUsers { get; set; }
-
- /// <summary>
- /// User Ids to send to (if SendToUserMode == Custom)
- /// </summary>
- public string[] SendToUsers { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this <see cref="NotificationOption"/> is enabled.
- /// </summary>
- /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
- public bool Enabled { get; set; }
-
- /// <summary>
- /// Gets or sets the title format string.
- /// </summary>
- /// <value>The title format string.</value>
- public string Title { get; set; }
-
- /// <summary>
- /// Gets or sets the description.
- /// </summary>
- /// <value>The description.</value>
- public string Description { get; set; }
-
- /// <summary>
- /// Gets or sets the disabled services.
- /// </summary>
- /// <value>The disabled services.</value>
- public string[] DisabledServices { get; set; }
-
- /// <summary>
- /// Gets or sets the send to user mode.
- /// </summary>
- /// <value>The send to user mode.</value>
- public SendToUserType SendToUserMode { get; set; }
-
- public NotificationOption()
- {
- DisabledServices = new string[] { };
- DisabledMonitorUsers = new string[] { };
- SendToUsers = new string[] { };
- }
- }
-
- public enum NotificationType
- {
- ApplicationUpdateAvailable,
- ApplicationUpdateInstalled,
- AudioPlayback,
- GamePlayback,
- InstallationFailed,
- PluginError,
- PluginInstalled,
- PluginUpdateInstalled,
- PluginUninstalled,
- NewLibraryContent,
- ServerRestartRequired,
- TaskFailed,
- VideoPlayback
- }
-
- public enum SendToUserType
- {
- All = 0,
- Admins = 1,
- Custom = 2
- }
}
diff --git a/MediaBrowser.Model/Configuration/NotificationType.cs b/MediaBrowser.Model/Configuration/NotificationType.cs
new file mode 100644
index 000000000..0ddcf4251
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/NotificationType.cs
@@ -0,0 +1,20 @@
+namespace MediaBrowser.Model.Configuration
+{
+ public enum NotificationType
+ {
+ ApplicationUpdateAvailable,
+ ApplicationUpdateInstalled,
+ AudioPlayback,
+ GamePlayback,
+ InstallationFailed,
+ PluginError,
+ PluginInstalled,
+ PluginUpdateInstalled,
+ PluginUninstalled,
+ NewLibraryContent,
+ NewLibraryContentMultiple,
+ ServerRestartRequired,
+ TaskFailed,
+ VideoPlayback
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/PathSubstitution.cs b/MediaBrowser.Model/Configuration/PathSubstitution.cs
new file mode 100644
index 000000000..576dd2d5a
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/PathSubstitution.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Model.Configuration
+{
+ public class PathSubstitution
+ {
+ public string From { get; set; }
+ public string To { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/SendToUserType.cs b/MediaBrowser.Model/Configuration/SendToUserType.cs
new file mode 100644
index 000000000..a2eac4c2d
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/SendToUserType.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Model.Configuration
+{
+ public enum SendToUserType
+ {
+ All = 0,
+ Admins = 1,
+ Custom = 2
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 0fb9db6c0..c19039439 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -221,6 +221,8 @@ namespace MediaBrowser.Model.Configuration
public NotificationOptions NotificationOptions { get; set; }
+ public SubtitleOptions SubtitleOptions { get; set; }
+
/// <summary>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
/// </summary>
@@ -269,7 +271,7 @@ namespace MediaBrowser.Model.Configuration
EnableRealtimeMonitor = true;
- var options = new List<MetadataOptions>
+ List<MetadataOptions> options = new List<MetadataOptions>
{
new MetadataOptions(1, 1280) {ItemType = "Book"},
new MetadataOptions(1, 1280) {ItemType = "MusicAlbum"},
@@ -284,31 +286,8 @@ namespace MediaBrowser.Model.Configuration
UICulture = "en-us";
NotificationOptions = new NotificationOptions();
- }
- }
-
- public enum ImageSavingConvention
- {
- Legacy,
- Compatible
- }
-
- public enum EncodingQuality
- {
- Auto,
- HighSpeed,
- HighQuality,
- MaxQuality
- }
- public class LiveTvOptions
- {
- public int? GuideDays { get; set; }
- }
-
- public class PathSubstitution
- {
- public string From { get; set; }
- public string To { get; set; }
+ SubtitleOptions = new SubtitleOptions();
+ }
}
}
diff --git a/MediaBrowser.Model/Configuration/SubtitleOptions.cs b/MediaBrowser.Model/Configuration/SubtitleOptions.cs
new file mode 100644
index 000000000..96e04e511
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/SubtitleOptions.cs
@@ -0,0 +1,21 @@
+namespace MediaBrowser.Model.Configuration
+{
+ public class SubtitleOptions
+ {
+ public bool SkipIfGraphicalSubtitlesPresent { get; set; }
+ public bool SkipIfAudioTrackMatches { get; set; }
+ public string[] DownloadLanguages { get; set; }
+ public bool DownloadMovieSubtitles { get; set; }
+ public bool DownloadEpisodeSubtitles { get; set; }
+
+ public string OpenSubtitlesUsername { get; set; }
+ public string OpenSubtitlesPasswordHash { get; set; }
+
+ public SubtitleOptions()
+ {
+ DownloadLanguages = new string[] { };
+
+ SkipIfAudioTrackMatches = true;
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/AutoOrganize.cs b/MediaBrowser.Model/Configuration/TvFileOrganizationOptions.cs
index fe32d4a80..fe32d4a80 100644
--- a/MediaBrowser.Model/Configuration/AutoOrganize.cs
+++ b/MediaBrowser.Model/Configuration/TvFileOrganizationOptions.cs
diff --git a/MediaBrowser.Model/Configuration/UnratedItem.cs b/MediaBrowser.Model/Configuration/UnratedItem.cs
new file mode 100644
index 000000000..1082d684b
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/UnratedItem.cs
@@ -0,0 +1,16 @@
+namespace MediaBrowser.Model.Configuration
+{
+ public enum UnratedItem
+ {
+ Movie,
+ Trailer,
+ Series,
+ Music,
+ Game,
+ Book,
+ LiveTvChannel,
+ LiveTvProgram,
+ ChannelContent,
+ Other
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs
index f8df19436..2658e8973 100644
--- a/MediaBrowser.Model/Configuration/UserConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs
@@ -79,18 +79,4 @@ namespace MediaBrowser.Model.Configuration
BlockUnratedItems = new UnratedItem[] { };
}
}
-
- public enum UnratedItem
- {
- Movie,
- Trailer,
- Series,
- Music,
- Game,
- Book,
- LiveTvChannel,
- LiveTvProgram,
- ChannelContent,
- Other
- }
}
diff --git a/MediaBrowser.Model/Dlna/AudioOptions.cs b/MediaBrowser.Model/Dlna/AudioOptions.cs
new file mode 100644
index 000000000..d04133a3d
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/AudioOptions.cs
@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using MediaBrowser.Model.Dto;
+
+namespace MediaBrowser.Model.Dlna
+{
+ /// <summary>
+ /// Class AudioOptions.
+ /// </summary>
+ public class AudioOptions
+ {
+ public string ItemId { get; set; }
+ public List<MediaSourceInfo> MediaSources { get; set; }
+ public DeviceProfile Profile { get; set; }
+
+ /// <summary>
+ /// Optional. Only needed if a specific AudioStreamIndex or SubtitleStreamIndex are requested.
+ /// </summary>
+ public string MediaSourceId { get; set; }
+
+ public string DeviceId { get; set; }
+
+ /// <summary>
+ /// Allows an override of supported number of audio channels
+ /// Example: DeviceProfile supports five channel, but user only has stereo speakers
+ /// </summary>
+ public int? MaxAudioChannels { get; set; }
+
+ /// <summary>
+ /// The application's configured quality setting
+ /// </summary>
+ public int? MaxBitrate { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/CodecProfile.cs b/MediaBrowser.Model/Dlna/CodecProfile.cs
index 2b04b7fdb..3e67b49f9 100644
--- a/MediaBrowser.Model/Dlna/CodecProfile.cs
+++ b/MediaBrowser.Model/Dlna/CodecProfile.cs
@@ -22,66 +22,19 @@ namespace MediaBrowser.Model.Dlna
public List<string> GetCodecs()
{
- return (Codec ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList();
+ List<string> list = new List<string>();
+ foreach (string i in (Codec ?? string.Empty).Split(','))
+ {
+ if (!string.IsNullOrEmpty(i)) list.Add(i);
+ }
+ return list;
}
public bool ContainsCodec(string codec)
{
- var codecs = GetCodecs();
+ List<string> codecs = GetCodecs();
return codecs.Count == 0 || codecs.Contains(codec, StringComparer.OrdinalIgnoreCase);
}
}
-
- public enum CodecType
- {
- Video = 0,
- VideoAudio = 1,
- Audio = 2
- }
-
- public class ProfileCondition
- {
- [XmlAttribute("condition")]
- public ProfileConditionType Condition { get; set; }
-
- [XmlAttribute("property")]
- public ProfileConditionValue Property { get; set; }
-
- [XmlAttribute("value")]
- public string Value { get; set; }
-
- [XmlAttribute("isRequired")]
- public bool IsRequired { get; set; }
-
- public ProfileCondition()
- {
- IsRequired = true;
- }
- }
-
- public enum ProfileConditionType
- {
- Equals = 0,
- NotEquals = 1,
- LessThanEqual = 2,
- GreaterThanEqual = 3
- }
-
- public enum ProfileConditionValue
- {
- AudioChannels,
- AudioBitrate,
- AudioProfile,
- Width,
- Height,
- Has64BitOffsets,
- PacketLength,
- VideoBitDepth,
- VideoBitrate,
- VideoFramerate,
- VideoLevel,
- VideoProfile,
- VideoTimestamp
- }
}
diff --git a/MediaBrowser.Model/Dlna/CodecType.cs b/MediaBrowser.Model/Dlna/CodecType.cs
new file mode 100644
index 000000000..415cae7ac
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/CodecType.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Model.Dlna
+{
+ public enum CodecType
+ {
+ Video = 0,
+ VideoAudio = 1,
+ Audio = 2
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs
index 27c4850e8..488d742f5 100644
--- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs
+++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs
@@ -136,7 +136,7 @@ namespace MediaBrowser.Model.Dlna
return !condition.IsRequired;
}
- var expected = condition.Value;
+ string expected = condition.Value;
switch (condition.Condition)
{
@@ -186,7 +186,7 @@ namespace MediaBrowser.Model.Dlna
return !condition.IsRequired;
}
- var expected = (TransportStreamTimestamp)Enum.Parse(typeof(TransportStreamTimestamp), condition.Value, true);
+ TransportStreamTimestamp expected = (TransportStreamTimestamp)Enum.Parse(typeof(TransportStreamTimestamp), condition.Value, true);
switch (condition.Condition)
{
diff --git a/MediaBrowser.Model/Dlna/ContainerProfile.cs b/MediaBrowser.Model/Dlna/ContainerProfile.cs
index 3a5fe3bd5..931194dd3 100644
--- a/MediaBrowser.Model/Dlna/ContainerProfile.cs
+++ b/MediaBrowser.Model/Dlna/ContainerProfile.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using System.Linq;
using System.Xml.Serialization;
namespace MediaBrowser.Model.Dlna
@@ -20,7 +19,12 @@ namespace MediaBrowser.Model.Dlna
public List<string> GetContainers()
{
- return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList();
+ List<string> list = new List<string>();
+ foreach (string i in (Container ?? string.Empty).Split(','))
+ {
+ if (!string.IsNullOrEmpty(i)) list.Add(i);
+ }
+ return list;
}
}
}
diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
index 7e21e1ef2..c97c06d34 100644
--- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
+++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
@@ -1,8 +1,5 @@
-using System;
+using MediaBrowser.Model.MediaInfo;
using System.Collections.Generic;
-using System.Linq;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Model.Dlna
{
@@ -19,30 +16,30 @@ namespace MediaBrowser.Model.Dlna
int? width,
int? height)
{
- var orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetImageOrgOpValue();
+ string orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetImageOrgOpValue();
// 0 = native, 1 = transcoded
const string orgCi = ";DLNA.ORG_CI=0";
- var flagValue = DlnaFlags.StreamingTransferMode |
+ DlnaFlags flagValue = DlnaFlags.StreamingTransferMode |
DlnaFlags.BackgroundTransferMode |
DlnaFlags.DlnaV15;
- var dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}",
- FlagsToString(flagValue));
+ string dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}",
+ DlnaMaps.FlagsToString(flagValue));
- var mediaProfile = _profile.GetImageMediaProfile(container,
+ ResponseProfile mediaProfile = _profile.GetImageMediaProfile(container,
width,
height);
- var orgPn = mediaProfile == null ? null : mediaProfile.OrgPn;
+ string orgPn = mediaProfile == null ? null : mediaProfile.OrgPn;
if (string.IsNullOrEmpty(orgPn))
{
orgPn = GetImageOrgPnValue(container, width, height);
}
- var contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
+ string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
}
@@ -57,12 +54,12 @@ namespace MediaBrowser.Model.Dlna
TranscodeSeekInfo transcodeSeekInfo)
{
// first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
- var orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetOrgOpValue(runtimeTicks.HasValue, isDirectStream, transcodeSeekInfo);
+ string orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetOrgOpValue(runtimeTicks.HasValue, isDirectStream, transcodeSeekInfo);
// 0 = native, 1 = transcoded
- var orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
+ string orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
- var flagValue = DlnaFlags.StreamingTransferMode |
+ DlnaFlags flagValue = DlnaFlags.StreamingTransferMode |
DlnaFlags.BackgroundTransferMode |
DlnaFlags.DlnaV15;
@@ -75,32 +72,26 @@ namespace MediaBrowser.Model.Dlna
//flagValue = flagValue | DlnaFlags.DLNA_ORG_FLAG_TIME_BASED_SEEK;
}
- var dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}",
- FlagsToString(flagValue));
+ string dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}",
+ DlnaMaps.FlagsToString(flagValue));
- var mediaProfile = _profile.GetAudioMediaProfile(container,
+ ResponseProfile mediaProfile = _profile.GetAudioMediaProfile(container,
audioCodec,
audioChannels,
audioBitrate);
- var orgPn = mediaProfile == null ? null : mediaProfile.OrgPn;
+ string orgPn = mediaProfile == null ? null : mediaProfile.OrgPn;
if (string.IsNullOrEmpty(orgPn))
{
orgPn = GetAudioOrgPnValue(container, audioBitrate, audioSampleRate, audioChannels);
}
- var contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
+ string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
}
- private static string FlagsToString(DlnaFlags flags)
- {
- //return Enum.Format(typeof(DlnaFlags), flags, "x");
- return string.Format("{0:X8}{1:D24}", (ulong)flags, 0);
- }
-
public string BuildVideoHeader(string container,
string videoCodec,
string audioCodec,
@@ -120,12 +111,12 @@ namespace MediaBrowser.Model.Dlna
TranscodeSeekInfo transcodeSeekInfo)
{
// first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
- var orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetOrgOpValue(runtimeTicks.HasValue, isDirectStream, transcodeSeekInfo);
+ string orgOp = ";DLNA.ORG_OP=" + DlnaMaps.GetOrgOpValue(runtimeTicks.HasValue, isDirectStream, transcodeSeekInfo);
// 0 = native, 1 = transcoded
- var orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
+ string orgCi = isDirectStream ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
- var flagValue = DlnaFlags.StreamingTransferMode |
+ DlnaFlags flagValue = DlnaFlags.StreamingTransferMode |
DlnaFlags.BackgroundTransferMode |
DlnaFlags.DlnaV15;
@@ -138,10 +129,10 @@ namespace MediaBrowser.Model.Dlna
//flagValue = flagValue | DlnaFlags.DLNA_ORG_FLAG_TIME_BASED_SEEK;
}
- var dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}",
- FlagsToString(flagValue));
+ string dlnaflags = string.Format(";DLNA.ORG_FLAGS={0}",
+ DlnaMaps.FlagsToString(flagValue));
- var mediaProfile = _profile.GetVideoMediaProfile(container,
+ ResponseProfile mediaProfile = _profile.GetVideoMediaProfile(container,
audioCodec,
videoCodec,
audioBitrate,
@@ -156,25 +147,35 @@ namespace MediaBrowser.Model.Dlna
packetLength,
timestamp);
- var orgPn = mediaProfile == null ? null : mediaProfile.OrgPn;
+ string orgPn = mediaProfile == null ? null : mediaProfile.OrgPn;
if (string.IsNullOrEmpty(orgPn))
{
- orgPn = GetVideoOrgPnValue(container, videoCodec, audioCodec, width, height, timestamp)
- .FirstOrDefault();
+ foreach (string s in GetVideoOrgPnValue(container, videoCodec, audioCodec, width, height, timestamp))
+ {
+ orgPn = s;
+ break;
+ }
+ }
+ if (string.IsNullOrEmpty(orgPn))
+ {
// TODO: Support multiple values and return multiple headers?
- orgPn = (orgPn ?? string.Empty).Split(',').FirstOrDefault();
+ foreach (string s in (orgPn ?? string.Empty).Split(','))
+ {
+ orgPn = s;
+ break;
+ }
}
- var contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
+ string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
}
private string GetImageOrgPnValue(string container, int? width, int? height)
{
- var format = new MediaFormatProfileResolver()
+ MediaFormatProfile? format = new MediaFormatProfileResolver()
.ResolveImageFormat(container,
width,
height);
@@ -184,7 +185,7 @@ namespace MediaBrowser.Model.Dlna
private string GetAudioOrgPnValue(string container, int? audioBitrate, int? audioSampleRate, int? audioChannels)
{
- var format = new MediaFormatProfileResolver()
+ MediaFormatProfile? format = new MediaFormatProfileResolver()
.ResolveAudioFormat(container,
audioBitrate,
audioSampleRate,
@@ -193,16 +194,12 @@ namespace MediaBrowser.Model.Dlna
return format.HasValue ? format.Value.ToString() : null;
}
- private IEnumerable<string> GetVideoOrgPnValue(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestamp)
+ private List<string> GetVideoOrgPnValue(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestamp)
{
- return new MediaFormatProfileResolver()
- .ResolveVideoFormat(container,
- videoCodec,
- audioCodec,
- width,
- height,
- timestamp)
- .Select(i => i.ToString());
+ List<string> list = new List<string>();
+ foreach (MediaFormatProfile i in new MediaFormatProfileResolver().ResolveVideoFormat(container, videoCodec, audioCodec, width, height, timestamp))
+ list.Add(i.ToString());
+ return list;
}
}
}
diff --git a/MediaBrowser.Model/Dlna/DeviceIdentification.cs b/MediaBrowser.Model/Dlna/DeviceIdentification.cs
index 87cf000b1..97f4409da 100644
--- a/MediaBrowser.Model/Dlna/DeviceIdentification.cs
+++ b/MediaBrowser.Model/Dlna/DeviceIdentification.cs
@@ -1,6 +1,4 @@
-using System.Xml.Serialization;
-
-namespace MediaBrowser.Model.Dlna
+namespace MediaBrowser.Model.Dlna
{
public class DeviceIdentification
{
@@ -60,23 +58,4 @@ namespace MediaBrowser.Model.Dlna
Headers = new HttpHeaderInfo[] {};
}
}
-
- public class HttpHeaderInfo
- {
- [XmlAttribute("name")]
- public string Name { get; set; }
-
- [XmlAttribute("value")]
- public string Value { get; set; }
-
- [XmlAttribute("match")]
- public HeaderMatchType Match { get; set; }
- }
-
- public enum HeaderMatchType
- {
- Equals = 0,
- Regex = 1,
- Substring = 2
- }
}
diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs
index b23ad876c..42ba5840c 100644
--- a/MediaBrowser.Model/Dlna/DeviceProfile.cs
+++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs
@@ -105,116 +105,154 @@ namespace MediaBrowser.Model.Dlna
public List<string> GetSupportedMediaTypes()
{
- return (SupportedMediaTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList();
+ List<string> list = new List<string>();
+ foreach (string i in (SupportedMediaTypes ?? string.Empty).Split(','))
+ {
+ if (!string.IsNullOrEmpty(i))
+ list.Add(i);
+ }
+ return list;
}
public TranscodingProfile GetAudioTranscodingProfile(string container, string audioCodec)
{
container = (container ?? string.Empty).TrimStart('.');
- return TranscodingProfiles.FirstOrDefault(i =>
+ foreach (var i in TranscodingProfiles)
{
if (i.Type != DlnaProfileType.Audio)
{
- return false;
+ continue;
}
if (!string.Equals(container, i.Container, StringComparison.OrdinalIgnoreCase))
{
- return false;
+ continue;
}
- if (!i.GetAudioCodecs().Contains(audioCodec ?? string.Empty))
+ if (!i.GetAudioCodecs().Contains(audioCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase))
{
- return false;
+ continue;
}
- return true;
- });
+ return i;
+ }
+ return null;
}
public TranscodingProfile GetVideoTranscodingProfile(string container, string audioCodec, string videoCodec)
{
container = (container ?? string.Empty).TrimStart('.');
- return TranscodingProfiles.FirstOrDefault(i =>
+ foreach (var i in TranscodingProfiles)
{
if (i.Type != DlnaProfileType.Video)
{
- return false;
+ continue;
}
if (!string.Equals(container, i.Container, StringComparison.OrdinalIgnoreCase))
{
- return false;
+ continue;
}
if (!i.GetAudioCodecs().Contains(audioCodec ?? string.Empty))
{
- return false;
+ continue;
}
if (!string.Equals(videoCodec, i.VideoCodec, StringComparison.OrdinalIgnoreCase))
{
- return false;
+ continue;
}
- return true;
- });
+ return i;
+ }
+ return null;
}
public ResponseProfile GetAudioMediaProfile(string container, string audioCodec, int? audioChannels, int? audioBitrate)
{
container = (container ?? string.Empty).TrimStart('.');
- return ResponseProfiles.FirstOrDefault(i =>
+ foreach (var i in ResponseProfiles)
{
if (i.Type != DlnaProfileType.Audio)
{
- return false;
+ continue;
+ }
+
+ List<string> containers = i.GetContainers();
+ if (containers.Count > 0 && !containers.Contains(container, StringComparer.OrdinalIgnoreCase))
+ {
+ continue;
}
- var containers = i.GetContainers().ToList();
- if (containers.Count > 0 && !containers.Contains(container))
+ List<string> audioCodecs = i.GetAudioCodecs();
+ if (audioCodecs.Count > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase))
{
- return false;
+ continue;
}
- var audioCodecs = i.GetAudioCodecs().ToList();
- if (audioCodecs.Count > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty))
+ ConditionProcessor conditionProcessor = new ConditionProcessor();
+
+ var anyOff = false;
+ foreach (ProfileCondition c in i.Conditions)
{
- return false;
+ if (!conditionProcessor.IsAudioConditionSatisfied(c, audioChannels, audioBitrate))
+ {
+ anyOff = true;
+ break;
+ }
}
- var conditionProcessor = new ConditionProcessor();
- return i.Conditions.All(c => conditionProcessor.IsAudioConditionSatisfied(c,
- audioChannels,
- audioBitrate));
- });
+ if (anyOff)
+ {
+ continue;
+ }
+
+ return i;
+ }
+ return null;
}
public ResponseProfile GetImageMediaProfile(string container, int? width, int? height)
{
container = (container ?? string.Empty).TrimStart('.');
- return ResponseProfiles.FirstOrDefault(i =>
+ foreach (var i in ResponseProfiles)
{
if (i.Type != DlnaProfileType.Photo)
{
- return false;
+ continue;
+ }
+
+ List<string> containers = i.GetContainers();
+ if (containers.Count > 0 && !containers.Contains(container, StringComparer.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ ConditionProcessor conditionProcessor = new ConditionProcessor();
+
+ var anyOff = false;
+ foreach (ProfileCondition c in i.Conditions)
+ {
+ if (!conditionProcessor.IsImageConditionSatisfied(c, width, height))
+ {
+ anyOff = true;
+ break;
+ }
}
- var containers = i.GetContainers().ToList();
- if (containers.Count > 0 && !containers.Contains(container))
+ if (anyOff)
{
- return false;
+ continue;
}
- var conditionProcessor = new ConditionProcessor();
- return i.Conditions.All(c => conditionProcessor.IsImageConditionSatisfied(c,
- width,
- height));
- });
+ return i;
+ }
+ return null;
}
public ResponseProfile GetVideoMediaProfile(string container,
@@ -234,69 +272,90 @@ namespace MediaBrowser.Model.Dlna
{
container = (container ?? string.Empty).TrimStart('.');
- return ResponseProfiles.FirstOrDefault(i =>
+ foreach (var i in ResponseProfiles)
{
if (i.Type != DlnaProfileType.Video)
{
- return false;
+ continue;
+ }
+
+ List<string> containers = i.GetContainers();
+ if (containers.Count > 0 && !containers.Contains(container, StringComparer.OrdinalIgnoreCase))
+ {
+ continue;
}
- var containers = i.GetContainers().ToList();
- if (containers.Count > 0 && !containers.Contains(container))
+ List<string> audioCodecs = i.GetAudioCodecs();
+ if (audioCodecs.Count > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase))
{
- return false;
+ continue;
}
- var audioCodecs = i.GetAudioCodecs().ToList();
- if (audioCodecs.Count > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty))
+ List<string> videoCodecs = i.GetVideoCodecs();
+ if (videoCodecs.Count > 0 && !videoCodecs.Contains(videoCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ ConditionProcessor conditionProcessor = new ConditionProcessor();
+
+ var anyOff = false;
+ foreach (ProfileCondition c in i.Conditions)
{
- return false;
+ if (!conditionProcessor.IsVideoConditionSatisfied(c, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp))
+ {
+ anyOff = true;
+ break;
+ }
}
- var videoCodecs = i.GetVideoCodecs().ToList();
- if (videoCodecs.Count > 0 && !videoCodecs.Contains(videoCodec ?? string.Empty))
+ if (anyOff)
{
- return false;
+ continue;
}
- var conditionProcessor = new ConditionProcessor();
- return i.Conditions.All(c => conditionProcessor.IsVideoConditionSatisfied(c,
- audioBitrate,
- audioChannels,
- width,
- height,
- bitDepth,
- videoBitrate,
- videoProfile,
- videoLevel,
- videoFramerate,
- packetLength,
- timestamp));
- });
+ return i;
+ }
+ return null;
}
public ResponseProfile GetPhotoMediaProfile(string container, int? width, int? height)
{
container = (container ?? string.Empty).TrimStart('.');
- return ResponseProfiles.FirstOrDefault(i =>
+ foreach (var i in ResponseProfiles)
{
if (i.Type != DlnaProfileType.Photo)
{
- return false;
+ continue;
+ }
+
+ List<string> containers = i.GetContainers().ToList();
+ if (containers.Count > 0 && !containers.Contains(container, StringComparer.OrdinalIgnoreCase))
+ {
+ continue;
+ }
+
+ ConditionProcessor conditionProcessor = new ConditionProcessor();
+
+ var anyOff = false;
+ foreach (ProfileCondition c in i.Conditions)
+ {
+ if (!conditionProcessor.IsImageConditionSatisfied(c, width, height))
+ {
+ anyOff = true;
+ break;
+ }
}
- var containers = i.GetContainers().ToList();
- if (containers.Count > 0 && !containers.Contains(container))
+ if (anyOff)
{
- return false;
+ continue;
}
- var conditionProcessor = new ConditionProcessor();
- return i.Conditions.All(c => conditionProcessor.IsImageConditionSatisfied(c,
- width,
- height));
- });
+ return i;
+ }
+ return null;
}
}
}
diff --git a/MediaBrowser.Model/Dlna/DeviceProfileInfo.cs b/MediaBrowser.Model/Dlna/DeviceProfileInfo.cs
index ceb27386c..b2afdf292 100644
--- a/MediaBrowser.Model/Dlna/DeviceProfileInfo.cs
+++ b/MediaBrowser.Model/Dlna/DeviceProfileInfo.cs
@@ -21,10 +21,4 @@ namespace MediaBrowser.Model.Dlna
/// <value>The type.</value>
public DeviceProfileType Type { get; set; }
}
-
- public enum DeviceProfileType
- {
- System = 0,
- User = 1
- }
}
diff --git a/MediaBrowser.Model/Dlna/DeviceProfileType.cs b/MediaBrowser.Model/Dlna/DeviceProfileType.cs
new file mode 100644
index 000000000..f881a4539
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/DeviceProfileType.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Model.Dlna
+{
+ public enum DeviceProfileType
+ {
+ System = 0,
+ User = 1
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/DirectPlayProfile.cs b/MediaBrowser.Model/Dlna/DirectPlayProfile.cs
index e195c9450..183299425 100644
--- a/MediaBrowser.Model/Dlna/DirectPlayProfile.cs
+++ b/MediaBrowser.Model/Dlna/DirectPlayProfile.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using System.Linq;
using System.Xml.Serialization;
namespace MediaBrowser.Model.Dlna
@@ -20,33 +19,32 @@ namespace MediaBrowser.Model.Dlna
public List<string> GetContainers()
{
- return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList();
+ List<string> list = new List<string>();
+ foreach (string i in (Container ?? string.Empty).Split(','))
+ {
+ if (!string.IsNullOrEmpty(i)) list.Add(i);
+ }
+ return list;
}
public List<string> GetAudioCodecs()
{
- return (AudioCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList();
+ List<string> list = new List<string>();
+ foreach (string i in (AudioCodec ?? string.Empty).Split(','))
+ {
+ if (!string.IsNullOrEmpty(i)) list.Add(i);
+ }
+ return list;
}
public List<string> GetVideoCodecs()
{
- return (VideoCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList();
+ List<string> list = new List<string>();
+ foreach (string i in (VideoCodec ?? string.Empty).Split(','))
+ {
+ if (!string.IsNullOrEmpty(i)) list.Add(i);
+ }
+ return list;
}
}
-
- public class XmlAttribute
- {
- [XmlAttribute("name")]
- public string Name { get; set; }
-
- [XmlAttribute("value")]
- public string Value { get; set; }
- }
-
- public enum DlnaProfileType
- {
- Audio = 0,
- Video = 1,
- Photo = 2
- }
}
diff --git a/MediaBrowser.Model/Dlna/DlnaFlags.cs b/MediaBrowser.Model/Dlna/DlnaFlags.cs
new file mode 100644
index 000000000..23859312d
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/DlnaFlags.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace MediaBrowser.Model.Dlna
+{
+ [Flags]
+ public enum DlnaFlags : ulong
+ {
+ BackgroundTransferMode = (1 << 22),
+ ByteBasedSeek = (1 << 29),
+ ConnectionStall = (1 << 21),
+ DlnaV15 = (1 << 20),
+ InteractiveTransferMode = (1 << 23),
+ PlayContainer = (1 << 28),
+ RtspPause = (1 << 25),
+ S0Increase = (1 << 27),
+ SenderPaced = (1L << 31),
+ SnIncrease = (1 << 26),
+ 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 d2871474a..036c1fc74 100644
--- a/MediaBrowser.Model/Dlna/DlnaMaps.cs
+++ b/MediaBrowser.Model/Dlna/DlnaMaps.cs
@@ -1,6 +1,4 @@
-using System;
-
-namespace MediaBrowser.Model.Dlna
+namespace MediaBrowser.Model.Dlna
{
public class DlnaMaps
{
@@ -27,7 +25,7 @@ namespace MediaBrowser.Model.Dlna
{
if (hasKnownRuntime)
{
- var orgOp = string.Empty;
+ string orgOp = string.Empty;
// Time-based seeking currently only possible when transcoding
orgOp += isDirectStream ? "0" : "1";
@@ -44,7 +42,7 @@ namespace MediaBrowser.Model.Dlna
public static string GetImageOrgOpValue()
{
- var orgOp = string.Empty;
+ string orgOp = string.Empty;
// Time-based seeking currently only possible when transcoding
orgOp += "0";
@@ -55,21 +53,4 @@ namespace MediaBrowser.Model.Dlna
return orgOp;
}
}
-
- [Flags]
- public enum DlnaFlags : ulong
- {
- BackgroundTransferMode = (1 << 22),
- ByteBasedSeek = (1 << 29),
- ConnectionStall = (1 << 21),
- DlnaV15 = (1 << 20),
- InteractiveTransferMode = (1 << 23),
- PlayContainer = (1 << 28),
- RtspPause = (1 << 25),
- S0Increase = (1 << 27),
- SenderPaced = (1L << 31),
- SnIncrease = (1 << 26),
- StreamingTransferMode = (1 << 24),
- TimeBasedSeek = (1 << 30)
- }
}
diff --git a/MediaBrowser.Model/Dlna/DlnaProfileType.cs b/MediaBrowser.Model/Dlna/DlnaProfileType.cs
new file mode 100644
index 000000000..1bad14081
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/DlnaProfileType.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Model.Dlna
+{
+ public enum DlnaProfileType
+ {
+ Audio = 0,
+ Video = 1,
+ Photo = 2
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/Filter.cs b/MediaBrowser.Model/Dlna/Filter.cs
index c8940734b..760adb585 100644
--- a/MediaBrowser.Model/Dlna/Filter.cs
+++ b/MediaBrowser.Model/Dlna/Filter.cs
@@ -19,9 +19,10 @@ namespace MediaBrowser.Model.Dlna
{
_all = string.Equals(filter, "*", StringComparison.OrdinalIgnoreCase);
- _fields = (filter ?? string.Empty)
- .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
- .ToList();
+ List<string> list = new List<string>();
+ foreach (string s in (filter ?? string.Empty).Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries))
+ list.Add(s);
+ _fields = list;
}
public bool Contains(string field)
diff --git a/MediaBrowser.Model/Dlna/HeaderMatchType.cs b/MediaBrowser.Model/Dlna/HeaderMatchType.cs
new file mode 100644
index 000000000..7a0d5c24f
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/HeaderMatchType.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Model.Dlna
+{
+ public enum HeaderMatchType
+ {
+ Equals = 0,
+ Regex = 1,
+ Substring = 2
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/HttpHeaderInfo.cs b/MediaBrowser.Model/Dlna/HttpHeaderInfo.cs
new file mode 100644
index 000000000..926963ef6
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/HttpHeaderInfo.cs
@@ -0,0 +1,16 @@
+using System.Xml.Serialization;
+
+namespace MediaBrowser.Model.Dlna
+{
+ public class HttpHeaderInfo
+ {
+ [XmlAttribute("name")]
+ public string Name { get; set; }
+
+ [XmlAttribute("value")]
+ public string Value { get; set; }
+
+ [XmlAttribute("match")]
+ public HeaderMatchType Match { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
index a62508fb1..3c35ca0f6 100644
--- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
+++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
@@ -1,7 +1,6 @@
-using System;
+using MediaBrowser.Model.MediaInfo;
+using System;
using System.Collections.Generic;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Model.Dlna
{
@@ -11,13 +10,13 @@ namespace MediaBrowser.Model.Dlna
{
if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase))
{
- var val = ResolveVideoASFFormat(videoCodec, audioCodec, width, height);
+ MediaFormatProfile? val = ResolveVideoASFFormat(videoCodec, audioCodec, width, height);
return val.HasValue ? new List<MediaFormatProfile> { val.Value } : new List<MediaFormatProfile>();
}
if (string.Equals(container, "mp4", StringComparison.OrdinalIgnoreCase))
{
- var val = ResolveVideoMP4Format(videoCodec, audioCodec, width, height);
+ MediaFormatProfile? val = ResolveVideoMP4Format(videoCodec, audioCodec, width, height);
return val.HasValue ? new List<MediaFormatProfile> { val.Value } : new List<MediaFormatProfile>();
}
@@ -51,7 +50,7 @@ namespace MediaBrowser.Model.Dlna
if (string.Equals(container, "3gp", StringComparison.OrdinalIgnoreCase))
{
- var val = ResolveVideo3GPFormat(videoCodec, audioCodec);
+ MediaFormatProfile? val = ResolveVideo3GPFormat(videoCodec, audioCodec);
return val.HasValue ? new List<MediaFormatProfile> { val.Value } : new List<MediaFormatProfile>();
}
@@ -63,7 +62,7 @@ namespace MediaBrowser.Model.Dlna
private IEnumerable<MediaFormatProfile> ResolveVideoMPEG2TSFormat(string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestampType)
{
- var suffix = "";
+ string suffix = "";
switch (timestampType)
{
@@ -75,7 +74,7 @@ namespace MediaBrowser.Model.Dlna
break;
}
- var resolution = "S";
+ string resolution = "S";
if ((width.HasValue && width.Value > 720) || (height.HasValue && height.Value > 576))
{
resolution = "H";
@@ -83,7 +82,7 @@ namespace MediaBrowser.Model.Dlna
if (string.Equals(videoCodec, "mpeg2video", StringComparison.OrdinalIgnoreCase))
{
- var list = new List<MediaFormatProfile>();
+ List<MediaFormatProfile> list = new List<MediaFormatProfile>();
list.Add(ValueOf("MPEG_TS_SD_NA" + suffix));
list.Add(ValueOf("MPEG_TS_SD_EU" + suffix));
diff --git a/MediaBrowser.Model/Dlna/ProfileCondition.cs b/MediaBrowser.Model/Dlna/ProfileCondition.cs
new file mode 100644
index 000000000..24733426c
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/ProfileCondition.cs
@@ -0,0 +1,24 @@
+using System.Xml.Serialization;
+
+namespace MediaBrowser.Model.Dlna
+{
+ public class ProfileCondition
+ {
+ [XmlAttribute("condition")]
+ public ProfileConditionType Condition { get; set; }
+
+ [XmlAttribute("property")]
+ public ProfileConditionValue Property { get; set; }
+
+ [XmlAttribute("value")]
+ public string Value { get; set; }
+
+ [XmlAttribute("isRequired")]
+ public bool IsRequired { get; set; }
+
+ public ProfileCondition()
+ {
+ IsRequired = true;
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/ProfileConditionType.cs b/MediaBrowser.Model/Dlna/ProfileConditionType.cs
new file mode 100644
index 000000000..22156c47d
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/ProfileConditionType.cs
@@ -0,0 +1,10 @@
+namespace MediaBrowser.Model.Dlna
+{
+ public enum ProfileConditionType
+ {
+ Equals = 0,
+ NotEquals = 1,
+ LessThanEqual = 2,
+ GreaterThanEqual = 3
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/ProfileConditionValue.cs b/MediaBrowser.Model/Dlna/ProfileConditionValue.cs
new file mode 100644
index 000000000..56a322f5a
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/ProfileConditionValue.cs
@@ -0,0 +1,19 @@
+namespace MediaBrowser.Model.Dlna
+{
+ public enum ProfileConditionValue
+ {
+ AudioChannels,
+ AudioBitrate,
+ AudioProfile,
+ Width,
+ Height,
+ Has64BitOffsets,
+ PacketLength,
+ VideoBitDepth,
+ VideoBitrate,
+ VideoFramerate,
+ VideoLevel,
+ VideoProfile,
+ VideoTimestamp
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/ResponseProfile.cs b/MediaBrowser.Model/Dlna/ResponseProfile.cs
index e84095ffe..c1735f3b7 100644
--- a/MediaBrowser.Model/Dlna/ResponseProfile.cs
+++ b/MediaBrowser.Model/Dlna/ResponseProfile.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using System.Linq;
using System.Xml.Serialization;
namespace MediaBrowser.Model.Dlna
@@ -33,17 +32,32 @@ namespace MediaBrowser.Model.Dlna
public List<string> GetContainers()
{
- return (Container ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList();
+ List<string> list = new List<string>();
+ foreach (string i in (Container ?? string.Empty).Split(','))
+ {
+ if (!string.IsNullOrEmpty(i)) list.Add(i);
+ }
+ return list;
}
-
+
public List<string> GetAudioCodecs()
{
- return (AudioCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList();
+ List<string> list = new List<string>();
+ foreach (string i in (AudioCodec ?? string.Empty).Split(','))
+ {
+ if (!string.IsNullOrEmpty(i)) list.Add(i);
+ }
+ return list;
}
public List<string> GetVideoCodecs()
{
- return (VideoCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList();
+ List<string> list = new List<string>();
+ foreach (string i in (VideoCodec ?? string.Empty).Split(','))
+ {
+ if (!string.IsNullOrEmpty(i)) list.Add(i);
+ }
+ return list;
}
}
}
diff --git a/MediaBrowser.Model/Dlna/SearchCriteria.cs b/MediaBrowser.Model/Dlna/SearchCriteria.cs
index d3f8b8332..bb4221b51 100644
--- a/MediaBrowser.Model/Dlna/SearchCriteria.cs
+++ b/MediaBrowser.Model/Dlna/SearchCriteria.cs
@@ -37,13 +37,4 @@ namespace MediaBrowser.Model.Dlna
}
}
}
-
- public enum SearchType
- {
- Unknown = 0,
- Audio = 1,
- Image = 2,
- Video = 3,
- Playlist = 4
- }
}
diff --git a/MediaBrowser.Model/Dlna/SearchType.cs b/MediaBrowser.Model/Dlna/SearchType.cs
new file mode 100644
index 000000000..68c047603
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/SearchType.cs
@@ -0,0 +1,11 @@
+namespace MediaBrowser.Model.Dlna
+{
+ public enum SearchType
+ {
+ Unknown = 0,
+ Audio = 1,
+ Image = 2,
+ Video = 3,
+ Playlist = 4
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index 21441d36a..48356ef92 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -16,22 +16,27 @@ namespace MediaBrowser.Model.Dlna
{
ValidateAudioInput(options);
- var mediaSources = options.MediaSources;
+ List<MediaSourceInfo> mediaSources = options.MediaSources;
// If the client wants a specific media soure, filter now
if (!string.IsNullOrEmpty(options.MediaSourceId))
{
// Avoid implicitly captured closure
- var mediaSourceId = options.MediaSourceId;
+ string mediaSourceId = options.MediaSourceId;
- mediaSources = mediaSources
- .Where(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase))
- .ToList();
+ mediaSources = new List<MediaSourceInfo>();
+ foreach (MediaSourceInfo i in mediaSources)
+ {
+ if (string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase))
+ mediaSources.Add(i);
+ }
}
- var streams = mediaSources.Select(i => BuildAudioItem(i, options)).ToList();
+ List<StreamInfo> streams = new List<StreamInfo>();
+ foreach (MediaSourceInfo i in mediaSources)
+ streams.Add(BuildAudioItem(i, options));
- foreach (var stream in streams)
+ foreach (StreamInfo stream in streams)
{
stream.DeviceId = options.DeviceId;
stream.DeviceProfileId = options.Profile.Id;
@@ -44,22 +49,27 @@ namespace MediaBrowser.Model.Dlna
{
ValidateInput(options);
- var mediaSources = options.MediaSources;
+ List<MediaSourceInfo> mediaSources = options.MediaSources;
// If the client wants a specific media soure, filter now
if (!string.IsNullOrEmpty(options.MediaSourceId))
{
// Avoid implicitly captured closure
- var mediaSourceId = options.MediaSourceId;
+ string mediaSourceId = options.MediaSourceId;
- mediaSources = mediaSources
- .Where(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase))
- .ToList();
+ mediaSources = new List<MediaSourceInfo>();
+ foreach (MediaSourceInfo i in mediaSources)
+ {
+ if (string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase))
+ mediaSources.Add(i);
+ }
}
- var streams = mediaSources.Select(i => BuildVideoItem(i, options)).ToList();
+ List<StreamInfo> streams = new List<StreamInfo>();
+ foreach (MediaSourceInfo i in mediaSources)
+ streams.Add(BuildVideoItem(i, options));
- foreach (var stream in streams)
+ foreach (StreamInfo stream in streams)
{
stream.DeviceId = options.DeviceId;
stream.DeviceProfileId = options.Profile.Id;
@@ -72,13 +82,24 @@ namespace MediaBrowser.Model.Dlna
{
// Grab the first one that can be direct streamed
// If that doesn't produce anything, just take the first
- return streams.FirstOrDefault(i => i.IsDirectStream) ??
- streams.FirstOrDefault();
+ foreach (StreamInfo i in streams)
+ {
+ if (i.IsDirectStream)
+ {
+ return i;
+ }
+ }
+
+ foreach (StreamInfo stream in streams)
+ {
+ return stream;
+ }
+ return null;
}
private StreamInfo BuildAudioItem(MediaSourceInfo item, AudioOptions options)
{
- var playlistItem = new StreamInfo
+ StreamInfo playlistItem = new StreamInfo
{
ItemId = options.ItemId,
MediaType = DlnaProfileType.Audio,
@@ -86,32 +107,53 @@ namespace MediaBrowser.Model.Dlna
RunTimeTicks = item.RunTimeTicks
};
- var maxBitrateSetting = options.MaxBitrate ?? options.Profile.MaxBitrate;
+ int? maxBitrateSetting = options.MaxBitrate ?? options.Profile.MaxBitrate;
- var audioStream = item.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
+ MediaStream audioStream = item.DefaultAudioStream;
// Honor the max bitrate setting
if (IsAudioEligibleForDirectPlay(item, maxBitrateSetting))
{
- var directPlay = options.Profile.DirectPlayProfiles
- .FirstOrDefault(i => i.Type == playlistItem.MediaType && IsAudioDirectPlaySupported(i, item, audioStream));
+ DirectPlayProfile directPlay = null;
+ foreach (DirectPlayProfile i in options.Profile.DirectPlayProfiles)
+ {
+ if (i.Type == playlistItem.MediaType && IsAudioDirectPlaySupported(i, item, audioStream))
+ {
+ directPlay = i;
+ break;
+ }
+ }
if (directPlay != null)
{
- var audioCodec = audioStream == null ? null : audioStream.Codec;
+ string audioCodec = audioStream == null ? null : audioStream.Codec;
// Make sure audio codec profiles are satisfied
if (!string.IsNullOrEmpty(audioCodec))
{
- var conditionProcessor = new ConditionProcessor();
+ ConditionProcessor conditionProcessor = new ConditionProcessor();
+
+ List<ProfileCondition> conditions = new List<ProfileCondition>();
+ foreach (CodecProfile i in options.Profile.CodecProfiles)
+ {
+ if (i.Type == CodecType.Audio && i.ContainsCodec(audioCodec))
+ conditions.AddRange(i.Conditions);
+ }
- var conditions = options.Profile.CodecProfiles.Where(i => i.Type == CodecType.Audio && i.ContainsCodec(audioCodec))
- .SelectMany(i => i.Conditions);
+ int? audioChannels = audioStream.Channels;
+ int? audioBitrate = audioStream.BitRate;
- var audioChannels = audioStream == null ? null : audioStream.Channels;
- var audioBitrate = audioStream == null ? null : audioStream.BitRate;
+ bool all = true;
+ foreach (ProfileCondition c in conditions)
+ {
+ if (!conditionProcessor.IsAudioConditionSatisfied(c, audioChannels, audioBitrate))
+ {
+ all = false;
+ break;
+ }
+ }
- if (conditions.All(c => conditionProcessor.IsAudioConditionSatisfied(c, audioChannels, audioBitrate)))
+ if (all)
{
playlistItem.IsDirectStream = true;
playlistItem.Container = item.Container;
@@ -122,8 +164,15 @@ namespace MediaBrowser.Model.Dlna
}
}
- var transcodingProfile = options.Profile.TranscodingProfiles
- .FirstOrDefault(i => i.Type == playlistItem.MediaType);
+ TranscodingProfile transcodingProfile = null;
+ foreach (TranscodingProfile i in options.Profile.TranscodingProfiles)
+ {
+ if (i.Type == playlistItem.MediaType)
+ {
+ transcodingProfile = i;
+ break;
+ }
+ }
if (transcodingProfile != null)
{
@@ -134,17 +183,27 @@ namespace MediaBrowser.Model.Dlna
playlistItem.AudioCodec = transcodingProfile.AudioCodec;
playlistItem.Protocol = transcodingProfile.Protocol;
- var audioTranscodingConditions = options.Profile.CodecProfiles
- .Where(i => i.Type == CodecType.Audio && i.ContainsCodec(transcodingProfile.AudioCodec))
- .Take(1)
- .SelectMany(i => i.Conditions);
+ List<CodecProfile> audioCodecProfiles = new List<CodecProfile>();
+ foreach (CodecProfile i in options.Profile.CodecProfiles)
+ {
+ if (i.Type == CodecType.Audio && i.ContainsCodec(transcodingProfile.AudioCodec))
+ {
+ audioCodecProfiles.Add(i);
+ }
+
+ if (audioCodecProfiles.Count >= 1) break;
+ }
+
+ List<ProfileCondition> audioTranscodingConditions = new List<ProfileCondition>();
+ foreach (CodecProfile i in audioCodecProfiles)
+ audioTranscodingConditions.AddRange(i.Conditions);
ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
// Honor requested max channels
if (options.MaxAudioChannels.HasValue)
{
- var currentValue = playlistItem.MaxAudioChannels ?? options.MaxAudioChannels.Value;
+ int currentValue = playlistItem.MaxAudioChannels ?? options.MaxAudioChannels.Value;
playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue);
}
@@ -152,7 +211,7 @@ namespace MediaBrowser.Model.Dlna
// Honor requested max bitrate
if (maxBitrateSetting.HasValue)
{
- var currentValue = playlistItem.AudioBitrate ?? maxBitrateSetting.Value;
+ int currentValue = playlistItem.AudioBitrate ?? maxBitrateSetting.Value;
playlistItem.AudioBitrate = Math.Min(maxBitrateSetting.Value, currentValue);
}
@@ -163,7 +222,7 @@ namespace MediaBrowser.Model.Dlna
private StreamInfo BuildVideoItem(MediaSourceInfo item, VideoOptions options)
{
- var playlistItem = new StreamInfo
+ StreamInfo playlistItem = new StreamInfo
{
ItemId = options.ItemId,
MediaType = DlnaProfileType.Video,
@@ -171,15 +230,15 @@ namespace MediaBrowser.Model.Dlna
RunTimeTicks = item.RunTimeTicks
};
- var audioStream = item.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
- var videoStream = item.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
+ MediaStream audioStream = item.DefaultAudioStream;
+ MediaStream videoStream = item.VideoStream;
- var maxBitrateSetting = options.MaxBitrate ?? options.Profile.MaxBitrate;
+ int? maxBitrateSetting = options.MaxBitrate ?? options.Profile.MaxBitrate;
if (IsEligibleForDirectPlay(item, options, maxBitrateSetting))
{
// See if it can be direct played
- var directPlay = GetVideoDirectPlayProfile(options.Profile, item, videoStream, audioStream);
+ DirectPlayProfile directPlay = GetVideoDirectPlayProfile(options.Profile, item, videoStream, audioStream);
if (directPlay != null)
{
@@ -191,8 +250,15 @@ namespace MediaBrowser.Model.Dlna
}
// Can't direct play, find the transcoding profile
- var transcodingProfile = options.Profile.TranscodingProfiles
- .FirstOrDefault(i => i.Type == playlistItem.MediaType);
+ TranscodingProfile transcodingProfile = null;
+ foreach (TranscodingProfile i in options.Profile.TranscodingProfiles)
+ {
+ if (i.Type == playlistItem.MediaType)
+ {
+ transcodingProfile = i;
+ break;
+ }
+ }
if (transcodingProfile != null)
{
@@ -200,30 +266,38 @@ namespace MediaBrowser.Model.Dlna
playlistItem.Container = transcodingProfile.Container;
playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength;
playlistItem.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo;
- playlistItem.AudioCodec = transcodingProfile.AudioCodec.Split(',').FirstOrDefault();
+ playlistItem.AudioCodec = transcodingProfile.AudioCodec.Split(',')[0];
playlistItem.VideoCodec = transcodingProfile.VideoCodec;
playlistItem.Protocol = transcodingProfile.Protocol;
playlistItem.AudioStreamIndex = options.AudioStreamIndex;
playlistItem.SubtitleStreamIndex = options.SubtitleStreamIndex;
- var videoTranscodingConditions = options.Profile.CodecProfiles
- .Where(i => i.Type == CodecType.Video && i.ContainsCodec(transcodingProfile.VideoCodec))
- .Take(1)
- .SelectMany(i => i.Conditions);
-
+ 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);
+ break;
+ }
+ }
ApplyTranscodingConditions(playlistItem, videoTranscodingConditions);
- var audioTranscodingConditions = options.Profile.CodecProfiles
- .Where(i => i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec))
- .Take(1)
- .SelectMany(i => i.Conditions);
-
+ List<ProfileCondition> audioTranscodingConditions = new List<ProfileCondition>();
+ foreach (CodecProfile i in options.Profile.CodecProfiles)
+ {
+ if (i.Type == CodecType.VideoAudio && i.ContainsCodec(transcodingProfile.AudioCodec))
+ {
+ audioTranscodingConditions.AddRange(i.Conditions);
+ break;
+ }
+ }
ApplyTranscodingConditions(playlistItem, audioTranscodingConditions);
// Honor requested max channels
if (options.MaxAudioChannels.HasValue)
{
- var currentValue = playlistItem.MaxAudioChannels ?? options.MaxAudioChannels.Value;
+ int currentValue = playlistItem.MaxAudioChannels ?? options.MaxAudioChannels.Value;
playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue);
}
@@ -231,7 +305,7 @@ namespace MediaBrowser.Model.Dlna
// Honor requested max bitrate
if (options.MaxAudioTranscodingBitrate.HasValue)
{
- var currentValue = playlistItem.AudioBitrate ?? options.MaxAudioTranscodingBitrate.Value;
+ int currentValue = playlistItem.AudioBitrate ?? options.MaxAudioTranscodingBitrate.Value;
playlistItem.AudioBitrate = Math.Min(options.MaxAudioTranscodingBitrate.Value, currentValue);
}
@@ -239,14 +313,14 @@ namespace MediaBrowser.Model.Dlna
// Honor max rate
if (maxBitrateSetting.HasValue)
{
- var videoBitrate = maxBitrateSetting.Value;
+ int videoBitrate = maxBitrateSetting.Value;
if (playlistItem.AudioBitrate.HasValue)
{
videoBitrate -= playlistItem.AudioBitrate.Value;
}
- var currentValue = playlistItem.VideoBitrate ?? videoBitrate;
+ int currentValue = playlistItem.VideoBitrate ?? videoBitrate;
playlistItem.VideoBitrate = Math.Min(videoBitrate, currentValue);
}
@@ -261,100 +335,103 @@ namespace MediaBrowser.Model.Dlna
MediaStream audioStream)
{
// See if it can be direct played
- var directPlay = profile.DirectPlayProfiles
- .FirstOrDefault(i => i.Type == DlnaProfileType.Video && IsVideoDirectPlaySupported(i, mediaSource, videoStream, audioStream));
+ DirectPlayProfile directPlay = null;
+ foreach (DirectPlayProfile i in profile.DirectPlayProfiles)
+ {
+ if (i.Type == DlnaProfileType.Video && IsVideoDirectPlaySupported(i, mediaSource, videoStream, audioStream))
+ {
+ directPlay = i;
+ break;
+ }
+ }
if (directPlay == null)
{
return null;
}
- var container = mediaSource.Container;
+ string container = mediaSource.Container;
- var conditions = profile.ContainerProfiles
- .Where(i => i.Type == DlnaProfileType.Video && i.GetContainers().Contains(container, StringComparer.OrdinalIgnoreCase))
- .SelectMany(i => i.Conditions);
+ List<ProfileCondition> conditions = new List<ProfileCondition>();
+ foreach (ContainerProfile i in profile.ContainerProfiles)
+ {
+ if (i.Type == DlnaProfileType.Video &&
+ i.GetContainers().Contains(container, StringComparer.OrdinalIgnoreCase))
+ {
+ conditions.AddRange(i.Conditions);
+ }
+ }
- var conditionProcessor = new ConditionProcessor();
+ ConditionProcessor conditionProcessor = new ConditionProcessor();
- var width = videoStream == null ? null : videoStream.Width;
- var height = videoStream == null ? null : videoStream.Height;
- var bitDepth = videoStream == null ? null : videoStream.BitDepth;
- var videoBitrate = videoStream == null ? null : videoStream.BitRate;
- var videoLevel = videoStream == null ? null : videoStream.Level;
- var videoProfile = videoStream == null ? null : videoStream.Profile;
- var videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate;
+ int? width = videoStream == null ? null : videoStream.Width;
+ int? height = videoStream == null ? null : videoStream.Height;
+ int? bitDepth = videoStream == null ? null : videoStream.BitDepth;
+ int? videoBitrate = videoStream == null ? null : videoStream.BitRate;
+ double? videoLevel = videoStream == null ? null : videoStream.Level;
+ string videoProfile = videoStream == null ? null : videoStream.Profile;
+ float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate;
- var audioBitrate = audioStream == null ? null : audioStream.BitRate;
- var audioChannels = audioStream == null ? null : audioStream.Channels;
- var audioProfile = audioStream == null ? null : audioStream.Profile;
+ int? audioBitrate = audioStream == null ? null : audioStream.BitRate;
+ int? audioChannels = audioStream == null ? null : audioStream.Channels;
+ string audioProfile = audioStream == null ? null : audioStream.Profile;
- var timestamp = videoStream == null ? TransportStreamTimestamp.None : mediaSource.Timestamp;
- var packetLength = videoStream == null ? null : videoStream.PacketLength;
+ TransportStreamTimestamp? timestamp = videoStream == null ? TransportStreamTimestamp.None : mediaSource.Timestamp;
+ int? packetLength = videoStream == null ? null : videoStream.PacketLength;
// Check container conditions
- if (!conditions.All(i => conditionProcessor.IsVideoConditionSatisfied(i,
- audioBitrate,
- audioChannels,
- width,
- height,
- bitDepth,
- videoBitrate,
- videoProfile,
- videoLevel,
- videoFramerate,
- packetLength,
- timestamp)))
+ foreach (ProfileCondition i in conditions)
{
- return null;
+ if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp))
+ {
+ return null;
+ }
}
- var videoCodec = videoStream == null ? null : videoStream.Codec;
+ string videoCodec = videoStream == null ? null : videoStream.Codec;
if (string.IsNullOrEmpty(videoCodec))
{
return null;
}
- conditions = profile.CodecProfiles
- .Where(i => i.Type == CodecType.Video && i.ContainsCodec(videoCodec))
- .SelectMany(i => i.Conditions);
+ conditions = new List<ProfileCondition>();
+ foreach (CodecProfile i in profile.CodecProfiles)
+ {
+ if (i.Type == CodecType.Video && i.ContainsCodec(videoCodec))
+ conditions.AddRange(i.Conditions);
+ }
- if (!conditions.All(i => conditionProcessor.IsVideoConditionSatisfied(i,
- audioBitrate,
- audioChannels,
- width,
- height,
- bitDepth,
- videoBitrate,
- videoProfile,
- videoLevel,
- videoFramerate,
- packetLength,
- timestamp)))
+ foreach (ProfileCondition i in conditions)
{
- return null;
+ if (!conditionProcessor.IsVideoConditionSatisfied(i, audioBitrate, audioChannels, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp))
+ {
+ return null;
+ }
}
if (audioStream != null)
{
- var audioCodec = audioStream.Codec;
+ string audioCodec = audioStream.Codec;
if (string.IsNullOrEmpty(audioCodec))
{
return null;
}
- conditions = profile.CodecProfiles
- .Where(i => i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec))
- .SelectMany(i => i.Conditions);
+ conditions = new List<ProfileCondition>();
+ foreach (CodecProfile i in profile.CodecProfiles)
+ {
+ if (i.Type == CodecType.VideoAudio && i.ContainsCodec(audioCodec))
+ conditions.AddRange(i.Conditions);
+ }
- if (!conditions.All(i => conditionProcessor.IsVideoAudioConditionSatisfied(i,
- audioChannels,
- audioBitrate,
- audioProfile)))
+ foreach (ProfileCondition i in conditions)
{
- return null;
+ if (!conditionProcessor.IsVideoAudioConditionSatisfied(i, audioChannels, audioBitrate, audioProfile))
+ {
+ return null;
+ }
}
}
@@ -368,12 +445,6 @@ namespace MediaBrowser.Model.Dlna
return false;
}
- if (options.AudioStreamIndex.HasValue &&
- item.MediaStreams.Count(i => i.Type == MediaStreamType.Audio) > 1)
- {
- return false;
- }
-
return IsAudioEligibleForDirectPlay(item, maxBitrate);
}
@@ -420,10 +491,14 @@ namespace MediaBrowser.Model.Dlna
private void ApplyTranscodingConditions(StreamInfo item, IEnumerable<ProfileCondition> conditions)
{
- foreach (var condition in conditions
- .Where(i => !string.IsNullOrEmpty(i.Value)))
+ foreach (ProfileCondition condition in conditions)
{
- var value = condition.Value;
+ string value = condition.Value;
+
+ if (string.IsNullOrEmpty(value))
+ {
+ continue;
+ }
switch (condition.Property)
{
@@ -515,8 +590,17 @@ namespace MediaBrowser.Model.Dlna
if (profile.Container.Length > 0)
{
// Check container type
- var mediaContainer = item.Container ?? string.Empty;
- if (!profile.GetContainers().Any(i => string.Equals(i, mediaContainer, StringComparison.OrdinalIgnoreCase)))
+ string mediaContainer = item.Container ?? string.Empty;
+ bool any = false;
+ foreach (string i in profile.GetContainers())
+ {
+ if (string.Equals(i, mediaContainer, StringComparison.OrdinalIgnoreCase))
+ {
+ any = true;
+ break;
+ }
+ }
+ if (!any)
{
return false;
}
@@ -536,29 +620,38 @@ namespace MediaBrowser.Model.Dlna
if (profile.Container.Length > 0)
{
// Check container type
- var mediaContainer = item.Container ?? string.Empty;
- if (!profile.GetContainers().Any(i => string.Equals(i, mediaContainer, StringComparison.OrdinalIgnoreCase)))
+ string mediaContainer = item.Container ?? string.Empty;
+ bool any = false;
+ foreach (string i in profile.GetContainers())
+ {
+ if (string.Equals(i, mediaContainer, StringComparison.OrdinalIgnoreCase))
+ {
+ any = true;
+ break;
+ }
+ }
+ if (!any)
{
return false;
}
}
// Check video codec
- var videoCodecs = profile.GetVideoCodecs();
+ List<string> videoCodecs = profile.GetVideoCodecs();
if (videoCodecs.Count > 0)
{
- var videoCodec = videoStream == null ? null : videoStream.Codec;
+ string videoCodec = videoStream == null ? null : videoStream.Codec;
if (string.IsNullOrEmpty(videoCodec) || !videoCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase))
{
return false;
}
}
- var audioCodecs = profile.GetAudioCodecs();
+ List<string> audioCodecs = profile.GetAudioCodecs();
if (audioCodecs.Count > 0)
{
// Check audio codecs
- var audioCodec = audioStream == null ? null : audioStream.Codec;
+ string audioCodec = audioStream == null ? null : audioStream.Codec;
if (string.IsNullOrEmpty(audioCodec) || !audioCodecs.Contains(audioCodec, StringComparer.OrdinalIgnoreCase))
{
return false;
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index fe49227e4..e4ec0d853 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -1,11 +1,10 @@
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.MediaInfo;
using System;
using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
-using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Model.Dlna
{
@@ -79,9 +78,9 @@ namespace MediaBrowser.Model.Dlna
throw new ArgumentNullException(baseUrl);
}
- var dlnaCommand = BuildDlnaParam(this);
+ string dlnaCommand = BuildDlnaParam(this);
- var extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container;
+ string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container;
baseUrl = baseUrl.TrimEnd('/');
@@ -98,11 +97,11 @@ namespace MediaBrowser.Model.Dlna
return string.Format("{0}/videos/{1}/stream{2}?{3}", baseUrl, ItemId, extension, dlnaCommand);
}
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
private static string BuildDlnaParam(StreamInfo item)
{
- var usCulture = new CultureInfo("en-US");
-
- var list = new List<string>
+ List<string> list = new List<string>
{
item.DeviceProfileId ?? string.Empty,
item.DeviceId ?? string.Empty,
@@ -110,16 +109,16 @@ namespace MediaBrowser.Model.Dlna
(item.IsDirectStream).ToString().ToLower(),
item.VideoCodec ?? string.Empty,
item.AudioCodec ?? string.Empty,
- item.AudioStreamIndex.HasValue ? item.AudioStreamIndex.Value.ToString(usCulture) : string.Empty,
- item.SubtitleStreamIndex.HasValue ? item.SubtitleStreamIndex.Value.ToString(usCulture) : string.Empty,
- item.VideoBitrate.HasValue ? item.VideoBitrate.Value.ToString(usCulture) : string.Empty,
- item.AudioBitrate.HasValue ? item.AudioBitrate.Value.ToString(usCulture) : string.Empty,
- item.MaxAudioChannels.HasValue ? item.MaxAudioChannels.Value.ToString(usCulture) : string.Empty,
- item.MaxFramerate.HasValue ? item.MaxFramerate.Value.ToString(usCulture) : string.Empty,
- item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(usCulture) : string.Empty,
- item.MaxHeight.HasValue ? item.MaxHeight.Value.ToString(usCulture) : string.Empty,
- item.StartPositionTicks.ToString(usCulture),
- item.VideoLevel.HasValue ? item.VideoLevel.Value.ToString(usCulture) : string.Empty
+ item.AudioStreamIndex.HasValue ? item.AudioStreamIndex.Value.ToString(UsCulture) : string.Empty,
+ item.SubtitleStreamIndex.HasValue ? item.SubtitleStreamIndex.Value.ToString(UsCulture) : string.Empty,
+ item.VideoBitrate.HasValue ? item.VideoBitrate.Value.ToString(UsCulture) : string.Empty,
+ item.AudioBitrate.HasValue ? item.AudioBitrate.Value.ToString(UsCulture) : string.Empty,
+ item.MaxAudioChannels.HasValue ? item.MaxAudioChannels.Value.ToString(UsCulture) : string.Empty,
+ item.MaxFramerate.HasValue ? item.MaxFramerate.Value.ToString(UsCulture) : string.Empty,
+ item.MaxWidth.HasValue ? item.MaxWidth.Value.ToString(UsCulture) : string.Empty,
+ item.MaxHeight.HasValue ? item.MaxHeight.Value.ToString(UsCulture) : string.Empty,
+ item.StartPositionTicks.ToString(UsCulture),
+ item.VideoLevel.HasValue ? item.VideoLevel.Value.ToString(UsCulture) : string.Empty
};
return string.Format("Params={0}", string.Join(";", list.ToArray()));
@@ -134,14 +133,17 @@ namespace MediaBrowser.Model.Dlna
{
if (MediaSource != null)
{
- var audioStreams = MediaSource.MediaStreams.Where(i => i.Type == MediaStreamType.Audio);
-
if (AudioStreamIndex.HasValue)
{
- return audioStreams.FirstOrDefault(i => i.Index == AudioStreamIndex.Value);
+ foreach (MediaStream i in MediaSource.MediaStreams)
+ {
+ if (i.Index == AudioStreamIndex.Value && i.Type == MediaStreamType.Audio)
+ return i;
+ }
+ return null;
}
- return audioStreams.FirstOrDefault();
+ return MediaSource.DefaultAudioStream;
}
return null;
@@ -157,8 +159,7 @@ namespace MediaBrowser.Model.Dlna
{
if (MediaSource != null)
{
- return MediaSource.MediaStreams
- .FirstOrDefault(i => i.Type == MediaStreamType.Video && (i.Codec ?? string.Empty).IndexOf("jpeg", StringComparison.OrdinalIgnoreCase) == -1);
+ return MediaSource.VideoStream;
}
return null;
@@ -172,7 +173,7 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var stream = TargetAudioStream;
+ MediaStream stream = TargetAudioStream;
return stream == null ? null : stream.SampleRate;
}
}
@@ -184,7 +185,7 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var stream = TargetVideoStream;
+ MediaStream stream = TargetVideoStream;
return stream == null || !IsDirectStream ? null : stream.BitDepth;
}
}
@@ -196,7 +197,7 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var stream = TargetVideoStream;
+ MediaStream stream = TargetVideoStream;
return MaxFramerate.HasValue && !IsDirectStream
? MaxFramerate
: stream == null ? null : stream.AverageFrameRate ?? stream.RealFrameRate;
@@ -210,7 +211,7 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var stream = TargetVideoStream;
+ MediaStream stream = TargetVideoStream;
return VideoLevel.HasValue && !IsDirectStream
? VideoLevel
: stream == null ? null : stream.Level;
@@ -224,7 +225,7 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var stream = TargetVideoStream;
+ MediaStream stream = TargetVideoStream;
return !IsDirectStream
? null
: stream == null ? null : stream.PacketLength;
@@ -238,7 +239,7 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var stream = TargetVideoStream;
+ MediaStream stream = TargetVideoStream;
return !string.IsNullOrEmpty(VideoProfile) && !IsDirectStream
? VideoProfile
: stream == null ? null : stream.Profile;
@@ -252,7 +253,7 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var stream = TargetAudioStream;
+ MediaStream stream = TargetAudioStream;
return AudioBitrate.HasValue && !IsDirectStream
? AudioBitrate
: stream == null ? null : stream.BitRate;
@@ -266,8 +267,8 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var stream = TargetAudioStream;
- var streamChannels = stream == null ? null : stream.Channels;
+ MediaStream stream = TargetAudioStream;
+ int? streamChannels = stream == null ? null : stream.Channels;
return MaxAudioChannels.HasValue && !IsDirectStream
? (streamChannels.HasValue ? Math.Min(MaxAudioChannels.Value, streamChannels.Value) : MaxAudioChannels.Value)
@@ -282,7 +283,7 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var stream = TargetAudioStream;
+ MediaStream stream = TargetAudioStream;
return IsDirectStream
? (stream == null ? null : stream.Codec)
@@ -304,10 +305,10 @@ namespace MediaBrowser.Model.Dlna
if (RunTimeTicks.HasValue)
{
- var totalBitrate = TargetTotalBitrate;
+ int? totalBitrate = TargetTotalBitrate;
return totalBitrate.HasValue ?
- Convert.ToInt64(totalBitrate * TimeSpan.FromTicks(RunTimeTicks.Value).TotalSeconds) :
+ Convert.ToInt64(totalBitrate.Value * TimeSpan.FromTicks(RunTimeTicks.Value).TotalSeconds) :
(long?)null;
}
@@ -319,7 +320,7 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var stream = TargetVideoStream;
+ MediaStream stream = TargetVideoStream;
return VideoBitrate.HasValue && !IsDirectStream
? VideoBitrate
@@ -331,7 +332,7 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var defaultValue = string.Equals(Container, "m2ts", StringComparison.OrdinalIgnoreCase)
+ TransportStreamTimestamp defaultValue = string.Equals(Container, "m2ts", StringComparison.OrdinalIgnoreCase)
? TransportStreamTimestamp.Valid
: TransportStreamTimestamp.None;
@@ -353,17 +354,17 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var videoStream = TargetVideoStream;
+ MediaStream videoStream = TargetVideoStream;
if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue)
{
- var size = new ImageSize
+ ImageSize size = new ImageSize
{
Width = videoStream.Width.Value,
Height = videoStream.Height.Value
};
- var newSize = DrawingUtils.Resize(size,
+ ImageSize newSize = DrawingUtils.Resize(size,
null,
null,
MaxWidth,
@@ -380,17 +381,17 @@ namespace MediaBrowser.Model.Dlna
{
get
{
- var videoStream = TargetVideoStream;
+ MediaStream videoStream = TargetVideoStream;
if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue)
{
- var size = new ImageSize
+ ImageSize size = new ImageSize
{
Width = videoStream.Width.Value,
Height = videoStream.Height.Value
};
- var newSize = DrawingUtils.Resize(size,
+ ImageSize newSize = DrawingUtils.Resize(size,
null,
null,
MaxWidth,
@@ -403,47 +404,4 @@ namespace MediaBrowser.Model.Dlna
}
}
}
-
- /// <summary>
- /// Class AudioOptions.
- /// </summary>
- public class AudioOptions
- {
- public string ItemId { get; set; }
- public List<MediaSourceInfo> MediaSources { get; set; }
- public DeviceProfile Profile { get; set; }
-
- /// <summary>
- /// Optional. Only needed if a specific AudioStreamIndex or SubtitleStreamIndex are requested.
- /// </summary>
- public string MediaSourceId { get; set; }
-
- public string DeviceId { get; set; }
-
- /// <summary>
- /// Allows an override of supported number of audio channels
- /// Example: DeviceProfile supports five channel, but user only has stereo speakers
- /// </summary>
- public int? MaxAudioChannels { get; set; }
-
- /// <summary>
- /// The application's configured quality setting
- /// </summary>
- public int? MaxBitrate { get; set; }
- }
-
- /// <summary>
- /// Class VideoOptions.
- /// </summary>
- public class VideoOptions : AudioOptions
- {
- public int? AudioStreamIndex { get; set; }
- public int? SubtitleStreamIndex { get; set; }
- public int? MaxAudioTranscodingBitrate { get; set; }
-
- public VideoOptions()
- {
- MaxAudioTranscodingBitrate = 128000;
- }
- }
}
diff --git a/MediaBrowser.Model/Dlna/TranscodeSeekInfo.cs b/MediaBrowser.Model/Dlna/TranscodeSeekInfo.cs
new file mode 100644
index 000000000..564ce5c60
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/TranscodeSeekInfo.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Model.Dlna
+{
+ public enum TranscodeSeekInfo
+ {
+ Auto = 0,
+ Bytes = 1
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dlna/TranscodingProfile.cs b/MediaBrowser.Model/Dlna/TranscodingProfile.cs
index ba02e9be2..51f4bfe61 100644
--- a/MediaBrowser.Model/Dlna/TranscodingProfile.cs
+++ b/MediaBrowser.Model/Dlna/TranscodingProfile.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using System.Linq;
using System.Xml.Serialization;
namespace MediaBrowser.Model.Dlna
@@ -35,13 +34,12 @@ namespace MediaBrowser.Model.Dlna
public List<string> GetAudioCodecs()
{
- return (AudioCodec ?? string.Empty).Split(',').Where(i => !string.IsNullOrEmpty(i)).ToList();
+ List<string> list = new List<string>();
+ foreach (string i in (AudioCodec ?? string.Empty).Split(','))
+ {
+ if (!string.IsNullOrEmpty(i)) list.Add(i);
+ }
+ return list;
}
}
-
- public enum TranscodeSeekInfo
- {
- Auto = 0,
- Bytes = 1
- }
}
diff --git a/MediaBrowser.Model/Dlna/VideoOptions.cs b/MediaBrowser.Model/Dlna/VideoOptions.cs
new file mode 100644
index 000000000..39a5ab1b1
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/VideoOptions.cs
@@ -0,0 +1,17 @@
+namespace MediaBrowser.Model.Dlna
+{
+ /// <summary>
+ /// Class VideoOptions.
+ /// </summary>
+ public class VideoOptions : AudioOptions
+ {
+ 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/Dlna/XmlAttribute.cs b/MediaBrowser.Model/Dlna/XmlAttribute.cs
new file mode 100644
index 000000000..e8e13ba0d
--- /dev/null
+++ b/MediaBrowser.Model/Dlna/XmlAttribute.cs
@@ -0,0 +1,13 @@
+using System.Xml.Serialization;
+
+namespace MediaBrowser.Model.Dlna
+{
+ public class XmlAttribute
+ {
+ [XmlAttribute("name")]
+ public string Name { get; set; }
+
+ [XmlAttribute("value")]
+ public string Value { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Drawing/DrawingUtils.cs b/MediaBrowser.Model/Drawing/DrawingUtils.cs
index e95b5e375..fcc5ddd16 100644
--- a/MediaBrowser.Model/Drawing/DrawingUtils.cs
+++ b/MediaBrowser.Model/Drawing/DrawingUtils.cs
@@ -1,6 +1,4 @@
-using System.Globalization;
-
-namespace MediaBrowser.Model.Drawing
+namespace MediaBrowser.Model.Drawing
{
/// <summary>
/// Class DrawingUtils
@@ -16,7 +14,12 @@ namespace MediaBrowser.Model.Drawing
/// <returns>ImageSize.</returns>
public static ImageSize Scale(double currentWidth, double currentHeight, double scaleFactor)
{
- return Scale(new ImageSize { Width = currentWidth, Height = currentHeight }, scaleFactor);
+ return Scale(new ImageSize
+ {
+ Width = currentWidth,
+ Height = currentHeight
+
+ }, scaleFactor);
}
/// <summary>
@@ -27,9 +30,9 @@ namespace MediaBrowser.Model.Drawing
/// <returns>ImageSize.</returns>
public static ImageSize Scale(ImageSize size, double scaleFactor)
{
- var newWidth = size.Width * scaleFactor;
+ double newWidth = size.Width * scaleFactor;
- return Resize(size.Width, size.Height, newWidth);
+ return Resize(size.Width, size.Height, newWidth, null, null, null);
}
/// <summary>
@@ -42,9 +45,19 @@ namespace MediaBrowser.Model.Drawing
/// <param name="maxWidth">A max fixed width, if desired</param>
/// <param name="maxHeight">A max fixed height, if desired</param>
/// <returns>ImageSize.</returns>
- public static ImageSize Resize(double currentWidth, double currentHeight, double? width = null, double? height = null, double? maxWidth = null, double? maxHeight = null)
+ public static ImageSize Resize(double currentWidth,
+ double currentHeight,
+ double? width,
+ double? height,
+ double? maxWidth,
+ double? maxHeight)
{
- return Resize(new ImageSize { Width = currentWidth, Height = currentHeight }, width, height, maxWidth, maxHeight);
+ return Resize(new ImageSize
+ {
+ Width = currentWidth,
+ Height = currentHeight
+
+ }, width, height, maxWidth, maxHeight);
}
/// <summary>
@@ -56,7 +69,11 @@ namespace MediaBrowser.Model.Drawing
/// <param name="maxWidth">A max fixed width, if desired</param>
/// <param name="maxHeight">A max fixed height, if desired</param>
/// <returns>A new size object</returns>
- public static ImageSize Resize(ImageSize size, double? width = null, double? height = null, double? maxWidth = null, double? maxHeight = null)
+ public static ImageSize Resize(ImageSize size,
+ double? width,
+ double? height,
+ double? maxWidth,
+ double? maxHeight)
{
double newWidth = size.Width;
double newHeight = size.Height;
@@ -79,13 +96,13 @@ namespace MediaBrowser.Model.Drawing
newWidth = width.Value;
}
- if (maxHeight.HasValue && maxHeight < newHeight)
+ if (maxHeight.HasValue && maxHeight.Value < newHeight)
{
newWidth = GetNewWidth(newHeight, newWidth, maxHeight.Value);
newHeight = maxHeight.Value;
}
- if (maxWidth.HasValue && maxWidth < newWidth)
+ if (maxWidth.HasValue && maxWidth.Value < newWidth)
{
newHeight = GetNewHeight(newHeight, newWidth, maxWidth.Value);
newWidth = maxWidth.Value;
@@ -103,7 +120,7 @@ namespace MediaBrowser.Model.Drawing
/// <returns>System.Double.</returns>
private static double GetNewWidth(double currentHeight, double currentWidth, double newHeight)
{
- var scaleFactor = newHeight;
+ double scaleFactor = newHeight;
scaleFactor /= currentHeight;
scaleFactor *= currentWidth;
@@ -119,90 +136,11 @@ namespace MediaBrowser.Model.Drawing
/// <returns>System.Double.</returns>
private static double GetNewHeight(double currentHeight, double currentWidth, double newWidth)
{
- var scaleFactor = newWidth;
+ double scaleFactor = newWidth;
scaleFactor /= currentWidth;
scaleFactor *= currentHeight;
return scaleFactor;
}
}
-
- /// <summary>
- /// Struct ImageSize
- /// </summary>
- public struct ImageSize
- {
- private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
- private double _height;
- private double _width;
-
- /// <summary>
- /// Gets or sets the height.
- /// </summary>
- /// <value>The height.</value>
- public double Height
- {
- get
- {
- return _height;
- }
- set
- {
- _height = value;
- }
- }
-
- /// <summary>
- /// Gets or sets the width.
- /// </summary>
- /// <value>The width.</value>
- public double Width
- {
- get { return _width; }
- set { _width = value; }
- }
-
- public bool Equals(ImageSize size)
- {
- return Width.Equals(size.Width) && Height.Equals(size.Height);
- }
-
- public override string ToString()
- {
- return string.Format("{0}-{1}", Width, Height);
- }
-
- public ImageSize(string value)
- {
- _width = 0;
-
- _height = 0;
-
- ParseValue(value);
- }
-
- private void ParseValue(string value)
- {
- if (!string.IsNullOrEmpty(value))
- {
- var parts = value.Split('-');
-
- if (parts.Length == 2)
- {
- double val;
-
- if (double.TryParse(parts[0], NumberStyles.Any, UsCulture, out val))
- {
- _width = val;
- }
-
- if (double.TryParse(parts[1], NumberStyles.Any, UsCulture, out val))
- {
- _height = val;
- }
- }
- }
- }
- }
}
diff --git a/MediaBrowser.Model/Drawing/ImageSize.cs b/MediaBrowser.Model/Drawing/ImageSize.cs
new file mode 100644
index 000000000..acc245938
--- /dev/null
+++ b/MediaBrowser.Model/Drawing/ImageSize.cs
@@ -0,0 +1,83 @@
+using System.Globalization;
+
+namespace MediaBrowser.Model.Drawing
+{
+ /// <summary>
+ /// Struct ImageSize
+ /// </summary>
+ public struct ImageSize
+ {
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
+ private double _height;
+ private double _width;
+
+ /// <summary>
+ /// Gets or sets the height.
+ /// </summary>
+ /// <value>The height.</value>
+ public double Height
+ {
+ get
+ {
+ return _height;
+ }
+ set
+ {
+ _height = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the width.
+ /// </summary>
+ /// <value>The width.</value>
+ public double Width
+ {
+ get { return _width; }
+ set { _width = value; }
+ }
+
+ public bool Equals(ImageSize size)
+ {
+ return Width.Equals(size.Width) && Height.Equals(size.Height);
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0}-{1}", Width, Height);
+ }
+
+ public ImageSize(string value)
+ {
+ _width = 0;
+
+ _height = 0;
+
+ ParseValue(value);
+ }
+
+ private void ParseValue(string value)
+ {
+ if (!string.IsNullOrEmpty(value))
+ {
+ string[] parts = value.Split('-');
+
+ if (parts.Length == 2)
+ {
+ double val;
+
+ if (double.TryParse(parts[0], NumberStyles.Any, UsCulture, out val))
+ {
+ _width = val;
+ }
+
+ if (double.TryParse(parts[1], NumberStyles.Any, UsCulture, out val))
+ {
+ _height = val;
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs
index a4bb0646a..c469d97d6 100644
--- a/MediaBrowser.Model/Dto/BaseItemDto.cs
+++ b/MediaBrowser.Model/Dto/BaseItemDto.cs
@@ -311,7 +311,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the parent backdrop image tags.
/// </summary>
/// <value>The parent backdrop image tags.</value>
- public List<Guid> ParentBackdropImageTags { get; set; }
+ public List<string> ParentBackdropImageTags { get; set; }
/// <summary>
/// Gets or sets the local trailer count.
@@ -326,12 +326,6 @@ namespace MediaBrowser.Model.Dto
public UserItemDataDto UserData { get; set; }
/// <summary>
- /// Gets or sets the recently added item count.
- /// </summary>
- /// <value>The recently added item count.</value>
- public int? RecentlyAddedItemCount { get; set; }
-
- /// <summary>
/// Gets or sets the played percentage.
/// </summary>
/// <value>The played percentage.</value>
@@ -466,13 +460,13 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the album image tag.
/// </summary>
/// <value>The album image tag.</value>
- public Guid? AlbumPrimaryImageTag { get; set; }
+ public string AlbumPrimaryImageTag { get; set; }
/// <summary>
/// Gets or sets the series primary image tag.
/// </summary>
/// <value>The series primary image tag.</value>
- public Guid? SeriesPrimaryImageTag { get; set; }
+ public string SeriesPrimaryImageTag { get; set; }
/// <summary>
/// Gets or sets the album artist.
@@ -529,25 +523,25 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the image tags.
/// </summary>
/// <value>The image tags.</value>
- public Dictionary<ImageType, Guid> ImageTags { get; set; }
+ public Dictionary<ImageType, string> ImageTags { get; set; }
/// <summary>
/// Gets or sets the backdrop image tags.
/// </summary>
/// <value>The backdrop image tags.</value>
- public List<Guid> BackdropImageTags { get; set; }
+ public List<string> BackdropImageTags { get; set; }
/// <summary>
/// Gets or sets the screenshot image tags.
/// </summary>
/// <value>The screenshot image tags.</value>
- public List<Guid> ScreenshotImageTags { get; set; }
+ public List<string> ScreenshotImageTags { get; set; }
/// <summary>
/// Gets or sets the parent logo image tag.
/// </summary>
/// <value>The parent logo image tag.</value>
- public Guid? ParentLogoImageTag { get; set; }
+ public string ParentLogoImageTag { get; set; }
/// <summary>
/// If the item does not have a art, this will hold the Id of the Parent that has one.
@@ -559,13 +553,13 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the parent art image tag.
/// </summary>
/// <value>The parent art image tag.</value>
- public Guid? ParentArtImageTag { get; set; }
+ public string ParentArtImageTag { get; set; }
/// <summary>
/// Gets or sets the series thumb image tag.
/// </summary>
/// <value>The series thumb image tag.</value>
- public Guid? SeriesThumbImageTag { get; set; }
+ public string SeriesThumbImageTag { get; set; }
/// <summary>
/// Gets or sets the series studio.
@@ -583,7 +577,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the parent thumb image tag.
/// </summary>
/// <value>The parent thumb image tag.</value>
- public Guid? ParentThumbImageTag { get; set; }
+ public string ParentThumbImageTag { get; set; }
/// <summary>
/// Gets or sets the chapters.
diff --git a/MediaBrowser.Model/Dto/BaseItemPerson.cs b/MediaBrowser.Model/Dto/BaseItemPerson.cs
index 1cc3f722d..b8393f444 100644
--- a/MediaBrowser.Model/Dto/BaseItemPerson.cs
+++ b/MediaBrowser.Model/Dto/BaseItemPerson.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 role.
/// </summary>
/// <value>The role.</value>
@@ -33,7 +38,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the primary image tag.
/// </summary>
/// <value>The primary image tag.</value>
- public Guid? PrimaryImageTag { get; set; }
+ public string PrimaryImageTag { get; set; }
/// <summary>
/// Gets a value indicating whether this instance has primary image.
@@ -44,7 +49,7 @@ namespace MediaBrowser.Model.Dto
{
get
{
- return PrimaryImageTag.HasValue;
+ return PrimaryImageTag != null;
}
}
diff --git a/MediaBrowser.Model/Dto/ChapterInfoDto.cs b/MediaBrowser.Model/Dto/ChapterInfoDto.cs
index 5a72110ce..09dd2d582 100644
--- a/MediaBrowser.Model/Dto/ChapterInfoDto.cs
+++ b/MediaBrowser.Model/Dto/ChapterInfoDto.cs
@@ -27,7 +27,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the image tag.
/// </summary>
/// <value>The image tag.</value>
- public Guid? ImageTag { get; set; }
+ public string ImageTag { get; set; }
/// <summary>
/// Gets a value indicating whether this instance has image.
@@ -36,7 +36,7 @@ namespace MediaBrowser.Model.Dto
[IgnoreDataMember]
public bool HasImage
{
- get { return ImageTag.HasValue; }
+ get { return ImageTag != null; }
}
public event PropertyChangedEventHandler PropertyChanged;
diff --git a/MediaBrowser.Model/Dto/IItemDto.cs b/MediaBrowser.Model/Dto/IItemDto.cs
index 3ec641918..af46d29b9 100644
--- a/MediaBrowser.Model/Dto/IItemDto.cs
+++ b/MediaBrowser.Model/Dto/IItemDto.cs
@@ -18,10 +18,4 @@ namespace MediaBrowser.Model.Dto
/// <value>The original primary image aspect ratio.</value>
double? OriginalPrimaryImageAspectRatio { get; set; }
}
-
- public enum RatingType
- {
- Score,
- Likes
- }
}
diff --git a/MediaBrowser.Model/Dto/ImageInfo.cs b/MediaBrowser.Model/Dto/ImageInfo.cs
index 0850ee0a4..fa3a38fcb 100644
--- a/MediaBrowser.Model/Dto/ImageInfo.cs
+++ b/MediaBrowser.Model/Dto/ImageInfo.cs
@@ -23,7 +23,7 @@ namespace MediaBrowser.Model.Dto
/// <summary>
/// The image tag
/// </summary>
- public Guid ImageTag;
+ public string ImageTag;
/// <summary>
/// Gets or sets the path.
diff --git a/MediaBrowser.Model/Dto/ImageOptions.cs b/MediaBrowser.Model/Dto/ImageOptions.cs
index 7fe162ff9..08ac7906a 100644
--- a/MediaBrowser.Model/Dto/ImageOptions.cs
+++ b/MediaBrowser.Model/Dto/ImageOptions.cs
@@ -56,7 +56,7 @@ namespace MediaBrowser.Model.Dto
/// If set this will result in strong, unconditional response caching
/// </summary>
/// <value>The hash.</value>
- public Guid? Tag { get; set; }
+ public string Tag { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [crop whitespace].
diff --git a/MediaBrowser.Model/Dto/ItemByNameCounts.cs b/MediaBrowser.Model/Dto/ItemByNameCounts.cs
index 31b6d2da0..7c51f07bd 100644
--- a/MediaBrowser.Model/Dto/ItemByNameCounts.cs
+++ b/MediaBrowser.Model/Dto/ItemByNameCounts.cs
@@ -7,7 +7,7 @@ namespace MediaBrowser.Model.Dto
/// </summary>
public class ItemByNameCounts
{
- public Guid UserId { get; set; }
+ public string UserId { get; set; }
/// <summary>
/// Gets or sets the total count.
diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs
new file mode 100644
index 000000000..4fe586333
--- /dev/null
+++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Runtime.Serialization;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.MediaInfo;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.Dto
+{
+ public class MediaSourceInfo
+ {
+ public string Id { get; set; }
+
+ public string Path { get; set; }
+
+ public string Container { get; set; }
+ public long? Size { get; set; }
+
+ public LocationType LocationType { get; set; }
+
+ public string Name { get; set; }
+
+ public long? RunTimeTicks { get; set; }
+
+ public VideoType? VideoType { get; set; }
+
+ public IsoType? IsoType { get; set; }
+
+ public Video3DFormat? Video3DFormat { get; set; }
+
+ public List<MediaStream> MediaStreams { get; set; }
+
+ public List<string> Formats { get; set; }
+
+ public int? Bitrate { get; set; }
+
+ public TransportStreamTimestamp? Timestamp { get; set; }
+
+ public MediaSourceInfo()
+ {
+ Formats = new List<string>();
+ MediaStreams = new List<MediaStream>();
+ }
+
+ [IgnoreDataMember]
+ public MediaStream DefaultAudioStream
+ {
+ get
+ {
+ foreach (MediaStream i in MediaStreams)
+ {
+ if (i.Type == MediaStreamType.Audio && i.IsDefault)
+ {
+ return i;
+ }
+ }
+
+ foreach (MediaStream i in MediaStreams)
+ {
+ if (i.Type == MediaStreamType.Audio)
+ {
+ return i;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ [IgnoreDataMember]
+ public MediaStream VideoStream
+ {
+ get
+ {
+ foreach (MediaStream i in MediaStreams)
+ {
+ if (i.Type == MediaStreamType.Video && (i.Codec ?? string.Empty).IndexOf("jpeg", StringComparison.OrdinalIgnoreCase) == -1)
+ {
+ return i;
+ }
+ }
+
+ return null;
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Model/Dto/MediaVersionInfo.cs b/MediaBrowser.Model/Dto/MediaVersionInfo.cs
deleted file mode 100644
index 2e94f4f0c..000000000
--- a/MediaBrowser.Model/Dto/MediaVersionInfo.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.MediaInfo;
-using System.Collections.Generic;
-
-namespace MediaBrowser.Model.Dto
-{
- public class MediaSourceInfo
- {
- public string Id { get; set; }
-
- public string Path { get; set; }
-
- public string Container { get; set; }
- public long? Size { get; set; }
-
- public LocationType LocationType { get; set; }
-
- public string Name { get; set; }
-
- public long? RunTimeTicks { get; set; }
-
- public VideoType? VideoType { get; set; }
-
- public IsoType? IsoType { get; set; }
-
- public Video3DFormat? Video3DFormat { get; set; }
-
- public List<MediaStream> MediaStreams { get; set; }
-
- public List<string> Formats { get; set; }
-
- public int? Bitrate { get; set; }
-
- public TransportStreamTimestamp? Timestamp { get; set; }
-
- public MediaSourceInfo()
- {
- Formats = new List<string>();
- MediaStreams = new List<MediaStream>();
- }
- }
-}
diff --git a/MediaBrowser.Model/Dto/RatingType.cs b/MediaBrowser.Model/Dto/RatingType.cs
new file mode 100644
index 000000000..f151adce9
--- /dev/null
+++ b/MediaBrowser.Model/Dto/RatingType.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Model.Dto
+{
+ public enum RatingType
+ {
+ Score,
+ Likes
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dto/RecommendationDto.cs b/MediaBrowser.Model/Dto/RecommendationDto.cs
index 68b71e466..275f97c28 100644
--- a/MediaBrowser.Model/Dto/RecommendationDto.cs
+++ b/MediaBrowser.Model/Dto/RecommendationDto.cs
@@ -11,19 +11,4 @@ namespace MediaBrowser.Model.Dto
public string CategoryId { get; set; }
}
-
- public enum RecommendationType
- {
- SimilarToRecentlyPlayed = 0,
-
- SimilarToLikedItem = 1,
-
- HasDirectorFromRecentlyPlayed = 2,
-
- HasActorFromRecentlyPlayed = 3,
-
- HasLikedDirector = 4,
-
- HasLikedActor = 5
- }
}
diff --git a/MediaBrowser.Model/Dto/RecommendationType.cs b/MediaBrowser.Model/Dto/RecommendationType.cs
new file mode 100644
index 000000000..1adf9b082
--- /dev/null
+++ b/MediaBrowser.Model/Dto/RecommendationType.cs
@@ -0,0 +1,17 @@
+namespace MediaBrowser.Model.Dto
+{
+ public enum RecommendationType
+ {
+ SimilarToRecentlyPlayed = 0,
+
+ SimilarToLikedItem = 1,
+
+ HasDirectorFromRecentlyPlayed = 2,
+
+ HasActorFromRecentlyPlayed = 3,
+
+ HasLikedDirector = 4,
+
+ HasLikedActor = 5
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dto/StreamOptions.cs b/MediaBrowser.Model/Dto/StreamOptions.cs
index b1ead2ca3..9cf301270 100644
--- a/MediaBrowser.Model/Dto/StreamOptions.cs
+++ b/MediaBrowser.Model/Dto/StreamOptions.cs
@@ -1,103 +1,6 @@
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; }
- }
-
- /// <summary>
/// Class StreamOptions
/// </summary>
public class StreamOptions
@@ -158,19 +61,4 @@
/// <value>The device id.</value>
public string DeviceId { get; set; }
}
-
- public class SubtitleOptions
- {
- /// <summary>
- /// Gets or sets the item identifier.
- /// </summary>
- /// <value>The item identifier.</value>
- public string ItemId { get; set; }
-
- /// <summary>
- /// Gets or sets the index of the stream.
- /// </summary>
- /// <value>The index of the stream.</value>
- public int StreamIndex { get; set; }
- }
}
diff --git a/MediaBrowser.Model/Dto/StudioDto.cs b/MediaBrowser.Model/Dto/StudioDto.cs
index 696213a40..4f21784fd 100644
--- a/MediaBrowser.Model/Dto/StudioDto.cs
+++ b/MediaBrowser.Model/Dto/StudioDto.cs
@@ -21,7 +21,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the primary image tag.
/// </summary>
/// <value>The primary image tag.</value>
- public Guid? PrimaryImageTag { get; set; }
+ public string PrimaryImageTag { get; set; }
/// <summary>
/// Gets a value indicating whether this instance has primary image.
@@ -32,7 +32,7 @@ namespace MediaBrowser.Model.Dto
{
get
{
- return PrimaryImageTag.HasValue;
+ return PrimaryImageTag != null;
}
}
diff --git a/MediaBrowser.Model/Dto/SubtitleDownloadOptions.cs b/MediaBrowser.Model/Dto/SubtitleDownloadOptions.cs
new file mode 100644
index 000000000..a0b49f42c
--- /dev/null
+++ b/MediaBrowser.Model/Dto/SubtitleDownloadOptions.cs
@@ -0,0 +1,17 @@
+namespace MediaBrowser.Model.Dto
+{
+ public class SubtitleDownloadOptions
+ {
+ /// <summary>
+ /// Gets or sets the item identifier.
+ /// </summary>
+ /// <value>The item identifier.</value>
+ public string ItemId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the index of the stream.
+ /// </summary>
+ /// <value>The index of the stream.</value>
+ public int StreamIndex { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Dto/UserDto.cs b/MediaBrowser.Model/Dto/UserDto.cs
index efbd64343..c4a43c512 100644
--- a/MediaBrowser.Model/Dto/UserDto.cs
+++ b/MediaBrowser.Model/Dto/UserDto.cs
@@ -28,7 +28,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the primary image tag.
/// </summary>
/// <value>The primary image tag.</value>
- public Guid? PrimaryImageTag { get; set; }
+ public string PrimaryImageTag { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance has password.
@@ -73,7 +73,7 @@ namespace MediaBrowser.Model.Dto
[IgnoreDataMember]
public bool HasPrimaryImage
{
- get { return PrimaryImageTag.HasValue; }
+ get { return PrimaryImageTag != null; }
}
/// <summary>
diff --git a/MediaBrowser.Model/Dto/VideoStreamOptions.cs b/MediaBrowser.Model/Dto/VideoStreamOptions.cs
new file mode 100644
index 000000000..73dc70018
--- /dev/null
+++ b/MediaBrowser.Model/Dto/VideoStreamOptions.cs
@@ -0,0 +1,99 @@
+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/BaseItemInfo.cs b/MediaBrowser.Model/Entities/BaseItemInfo.cs
index a280b1f71..88af18289 100644
--- a/MediaBrowser.Model/Entities/BaseItemInfo.cs
+++ b/MediaBrowser.Model/Entities/BaseItemInfo.cs
@@ -1,4 +1,5 @@
-using System;
+using MediaBrowser.Model.Dto;
+using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Serialization;
@@ -34,7 +35,7 @@ namespace MediaBrowser.Model.Entities
/// </summary>
/// <value>The type of the media.</value>
public string MediaType { get; set; }
-
+
/// <summary>
/// Gets or sets the run time ticks.
/// </summary>
@@ -45,7 +46,7 @@ namespace MediaBrowser.Model.Entities
/// Gets or sets the primary image tag.
/// </summary>
/// <value>The primary image tag.</value>
- public Guid? PrimaryImageTag { get; set; }
+ public string PrimaryImageTag { get; set; }
/// <summary>
/// Gets or sets the primary image item identifier.
@@ -57,19 +58,19 @@ namespace MediaBrowser.Model.Entities
/// Gets or sets the logo image tag.
/// </summary>
/// <value>The logo image tag.</value>
- public Guid? LogoImageTag { get; set; }
+ public string LogoImageTag { get; set; }
/// <summary>
/// Gets or sets the logo item identifier.
/// </summary>
/// <value>The logo item identifier.</value>
public string LogoItemId { get; set; }
-
+
/// <summary>
/// Gets or sets the thumb image tag.
/// </summary>
/// <value>The thumb image tag.</value>
- public Guid? ThumbImageTag { get; set; }
+ public string ThumbImageTag { get; set; }
/// <summary>
/// Gets or sets the thumb item identifier.
@@ -81,7 +82,7 @@ namespace MediaBrowser.Model.Entities
/// Gets or sets the thumb image tag.
/// </summary>
/// <value>The thumb image tag.</value>
- public Guid? BackdropImageTag { get; set; }
+ public string BackdropImageTag { get; set; }
/// <summary>
/// Gets or sets the thumb item identifier.
@@ -136,7 +137,25 @@ namespace MediaBrowser.Model.Entities
/// </summary>
/// <value>The artists.</value>
public List<string> Artists { get; set; }
-
+
+ /// <summary>
+ /// Gets or sets the media streams.
+ /// </summary>
+ /// <value>The media streams.</value>
+ public List<MediaStream> MediaStreams { get; set; }
+
+ /// <summary>
+ /// Gets or sets the chapter images item identifier.
+ /// </summary>
+ /// <value>The chapter images item identifier.</value>
+ public string ChapterImagesItemId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the chapters.
+ /// </summary>
+ /// <value>The chapters.</value>
+ public List<ChapterInfoDto> Chapters { get; set; }
+
/// <summary>
/// Gets a value indicating whether this instance has primary image.
/// </summary>
@@ -144,12 +163,14 @@ namespace MediaBrowser.Model.Entities
[IgnoreDataMember]
public bool HasPrimaryImage
{
- get { return PrimaryImageTag.HasValue; }
+ get { return PrimaryImageTag != null; }
}
public BaseItemInfo()
{
Artists = new List<string>();
+ MediaStreams = new List<MediaStream>();
+ Chapters = new List<ChapterInfoDto>();
}
}
}
diff --git a/MediaBrowser.Model/Entities/DisplayPreferences.cs b/MediaBrowser.Model/Entities/DisplayPreferences.cs
index 829affd01..56a2c6194 100644
--- a/MediaBrowser.Model/Entities/DisplayPreferences.cs
+++ b/MediaBrowser.Model/Entities/DisplayPreferences.cs
@@ -36,7 +36,7 @@ namespace MediaBrowser.Model.Entities
/// Gets or sets the user id.
/// </summary>
/// <value>The user id.</value>
- public Guid Id { get; set; }
+ public string Id { get; set; }
/// <summary>
/// Gets or sets the type of the view.
/// </summary>
@@ -103,9 +103,9 @@ namespace MediaBrowser.Model.Entities
/// </summary>
public void IncreaseImageSize()
{
- var newWidth = PrimaryImageWidth / ImageScale;
+ double newWidth = PrimaryImageWidth / ImageScale;
- var size = DrawingUtils.Resize(PrimaryImageWidth, PrimaryImageHeight, newWidth);
+ ImageSize size = DrawingUtils.Resize(PrimaryImageWidth, PrimaryImageHeight, newWidth, null, null, null);
PrimaryImageWidth = Convert.ToInt32(size.Width);
PrimaryImageHeight = Convert.ToInt32(size.Height);
@@ -116,40 +116,10 @@ namespace MediaBrowser.Model.Entities
/// </summary>
public void DecreaseImageSize()
{
- var size = DrawingUtils.Scale(PrimaryImageWidth, PrimaryImageHeight, ImageScale);
+ ImageSize size = DrawingUtils.Scale(PrimaryImageWidth, PrimaryImageHeight, ImageScale);
PrimaryImageWidth = Convert.ToInt32(size.Width);
PrimaryImageHeight = Convert.ToInt32(size.Height);
}
}
-
- /// <summary>
- /// Enum ScrollDirection
- /// </summary>
- public enum ScrollDirection
- {
- /// <summary>
- /// The horizontal
- /// </summary>
- Horizontal,
- /// <summary>
- /// The vertical
- /// </summary>
- Vertical
- }
-
- /// <summary>
- /// Enum SortOrder
- /// </summary>
- public enum SortOrder
- {
- /// <summary>
- /// The ascending
- /// </summary>
- Ascending,
- /// <summary>
- /// The descending
- /// </summary>
- Descending
- }
}
diff --git a/MediaBrowser.Model/Entities/RequestResult.cs b/MediaBrowser.Model/Entities/EmptyRequestResult.cs
index 5c9a725fd..5c9a725fd 100644
--- a/MediaBrowser.Model/Entities/RequestResult.cs
+++ b/MediaBrowser.Model/Entities/EmptyRequestResult.cs
diff --git a/MediaBrowser.Model/Entities/IHasProviderIds.cs b/MediaBrowser.Model/Entities/IHasProviderIds.cs
index efb75412f..796850dbd 100644
--- a/MediaBrowser.Model/Entities/IHasProviderIds.cs
+++ b/MediaBrowser.Model/Entities/IHasProviderIds.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
namespace MediaBrowser.Model.Entities
{
@@ -14,102 +13,4 @@ namespace MediaBrowser.Model.Entities
/// <value>The provider ids.</value>
Dictionary<string, string> ProviderIds { get; set; }
}
-
- /// <summary>
- /// Class ProviderIdsExtensions
- /// </summary>
- public static class ProviderIdsExtensions
- {
- /// <summary>
- /// Determines whether [has provider identifier] [the specified instance].
- /// </summary>
- /// <param name="instance">The instance.</param>
- /// <param name="provider">The provider.</param>
- /// <returns><c>true</c> if [has provider identifier] [the specified instance]; otherwise, <c>false</c>.</returns>
- public static bool HasProviderId(this IHasProviderIds instance, MetadataProviders provider)
- {
- return !string.IsNullOrEmpty(instance.GetProviderId(provider.ToString()));
- }
-
- /// <summary>
- /// Gets a provider id
- /// </summary>
- /// <param name="instance">The instance.</param>
- /// <param name="provider">The provider.</param>
- /// <returns>System.String.</returns>
- public static string GetProviderId(this IHasProviderIds instance, MetadataProviders provider)
- {
- return instance.GetProviderId(provider.ToString());
- }
-
- /// <summary>
- /// Gets a provider id
- /// </summary>
- /// <param name="instance">The instance.</param>
- /// <param name="name">The name.</param>
- /// <returns>System.String.</returns>
- public static string GetProviderId(this IHasProviderIds instance, string name)
- {
- if (instance == null)
- {
- throw new ArgumentNullException("instance");
- }
-
- if (instance.ProviderIds == null)
- {
- return null;
- }
-
- string id;
- instance.ProviderIds.TryGetValue(name, out id);
- return id;
- }
-
- /// <summary>
- /// Sets a provider id
- /// </summary>
- /// <param name="instance">The instance.</param>
- /// <param name="name">The name.</param>
- /// <param name="value">The value.</param>
- public static void SetProviderId(this IHasProviderIds instance, string name, string value)
- {
- if (instance == null)
- {
- throw new ArgumentNullException("instance");
- }
-
- // If it's null remove the key from the dictionary
- if (string.IsNullOrEmpty(value))
- {
- if (instance.ProviderIds != null)
- {
- if (instance.ProviderIds.ContainsKey(name))
- {
- instance.ProviderIds.Remove(name);
- }
- }
- }
- else
- {
- // Ensure it exists
- if (instance.ProviderIds == null)
- {
- instance.ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
- }
-
- instance.ProviderIds[name] = value;
- }
- }
-
- /// <summary>
- /// Sets a provider id
- /// </summary>
- /// <param name="instance">The instance.</param>
- /// <param name="provider">The provider.</param>
- /// <param name="value">The value.</param>
- public static void SetProviderId(this IHasProviderIds instance, MetadataProviders provider, string value)
- {
- instance.SetProviderId(provider.ToString(), value);
- }
- }
}
diff --git a/MediaBrowser.Model/Entities/IsoType.cs b/MediaBrowser.Model/Entities/IsoType.cs
new file mode 100644
index 000000000..567b98ab9
--- /dev/null
+++ b/MediaBrowser.Model/Entities/IsoType.cs
@@ -0,0 +1,17 @@
+namespace MediaBrowser.Model.Entities
+{
+ /// <summary>
+ /// Enum IsoType
+ /// </summary>
+ public enum IsoType
+ {
+ /// <summary>
+ /// The DVD
+ /// </summary>
+ Dvd,
+ /// <summary>
+ /// The blu ray
+ /// </summary>
+ BluRay
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Entities/LibraryUpdateInfo.cs b/MediaBrowser.Model/Entities/LibraryUpdateInfo.cs
index dca8cd584..4371ddae4 100644
--- a/MediaBrowser.Model/Entities/LibraryUpdateInfo.cs
+++ b/MediaBrowser.Model/Entities/LibraryUpdateInfo.cs
@@ -12,41 +12,41 @@ namespace MediaBrowser.Model.Entities
/// Gets or sets the folders added to.
/// </summary>
/// <value>The folders added to.</value>
- public List<Guid> FoldersAddedTo { get; set; }
+ public List<string> FoldersAddedTo { get; set; }
/// <summary>
/// Gets or sets the folders removed from.
/// </summary>
/// <value>The folders removed from.</value>
- public List<Guid> FoldersRemovedFrom { get; set; }
+ public List<string> FoldersRemovedFrom { get; set; }
/// <summary>
/// Gets or sets the items added.
/// </summary>
/// <value>The items added.</value>
- public List<Guid> ItemsAdded { get; set; }
+ public List<string> ItemsAdded { get; set; }
/// <summary>
/// Gets or sets the items removed.
/// </summary>
/// <value>The items removed.</value>
- public List<Guid> ItemsRemoved { get; set; }
+ public List<string> ItemsRemoved { get; set; }
/// <summary>
/// Gets or sets the items updated.
/// </summary>
/// <value>The items updated.</value>
- public List<Guid> ItemsUpdated { get; set; }
+ public List<string> ItemsUpdated { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="LibraryUpdateInfo"/> class.
/// </summary>
public LibraryUpdateInfo()
{
- FoldersAddedTo = new List<Guid>();
- FoldersRemovedFrom = new List<Guid>();
- ItemsAdded = new List<Guid>();
- ItemsRemoved = new List<Guid>();
- ItemsUpdated = new List<Guid>();
+ FoldersAddedTo = new List<string>();
+ FoldersRemovedFrom = new List<string>();
+ ItemsAdded = new List<string>();
+ ItemsRemoved = new List<string>();
+ ItemsUpdated = new List<string>();
}
}
}
diff --git a/MediaBrowser.Model/Entities/MediaInfo.cs b/MediaBrowser.Model/Entities/MediaInfo.cs
new file mode 100644
index 000000000..ef26cfa14
--- /dev/null
+++ b/MediaBrowser.Model/Entities/MediaInfo.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.Entities
+{
+ public class MediaInfo
+ {
+ /// <summary>
+ /// Gets or sets the media streams.
+ /// </summary>
+ /// <value>The media streams.</value>
+ public List<MediaStream> MediaStreams { get; set; }
+
+ /// <summary>
+ /// Gets or sets the format.
+ /// </summary>
+ /// <value>The format.</value>
+ public string Format { get; set; }
+
+ public int? TotalBitrate { get; set; }
+
+ public MediaInfo()
+ {
+ MediaStreams = new List<MediaStream>();
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs
index d54e3c0ef..9f64b36e4 100644
--- a/MediaBrowser.Model/Entities/MediaStream.cs
+++ b/MediaBrowser.Model/Entities/MediaStream.cs
@@ -1,5 +1,6 @@
-using System.Collections.Generic;
+using System;
using System.Diagnostics;
+using System.Runtime.Serialization;
namespace MediaBrowser.Model.Entities
{
@@ -129,6 +130,20 @@ namespace MediaBrowser.Model.Entities
/// <value><c>true</c> if this instance is external; otherwise, <c>false</c>.</value>
public bool IsExternal { get; set; }
+ [IgnoreDataMember]
+ public bool IsGraphicalSubtitleStream
+ {
+ get
+ {
+ if (IsExternal) return false;
+
+ var codec = Codec ?? string.Empty;
+
+ return codec.IndexOf("pgs", StringComparison.OrdinalIgnoreCase) != -1 ||
+ codec.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1;
+ }
+ }
+
/// <summary>
/// Gets or sets the filename.
/// </summary>
@@ -147,49 +162,4 @@ namespace MediaBrowser.Model.Entities
/// <value>The level.</value>
public double? Level { get; set; }
}
-
- /// <summary>
- /// Enum MediaStreamType
- /// </summary>
- public enum MediaStreamType
- {
- /// <summary>
- /// The audio
- /// </summary>
- Audio,
- /// <summary>
- /// The video
- /// </summary>
- Video,
- /// <summary>
- /// The subtitle
- /// </summary>
- Subtitle,
- /// <summary>
- /// The embedded image
- /// </summary>
- EmbeddedImage
- }
-
- public class MediaInfo
- {
- /// <summary>
- /// Gets or sets the media streams.
- /// </summary>
- /// <value>The media streams.</value>
- public List<MediaStream> MediaStreams { get; set; }
-
- /// <summary>
- /// Gets or sets the format.
- /// </summary>
- /// <value>The format.</value>
- public string Format { get; set; }
-
- public int? TotalBitrate { get; set; }
-
- public MediaInfo()
- {
- MediaStreams = new List<MediaStream>();
- }
- }
}
diff --git a/MediaBrowser.Model/Entities/MediaStreamType.cs b/MediaBrowser.Model/Entities/MediaStreamType.cs
new file mode 100644
index 000000000..084a411f9
--- /dev/null
+++ b/MediaBrowser.Model/Entities/MediaStreamType.cs
@@ -0,0 +1,25 @@
+namespace MediaBrowser.Model.Entities
+{
+ /// <summary>
+ /// Enum MediaStreamType
+ /// </summary>
+ public enum MediaStreamType
+ {
+ /// <summary>
+ /// The audio
+ /// </summary>
+ Audio,
+ /// <summary>
+ /// The video
+ /// </summary>
+ Video,
+ /// <summary>
+ /// The subtitle
+ /// </summary>
+ Subtitle,
+ /// <summary>
+ /// The embedded image
+ /// </summary>
+ EmbeddedImage
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Entities/MediaUrl.cs b/MediaBrowser.Model/Entities/MediaUrl.cs
index 857e91fec..9aa7207ed 100644
--- a/MediaBrowser.Model/Entities/MediaUrl.cs
+++ b/MediaBrowser.Model/Entities/MediaUrl.cs
@@ -8,10 +8,4 @@ namespace MediaBrowser.Model.Entities
public VideoSize? VideoSize { get; set; }
public bool IsDirectLink { get; set; }
}
-
- public enum VideoSize
- {
- StandardDefinition,
- HighDefinition
- }
}
diff --git a/MediaBrowser.Model/Entities/PackageReviewInfo.cs b/MediaBrowser.Model/Entities/PackageReviewInfo.cs
index c350935f4..52500a41e 100644
--- a/MediaBrowser.Model/Entities/PackageReviewInfo.cs
+++ b/MediaBrowser.Model/Entities/PackageReviewInfo.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace MediaBrowser.Model.Entities
{
diff --git a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs
new file mode 100644
index 000000000..e10232baa
--- /dev/null
+++ b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs
@@ -0,0 +1,103 @@
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.Entities
+{
+ /// <summary>
+ /// Class ProviderIdsExtensions
+ /// </summary>
+ public static class ProviderIdsExtensions
+ {
+ /// <summary>
+ /// Determines whether [has provider identifier] [the specified instance].
+ /// </summary>
+ /// <param name="instance">The instance.</param>
+ /// <param name="provider">The provider.</param>
+ /// <returns><c>true</c> if [has provider identifier] [the specified instance]; otherwise, <c>false</c>.</returns>
+ public static bool HasProviderId(this IHasProviderIds instance, MetadataProviders provider)
+ {
+ return !string.IsNullOrEmpty(instance.GetProviderId(provider.ToString()));
+ }
+
+ /// <summary>
+ /// Gets a provider id
+ /// </summary>
+ /// <param name="instance">The instance.</param>
+ /// <param name="provider">The provider.</param>
+ /// <returns>System.String.</returns>
+ public static string GetProviderId(this IHasProviderIds instance, MetadataProviders provider)
+ {
+ return instance.GetProviderId(provider.ToString());
+ }
+
+ /// <summary>
+ /// Gets a provider id
+ /// </summary>
+ /// <param name="instance">The instance.</param>
+ /// <param name="name">The name.</param>
+ /// <returns>System.String.</returns>
+ public static string GetProviderId(this IHasProviderIds instance, string name)
+ {
+ if (instance == null)
+ {
+ throw new ArgumentNullException("instance");
+ }
+
+ if (instance.ProviderIds == null)
+ {
+ return null;
+ }
+
+ string id;
+ instance.ProviderIds.TryGetValue(name, out id);
+ return id;
+ }
+
+ /// <summary>
+ /// Sets a provider id
+ /// </summary>
+ /// <param name="instance">The instance.</param>
+ /// <param name="name">The name.</param>
+ /// <param name="value">The value.</param>
+ public static void SetProviderId(this IHasProviderIds instance, string name, string value)
+ {
+ if (instance == null)
+ {
+ throw new ArgumentNullException("instance");
+ }
+
+ // If it's null remove the key from the dictionary
+ if (string.IsNullOrEmpty(value))
+ {
+ if (instance.ProviderIds != null)
+ {
+ if (instance.ProviderIds.ContainsKey(name))
+ {
+ instance.ProviderIds.Remove(name);
+ }
+ }
+ }
+ else
+ {
+ // Ensure it exists
+ if (instance.ProviderIds == null)
+ {
+ instance.ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ }
+
+ instance.ProviderIds[name] = value;
+ }
+ }
+
+ /// <summary>
+ /// Sets a provider id
+ /// </summary>
+ /// <param name="instance">The instance.</param>
+ /// <param name="provider">The provider.</param>
+ /// <param name="value">The value.</param>
+ public static void SetProviderId(this IHasProviderIds instance, MetadataProviders provider, string value)
+ {
+ instance.SetProviderId(provider.ToString(), value);
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Entities/ScrollDirection.cs b/MediaBrowser.Model/Entities/ScrollDirection.cs
new file mode 100644
index 000000000..ed2210300
--- /dev/null
+++ b/MediaBrowser.Model/Entities/ScrollDirection.cs
@@ -0,0 +1,17 @@
+namespace MediaBrowser.Model.Entities
+{
+ /// <summary>
+ /// Enum ScrollDirection
+ /// </summary>
+ public enum ScrollDirection
+ {
+ /// <summary>
+ /// The horizontal
+ /// </summary>
+ Horizontal,
+ /// <summary>
+ /// The vertical
+ /// </summary>
+ Vertical
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Entities/SortOrder.cs b/MediaBrowser.Model/Entities/SortOrder.cs
new file mode 100644
index 000000000..5130449ba
--- /dev/null
+++ b/MediaBrowser.Model/Entities/SortOrder.cs
@@ -0,0 +1,17 @@
+namespace MediaBrowser.Model.Entities
+{
+ /// <summary>
+ /// Enum SortOrder
+ /// </summary>
+ public enum SortOrder
+ {
+ /// <summary>
+ /// The ascending
+ /// </summary>
+ Ascending,
+ /// <summary>
+ /// The descending
+ /// </summary>
+ Descending
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Entities/VideoSize.cs b/MediaBrowser.Model/Entities/VideoSize.cs
new file mode 100644
index 000000000..0100f3b90
--- /dev/null
+++ b/MediaBrowser.Model/Entities/VideoSize.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Model.Entities
+{
+ public enum VideoSize
+ {
+ StandardDefinition,
+ HighDefinition
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Entities/VideoType.cs b/MediaBrowser.Model/Entities/VideoType.cs
index b2742add1..aa9a3c55f 100644
--- a/MediaBrowser.Model/Entities/VideoType.cs
+++ b/MediaBrowser.Model/Entities/VideoType.cs
@@ -27,19 +27,4 @@ namespace MediaBrowser.Model.Entities
/// </summary>
HdDvd
}
-
- /// <summary>
- /// Enum IsoType
- /// </summary>
- public enum IsoType
- {
- /// <summary>
- /// The DVD
- /// </summary>
- Dvd,
- /// <summary>
- /// The blu ray
- /// </summary>
- BluRay
- }
}
diff --git a/MediaBrowser.Common/Events/GenericEventArgs.cs b/MediaBrowser.Model/Events/GenericEventArgs.cs
index e7cf524d4..5a83419e1 100644
--- a/MediaBrowser.Common/Events/GenericEventArgs.cs
+++ b/MediaBrowser.Model/Events/GenericEventArgs.cs
@@ -1,6 +1,6 @@
using System;
-namespace MediaBrowser.Common.Events
+namespace MediaBrowser.Model.Events
{
/// <summary>
/// Provides a generic EventArgs subclass that can hold any kind of object
diff --git a/MediaBrowser.Model/FileOrganization/EpisodeFileOrganizationRequest.cs b/MediaBrowser.Model/FileOrganization/EpisodeFileOrganizationRequest.cs
new file mode 100644
index 000000000..0b12ebc51
--- /dev/null
+++ b/MediaBrowser.Model/FileOrganization/EpisodeFileOrganizationRequest.cs
@@ -0,0 +1,17 @@
+namespace MediaBrowser.Model.FileOrganization
+{
+ public class EpisodeFileOrganizationRequest
+ {
+ public string ResultId { get; set; }
+
+ public string SeriesId { get; set; }
+
+ public int SeasonNumber { get; set; }
+
+ public int EpisodeNumber { get; set; }
+
+ public int? EndingEpisodeNumber { get; set; }
+
+ public bool RememberCorrection { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/FileOrganization/FileOrganizationResult.cs b/MediaBrowser.Model/FileOrganization/FileOrganizationResult.cs
index 4a3235a42..ef9d0ca2a 100644
--- a/MediaBrowser.Model/FileOrganization/FileOrganizationResult.cs
+++ b/MediaBrowser.Model/FileOrganization/FileOrganizationResult.cs
@@ -100,18 +100,4 @@ namespace MediaBrowser.Model.FileOrganization
DuplicatePaths = new List<string>();
}
}
-
- public enum FileSortingStatus
- {
- Success,
- Failure,
- SkippedExisting
- }
-
- public enum FileOrganizerType
- {
- Movie,
- Episode,
- Song
- }
}
diff --git a/MediaBrowser.Model/FileOrganization/FileOrganizationQuery.cs b/MediaBrowser.Model/FileOrganization/FileOrganizationResultQuery.cs
index ce5750757..18287534e 100644
--- a/MediaBrowser.Model/FileOrganization/FileOrganizationQuery.cs
+++ b/MediaBrowser.Model/FileOrganization/FileOrganizationResultQuery.cs
@@ -15,19 +15,4 @@ namespace MediaBrowser.Model.FileOrganization
/// <value>The limit.</value>
public int? Limit { get; set; }
}
-
- public class EpisodeFileOrganizationRequest
- {
- public string ResultId { get; set; }
-
- public string SeriesId { get; set; }
-
- public int SeasonNumber { get; set; }
-
- public int EpisodeNumber { get; set; }
-
- public int? EndingEpisodeNumber { get; set; }
-
- public bool RememberCorrection { get; set; }
- }
}
diff --git a/MediaBrowser.Model/FileOrganization/FileOrganizerType.cs b/MediaBrowser.Model/FileOrganization/FileOrganizerType.cs
new file mode 100644
index 000000000..cbbeb9ce2
--- /dev/null
+++ b/MediaBrowser.Model/FileOrganization/FileOrganizerType.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Model.FileOrganization
+{
+ public enum FileOrganizerType
+ {
+ Movie,
+ Episode,
+ Song
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/FileOrganization/FileSortingStatus.cs b/MediaBrowser.Model/FileOrganization/FileSortingStatus.cs
new file mode 100644
index 000000000..8a467c05f
--- /dev/null
+++ b/MediaBrowser.Model/FileOrganization/FileSortingStatus.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Model.FileOrganization
+{
+ public enum FileSortingStatus
+ {
+ Success,
+ Failure,
+ SkippedExisting
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Globalization/CountryInfo.cs b/MediaBrowser.Model/Globalization/CountryInfo.cs
index 9f5f00d80..16aea8436 100644
--- a/MediaBrowser.Model/Globalization/CountryInfo.cs
+++ b/MediaBrowser.Model/Globalization/CountryInfo.cs
@@ -30,10 +30,4 @@ namespace MediaBrowser.Model.Globalization
/// <value>The name of the three letter ISO region.</value>
public string ThreeLetterISORegionName { get; set; }
}
-
- public class LocalizatonOption
- {
- public string Name { get; set; }
- public string Value { get; set; }
- }
}
diff --git a/MediaBrowser.Model/Globalization/LocalizatonOption.cs b/MediaBrowser.Model/Globalization/LocalizatonOption.cs
new file mode 100644
index 000000000..61749cbc3
--- /dev/null
+++ b/MediaBrowser.Model/Globalization/LocalizatonOption.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Model.Globalization
+{
+ public class LocalizatonOption
+ {
+ public string Name { get; set; }
+ public string Value { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/IO/FileSystemEntryInfo.cs b/MediaBrowser.Model/IO/FileSystemEntryInfo.cs
index dc4840456..f17e2e5c3 100644
--- a/MediaBrowser.Model/IO/FileSystemEntryInfo.cs
+++ b/MediaBrowser.Model/IO/FileSystemEntryInfo.cs
@@ -24,27 +24,4 @@ namespace MediaBrowser.Model.IO
/// <value>The type.</value>
public FileSystemEntryType Type { get; set; }
}
-
- /// <summary>
- /// Enum FileSystemEntryType
- /// </summary>
- public enum FileSystemEntryType
- {
- /// <summary>
- /// The file
- /// </summary>
- File,
- /// <summary>
- /// The directory
- /// </summary>
- Directory,
- /// <summary>
- /// The network computer
- /// </summary>
- NetworkComputer,
- /// <summary>
- /// The network share
- /// </summary>
- NetworkShare
- }
}
diff --git a/MediaBrowser.Model/IO/FileSystemEntryType.cs b/MediaBrowser.Model/IO/FileSystemEntryType.cs
new file mode 100644
index 000000000..e7c67c606
--- /dev/null
+++ b/MediaBrowser.Model/IO/FileSystemEntryType.cs
@@ -0,0 +1,25 @@
+namespace MediaBrowser.Model.IO
+{
+ /// <summary>
+ /// Enum FileSystemEntryType
+ /// </summary>
+ public enum FileSystemEntryType
+ {
+ /// <summary>
+ /// The file
+ /// </summary>
+ File,
+ /// <summary>
+ /// The directory
+ /// </summary>
+ Directory,
+ /// <summary>
+ /// The network computer
+ /// </summary>
+ NetworkComputer,
+ /// <summary>
+ /// The network share
+ /// </summary>
+ NetworkShare
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs
new file mode 100644
index 000000000..2d88215bb
--- /dev/null
+++ b/MediaBrowser.Model/LiveTv/BaseTimerInfoDto.cs
@@ -0,0 +1,108 @@
+using System;
+using System.ComponentModel;
+
+namespace MediaBrowser.Model.LiveTv
+{
+ public class BaseTimerInfoDto : INotifyPropertyChanged
+ {
+ /// <summary>
+ /// Occurs when a property value changes.
+ /// </summary>
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ /// <summary>
+ /// Id of the recording.
+ /// </summary>
+ public string Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the external identifier.
+ /// </summary>
+ /// <value>The external identifier.</value>
+ public string ExternalId { get; set; }
+
+ /// <summary>
+ /// ChannelId of the recording.
+ /// </summary>
+ public string ChannelId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the external channel identifier.
+ /// </summary>
+ /// <value>The external channel identifier.</value>
+ public string ExternalChannelId { get; set; }
+
+ /// <summary>
+ /// ChannelName of the recording.
+ /// </summary>
+ public string ChannelName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the program identifier.
+ /// </summary>
+ /// <value>The program identifier.</value>
+ public string ProgramId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the external program identifier.
+ /// </summary>
+ /// <value>The external program identifier.</value>
+ public string ExternalProgramId { get; set; }
+
+ /// <summary>
+ /// Name of the recording.
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Description of the recording.
+ /// </summary>
+ public string Overview { get; set; }
+
+ /// <summary>
+ /// The start date of the recording, in UTC.
+ /// </summary>
+ public DateTime StartDate { get; set; }
+
+ /// <summary>
+ /// The end date of the recording, in UTC.
+ /// </summary>
+ public DateTime EndDate { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the service.
+ /// </summary>
+ /// <value>The name of the service.</value>
+ public string ServiceName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the priority.
+ /// </summary>
+ /// <value>The priority.</value>
+ public int Priority { get; set; }
+
+ /// <summary>
+ /// Gets or sets the pre padding seconds.
+ /// </summary>
+ /// <value>The pre padding seconds.</value>
+ public int PrePaddingSeconds { get; set; }
+
+ /// <summary>
+ /// Gets or sets the post padding seconds.
+ /// </summary>
+ /// <value>The post padding seconds.</value>
+ public int PostPaddingSeconds { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is pre padding required.
+ /// </summary>
+ /// <value><c>true</c> if this instance is pre padding required; otherwise, <c>false</c>.</value>
+ public bool IsPrePaddingRequired { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is post padding required.
+ /// </summary>
+ /// <value><c>true</c> if this instance is post padding required; otherwise, <c>false</c>.</value>
+ public bool IsPostPaddingRequired { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs b/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs
index fe6faf363..3fec0ee56 100644
--- a/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/ChannelInfoDto.cs
@@ -39,7 +39,7 @@ namespace MediaBrowser.Model.LiveTv
/// Gets or sets the image tags.
/// </summary>
/// <value>The image tags.</value>
- public Dictionary<ImageType, Guid> ImageTags { get; set; }
+ public Dictionary<ImageType, string> ImageTags { get; set; }
/// <summary>
/// Gets or sets the number.
@@ -113,7 +113,7 @@ namespace MediaBrowser.Model.LiveTv
public ChannelInfoDto()
{
- ImageTags = new Dictionary<ImageType, Guid>();
+ ImageTags = new Dictionary<ImageType, string>();
MediaSources = new List<MediaSourceInfo>();
}
diff --git a/MediaBrowser.Model/LiveTv/DayPattern.cs b/MediaBrowser.Model/LiveTv/DayPattern.cs
new file mode 100644
index 000000000..8251795dc
--- /dev/null
+++ b/MediaBrowser.Model/LiveTv/DayPattern.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Model.LiveTv
+{
+ public enum DayPattern
+ {
+ Daily,
+ Weekdays,
+ Weekends
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/GuideInfo.cs b/MediaBrowser.Model/LiveTv/GuideInfo.cs
new file mode 100644
index 000000000..c21f6d871
--- /dev/null
+++ b/MediaBrowser.Model/LiveTv/GuideInfo.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace MediaBrowser.Model.LiveTv
+{
+ public class GuideInfo
+ {
+ /// <summary>
+ /// Gets or sets the start date.
+ /// </summary>
+ /// <value>The start date.</value>
+ public DateTime StartDate { get; set; }
+
+ /// <summary>
+ /// Gets or sets the end date.
+ /// </summary>
+ /// <value>The end date.</value>
+ public DateTime EndDate { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/LiveTvInfo.cs b/MediaBrowser.Model/LiveTv/LiveTvInfo.cs
new file mode 100644
index 000000000..dd31c5a6b
--- /dev/null
+++ b/MediaBrowser.Model/LiveTv/LiveTvInfo.cs
@@ -0,0 +1,49 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.LiveTv
+{
+ public class LiveTvInfo
+ {
+ /// <summary>
+ /// Gets or sets the services.
+ /// </summary>
+ /// <value>The services.</value>
+ public List<LiveTvServiceInfo> Services { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the active service.
+ /// </summary>
+ /// <value>The name of the active service.</value>
+ public string ActiveServiceName { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is enabled.
+ /// </summary>
+ /// <value><c>true</c> if this instance is enabled; otherwise, <c>false</c>.</value>
+ public bool IsEnabled { get; set; }
+
+ /// <summary>
+ /// Gets or sets the enabled users.
+ /// </summary>
+ /// <value>The enabled users.</value>
+ public List<string> EnabledUsers { get; set; }
+
+ /// <summary>
+ /// Gets or sets the status.
+ /// </summary>
+ /// <value>The status.</value>
+ public LiveTvServiceStatus Status { get; set; }
+
+ /// <summary>
+ /// Gets or sets the status message.
+ /// </summary>
+ /// <value>The status message.</value>
+ public string StatusMessage { get; set; }
+
+ public LiveTvInfo()
+ {
+ Services = new List<LiveTvServiceInfo>();
+ EnabledUsers = new List<string>();
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs b/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs
index 85f58be3b..264870ffb 100644
--- a/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs
+++ b/MediaBrowser.Model/LiveTv/LiveTvServiceInfo.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
namespace MediaBrowser.Model.LiveTv
{
@@ -51,140 +50,4 @@ namespace MediaBrowser.Model.LiveTv
Tuners = new List<LiveTvTunerInfoDto>();
}
}
-
- public class GuideInfo
- {
- /// <summary>
- /// Gets or sets the start date.
- /// </summary>
- /// <value>The start date.</value>
- public DateTime StartDate { get; set; }
-
- /// <summary>
- /// Gets or sets the end date.
- /// </summary>
- /// <value>The end date.</value>
- public DateTime EndDate { get; set; }
- }
-
- public class LiveTvInfo
- {
- /// <summary>
- /// Gets or sets the services.
- /// </summary>
- /// <value>The services.</value>
- public List<LiveTvServiceInfo> Services { get; set; }
-
- /// <summary>
- /// Gets or sets the name of the active service.
- /// </summary>
- /// <value>The name of the active service.</value>
- public string ActiveServiceName { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance is enabled.
- /// </summary>
- /// <value><c>true</c> if this instance is enabled; otherwise, <c>false</c>.</value>
- public bool IsEnabled { get; set; }
-
- /// <summary>
- /// Gets or sets the enabled users.
- /// </summary>
- /// <value>The enabled users.</value>
- public List<string> EnabledUsers { get; set; }
-
- /// <summary>
- /// Gets or sets the status.
- /// </summary>
- /// <value>The status.</value>
- public LiveTvServiceStatus Status { get; set; }
-
- /// <summary>
- /// Gets or sets the status message.
- /// </summary>
- /// <value>The status message.</value>
- public string StatusMessage { get; set; }
-
- public LiveTvInfo()
- {
- Services = new List<LiveTvServiceInfo>();
- EnabledUsers = new List<string>();
- }
- }
-
- public class LiveTvTunerInfoDto
- {
- /// <summary>
- /// Gets or sets the type of the source.
- /// </summary>
- /// <value>The type of the source.</value>
- public string SourceType { get; set; }
-
- /// <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; }
-
- /// <summary>
- /// Gets or sets the status.
- /// </summary>
- /// <value>The status.</value>
- public LiveTvTunerStatus Status { get; set; }
-
- /// <summary>
- /// Gets or sets the channel identifier.
- /// </summary>
- /// <value>The channel identifier.</value>
- public string ChannelId { get; set; }
-
- /// <summary>
- /// Gets or sets the name of the channel.
- /// </summary>
- /// <value>The name of the channel.</value>
- public string ChannelName { get; set; }
-
- /// <summary>
- /// Gets or sets the recording identifier.
- /// </summary>
- /// <value>The recording identifier.</value>
- public string RecordingId { get; set; }
-
- /// <summary>
- /// Gets or sets the name of the program.
- /// </summary>
- /// <value>The name of the program.</value>
- public string ProgramName { get; set; }
-
- /// <summary>
- /// Gets or sets the clients.
- /// </summary>
- /// <value>The clients.</value>
- public List<string> Clients { get; set; }
-
- public LiveTvTunerInfoDto()
- {
- Clients = new List<string>();
- }
- }
-
- public enum LiveTvServiceStatus
- {
- Ok = 0,
- Unavailable = 1
- }
-
- public enum LiveTvTunerStatus
- {
- Available = 0,
- Disabled = 1,
- RecordingTv = 2,
- LiveTv = 3
- }
}
diff --git a/MediaBrowser.Model/LiveTv/LiveTvServiceStatus.cs b/MediaBrowser.Model/LiveTv/LiveTvServiceStatus.cs
new file mode 100644
index 000000000..20fe84500
--- /dev/null
+++ b/MediaBrowser.Model/LiveTv/LiveTvServiceStatus.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Model.LiveTv
+{
+ public enum LiveTvServiceStatus
+ {
+ Ok = 0,
+ Unavailable = 1
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/LiveTvTunerInfoDto.cs b/MediaBrowser.Model/LiveTv/LiveTvTunerInfoDto.cs
new file mode 100644
index 000000000..28e8c158a
--- /dev/null
+++ b/MediaBrowser.Model/LiveTv/LiveTvTunerInfoDto.cs
@@ -0,0 +1,66 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.LiveTv
+{
+ public class LiveTvTunerInfoDto
+ {
+ /// <summary>
+ /// Gets or sets the type of the source.
+ /// </summary>
+ /// <value>The type of the source.</value>
+ public string SourceType { get; set; }
+
+ /// <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; }
+
+ /// <summary>
+ /// Gets or sets the status.
+ /// </summary>
+ /// <value>The status.</value>
+ public LiveTvTunerStatus Status { get; set; }
+
+ /// <summary>
+ /// Gets or sets the channel identifier.
+ /// </summary>
+ /// <value>The channel identifier.</value>
+ public string ChannelId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the channel.
+ /// </summary>
+ /// <value>The name of the channel.</value>
+ public string ChannelName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the recording identifier.
+ /// </summary>
+ /// <value>The recording identifier.</value>
+ public string RecordingId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the program.
+ /// </summary>
+ /// <value>The name of the program.</value>
+ public string ProgramName { get; set; }
+
+ /// <summary>
+ /// Gets or sets the clients.
+ /// </summary>
+ /// <value>The clients.</value>
+ public List<string> Clients { get; set; }
+
+ public LiveTvTunerInfoDto()
+ {
+ Clients = new List<string>();
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/LiveTvTunerStatus.cs b/MediaBrowser.Model/LiveTv/LiveTvTunerStatus.cs
new file mode 100644
index 000000000..055199fca
--- /dev/null
+++ b/MediaBrowser.Model/LiveTv/LiveTvTunerStatus.cs
@@ -0,0 +1,10 @@
+namespace MediaBrowser.Model.LiveTv
+{
+ public enum LiveTvTunerStatus
+ {
+ Available = 0,
+ Disabled = 1,
+ RecordingTv = 2,
+ LiveTv = 3
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/ProgramAudio.cs b/MediaBrowser.Model/LiveTv/ProgramAudio.cs
new file mode 100644
index 000000000..902079b9a
--- /dev/null
+++ b/MediaBrowser.Model/LiveTv/ProgramAudio.cs
@@ -0,0 +1,11 @@
+namespace MediaBrowser.Model.LiveTv
+{
+ public enum ProgramAudio
+ {
+ Mono,
+ Stereo,
+ Dolby,
+ DolbyDigital,
+ Thx
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs b/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs
index f6b343bdb..fb931820e 100644
--- a/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/ProgramInfoDto.cs
@@ -45,7 +45,7 @@ namespace MediaBrowser.Model.LiveTv
/// Gets or sets the channel primary image tag.
/// </summary>
/// <value>The channel primary image tag.</value>
- public Guid? ChannelPrimaryImageTag { get; set; }
+ public string ChannelPrimaryImageTag { get; set; }
/// <summary>
/// Gets or sets the play access.
@@ -136,7 +136,7 @@ namespace MediaBrowser.Model.LiveTv
/// Gets or sets the image tags.
/// </summary>
/// <value>The image tags.</value>
- public Dictionary<ImageType, Guid> ImageTags { get; set; }
+ public Dictionary<ImageType, string> ImageTags { get; set; }
/// <summary>
/// Gets or sets the user data.
@@ -211,18 +211,9 @@ namespace MediaBrowser.Model.LiveTv
public ProgramInfoDto()
{
Genres = new List<string>();
- ImageTags = new Dictionary<ImageType, Guid>();
+ ImageTags = new Dictionary<ImageType, string>();
}
public event PropertyChangedEventHandler PropertyChanged;
}
-
- public enum ProgramAudio
- {
- Mono,
- Stereo,
- Dolby,
- DolbyDigital,
- Thx
- }
} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/ProgramQuery.cs b/MediaBrowser.Model/LiveTv/ProgramQuery.cs
index a2a824994..36c06d4c0 100644
--- a/MediaBrowser.Model/LiveTv/ProgramQuery.cs
+++ b/MediaBrowser.Model/LiveTv/ProgramQuery.cs
@@ -32,31 +32,4 @@ namespace MediaBrowser.Model.LiveTv
ChannelIdList = new string[] { };
}
}
-
- public class RecommendedProgramQuery
- {
- /// <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 airing.
- /// </summary>
- /// <value><c>true</c> if this instance is airing; otherwise, <c>false</c>.</value>
- public bool? IsAiring { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance has aired.
- /// </summary>
- /// <value><c>null</c> if [has aired] contains no value, <c>true</c> if [has aired]; otherwise, <c>false</c>.</value>
- public bool? HasAired { get; set; }
-
- /// <summary>
- /// The maximum number of items to return
- /// </summary>
- /// <value>The limit.</value>
- public int? Limit { get; set; }
- }
}
diff --git a/MediaBrowser.Model/LiveTv/RecommendedProgramQuery.cs b/MediaBrowser.Model/LiveTv/RecommendedProgramQuery.cs
new file mode 100644
index 000000000..907902123
--- /dev/null
+++ b/MediaBrowser.Model/LiveTv/RecommendedProgramQuery.cs
@@ -0,0 +1,29 @@
+namespace MediaBrowser.Model.LiveTv
+{
+ public class RecommendedProgramQuery
+ {
+ /// <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 airing.
+ /// </summary>
+ /// <value><c>true</c> if this instance is airing; otherwise, <c>false</c>.</value>
+ public bool? IsAiring { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance has aired.
+ /// </summary>
+ /// <value><c>null</c> if [has aired] contains no value, <c>true</c> if [has aired]; otherwise, <c>false</c>.</value>
+ public bool? HasAired { get; set; }
+
+ /// <summary>
+ /// The maximum number of items to return
+ /// </summary>
+ /// <value>The limit.</value>
+ public int? Limit { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/RecordingGroupQuery.cs b/MediaBrowser.Model/LiveTv/RecordingGroupQuery.cs
new file mode 100644
index 000000000..8c20e7f3f
--- /dev/null
+++ b/MediaBrowser.Model/LiveTv/RecordingGroupQuery.cs
@@ -0,0 +1,11 @@
+namespace MediaBrowser.Model.LiveTv
+{
+ public class RecordingGroupQuery
+ {
+ /// <summary>
+ /// Gets or sets the user identifier.
+ /// </summary>
+ /// <value>The user identifier.</value>
+ public string UserId { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs
index de07382c0..3705b7a29 100644
--- a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs
@@ -50,7 +50,7 @@ namespace MediaBrowser.Model.LiveTv
/// Gets or sets the channel primary image tag.
/// </summary>
/// <value>The channel primary image tag.</value>
- public Guid? ChannelPrimaryImageTag { get; set; }
+ public string ChannelPrimaryImageTag { get; set; }
/// <summary>
/// ChannelName of the recording.
@@ -224,7 +224,7 @@ namespace MediaBrowser.Model.LiveTv
/// Gets or sets the image tags.
/// </summary>
/// <value>The image tags.</value>
- public Dictionary<ImageType, Guid> ImageTags { get; set; }
+ public Dictionary<ImageType, string> ImageTags { get; set; }
/// <summary>
/// Gets or sets the user data.
@@ -253,7 +253,7 @@ namespace MediaBrowser.Model.LiveTv
public RecordingInfoDto()
{
Genres = new List<string>();
- ImageTags = new Dictionary<ImageType, Guid>();
+ ImageTags = new Dictionary<ImageType, string>();
MediaSources = new List<MediaSourceInfo>();
}
diff --git a/MediaBrowser.Model/LiveTv/RecordingQuery.cs b/MediaBrowser.Model/LiveTv/RecordingQuery.cs
index 1fa9af49b..daa137db6 100644
--- a/MediaBrowser.Model/LiveTv/RecordingQuery.cs
+++ b/MediaBrowser.Model/LiveTv/RecordingQuery.cs
@@ -1,6 +1,4 @@
-using MediaBrowser.Model.Entities;
-
-namespace MediaBrowser.Model.LiveTv
+namespace MediaBrowser.Model.LiveTv
{
/// <summary>
/// Class RecordingQuery.
@@ -61,43 +59,4 @@ namespace MediaBrowser.Model.LiveTv
/// <value>The series timer identifier.</value>
public string SeriesTimerId { get; set; }
}
-
- public class RecordingGroupQuery
- {
- /// <summary>
- /// Gets or sets the user identifier.
- /// </summary>
- /// <value>The user identifier.</value>
- public string UserId { get; set; }
- }
-
- public class TimerQuery
- {
- /// <summary>
- /// Gets or sets the channel identifier.
- /// </summary>
- /// <value>The channel identifier.</value>
- public string ChannelId { get; set; }
-
- /// <summary>
- /// Gets or sets the series timer identifier.
- /// </summary>
- /// <value>The series timer identifier.</value>
- public string SeriesTimerId { get; set; }
- }
-
- public class SeriesTimerQuery
- {
- /// <summary>
- /// Gets or sets the sort by - SortName, Priority
- /// </summary>
- /// <value>The sort by.</value>
- public string SortBy { get; set; }
-
- /// <summary>
- /// Gets or sets the sort order.
- /// </summary>
- /// <value>The sort order.</value>
- public SortOrder SortOrder { get; set; }
- }
}
diff --git a/MediaBrowser.Model/LiveTv/RecordingStatus.cs b/MediaBrowser.Model/LiveTv/RecordingStatus.cs
index 95e9dcb01..7ab716c4d 100644
--- a/MediaBrowser.Model/LiveTv/RecordingStatus.cs
+++ b/MediaBrowser.Model/LiveTv/RecordingStatus.cs
@@ -13,11 +13,4 @@ namespace MediaBrowser.Model.LiveTv
ConflictedNotOk,
Error
}
-
- public enum DayPattern
- {
- Daily,
- Weekdays,
- Weekends
- }
}
diff --git a/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs b/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs
index 393233c1b..7c590307f 100644
--- a/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/SeriesTimerInfoDto.cs
@@ -43,7 +43,7 @@ namespace MediaBrowser.Model.LiveTv
/// Gets or sets the image tags.
/// </summary>
/// <value>The image tags.</value>
- public Dictionary<ImageType, Guid> ImageTags { get; set; }
+ public Dictionary<ImageType, string> ImageTags { get; set; }
/// <summary>
/// Gets a value indicating whether this instance has primary image.
@@ -57,7 +57,7 @@ namespace MediaBrowser.Model.LiveTv
public SeriesTimerInfoDto()
{
- ImageTags = new Dictionary<ImageType, Guid>();
+ ImageTags = new Dictionary<ImageType, string>();
Days = new List<DayOfWeek>();
}
}
diff --git a/MediaBrowser.Model/LiveTv/SeriesTimerQuery.cs b/MediaBrowser.Model/LiveTv/SeriesTimerQuery.cs
new file mode 100644
index 000000000..95260cc0e
--- /dev/null
+++ b/MediaBrowser.Model/LiveTv/SeriesTimerQuery.cs
@@ -0,0 +1,19 @@
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Model.LiveTv
+{
+ public class SeriesTimerQuery
+ {
+ /// <summary>
+ /// Gets or sets the sort by - SortName, Priority
+ /// </summary>
+ /// <value>The sort by.</value>
+ public string SortBy { get; set; }
+
+ /// <summary>
+ /// Gets or sets the sort order.
+ /// </summary>
+ /// <value>The sort order.</value>
+ public SortOrder SortOrder { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/LiveTv/TimerInfoDto.cs b/MediaBrowser.Model/LiveTv/TimerInfoDto.cs
index 137c95719..16cac945f 100644
--- a/MediaBrowser.Model/LiveTv/TimerInfoDto.cs
+++ b/MediaBrowser.Model/LiveTv/TimerInfoDto.cs
@@ -1,7 +1,4 @@
-using System;
-using System.ComponentModel;
-
-namespace MediaBrowser.Model.LiveTv
+namespace MediaBrowser.Model.LiveTv
{
public class TimerInfoDto : BaseTimerInfoDto
{
@@ -36,107 +33,4 @@ namespace MediaBrowser.Model.LiveTv
public ProgramInfoDto ProgramInfo { get; set; }
}
-
- public class BaseTimerInfoDto : INotifyPropertyChanged
- {
- /// <summary>
- /// Occurs when a property value changes.
- /// </summary>
- public event PropertyChangedEventHandler PropertyChanged;
-
- /// <summary>
- /// Id of the recording.
- /// </summary>
- public string Id { get; set; }
-
- /// <summary>
- /// Gets or sets the external identifier.
- /// </summary>
- /// <value>The external identifier.</value>
- public string ExternalId { get; set; }
-
- /// <summary>
- /// ChannelId of the recording.
- /// </summary>
- public string ChannelId { get; set; }
-
- /// <summary>
- /// Gets or sets the external channel identifier.
- /// </summary>
- /// <value>The external channel identifier.</value>
- public string ExternalChannelId { get; set; }
-
- /// <summary>
- /// ChannelName of the recording.
- /// </summary>
- public string ChannelName { get; set; }
-
- /// <summary>
- /// Gets or sets the program identifier.
- /// </summary>
- /// <value>The program identifier.</value>
- public string ProgramId { get; set; }
-
- /// <summary>
- /// Gets or sets the external program identifier.
- /// </summary>
- /// <value>The external program identifier.</value>
- public string ExternalProgramId { get; set; }
-
- /// <summary>
- /// Name of the recording.
- /// </summary>
- public string Name { get; set; }
-
- /// <summary>
- /// Description of the recording.
- /// </summary>
- public string Overview { get; set; }
-
- /// <summary>
- /// The start date of the recording, in UTC.
- /// </summary>
- public DateTime StartDate { get; set; }
-
- /// <summary>
- /// The end date of the recording, in UTC.
- /// </summary>
- public DateTime EndDate { get; set; }
-
- /// <summary>
- /// Gets or sets the name of the service.
- /// </summary>
- /// <value>The name of the service.</value>
- public string ServiceName { get; set; }
-
- /// <summary>
- /// Gets or sets the priority.
- /// </summary>
- /// <value>The priority.</value>
- public int Priority { get; set; }
-
- /// <summary>
- /// Gets or sets the pre padding seconds.
- /// </summary>
- /// <value>The pre padding seconds.</value>
- public int PrePaddingSeconds { get; set; }
-
- /// <summary>
- /// Gets or sets the post padding seconds.
- /// </summary>
- /// <value>The post padding seconds.</value>
- public int PostPaddingSeconds { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance is pre padding required.
- /// </summary>
- /// <value><c>true</c> if this instance is pre padding required; otherwise, <c>false</c>.</value>
- public bool IsPrePaddingRequired { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether this instance is post padding required.
- /// </summary>
- /// <value><c>true</c> if this instance is post padding required; otherwise, <c>false</c>.</value>
- public bool IsPostPaddingRequired { get; set; }
- }
}
diff --git a/MediaBrowser.Model/LiveTv/TimerQuery.cs b/MediaBrowser.Model/LiveTv/TimerQuery.cs
new file mode 100644
index 000000000..e6ceff530
--- /dev/null
+++ b/MediaBrowser.Model/LiveTv/TimerQuery.cs
@@ -0,0 +1,17 @@
+namespace MediaBrowser.Model.LiveTv
+{
+ public class TimerQuery
+ {
+ /// <summary>
+ /// Gets or sets the channel identifier.
+ /// </summary>
+ /// <value>The channel identifier.</value>
+ public string ChannelId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the series timer identifier.
+ /// </summary>
+ /// <value>The series timer identifier.</value>
+ public string SeriesTimerId { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index 710e5f6b4..2c714f831 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -57,35 +57,66 @@
<Compile Include="ApiClient\IApiClient.cs" />
<Compile Include="ApiClient\ApiClientExtensions.cs" />
<Compile Include="ApiClient\IServerEvents.cs" />
- <Compile Include="ApiClient\ServerEventArgs.cs" />
+ <Compile Include="ApiClient\GeneralCommandEventArgs.cs" />
+ <Compile Include="ApiClient\SessionUpdatesEventArgs.cs" />
+ <Compile Include="Channels\ChannelItemQuery.cs" />
<Compile Include="Channels\ChannelQuery.cs" />
- <Compile Include="Configuration\AutoOrganize.cs" />
+ <Compile Include="Chapters\RemoteChapterInfo.cs" />
+ <Compile Include="Chapters\RemoteChapterResult.cs" />
+ <Compile Include="Configuration\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="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="Configuration\PathSubstitution.cs" />
+ <Compile Include="Configuration\SendToUserType.cs" />
<Compile Include="Configuration\ServerConfiguration.cs" />
+ <Compile Include="Configuration\SubtitleOptions.cs" />
+ <Compile Include="Configuration\UnratedItem.cs" />
+ <Compile Include="Dlna\AudioOptions.cs" />
<Compile Include="Dlna\CodecProfile.cs" />
+ <Compile Include="Dlna\CodecType.cs" />
<Compile Include="Dlna\ConditionProcessor.cs" />
<Compile Include="Dlna\ContainerProfile.cs" />
<Compile Include="Dlna\ContentFeatureBuilder.cs" />
<Compile Include="Dlna\DeviceIdentification.cs" />
<Compile Include="Dlna\DeviceProfile.cs" />
<Compile Include="Dlna\DeviceProfileInfo.cs" />
+ <Compile Include="Dlna\DeviceProfileType.cs" />
<Compile Include="Dlna\DirectPlayProfile.cs" />
+ <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" />
<Compile Include="Dlna\MediaFormatProfileResolver.cs" />
+ <Compile Include="Dlna\ProfileCondition.cs" />
+ <Compile Include="Dlna\ProfileConditionType.cs" />
+ <Compile Include="Dlna\ProfileConditionValue.cs" />
<Compile Include="Dlna\ResponseProfile.cs" />
<Compile Include="Dlna\SearchCriteria.cs" />
+ <Compile Include="Dlna\SearchType.cs" />
<Compile Include="Dlna\SortCriteria.cs" />
<Compile Include="Dlna\StreamBuilder.cs" />
<Compile Include="Dlna\StreamInfo.cs" />
+ <Compile Include="Dlna\TranscodeSeekInfo.cs" />
<Compile Include="Dlna\TranscodingProfile.cs" />
+ <Compile Include="Dlna\VideoOptions.cs" />
+ <Compile Include="Dlna\XmlAttribute.cs" />
<Compile Include="Drawing\ImageOutputFormat.cs" />
+ <Compile Include="Drawing\ImageSize.cs" />
<Compile Include="Dto\BaseItemPerson.cs" />
<Compile Include="Dto\ChapterInfoDto.cs" />
<Compile Include="Dto\GameSystemSummary.cs" />
@@ -94,24 +125,64 @@
<Compile Include="Dto\ItemByNameCounts.cs" />
<Compile Include="Dto\ItemCounts.cs" />
<Compile Include="Dto\ItemIndex.cs" />
+ <Compile Include="Dto\RatingType.cs" />
<Compile Include="Dto\RecommendationDto.cs" />
- <Compile Include="Dto\MediaVersionInfo.cs" />
+ <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" />
<Compile Include="Entities\PackageReviewInfo.cs" />
+ <Compile Include="Entities\ProviderIdsExtensions.cs" />
+ <Compile Include="Entities\ScrollDirection.cs" />
+ <Compile Include="Entities\SortOrder.cs" />
+ <Compile Include="Entities\VideoSize.cs" />
+ <Compile Include="Events\GenericEventArgs.cs" />
+ <Compile Include="FileOrganization\EpisodeFileOrganizationRequest.cs" />
<Compile Include="FileOrganization\FileOrganizationResult.cs" />
- <Compile Include="FileOrganization\FileOrganizationQuery.cs" />
+ <Compile Include="FileOrganization\FileOrganizationResultQuery.cs" />
+ <Compile Include="FileOrganization\FileOrganizerType.cs" />
+ <Compile Include="FileOrganization\FileSortingStatus.cs" />
+ <Compile Include="Globalization\LocalizatonOption.cs" />
+ <Compile Include="IO\FileSystemEntryType.cs" />
<Compile Include="Library\PlayAccess.cs" />
+ <Compile Include="LiveTv\BaseTimerInfoDto.cs" />
<Compile Include="LiveTv\ChannelInfoDto.cs" />
<Compile Include="LiveTv\ChannelQuery.cs" />
+ <Compile Include="LiveTv\DayPattern.cs" />
+ <Compile Include="LiveTv\GuideInfo.cs" />
+ <Compile Include="LiveTv\LiveTvInfo.cs" />
+ <Compile Include="LiveTv\LiveTvServiceStatus.cs" />
+ <Compile Include="LiveTv\LiveTvTunerInfoDto.cs" />
+ <Compile Include="LiveTv\LiveTvTunerStatus.cs" />
+ <Compile Include="LiveTv\ProgramAudio.cs" />
<Compile Include="LiveTv\ProgramInfoDto.cs" />
<Compile Include="LiveTv\ProgramQuery.cs" />
+ <Compile Include="LiveTv\RecommendedProgramQuery.cs" />
<Compile Include="LiveTv\RecordingGroupDto.cs" />
+ <Compile Include="LiveTv\RecordingGroupQuery.cs" />
<Compile Include="LiveTv\RecordingQuery.cs" />
<Compile Include="LiveTv\RecordingStatus.cs" />
<Compile Include="LiveTv\SeriesTimerInfoDto.cs" />
+ <Compile Include="LiveTv\SeriesTimerQuery.cs" />
<Compile Include="LiveTv\TimerInfoDto.cs" />
+ <Compile Include="LiveTv\TimerQuery.cs" />
<Compile Include="Logging\NullLogger.cs" />
+ <Compile Include="MediaInfo\AudioCodec.cs" />
+ <Compile Include="MediaInfo\Container.cs" />
+ <Compile Include="MediaInfo\SubtitleFormat.cs" />
+ <Compile Include="MediaInfo\TransportStreamTimestamp.cs" />
+ <Compile Include="MediaInfo\VideoCodec.cs" />
+ <Compile Include="News\NewsChannel.cs" />
<Compile Include="News\NewsItem.cs" />
+ <Compile Include="News\NewsQuery.cs" />
+ <Compile Include="Notifications\NotificationRequest.cs" />
+ <Compile Include="Notifications\NotificationServiceInfo.cs" />
+ <Compile Include="Notifications\NotificationTypeInfo.cs" />
<Compile Include="Providers\ExternalIdInfo.cs" />
+ <Compile Include="Providers\ExternalUrl.cs" />
<Compile Include="Providers\ImageProviderInfo.cs" />
<Compile Include="Providers\RemoteImageInfo.cs" />
<Compile Include="Dto\StudioDto.cs" />
@@ -136,8 +207,11 @@
<Compile Include="Notifications\NotificationQuery.cs" />
<Compile Include="Notifications\NotificationResult.cs" />
<Compile Include="Notifications\NotificationsSummary.cs" />
+ <Compile Include="Providers\RemoteImageQuery.cs" />
<Compile Include="Providers\RemoteImageResult.cs" />
<Compile Include="Providers\RemoteSearchResult.cs" />
+ <Compile Include="Providers\RemoteSubtitleInfo.cs" />
+ <Compile Include="Querying\AllThemeMediaResult.cs" />
<Compile Include="Querying\ArtistsQuery.cs" />
<Compile Include="Querying\EpisodeQuery.cs" />
<Compile Include="Querying\ItemCountsQuery.cs" />
@@ -145,14 +219,24 @@
<Compile Include="Entities\BaseItemInfo.cs" />
<Compile Include="Querying\NextUpQuery.cs" />
<Compile Include="Querying\QueryResult.cs" />
+ <Compile Include="Querying\SeasonQuery.cs" />
<Compile Include="Querying\SessionQuery.cs" />
+ <Compile Include="Querying\SimilarItemsByNameQuery.cs" />
<Compile Include="Querying\SimilarItemsQuery.cs" />
+ <Compile Include="Querying\UpcomingEpisodesQuery.cs" />
<Compile Include="Querying\UserQuery.cs" />
<Compile Include="Search\SearchQuery.cs" />
<Compile Include="Session\BrowseRequest.cs" />
+ <Compile Include="Session\ClientCapabilities.cs" />
<Compile Include="Session\GeneralCommand.cs" />
+ <Compile Include="Session\GeneralCommandType.cs" />
<Compile Include="Session\MessageCommand.cs" />
- <Compile Include="Session\PlaybackReports.cs" />
+ <Compile Include="Session\PlaybackProgressInfo.cs" />
+ <Compile Include="Session\PlaybackStartInfo.cs" />
+ <Compile Include="Session\PlaybackStopInfo.cs" />
+ <Compile Include="Session\PlayCommand.cs" />
+ <Compile Include="Session\PlayerStateInfo.cs" />
+ <Compile Include="Session\PlayMethod.cs" />
<Compile Include="Session\PlayRequest.cs" />
<Compile Include="Session\PlaystateCommand.cs" />
<Compile Include="Logging\ILogManager.cs" />
@@ -181,22 +265,25 @@
<Compile Include="Net\NetworkShare.cs" />
<Compile Include="Net\NetworkShareType.cs" />
<Compile Include="Querying\PersonsQuery.cs" />
- <Compile Include="Querying\ThemeSongsResult.cs" />
+ <Compile Include="Querying\ThemeMediaResult.cs" />
<Compile Include="Search\SearchHint.cs" />
<Compile Include="Search\SearchHintResult.cs" />
<Compile Include="Serialization\IJsonSerializer.cs" />
<Compile Include="Serialization\IXmlSerializer.cs" />
+ <Compile Include="Session\PlaystateRequest.cs" />
<Compile Include="Session\SessionCapabilities.cs" />
<Compile Include="Session\SessionInfoDto.cs" />
+ <Compile Include="Session\SessionUserInfo.cs" />
<Compile Include="Session\UserDataChangeInfo.cs" />
<Compile Include="Themes\AppTheme.cs" />
+ <Compile Include="Themes\AppThemeInfo.cs" />
<Compile Include="Themes\ThemeImage.cs" />
<Compile Include="Updates\CheckForUpdateResult.cs" />
<Compile Include="Updates\PackageTargetSystem.cs" />
<Compile Include="Updates\InstallationInfo.cs" />
<Compile Include="Updates\PackageType.cs" />
<Compile Include="Updates\PackageVersionClass.cs" />
- <Compile Include="Entities\RequestResult.cs" />
+ <Compile Include="Entities\EmptyRequestResult.cs" />
<Compile Include="Configuration\UserConfiguration.cs" />
<Compile Include="Drawing\DrawingUtils.cs" />
<Compile Include="Dto\UserItemDataDto.cs" />
diff --git a/MediaBrowser.Model/MediaInfo/AudioCodec.cs b/MediaBrowser.Model/MediaInfo/AudioCodec.cs
new file mode 100644
index 000000000..a76c0e742
--- /dev/null
+++ b/MediaBrowser.Model/MediaInfo/AudioCodec.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Model.MediaInfo
+{
+ public class AudioCodec
+ {
+ public const string AAC = "AAC";
+ public const string MP3 = "MP3";
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/MediaInfo/BlurayDiscInfo.cs b/MediaBrowser.Model/MediaInfo/BlurayDiscInfo.cs
index 01e75e6f8..963e8dd95 100644
--- a/MediaBrowser.Model/MediaInfo/BlurayDiscInfo.cs
+++ b/MediaBrowser.Model/MediaInfo/BlurayDiscInfo.cs
@@ -34,11 +34,4 @@ namespace MediaBrowser.Model.MediaInfo
/// <value>The chapters.</value>
public List<double> Chapters { get; set; }
}
-
- public enum TransportStreamTimestamp
- {
- None,
- Zero,
- Valid
- }
}
diff --git a/MediaBrowser.Model/MediaInfo/Container.cs b/MediaBrowser.Model/MediaInfo/Container.cs
new file mode 100644
index 000000000..0305b9cfa
--- /dev/null
+++ b/MediaBrowser.Model/MediaInfo/Container.cs
@@ -0,0 +1,8 @@
+
+namespace MediaBrowser.Model.MediaInfo
+{
+ public class Container
+ {
+ public const string MP4 = "MP4";
+ }
+}
diff --git a/MediaBrowser.Model/MediaInfo/SubtitleFormat.cs b/MediaBrowser.Model/MediaInfo/SubtitleFormat.cs
new file mode 100644
index 000000000..51a0dbc9e
--- /dev/null
+++ b/MediaBrowser.Model/MediaInfo/SubtitleFormat.cs
@@ -0,0 +1,7 @@
+namespace MediaBrowser.Model.MediaInfo
+{
+ public class SubtitleFormat
+ {
+ public const string SRT = "SRT";
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/MediaInfo/TransportStreamTimestamp.cs b/MediaBrowser.Model/MediaInfo/TransportStreamTimestamp.cs
new file mode 100644
index 000000000..4c808a8dc
--- /dev/null
+++ b/MediaBrowser.Model/MediaInfo/TransportStreamTimestamp.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Model.MediaInfo
+{
+ public enum TransportStreamTimestamp
+ {
+ None,
+ Zero,
+ Valid
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/MediaInfo/VideoCodec.cs b/MediaBrowser.Model/MediaInfo/VideoCodec.cs
new file mode 100644
index 000000000..7405eb13e
--- /dev/null
+++ b/MediaBrowser.Model/MediaInfo/VideoCodec.cs
@@ -0,0 +1,12 @@
+namespace MediaBrowser.Model.MediaInfo
+{
+ public class VideoCodec
+ {
+ public const string H263 = "H263";
+ public const string H264 = "H264";
+ public const string H265 = "H265";
+ public const string MPEG4 = "MPEG4";
+ public const string MSMPEG4 = "MSMPEG4";
+ public const string VC1 = "VC1";
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/News/NewsChannel.cs b/MediaBrowser.Model/News/NewsChannel.cs
new file mode 100644
index 000000000..c3955b0a0
--- /dev/null
+++ b/MediaBrowser.Model/News/NewsChannel.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.News
+{
+ public class NewsChannel
+ {
+ public string Title { get; set; }
+ public string Link { get; set; }
+ public string Description { get; set; }
+ public List<NewsItem> Items { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/News/NewsItem.cs b/MediaBrowser.Model/News/NewsItem.cs
index 181f43db7..2a05c420a 100644
--- a/MediaBrowser.Model/News/NewsItem.cs
+++ b/MediaBrowser.Model/News/NewsItem.cs
@@ -1,16 +1,7 @@
using System;
-using System.Collections.Generic;
namespace MediaBrowser.Model.News
{
- public class NewsChannel
- {
- public string Title { get; set; }
- public string Link { get; set; }
- public string Description { get; set; }
- public List<NewsItem> Items { get; set; }
- }
-
public class NewsItem
{
public string Title { get; set; }
@@ -20,11 +11,4 @@ namespace MediaBrowser.Model.News
public string Guid { get; set; }
public DateTime Date { get; set; }
}
-
- public class NewsQuery
- {
- public int? StartIndex { get; set; }
-
- public int? Limit { get; set; }
- }
}
diff --git a/MediaBrowser.Model/News/NewsQuery.cs b/MediaBrowser.Model/News/NewsQuery.cs
new file mode 100644
index 000000000..567888921
--- /dev/null
+++ b/MediaBrowser.Model/News/NewsQuery.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Model.News
+{
+ public class NewsQuery
+ {
+ public int? StartIndex { get; set; }
+
+ public int? Limit { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Notifications/Notification.cs b/MediaBrowser.Model/Notifications/Notification.cs
index d894911e7..731c3d303 100644
--- a/MediaBrowser.Model/Notifications/Notification.cs
+++ b/MediaBrowser.Model/Notifications/Notification.cs
@@ -1,6 +1,4 @@
-using MediaBrowser.Model.Configuration;
-using System;
-using System.Collections.Generic;
+using System;
namespace MediaBrowser.Model.Notifications
{
@@ -27,70 +25,4 @@ namespace MediaBrowser.Model.Notifications
Date = DateTime.UtcNow;
}
}
-
- public class NotificationRequest
- {
- public string Name { get; set; }
-
- public string Description { get; set; }
-
- public string Url { get; set; }
-
- public NotificationLevel Level { get; set; }
-
- public List<string> UserIds { get; set; }
-
- public DateTime Date { get; set; }
-
- /// <summary>
- /// The corresponding type name used in configuration. Not for display.
- /// </summary>
- public string NotificationType { get; set; }
-
- public Dictionary<string, string> Variables { get; set; }
-
- 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>();
- }
- }
-
- public class NotificationTypeInfo
- {
- public string Type { get; set; }
-
- public string Name { get; set; }
-
- public bool Enabled { get; set; }
-
- public string Category { get; set; }
-
- public bool IsBasedOnUserEvent { get; set; }
-
- public string DefaultTitle { get; set; }
-
- public string DefaultDescription { get; set; }
-
- public List<string> Variables { get; set; }
-
- public NotificationTypeInfo()
- {
- Variables = new List<string>();
- }
- }
-
- public class NotificationServiceInfo
- {
- public string Name { get; set; }
- public string Id { get; set; }
- }
}
diff --git a/MediaBrowser.Model/Notifications/NotificationRequest.cs b/MediaBrowser.Model/Notifications/NotificationRequest.cs
new file mode 100644
index 000000000..d47e9c4f2
--- /dev/null
+++ b/MediaBrowser.Model/Notifications/NotificationRequest.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using MediaBrowser.Model.Configuration;
+
+namespace MediaBrowser.Model.Notifications
+{
+ public class NotificationRequest
+ {
+ public string Name { get; set; }
+
+ public string Description { get; set; }
+
+ public string Url { get; set; }
+
+ public NotificationLevel Level { get; set; }
+
+ public List<string> UserIds { get; set; }
+
+ public DateTime Date { get; set; }
+
+ /// <summary>
+ /// The corresponding type name used in configuration. Not for display.
+ /// </summary>
+ public string NotificationType { get; set; }
+
+ public Dictionary<string, string> Variables { get; set; }
+
+ 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>();
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Notifications/NotificationServiceInfo.cs b/MediaBrowser.Model/Notifications/NotificationServiceInfo.cs
new file mode 100644
index 000000000..0ffe7d4ae
--- /dev/null
+++ b/MediaBrowser.Model/Notifications/NotificationServiceInfo.cs
@@ -0,0 +1,8 @@
+namespace MediaBrowser.Model.Notifications
+{
+ public class NotificationServiceInfo
+ {
+ public string Name { get; set; }
+ public string Id { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Notifications/NotificationTypeInfo.cs b/MediaBrowser.Model/Notifications/NotificationTypeInfo.cs
new file mode 100644
index 000000000..59b39fbc7
--- /dev/null
+++ b/MediaBrowser.Model/Notifications/NotificationTypeInfo.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.Notifications
+{
+ public class NotificationTypeInfo
+ {
+ public string Type { get; set; }
+
+ public string Name { get; set; }
+
+ public bool Enabled { get; set; }
+
+ public string Category { get; set; }
+
+ public bool IsBasedOnUserEvent { get; set; }
+
+ public string DefaultTitle { get; set; }
+
+ public string DefaultDescription { get; set; }
+
+ public List<string> Variables { get; set; }
+
+ public NotificationTypeInfo()
+ {
+ Variables = new List<string>();
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Plugins/BasePluginConfiguration.cs b/MediaBrowser.Model/Plugins/BasePluginConfiguration.cs
index 4c7b8812f..9a8bfadd1 100644
--- a/MediaBrowser.Model/Plugins/BasePluginConfiguration.cs
+++ b/MediaBrowser.Model/Plugins/BasePluginConfiguration.cs
@@ -1,5 +1,4 @@
-using MediaBrowser.Model.Updates;
-
+
namespace MediaBrowser.Model.Plugins
{
/// <summary>
@@ -7,26 +6,5 @@ namespace MediaBrowser.Model.Plugins
/// </summary>
public class BasePluginConfiguration
{
- /// <summary>
- /// Whether or not this plug-in should be automatically updated when a
- /// compatible new version is released
- /// </summary>
- /// <value><c>true</c> if [enable auto update]; otherwise, <c>false</c>.</value>
- public bool EnableAutoUpdate { get; set; }
-
- /// <summary>
- /// The classification of updates to which to subscribe.
- /// Options are: Dev, Beta or Release
- /// </summary>
- /// <value>The update class.</value>
- public PackageVersionClass UpdateClass { get; set; }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="BasePluginConfiguration" /> class.
- /// </summary>
- public BasePluginConfiguration()
- {
- EnableAutoUpdate = true;
- }
}
}
diff --git a/MediaBrowser.Model/Plugins/PluginInfo.cs b/MediaBrowser.Model/Plugins/PluginInfo.cs
index fbc2e2927..e84c06c21 100644
--- a/MediaBrowser.Model/Plugins/PluginInfo.cs
+++ b/MediaBrowser.Model/Plugins/PluginInfo.cs
@@ -49,25 +49,5 @@ namespace MediaBrowser.Model.Plugins
/// </summary>
/// <value>The unique id.</value>
public string Id { get; set; }
-
- /// <summary>
- /// Whether or not this plug-in should be automatically updated when a
- /// compatible new version is released
- /// </summary>
- /// <value><c>true</c> if [enable auto update]; otherwise, <c>false</c>.</value>
- public bool EnableAutoUpdate { get; set; }
-
- /// <summary>
- /// The classification of updates to which to subscribe.
- /// Options are: Dev, Beta or Release
- /// </summary>
- /// <value>The update class.</value>
- public PackageVersionClass UpdateClass { get; set; }
-
- /// <summary>
- /// Gets or sets the minimum required UI version.
- /// </summary>
- /// <value>The minimum required UI version.</value>
- public string MinimumRequiredUIVersion { get; set; }
}
}
diff --git a/MediaBrowser.Model/Providers/ExternalIdInfo.cs b/MediaBrowser.Model/Providers/ExternalIdInfo.cs
index e041f06af..2c5cfe91b 100644
--- a/MediaBrowser.Model/Providers/ExternalIdInfo.cs
+++ b/MediaBrowser.Model/Providers/ExternalIdInfo.cs
@@ -21,19 +21,4 @@ namespace MediaBrowser.Model.Providers
/// <value>The URL format string.</value>
public string UrlFormatString { get; set; }
}
-
- public class ExternalUrl
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { get; set; }
-
- /// <summary>
- /// Gets or sets the type of the item.
- /// </summary>
- /// <value>The type of the item.</value>
- public string Url { get; set; }
- }
}
diff --git a/MediaBrowser.Model/Providers/ExternalUrl.cs b/MediaBrowser.Model/Providers/ExternalUrl.cs
new file mode 100644
index 000000000..fb744f446
--- /dev/null
+++ b/MediaBrowser.Model/Providers/ExternalUrl.cs
@@ -0,0 +1,17 @@
+namespace MediaBrowser.Model.Providers
+{
+ public class ExternalUrl
+ {
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Gets or sets the type of the item.
+ /// </summary>
+ /// <value>The type of the item.</value>
+ public string Url { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Providers/RemoteImageQuery.cs b/MediaBrowser.Model/Providers/RemoteImageQuery.cs
new file mode 100644
index 000000000..8d5231a25
--- /dev/null
+++ b/MediaBrowser.Model/Providers/RemoteImageQuery.cs
@@ -0,0 +1,15 @@
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Model.Providers
+{
+ public class RemoteImageQuery
+ {
+ public string ProviderName { get; set; }
+
+ public ImageType? ImageType { get; set; }
+
+ public bool IncludeDisabledProviders { get; set; }
+
+ public bool IncludeAllLanguages { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Providers/RemoteImageResult.cs b/MediaBrowser.Model/Providers/RemoteImageResult.cs
index ed2788c0b..1c60db6ae 100644
--- a/MediaBrowser.Model/Providers/RemoteImageResult.cs
+++ b/MediaBrowser.Model/Providers/RemoteImageResult.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using MediaBrowser.Model.Entities;
namespace MediaBrowser.Model.Providers
{
@@ -26,15 +25,4 @@ namespace MediaBrowser.Model.Providers
/// <value>The providers.</value>
public List<string> Providers { get; set; }
}
-
- public class RemoteImageQuery
- {
- public string ProviderName { get; set; }
-
- public ImageType? ImageType { get; set; }
-
- public bool IncludeDisabledProviders { get; set; }
-
- public bool IncludeAllLanguages { get; set; }
- }
}
diff --git a/MediaBrowser.Model/Providers/RemoteSubtitleInfo.cs b/MediaBrowser.Model/Providers/RemoteSubtitleInfo.cs
new file mode 100644
index 000000000..0a4a52cd5
--- /dev/null
+++ b/MediaBrowser.Model/Providers/RemoteSubtitleInfo.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace MediaBrowser.Model.Providers
+{
+ public class RemoteSubtitleInfo
+ {
+ public string ThreeLetterISOLanguageName { get; set; }
+ public string Id { get; set; }
+ public string ProviderName { get; set; }
+ public string Name { get; set; }
+ public string Format { get; set; }
+ public string Author { get; set; }
+ public string Comment { get; set; }
+ public DateTime? DateCreated { get; set; }
+ public float? CommunityRating { get; set; }
+ public int? DownloadCount { get; set; }
+ public bool? IsHashMatch { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Querying/ThemeSongsResult.cs b/MediaBrowser.Model/Querying/AllThemeMediaResult.cs
index 9b0a1c61b..89640eb65 100644
--- a/MediaBrowser.Model/Querying/ThemeSongsResult.cs
+++ b/MediaBrowser.Model/Querying/AllThemeMediaResult.cs
@@ -1,18 +1,5 @@
-
-namespace MediaBrowser.Model.Querying
+namespace MediaBrowser.Model.Querying
{
- /// <summary>
- /// Class ThemeMediaResult
- /// </summary>
- public class ThemeMediaResult : ItemsResult
- {
- /// <summary>
- /// Gets or sets the owner id.
- /// </summary>
- /// <value>The owner id.</value>
- public string OwnerId { get; set; }
- }
-
public class AllThemeMediaResult
{
public ThemeMediaResult ThemeVideosResult { get; set; }
@@ -30,4 +17,4 @@ namespace MediaBrowser.Model.Querying
SoundtrackSongsResult = new ThemeMediaResult();
}
}
-}
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Querying/EpisodeQuery.cs b/MediaBrowser.Model/Querying/EpisodeQuery.cs
index 589b46433..e2fc3220a 100644
--- a/MediaBrowser.Model/Querying/EpisodeQuery.cs
+++ b/MediaBrowser.Model/Querying/EpisodeQuery.cs
@@ -22,24 +22,4 @@ namespace MediaBrowser.Model.Querying
Fields = new ItemFields[] { };
}
}
-
- public class SeasonQuery
- {
- public string UserId { get; set; }
-
- public string SeriesId { get; set; }
-
- public bool? IsMissing { get; set; }
-
- public bool? IsVirtualUnaired { get; set; }
-
- public ItemFields[] Fields { get; set; }
-
- public bool? IsSpecialSeason { get; set; }
-
- public SeasonQuery()
- {
- Fields = new ItemFields[] { };
- }
- }
}
diff --git a/MediaBrowser.Model/Querying/ItemFilter.cs b/MediaBrowser.Model/Querying/ItemFilter.cs
index 2e88a98c9..d30978ebf 100644
--- a/MediaBrowser.Model/Querying/ItemFilter.cs
+++ b/MediaBrowser.Model/Querying/ItemFilter.cs
@@ -27,6 +27,10 @@ namespace MediaBrowser.Model.Querying
/// </summary>
IsFavorite = 5,
/// <summary>
+ /// The is recently added
+ /// </summary>
+ IsRecentlyAdded = 6,
+ /// <summary>
/// The item is resumable
/// </summary>
IsResumable = 7,
diff --git a/MediaBrowser.Model/Querying/NextUpQuery.cs b/MediaBrowser.Model/Querying/NextUpQuery.cs
index cdce2e307..0e9c9882f 100644
--- a/MediaBrowser.Model/Querying/NextUpQuery.cs
+++ b/MediaBrowser.Model/Querying/NextUpQuery.cs
@@ -10,6 +10,12 @@ namespace MediaBrowser.Model.Querying
public string UserId { get; set; }
/// <summary>
+ /// Gets or sets the parent identifier.
+ /// </summary>
+ /// <value>The parent identifier.</value>
+ public string ParentId { get; set; }
+
+ /// <summary>
/// Gets or sets the series id.
/// </summary>
/// <value>The series id.</value>
@@ -33,32 +39,4 @@ namespace MediaBrowser.Model.Querying
/// <value>The fields.</value>
public ItemFields[] Fields { get; set; }
}
-
- public class UpcomingEpisodesQuery
- {
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- 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>
- 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; }
- }
-
}
diff --git a/MediaBrowser.Model/Querying/SeasonQuery.cs b/MediaBrowser.Model/Querying/SeasonQuery.cs
new file mode 100644
index 000000000..b1fe635bb
--- /dev/null
+++ b/MediaBrowser.Model/Querying/SeasonQuery.cs
@@ -0,0 +1,22 @@
+namespace MediaBrowser.Model.Querying
+{
+ public class SeasonQuery
+ {
+ public string UserId { get; set; }
+
+ public string SeriesId { get; set; }
+
+ public bool? IsMissing { get; set; }
+
+ public bool? IsVirtualUnaired { get; set; }
+
+ public ItemFields[] Fields { get; set; }
+
+ public bool? IsSpecialSeason { get; set; }
+
+ public SeasonQuery()
+ {
+ Fields = new ItemFields[] { };
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Querying/SimilarItemsByNameQuery.cs b/MediaBrowser.Model/Querying/SimilarItemsByNameQuery.cs
new file mode 100644
index 000000000..7d0d4da31
--- /dev/null
+++ b/MediaBrowser.Model/Querying/SimilarItemsByNameQuery.cs
@@ -0,0 +1,29 @@
+namespace MediaBrowser.Model.Querying
+{
+ public class SimilarItemsByNameQuery
+ {
+ /// <summary>
+ /// The user to localize search results for
+ /// </summary>
+ /// <value>The user id.</value>
+ public string UserId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { 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; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Querying/SimilarItemsQuery.cs b/MediaBrowser.Model/Querying/SimilarItemsQuery.cs
index d792aa76d..0dd491550 100644
--- a/MediaBrowser.Model/Querying/SimilarItemsQuery.cs
+++ b/MediaBrowser.Model/Querying/SimilarItemsQuery.cs
@@ -26,31 +26,4 @@
/// <value>The fields.</value>
public ItemFields[] Fields { get; set; }
}
-
- public class SimilarItemsByNameQuery
- {
- /// <summary>
- /// The user to localize search results for
- /// </summary>
- /// <value>The user id.</value>
- public string UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name { 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; }
- }
}
diff --git a/MediaBrowser.Model/Querying/ThemeMediaResult.cs b/MediaBrowser.Model/Querying/ThemeMediaResult.cs
new file mode 100644
index 000000000..80478a910
--- /dev/null
+++ b/MediaBrowser.Model/Querying/ThemeMediaResult.cs
@@ -0,0 +1,15 @@
+
+namespace MediaBrowser.Model.Querying
+{
+ /// <summary>
+ /// Class ThemeMediaResult
+ /// </summary>
+ public class ThemeMediaResult : ItemsResult
+ {
+ /// <summary>
+ /// Gets or sets the owner id.
+ /// </summary>
+ /// <value>The owner id.</value>
+ public string OwnerId { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs b/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs
new file mode 100644
index 000000000..e5a875e88
--- /dev/null
+++ b/MediaBrowser.Model/Querying/UpcomingEpisodesQuery.cs
@@ -0,0 +1,35 @@
+namespace MediaBrowser.Model.Querying
+{
+ public class UpcomingEpisodesQuery
+ {
+ /// <summary>
+ /// Gets or sets the user id.
+ /// </summary>
+ /// <value>The user id.</value>
+ public string UserId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the parent identifier.
+ /// </summary>
+ /// <value>The parent identifier.</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; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Search/SearchHint.cs b/MediaBrowser.Model/Search/SearchHint.cs
index 002200c0f..4eced7706 100644
--- a/MediaBrowser.Model/Search/SearchHint.cs
+++ b/MediaBrowser.Model/Search/SearchHint.cs
@@ -47,13 +47,13 @@ namespace MediaBrowser.Model.Search
/// Gets or sets the image tag.
/// </summary>
/// <value>The image tag.</value>
- public Guid? PrimaryImageTag { get; set; }
+ public string PrimaryImageTag { get; set; }
/// <summary>
/// Gets or sets the thumb image tag.
/// </summary>
/// <value>The thumb image tag.</value>
- public Guid? ThumbImageTag { get; set; }
+ public string ThumbImageTag { get; set; }
/// <summary>
/// Gets or sets the thumb image item identifier.
@@ -65,7 +65,7 @@ namespace MediaBrowser.Model.Search
/// Gets or sets the backdrop image tag.
/// </summary>
/// <value>The backdrop image tag.</value>
- public Guid? BackdropImageTag { get; set; }
+ public string BackdropImageTag { get; set; }
/// <summary>
/// Gets or sets the backdrop image item identifier.
diff --git a/MediaBrowser.Model/Session/ClientCapabilities.cs b/MediaBrowser.Model/Session/ClientCapabilities.cs
new file mode 100644
index 000000000..5bee06087
--- /dev/null
+++ b/MediaBrowser.Model/Session/ClientCapabilities.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.Session
+{
+ public class ClientCapabilities
+ {
+ public List<string> PlayableMediaTypes { get; set; }
+ public List<string> SupportedCommands { get; set; }
+
+ public ClientCapabilities()
+ {
+ PlayableMediaTypes = new List<string>();
+ SupportedCommands = new List<string>();
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Session/GeneralCommand.cs b/MediaBrowser.Model/Session/GeneralCommand.cs
index 071eac954..7e818245d 100644
--- a/MediaBrowser.Model/Session/GeneralCommand.cs
+++ b/MediaBrowser.Model/Session/GeneralCommand.cs
@@ -16,39 +16,4 @@ namespace MediaBrowser.Model.Session
Arguments = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}
-
- /// <summary>
- /// This exists simply to identify a set of known commands.
- /// </summary>
- public enum GeneralCommandType
- {
- MoveUp = 0,
- MoveDown = 1,
- MoveLeft = 2,
- MoveRight = 3,
- PageUp = 4,
- PageDown = 5,
- PreviousLetter = 6,
- NextLetter = 7,
- ToggleOsd = 8,
- ToggleContextMenu = 9,
- Select = 10,
- Back = 11,
- TakeScreenshot = 12,
- SendKey = 13,
- SendString = 14,
- GoHome = 15,
- GoToSettings = 16,
- VolumeUp = 17,
- VolumeDown = 18,
- Mute = 19,
- Unmute = 20,
- ToggleMute = 21,
- SetVolume = 22,
- SetAudioStreamIndex = 23,
- SetSubtitleStreamIndex = 24,
- ToggleFullscreen = 25,
- DisplayContent = 26,
- GoToSearch = 27
- }
}
diff --git a/MediaBrowser.Model/Session/GeneralCommandType.cs b/MediaBrowser.Model/Session/GeneralCommandType.cs
new file mode 100644
index 000000000..f8773a246
--- /dev/null
+++ b/MediaBrowser.Model/Session/GeneralCommandType.cs
@@ -0,0 +1,38 @@
+namespace MediaBrowser.Model.Session
+{
+ /// <summary>
+ /// This exists simply to identify a set of known commands.
+ /// </summary>
+ public enum GeneralCommandType
+ {
+ MoveUp = 0,
+ MoveDown = 1,
+ MoveLeft = 2,
+ MoveRight = 3,
+ PageUp = 4,
+ PageDown = 5,
+ PreviousLetter = 6,
+ NextLetter = 7,
+ ToggleOsd = 8,
+ ToggleContextMenu = 9,
+ Select = 10,
+ Back = 11,
+ TakeScreenshot = 12,
+ SendKey = 13,
+ SendString = 14,
+ GoHome = 15,
+ GoToSettings = 16,
+ VolumeUp = 17,
+ VolumeDown = 18,
+ Mute = 19,
+ Unmute = 20,
+ ToggleMute = 21,
+ SetVolume = 22,
+ SetAudioStreamIndex = 23,
+ SetSubtitleStreamIndex = 24,
+ ToggleFullscreen = 25,
+ DisplayContent = 26,
+ GoToSearch = 27,
+ DisplayMessage = 28
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Session/PlayCommand.cs b/MediaBrowser.Model/Session/PlayCommand.cs
new file mode 100644
index 000000000..3a5a951d7
--- /dev/null
+++ b/MediaBrowser.Model/Session/PlayCommand.cs
@@ -0,0 +1,29 @@
+namespace MediaBrowser.Model.Session
+{
+ /// <summary>
+ /// Enum PlayCommand
+ /// </summary>
+ public enum PlayCommand
+ {
+ /// <summary>
+ /// The play now
+ /// </summary>
+ PlayNow = 0,
+ /// <summary>
+ /// The play next
+ /// </summary>
+ PlayNext = 1,
+ /// <summary>
+ /// The play last
+ /// </summary>
+ PlayLast = 2,
+ /// <summary>
+ /// The play instant mix
+ /// </summary>
+ PlayInstantMix = 3,
+ /// <summary>
+ /// The play shuffle
+ /// </summary>
+ PlayShuffle = 4
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Session/PlayMethod.cs b/MediaBrowser.Model/Session/PlayMethod.cs
new file mode 100644
index 000000000..87b728627
--- /dev/null
+++ b/MediaBrowser.Model/Session/PlayMethod.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Model.Session
+{
+ public enum PlayMethod
+ {
+ Transcode = 0,
+ DirectStream = 1,
+ DirectPlay = 2
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Session/PlayRequest.cs b/MediaBrowser.Model/Session/PlayRequest.cs
index 74d7a70a3..5db5e90cb 100644
--- a/MediaBrowser.Model/Session/PlayRequest.cs
+++ b/MediaBrowser.Model/Session/PlayRequest.cs
@@ -30,31 +30,4 @@ namespace MediaBrowser.Model.Session
/// <value>The controlling user identifier.</value>
public string ControllingUserId { get; set; }
}
-
- /// <summary>
- /// Enum PlayCommand
- /// </summary>
- public enum PlayCommand
- {
- /// <summary>
- /// The play now
- /// </summary>
- PlayNow = 0,
- /// <summary>
- /// The play next
- /// </summary>
- PlayNext = 1,
- /// <summary>
- /// The play last
- /// </summary>
- PlayLast = 2,
- /// <summary>
- /// The play instant mix
- /// </summary>
- PlayInstantMix = 3,
- /// <summary>
- /// The play shuffle
- /// </summary>
- PlayShuffle = 4
- }
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Session/PlaybackReports.cs b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs
index 93960076e..f04dea1ea 100644
--- a/MediaBrowser.Model/Session/PlaybackReports.cs
+++ b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs
@@ -1,26 +1,8 @@
using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
namespace MediaBrowser.Model.Session
{
/// <summary>
- /// Class PlaybackStartInfo.
- /// </summary>
- public class PlaybackStartInfo : PlaybackProgressInfo
- {
- public PlaybackStartInfo()
- {
- QueueableMediaTypes = new List<string>();
- }
-
- /// <summary>
- /// Gets or sets the queueable media types.
- /// </summary>
- /// <value>The queueable media types.</value>
- public List<string> QueueableMediaTypes { get; set; }
- }
-
- /// <summary>
/// Class PlaybackProgressInfo.
/// </summary>
public class PlaybackProgressInfo
@@ -97,47 +79,4 @@ namespace MediaBrowser.Model.Session
/// <value>The play method.</value>
public PlayMethod PlayMethod { get; set; }
}
-
- public enum PlayMethod
- {
- Transcode = 0,
- DirectStream = 1,
- DirectPlay = 2
- }
-
- /// <summary>
- /// Class PlaybackStopInfo.
- /// </summary>
- public class PlaybackStopInfo
- {
- /// <summary>
- /// Gets or sets the item.
- /// </summary>
- /// <value>The item.</value>
- public BaseItemInfo Item { 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 session id.
- /// </summary>
- /// <value>The session id.</value>
- public string SessionId { get; set; }
-
- /// <summary>
- /// Gets or sets the media version identifier.
- /// </summary>
- /// <value>The media version identifier.</value>
- public string MediaSourceId { get; set; }
-
- /// <summary>
- /// Gets or sets the position ticks.
- /// </summary>
- /// <value>The position ticks.</value>
- public long? PositionTicks { get; set; }
- }
-}
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Session/PlaybackStartInfo.cs b/MediaBrowser.Model/Session/PlaybackStartInfo.cs
new file mode 100644
index 000000000..d1ea2841e
--- /dev/null
+++ b/MediaBrowser.Model/Session/PlaybackStartInfo.cs
@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.Session
+{
+ /// <summary>
+ /// Class PlaybackStartInfo.
+ /// </summary>
+ public class PlaybackStartInfo : PlaybackProgressInfo
+ {
+ public PlaybackStartInfo()
+ {
+ QueueableMediaTypes = new List<string>();
+ }
+
+ /// <summary>
+ /// Gets or sets the queueable media types.
+ /// </summary>
+ /// <value>The queueable media types.</value>
+ public List<string> QueueableMediaTypes { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Session/PlaybackStopInfo.cs b/MediaBrowser.Model/Session/PlaybackStopInfo.cs
new file mode 100644
index 000000000..38025f183
--- /dev/null
+++ b/MediaBrowser.Model/Session/PlaybackStopInfo.cs
@@ -0,0 +1,40 @@
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Model.Session
+{
+ /// <summary>
+ /// Class PlaybackStopInfo.
+ /// </summary>
+ public class PlaybackStopInfo
+ {
+ /// <summary>
+ /// Gets or sets the item.
+ /// </summary>
+ /// <value>The item.</value>
+ public BaseItemInfo Item { 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 session id.
+ /// </summary>
+ /// <value>The session id.</value>
+ public string SessionId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the media version identifier.
+ /// </summary>
+ /// <value>The media version identifier.</value>
+ public string MediaSourceId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the position ticks.
+ /// </summary>
+ /// <value>The position ticks.</value>
+ public long? PositionTicks { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Session/PlayerStateInfo.cs b/MediaBrowser.Model/Session/PlayerStateInfo.cs
new file mode 100644
index 000000000..c9afef8e0
--- /dev/null
+++ b/MediaBrowser.Model/Session/PlayerStateInfo.cs
@@ -0,0 +1,59 @@
+namespace MediaBrowser.Model.Session
+{
+ public class PlayerStateInfo
+ {
+ /// <summary>
+ /// Gets or sets the now playing position ticks.
+ /// </summary>
+ /// <value>The now playing position ticks.</value>
+ public long? PositionTicks { get; set; }
+
+ /// <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 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 volume level.
+ /// </summary>
+ /// <value>The volume level.</value>
+ public int? VolumeLevel { get; set; }
+
+ /// <summary>
+ /// Gets or sets the index of the now playing audio stream.
+ /// </summary>
+ /// <value>The index of the now playing audio stream.</value>
+ public int? AudioStreamIndex { get; set; }
+
+ /// <summary>
+ /// Gets or sets the index of the now playing subtitle stream.
+ /// </summary>
+ /// <value>The index of the now playing subtitle stream.</value>
+ public int? SubtitleStreamIndex { get; set; }
+
+ /// <summary>
+ /// Gets or sets the now playing media version identifier.
+ /// </summary>
+ /// <value>The now playing media version identifier.</value>
+ public string MediaSourceId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the play method.
+ /// </summary>
+ /// <value>The play method.</value>
+ public PlayMethod? PlayMethod { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Session/PlaystateCommand.cs b/MediaBrowser.Model/Session/PlaystateCommand.cs
index 6466c6485..2af4f26e3 100644
--- a/MediaBrowser.Model/Session/PlaystateCommand.cs
+++ b/MediaBrowser.Model/Session/PlaystateCommand.cs
@@ -39,17 +39,4 @@ namespace MediaBrowser.Model.Session
/// </summary>
FastForward
}
-
- public class PlaystateRequest
- {
- public PlaystateCommand Command { get; set; }
-
- public long? SeekPositionTicks { get; set; }
-
- /// <summary>
- /// Gets or sets the controlling user identifier.
- /// </summary>
- /// <value>The controlling user identifier.</value>
- public string ControllingUserId { get; set; }
- }
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Session/PlaystateRequest.cs b/MediaBrowser.Model/Session/PlaystateRequest.cs
new file mode 100644
index 000000000..8a046b503
--- /dev/null
+++ b/MediaBrowser.Model/Session/PlaystateRequest.cs
@@ -0,0 +1,15 @@
+namespace MediaBrowser.Model.Session
+{
+ public class PlaystateRequest
+ {
+ public PlaystateCommand Command { get; set; }
+
+ public long? SeekPositionTicks { get; set; }
+
+ /// <summary>
+ /// Gets or sets the controlling user identifier.
+ /// </summary>
+ /// <value>The controlling user identifier.</value>
+ public string ControllingUserId { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Session/SessionInfoDto.cs b/MediaBrowser.Model/Session/SessionInfoDto.cs
index cd6ecbbb2..46e214d24 100644
--- a/MediaBrowser.Model/Session/SessionInfoDto.cs
+++ b/MediaBrowser.Model/Session/SessionInfoDto.cs
@@ -55,7 +55,7 @@ namespace MediaBrowser.Model.Session
/// Gets or sets the user primary image tag.
/// </summary>
/// <value>The user primary image tag.</value>
- public Guid? UserPrimaryImageTag { get; set; }
+ public string UserPrimaryImageTag { get; set; }
/// <summary>
/// Gets or sets the name of the user.
@@ -148,90 +148,4 @@ namespace MediaBrowser.Model.Session
SupportedCommands = new List<string>();
}
}
-
- /// <summary>
- /// Class SessionUserInfo.
- /// </summary>
- public class SessionUserInfo
- {
- /// <summary>
- /// Gets or sets the user identifier.
- /// </summary>
- /// <value>The user identifier.</value>
- public string UserId { get; set; }
- /// <summary>
- /// Gets or sets the name of the user.
- /// </summary>
- /// <value>The name of the user.</value>
- public string UserName { get; set; }
- }
-
- public class ClientCapabilities
- {
- public List<string> PlayableMediaTypes { get; set; }
- public List<string> SupportedCommands { get; set; }
-
- public ClientCapabilities()
- {
- PlayableMediaTypes = new List<string>();
- SupportedCommands = new List<string>();
- }
- }
-
- public class PlayerStateInfo
- {
- /// <summary>
- /// Gets or sets the now playing position ticks.
- /// </summary>
- /// <value>The now playing position ticks.</value>
- public long? PositionTicks { get; set; }
-
- /// <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 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 volume level.
- /// </summary>
- /// <value>The volume level.</value>
- public int? VolumeLevel { get; set; }
-
- /// <summary>
- /// Gets or sets the index of the now playing audio stream.
- /// </summary>
- /// <value>The index of the now playing audio stream.</value>
- public int? AudioStreamIndex { get; set; }
-
- /// <summary>
- /// Gets or sets the index of the now playing subtitle stream.
- /// </summary>
- /// <value>The index of the now playing subtitle stream.</value>
- public int? SubtitleStreamIndex { get; set; }
-
- /// <summary>
- /// Gets or sets the now playing media version identifier.
- /// </summary>
- /// <value>The now playing media version identifier.</value>
- public string MediaSourceId { get; set; }
-
- /// <summary>
- /// Gets or sets the play method.
- /// </summary>
- /// <value>The play method.</value>
- public PlayMethod? PlayMethod { get; set; }
- }
}
diff --git a/MediaBrowser.Model/Session/SessionUserInfo.cs b/MediaBrowser.Model/Session/SessionUserInfo.cs
new file mode 100644
index 000000000..39b96931a
--- /dev/null
+++ b/MediaBrowser.Model/Session/SessionUserInfo.cs
@@ -0,0 +1,19 @@
+namespace MediaBrowser.Model.Session
+{
+ /// <summary>
+ /// Class SessionUserInfo.
+ /// </summary>
+ public class SessionUserInfo
+ {
+ /// <summary>
+ /// Gets or sets the user identifier.
+ /// </summary>
+ /// <value>The user identifier.</value>
+ public string UserId { get; set; }
+ /// <summary>
+ /// Gets or sets the name of the user.
+ /// </summary>
+ /// <value>The name of the user.</value>
+ public string UserName { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Tasks/TaskInfo.cs b/MediaBrowser.Model/Tasks/TaskInfo.cs
index 8e795f22f..83ee0b7e6 100644
--- a/MediaBrowser.Model/Tasks/TaskInfo.cs
+++ b/MediaBrowser.Model/Tasks/TaskInfo.cs
@@ -30,7 +30,7 @@ namespace MediaBrowser.Model.Tasks
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
- public Guid Id { get; set; }
+ public string Id { get; set; }
/// <summary>
/// Gets or sets the last execution result.
diff --git a/MediaBrowser.Model/Tasks/TaskResult.cs b/MediaBrowser.Model/Tasks/TaskResult.cs
index c04d2f2fe..e73b4c9a1 100644
--- a/MediaBrowser.Model/Tasks/TaskResult.cs
+++ b/MediaBrowser.Model/Tasks/TaskResult.cs
@@ -35,7 +35,7 @@ namespace MediaBrowser.Model.Tasks
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
- public Guid Id { get; set; }
+ public string Id { get; set; }
/// <summary>
/// Gets or sets the error message.
diff --git a/MediaBrowser.Model/Themes/AppTheme.cs b/MediaBrowser.Model/Themes/AppTheme.cs
index a814fec33..40a729963 100644
--- a/MediaBrowser.Model/Themes/AppTheme.cs
+++ b/MediaBrowser.Model/Themes/AppTheme.cs
@@ -20,11 +20,4 @@ namespace MediaBrowser.Model.Themes
Images = new List<ThemeImage>();
}
}
-
- public class AppThemeInfo
- {
- public string AppName { get; set; }
-
- public string Name { get; set; }
- }
}
diff --git a/MediaBrowser.Model/Themes/AppThemeInfo.cs b/MediaBrowser.Model/Themes/AppThemeInfo.cs
new file mode 100644
index 000000000..bc359530a
--- /dev/null
+++ b/MediaBrowser.Model/Themes/AppThemeInfo.cs
@@ -0,0 +1,9 @@
+namespace MediaBrowser.Model.Themes
+{
+ public class AppThemeInfo
+ {
+ public string AppName { get; set; }
+
+ public string Name { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Model/Updates/InstallationInfo.cs b/MediaBrowser.Model/Updates/InstallationInfo.cs
index 09b4975a8..b904a0e58 100644
--- a/MediaBrowser.Model/Updates/InstallationInfo.cs
+++ b/MediaBrowser.Model/Updates/InstallationInfo.cs
@@ -11,7 +11,7 @@ namespace MediaBrowser.Model.Updates
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
- public Guid Id { get; set; }
+ public string Id { get; set; }
/// <summary>
/// Gets or sets the name.
diff --git a/MediaBrowser.Model/Updates/PackageVersionInfo.cs b/MediaBrowser.Model/Updates/PackageVersionInfo.cs
index 3b0a94019..b3d297e8e 100644
--- a/MediaBrowser.Model/Updates/PackageVersionInfo.cs
+++ b/MediaBrowser.Model/Updates/PackageVersionInfo.cs
@@ -47,7 +47,7 @@ namespace MediaBrowser.Model.Updates
/// <param name="str">The STR.</param>
/// <param name="def">The def.</param>
/// <returns>System.String.</returns>
- private static string ValueOrDefault(string str, string def = "")
+ private static string ValueOrDefault(string str, string def)
{
return string.IsNullOrEmpty(str) ? def : str;
}
@@ -80,7 +80,7 @@ namespace MediaBrowser.Model.Updates
/// Gets or sets the source URL.
/// </summary>
/// <value>The source URL.</value>
- public Guid checksum { get; set; }
+ public string checksum { get; set; }
/// <summary>
/// Gets or sets the target filename.
diff --git a/MediaBrowser.Model/Web/QueryStringDictionary.cs b/MediaBrowser.Model/Web/QueryStringDictionary.cs
index 905fbb215..b011d4d9c 100644
--- a/MediaBrowser.Model/Web/QueryStringDictionary.cs
+++ b/MediaBrowser.Model/Web/QueryStringDictionary.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
namespace MediaBrowser.Model.Web
@@ -24,7 +25,7 @@ namespace MediaBrowser.Model.Web
/// <param name="value">The value.</param>
public void Add(string name, int value)
{
- Add(name, value.ToString());
+ Add(name, value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
@@ -34,7 +35,7 @@ namespace MediaBrowser.Model.Web
/// <param name="value">The value.</param>
public void Add(string name, long value)
{
- Add(name, value.ToString());
+ Add(name, value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
@@ -44,7 +45,7 @@ namespace MediaBrowser.Model.Web
/// <param name="value">The value.</param>
public void Add(string name, double value)
{
- Add(name, value.ToString());
+ Add(name, value.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
@@ -128,50 +129,6 @@ namespace MediaBrowser.Model.Web
/// <param name="name">The name.</param>
/// <param name="value">The value.</param>
/// <exception cref="System.ArgumentNullException">value</exception>
- public void Add(string name, Guid value)
- {
- if (value == Guid.Empty)
- {
- throw new ArgumentNullException("value");
- }
-
- Add(name, value.ToString());
- }
-
- /// <summary>
- /// Adds if not empty.
- /// </summary>
- /// <param name="name">The name.</param>
- /// <param name="value">The value.</param>
- public void AddIfNotEmpty(string name, Guid value)
- {
- if (value != Guid.Empty)
- {
- Add(name, value);
- }
-
- Add(name, value);
- }
-
- /// <summary>
- /// Adds if not null.
- /// </summary>
- /// <param name="name">The name.</param>
- /// <param name="value">The value.</param>
- public void AddIfNotNull(string name, Guid? value)
- {
- if (value.HasValue)
- {
- Add(name, value.Value);
- }
- }
-
- /// <summary>
- /// Adds the specified name.
- /// </summary>
- /// <param name="name">The name.</param>
- /// <param name="value">The value.</param>
- /// <exception cref="System.ArgumentNullException">value</exception>
public void Add(string name, IEnumerable<int> value)
{
if (value == null)
@@ -179,7 +136,7 @@ namespace MediaBrowser.Model.Web
throw new ArgumentNullException("value");
}
- Add(name, string.Join(",", value.Select(v => v.ToString()).ToArray()));
+ Add(name, string.Join(",", value.Select(v => v.ToString(CultureInfo.InvariantCulture)).ToArray()));
}
/// <summary>
@@ -208,7 +165,7 @@ namespace MediaBrowser.Model.Web
throw new ArgumentNullException("value");
}
- var paramValue = string.Join(",", value.ToArray());
+ string paramValue = string.Join(",", value.ToArray());
Add(name, paramValue);
}
@@ -232,7 +189,7 @@ namespace MediaBrowser.Model.Web
/// <param name="name">The name.</param>
/// <param name="value">The value.</param>
/// <param name="delimiter">The delimiter.</param>
- /// <exception cref="System.ArgumentNullException">value</exception>
+ /// <exception cref="ArgumentNullException">value</exception>
public void Add(string name, IEnumerable<string> value, string delimiter)
{
if (value == null)
@@ -240,7 +197,7 @@ namespace MediaBrowser.Model.Web
throw new ArgumentNullException("value");
}
- var paramValue = string.Join(delimiter, value.ToArray());
+ string paramValue = string.Join(delimiter, value.ToArray());
Add(name, paramValue);
}
@@ -265,7 +222,7 @@ namespace MediaBrowser.Model.Web
/// <returns>System.String.</returns>
public string GetQueryString()
{
- var queryParams = this.Select(i => string.Format("{0}={1}", i.Key, GetEncodedValue(i.Value))).ToArray();
+ string[] queryParams = this.Select(i => string.Format("{0}={1}", i.Key, GetEncodedValue(i.Value))).ToArray();
return string.Join("&", queryParams);
}
@@ -287,7 +244,7 @@ namespace MediaBrowser.Model.Web
/// <returns>System.String.</returns>
public string GetUrl(string prefix)
{
- var query = GetQueryString();
+ string query = GetQueryString();
if (string.IsNullOrEmpty(query))
{
diff --git a/MediaBrowser.Mono.sln b/MediaBrowser.Mono.sln
index a5b084812..9c2397046 100644
--- a/MediaBrowser.Mono.sln
+++ b/MediaBrowser.Mono.sln
@@ -23,6 +23,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Dlna", "MediaB
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSubtitlesHandler", "OpenSubtitlesHandler\OpenSubtitlesHandler.csproj", "{4A4402D4-E910-443B-B8FC-2C18286A2CA0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
@@ -33,8 +35,8 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.ActiveCfg = Debug|Any CPU
{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.Build.0 = Debug|Any CPU
- {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU
- {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|Any CPU.Build.0 = Release|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|Any CPU.Build.0 = 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|x86.ActiveCfg = Release|Any CPU
@@ -71,6 +73,14 @@ Global
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.Build.0 = Release|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.ActiveCfg = Release|Any CPU
{442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.Build.0 = Release|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|x86.Build.0 = Debug|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release Mono|Any CPU.Build.0 = 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|x86.ActiveCfg = Release|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x86.Build.0 = Release|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 Mono|Any CPU.ActiveCfg = Release Mono|Any CPU
diff --git a/MediaBrowser.Mono.userprefs b/MediaBrowser.Mono.userprefs
index 15813ef56..f115a532e 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="36" Column="37" />
+ <File FileName="MediaBrowser.Server.Mono\Program.cs" Line="24" Column="15" />
</Files>
</MonoDevelop.Ide.Workbench>
<MonoDevelop.Ide.DebuggingService.Breakpoints>
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 817ecdbb8..43402123c 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -108,6 +108,7 @@
<Compile Include="MediaInfo\FFProbeHelpers.cs" />
<Compile Include="MediaInfo\FFProbeProvider.cs" />
<Compile Include="MediaInfo\FFProbeVideoInfo.cs" />
+ <Compile Include="MediaInfo\SubtitleDownloader.cs" />
<Compile Include="Movies\MovieDbTrailerProvider.cs" />
<Compile Include="Movies\MovieExternalIds.cs" />
<Compile Include="Movies\TrailerMetadataService.cs" />
@@ -186,6 +187,8 @@
<Compile Include="Savers\XmlSaverHelpers.cs" />
<Compile Include="Studios\StudiosImageProvider.cs" />
<Compile Include="Studios\StudioMetadataService.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" />
@@ -229,6 +232,10 @@
<Project>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</Project>
<Name>MediaBrowser.Model</Name>
</ProjectReference>
+ <ProjectReference Include="..\OpenSubtitlesHandler\OpenSubtitlesHandler.csproj">
+ <Project>{4a4402d4-e910-443b-b8fc-2c18286a2ca0}</Project>
+ <Name>OpenSubtitlesHandler</Name>
+ </ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
index 7a71a7551..7318fd17a 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
@@ -10,15 +11,16 @@ using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Serialization;
using System;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using System.Linq;
namespace MediaBrowser.Providers.MediaInfo
{
@@ -45,6 +47,8 @@ namespace MediaBrowser.Providers.MediaInfo
private readonly IJsonSerializer _json;
private readonly IEncodingManager _encodingManager;
private readonly IFileSystem _fileSystem;
+ private readonly IServerConfigurationManager _config;
+ private readonly ISubtitleManager _subtitleManager;
public string Name
{
@@ -96,7 +100,7 @@ namespace MediaBrowser.Providers.MediaInfo
return FetchAudioInfo(item, cancellationToken);
}
- public FFProbeProvider(ILogger logger, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IBlurayExaminer blurayExaminer, ILocalizationManager localization, IApplicationPaths appPaths, IJsonSerializer json, IEncodingManager encodingManager, IFileSystem fileSystem)
+ public FFProbeProvider(ILogger logger, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IBlurayExaminer blurayExaminer, ILocalizationManager localization, IApplicationPaths appPaths, IJsonSerializer json, IEncodingManager encodingManager, IFileSystem fileSystem, IServerConfigurationManager config, ISubtitleManager subtitleManager)
{
_logger = logger;
_isoManager = isoManager;
@@ -108,6 +112,8 @@ namespace MediaBrowser.Providers.MediaInfo
_json = json;
_encodingManager = encodingManager;
_fileSystem = fileSystem;
+ _config = config;
+ _subtitleManager = subtitleManager;
}
private readonly Task<ItemUpdateType> _cachedTask = Task.FromResult(ItemUpdateType.None);
@@ -134,7 +140,7 @@ namespace MediaBrowser.Providers.MediaInfo
return _cachedTask;
}
- var prober = new FFProbeVideoInfo(_logger, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager, _fileSystem);
+ var prober = new FFProbeVideoInfo(_logger, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager, _fileSystem, _config, _subtitleManager);
return prober.ProbeVideo(item, directoryService, cancellationToken);
}
@@ -165,9 +171,9 @@ namespace MediaBrowser.Providers.MediaInfo
if (video != null && !video.IsPlaceHolder)
{
- var prober = new FFProbeVideoInfo(_logger, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager, _fileSystem);
+ var prober = new FFProbeVideoInfo(_logger, _isoManager, _mediaEncoder, _itemRepo, _blurayExaminer, _localization, _appPaths, _json, _encodingManager, _fileSystem, _config, _subtitleManager);
- return !video.SubtitleFiles.SequenceEqual(prober.GetSubtitleFiles(video, directoryService).Select(i => i.FullName).OrderBy(i => i), StringComparer.OrdinalIgnoreCase);
+ return !video.SubtitleFiles.SequenceEqual(prober.GetSubtitleFiles(video, directoryService, 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 a7d4a480e..47a441a4d 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -2,12 +2,16 @@
using MediaBrowser.Common.Configuration;
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.Localization;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
@@ -35,10 +39,12 @@ namespace MediaBrowser.Providers.MediaInfo
private readonly IJsonSerializer _json;
private readonly IEncodingManager _encodingManager;
private readonly IFileSystem _fileSystem;
+ private readonly IServerConfigurationManager _config;
+ private readonly ISubtitleManager _subtitleManager;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- public FFProbeVideoInfo(ILogger logger, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IBlurayExaminer blurayExaminer, ILocalizationManager localization, IApplicationPaths appPaths, IJsonSerializer json, IEncodingManager encodingManager, IFileSystem fileSystem)
+ public FFProbeVideoInfo(ILogger logger, IIsoManager isoManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IBlurayExaminer blurayExaminer, ILocalizationManager localization, IApplicationPaths appPaths, IJsonSerializer json, IEncodingManager encodingManager, IFileSystem fileSystem, IServerConfigurationManager config, ISubtitleManager subtitleManager)
{
_logger = logger;
_isoManager = isoManager;
@@ -50,6 +56,8 @@ namespace MediaBrowser.Providers.MediaInfo
_json = json;
_encodingManager = encodingManager;
_fileSystem = fileSystem;
+ _config = config;
+ _subtitleManager = subtitleManager;
}
public async Task<ItemUpdateType> ProbeVideo<T>(T item, IDirectoryService directoryService, CancellationToken cancellationToken)
@@ -118,7 +126,7 @@ namespace MediaBrowser.Providers.MediaInfo
cancellationToken.ThrowIfCancellationRequested();
var idString = item.Id.ToString("N");
- var cachePath = Path.Combine(_appPaths.CachePath,
+ var cachePath = Path.Combine(_appPaths.CachePath,
"ffprobe-video",
idString.Substring(0, 2), idString, "v" + SchemaVersion + _mediaEncoder.Version + item.DateModified.Ticks.ToString(_usCulture) + ".json");
@@ -200,7 +208,7 @@ namespace MediaBrowser.Providers.MediaInfo
FetchBdInfo(video, chapters, mediaStreams, blurayInfo);
}
- AddExternalSubtitles(video, mediaStreams, directoryService);
+ await AddExternalSubtitles(video, mediaStreams, directoryService, cancellationToken).ConfigureAwait(false);
FetchWtvInfo(video, data);
@@ -247,7 +255,7 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
- info.StartPositionTicks = chapter.start/100;
+ info.StartPositionTicks = chapter.start / 100;
return info;
}
@@ -405,11 +413,11 @@ namespace MediaBrowser.Providers.MediaInfo
{
get
{
- return new[] { ".srt", ".ssa", ".ass" };
+ return new[] { ".srt", ".ssa", ".ass", ".sub" };
}
}
- public IEnumerable<FileSystemInfo> GetSubtitleFiles(Video video, IDirectoryService directoryService)
+ public IEnumerable<FileSystemInfo> GetSubtitleFiles(Video video, IDirectoryService directoryService, bool clearCache)
{
var containingPath = video.ContainingFolderPath;
@@ -418,7 +426,7 @@ namespace MediaBrowser.Providers.MediaInfo
throw new ArgumentException(string.Format("Cannot search for items that don't have a path: {0} {1}", video.Name, video.Id));
}
- var files = directoryService.GetFiles(containingPath);
+ var files = directoryService.GetFiles(containingPath, clearCache);
var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
@@ -450,11 +458,44 @@ namespace MediaBrowser.Providers.MediaInfo
/// </summary>
/// <param name="video">The video.</param>
/// <param name="currentStreams">The current streams.</param>
- private void AddExternalSubtitles(Video video, List<MediaStream> currentStreams, IDirectoryService directoryService)
+ private async Task AddExternalSubtitles(Video video, List<MediaStream> currentStreams, IDirectoryService directoryService, CancellationToken cancellationToken)
{
- var files = GetSubtitleFiles(video, directoryService);
+ var externalSubtitleStreams = GetExternalSubtitleStreams(video, currentStreams.Count, directoryService, false).ToList();
+
+ if ((_config.Configuration.SubtitleOptions.DownloadEpisodeSubtitles &&
+ video is Episode) ||
+ (_config.Configuration.SubtitleOptions.DownloadMovieSubtitles &&
+ video is Movie))
+ {
+ var downloadedLanguages = await new SubtitleDownloader(_logger,
+ _subtitleManager)
+ .DownloadSubtitles(video,
+ currentStreams,
+ externalSubtitleStreams,
+ _config.Configuration.SubtitleOptions.SkipIfGraphicalSubtitlesPresent,
+ _config.Configuration.SubtitleOptions.SkipIfAudioTrackMatches,
+ _config.Configuration.SubtitleOptions.DownloadLanguages,
+ cancellationToken).ConfigureAwait(false);
+
+ // Rescan
+ if (downloadedLanguages.Count > 0)
+ {
+ externalSubtitleStreams = GetExternalSubtitleStreams(video, currentStreams.Count, directoryService, true).ToList();
+ }
+ }
+
+ video.SubtitleFiles = externalSubtitleStreams.Select(i => i.Path).OrderBy(i => i).ToList();
+
+ currentStreams.AddRange(externalSubtitleStreams);
+ }
+
+ private IEnumerable<MediaStream> GetExternalSubtitleStreams(Video video,
+ int startIndex,
+ IDirectoryService directoryService,
+ bool clearCache)
+ {
+ var files = GetSubtitleFiles(video, directoryService, clearCache);
- var startIndex = currentStreams.Count;
var streams = new List<MediaStream>();
var videoFileNameWithoutExtension = Path.GetFileNameWithoutExtension(video.Path);
@@ -504,9 +545,7 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
- video.SubtitleFiles = streams.Select(i => i.Path).OrderBy(i => i).ToList();
-
- currentStreams.AddRange(streams);
+ return streams;
}
/// <summary>
@@ -627,7 +666,7 @@ namespace MediaBrowser.Providers.MediaInfo
{
var path = mount == null ? item.Path : mount.MountedPath;
var dvd = new Dvd(path);
-
+
var primaryTitle = dvd.Titles.OrderByDescending(GetRuntime).FirstOrDefault();
byte? titleNumber = null;
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
new file mode 100644
index 000000000..cf14cfadc
--- /dev/null
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
@@ -0,0 +1,160 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Controller.Subtitles;
+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.Providers.MediaInfo
+{
+ public class SubtitleDownloader
+ {
+ private readonly ILogger _logger;
+ private readonly ISubtitleManager _subtitleManager;
+
+ public SubtitleDownloader(ILogger logger, ISubtitleManager subtitleManager)
+ {
+ _logger = logger;
+ _subtitleManager = subtitleManager;
+ }
+
+ public async Task<List<string>> DownloadSubtitles(Video video,
+ List<MediaStream> internalMediaStreams,
+ List<MediaStream> externalSubtitleStreams,
+ bool skipIfGraphicalSubtitlesPresent,
+ bool skipIfAudioTrackMatches,
+ IEnumerable<string> languages,
+ CancellationToken cancellationToken)
+ {
+ if (video.LocationType != LocationType.FileSystem ||
+ video.VideoType != VideoType.VideoFile)
+ {
+ return new List<string>();
+ }
+
+ VideoContentType mediaType;
+
+ if (video is Episode)
+ {
+ mediaType = VideoContentType.Episode;
+ }
+ else if (video is Movie)
+ {
+ mediaType = VideoContentType.Movie;
+ }
+ else
+ {
+ // These are the only supported types
+ return new List<string>();
+ }
+
+ var downloadedLanguages = new List<string>();
+
+ foreach (var lang in languages)
+ {
+ try
+ {
+ var downloaded = await DownloadSubtitles(video, internalMediaStreams, externalSubtitleStreams, skipIfGraphicalSubtitlesPresent, skipIfAudioTrackMatches, lang, mediaType, cancellationToken)
+ .ConfigureAwait(false);
+
+ if (downloaded)
+ {
+ downloadedLanguages.Add(lang);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error downloading subtitles", ex);
+ }
+ }
+
+ return downloadedLanguages;
+ }
+
+ private async Task<bool> DownloadSubtitles(Video video,
+ List<MediaStream> internalMediaStreams,
+ IEnumerable<MediaStream> externalSubtitleStreams,
+ bool skipIfGraphicalSubtitlesPresent,
+ bool skipIfAudioTrackMatches,
+ string language,
+ VideoContentType mediaType,
+ CancellationToken cancellationToken)
+ {
+ // There's already subtitles for this language
+ if (externalSubtitleStreams.Any(i => string.Equals(i.Language, language, StringComparison.OrdinalIgnoreCase)))
+ {
+ return false;
+ }
+
+ var audioStreams = internalMediaStreams.Where(i => i.Type == MediaStreamType.Audio).ToList();
+ var defaultAudioStreams = audioStreams.Where(i => i.IsDefault).ToList();
+
+ // If none are marked as default, just take a guess
+ if (defaultAudioStreams.Count == 0)
+ {
+ defaultAudioStreams = audioStreams.Take(1).ToList();
+ }
+
+ // There's already a default audio stream for this language
+ if (skipIfAudioTrackMatches &&
+ defaultAudioStreams.Any(i => string.Equals(i.Language, language, StringComparison.OrdinalIgnoreCase)))
+ {
+ return false;
+ }
+
+ // There's an internal subtitle stream for this language
+ if (skipIfGraphicalSubtitlesPresent &&
+ internalMediaStreams.Any(i => i.Type == MediaStreamType.Subtitle && i.IsGraphicalSubtitleStream && string.Equals(i.Language, language, StringComparison.OrdinalIgnoreCase)))
+ {
+ return false;
+ }
+
+ var request = new SubtitleSearchRequest
+ {
+ ContentType = mediaType,
+ IndexNumber = video.IndexNumber,
+ Language = language,
+ MediaPath = video.Path,
+ Name = video.Name,
+ ParentIndexNumber = video.ParentIndexNumber,
+ ProductionYear = video.ProductionYear,
+ ProviderIds = video.ProviderIds
+ };
+
+ var episode = video as Episode;
+
+ if (episode != null)
+ {
+ request.IndexNumberEnd = episode.IndexNumberEnd;
+ request.SeriesName = episode.SeriesName;
+ }
+
+ try
+ {
+ var searchResults = await _subtitleManager.SearchSubtitles(request, cancellationToken).ConfigureAwait(false);
+
+ var result = searchResults.FirstOrDefault();
+
+ if (result != null)
+ {
+ await _subtitleManager.DownloadSubtitles(video, result.Id, result.ProviderName, cancellationToken)
+ .ConfigureAwait(false);
+
+ return true;
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error downloading subtitles", ex);
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
index c83e127ae..d812abe9f 100644
--- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs
+++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs
@@ -356,8 +356,6 @@ namespace MediaBrowser.Providers.Movies
await Task.Delay(Convert.ToInt32(diff), cancellationToken).ConfigureAwait(false);
}
- _lastRequestDate = DateTime.Now;
-
return await _httpClient.Get(options).ConfigureAwait(false);
}
finally
diff --git a/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs b/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs
new file mode 100644
index 000000000..297f05867
--- /dev/null
+++ b/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs
@@ -0,0 +1,277 @@
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Providers;
+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;
+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.Subtitles
+{
+ public class OpenSubtitleDownloader : ISubtitleProvider, IDisposable
+ {
+ private readonly ILogger _logger;
+ private readonly IHttpClient _httpClient;
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
+ private readonly IServerConfigurationManager _config;
+ private readonly IEncryptionManager _encryption;
+
+ public OpenSubtitleDownloader(ILogManager logManager, IHttpClient httpClient, IServerConfigurationManager config, IEncryptionManager encryption)
+ {
+ _logger = logManager.GetLogger(GetType().Name);
+ _httpClient = httpClient;
+ _config = config;
+ _encryption = encryption;
+
+ _config.ConfigurationUpdating += _config_ConfigurationUpdating;
+ }
+
+ private const string PasswordHashPrefix = "h:";
+ void _config_ConfigurationUpdating(object sender, GenericEventArgs<ServerConfiguration> e)
+ {
+ var options = e.Argument.SubtitleOptions;
+
+ if (options != null &&
+ !string.IsNullOrWhiteSpace(options.OpenSubtitlesPasswordHash) &&
+ !options.OpenSubtitlesPasswordHash.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase))
+ {
+ options.OpenSubtitlesPasswordHash = EncryptPassword(options.OpenSubtitlesPasswordHash);
+ }
+ }
+
+ private string EncryptPassword(string password)
+ {
+ return PasswordHashPrefix + _encryption.EncryptString(password);
+ }
+
+ private string DecryptPassword(string password)
+ {
+ if (password == null ||
+ !password.StartsWith(PasswordHashPrefix, StringComparison.OrdinalIgnoreCase))
+ {
+ return string.Empty;
+ }
+
+ return _encryption.DecryptString(password.Substring(2));
+ }
+
+ public string Name
+ {
+ get { return "Open Subtitles"; }
+ }
+
+ public IEnumerable<VideoContentType> SupportedMediaTypes
+ {
+ get
+ {
+ if (string.IsNullOrWhiteSpace(_config.Configuration.SubtitleOptions.OpenSubtitlesUsername) ||
+ string.IsNullOrWhiteSpace(_config.Configuration.SubtitleOptions.OpenSubtitlesPasswordHash))
+ {
+ return new VideoContentType[] { };
+ }
+
+ return new[] { VideoContentType.Episode, VideoContentType.Movie };
+ }
+ }
+
+ public Task<SubtitleResponse> GetSubtitles(string id, CancellationToken cancellationToken)
+ {
+ return GetSubtitlesInternal(id, cancellationToken);
+ }
+
+ private async Task<SubtitleResponse> GetSubtitlesInternal(string id,
+ CancellationToken cancellationToken)
+ {
+ if (string.IsNullOrWhiteSpace(id))
+ {
+ throw new ArgumentNullException("id");
+ }
+
+ var idParts = id.Split(new[] { '-' }, 3);
+
+ var format = idParts[0];
+ var language = idParts[1];
+ var ossId = idParts[2];
+
+ var downloadsList = new[] { int.Parse(ossId, _usCulture) };
+
+ await Login(cancellationToken).ConfigureAwait(false);
+
+ var resultDownLoad = await OpenSubtitles.DownloadSubtitlesAsync(downloadsList, cancellationToken).ConfigureAwait(false);
+
+ if (!(resultDownLoad is MethodResponseSubtitleDownload))
+ {
+ throw new ApplicationException("Invalid response type");
+ }
+
+ var results = ((MethodResponseSubtitleDownload)resultDownLoad).Results;
+
+ if (results.Count == 0)
+ {
+ var msg = string.Format("Subtitle with Id {0} was not found. Name: {1}. Status: {2}. Message: {3}",
+ ossId,
+ resultDownLoad.Name ?? string.Empty,
+ resultDownLoad.Message ?? string.Empty,
+ resultDownLoad.Status ?? string.Empty);
+
+ throw new ResourceNotFoundException(msg);
+ }
+
+ var data = Convert.FromBase64String(results.First().Data);
+
+ return new SubtitleResponse
+ {
+ Format = format,
+ Language = language,
+
+ Stream = new MemoryStream(Utilities.Decompress(new MemoryStream(data)))
+ };
+ }
+
+ private DateTime _lastLogin;
+ private async Task Login(CancellationToken cancellationToken)
+ {
+ if ((DateTime.UtcNow - _lastLogin).TotalSeconds < 60)
+ {
+ return;
+ }
+
+ var options = _config.Configuration.SubtitleOptions ?? new SubtitleOptions();
+
+ var user = options.OpenSubtitlesUsername ?? string.Empty;
+ var password = DecryptPassword(options.OpenSubtitlesPasswordHash);
+
+ var loginResponse = await OpenSubtitles.LogInAsync(user, password, "en", cancellationToken).ConfigureAwait(false);
+
+ if (!(loginResponse is MethodResponseLogIn))
+ {
+ throw new UnauthorizedAccessException("Authentication to OpenSubtitles failed.");
+ }
+
+ _lastLogin = DateTime.UtcNow;
+ }
+
+ public async Task<IEnumerable<RemoteSubtitleInfo>> Search(SubtitleSearchRequest request, CancellationToken cancellationToken)
+ {
+ var imdbIdText = request.GetProviderId(MetadataProviders.Imdb);
+ long imdbId = 0;
+
+ switch (request.ContentType)
+ {
+ case VideoContentType.Episode:
+ if (!request.IndexNumber.HasValue || !request.ParentIndexNumber.HasValue || string.IsNullOrEmpty(request.SeriesName))
+ {
+ _logger.Debug("Episode information missing");
+ return new List<RemoteSubtitleInfo>();
+ }
+ break;
+ case VideoContentType.Movie:
+ if (string.IsNullOrEmpty(request.Name))
+ {
+ _logger.Debug("Movie name missing");
+ return new List<RemoteSubtitleInfo>();
+ }
+ if (string.IsNullOrWhiteSpace(imdbIdText) || !long.TryParse(imdbIdText.TrimStart('t'), NumberStyles.Any, _usCulture, out imdbId))
+ {
+ _logger.Debug("Imdb id missing");
+ return new List<RemoteSubtitleInfo>();
+ }
+ break;
+ }
+
+ if (string.IsNullOrEmpty(request.MediaPath))
+ {
+ _logger.Debug("Path Missing");
+ return new List<RemoteSubtitleInfo>();
+ }
+
+ Utilities.HttpClient = _httpClient;
+ OpenSubtitles.SetUserAgent("OS Test User Agent");
+
+ await Login(cancellationToken).ConfigureAwait(false);
+
+ var subLanguageId = request.Language;
+ var hash = Utilities.ComputeHash(request.MediaPath);
+ var fileInfo = new FileInfo(request.MediaPath);
+ var movieByteSize = fileInfo.Length;
+ var searchImdbId = request.ContentType == VideoContentType.Movie ? imdbId.ToString(_usCulture) : "";
+ var subtitleSearchParameters = request.ContentType == VideoContentType.Episode
+ ? new List<SubtitleSearchParameters> {
+ new SubtitleSearchParameters(subLanguageId,
+ query: request.SeriesName,
+ season: request.ParentIndexNumber.Value.ToString(_usCulture),
+ episode: request.IndexNumber.Value.ToString(_usCulture))
+ }
+ : new List<SubtitleSearchParameters> {
+ new SubtitleSearchParameters(subLanguageId, imdbid: searchImdbId),
+ new SubtitleSearchParameters(subLanguageId, query: request.Name, imdbid: searchImdbId)
+ };
+ var parms = new List<SubtitleSearchParameters> {
+ new SubtitleSearchParameters( subLanguageId,
+ movieHash: hash,
+ movieByteSize: movieByteSize,
+ imdbid: searchImdbId ),
+ };
+ parms.AddRange(subtitleSearchParameters);
+ var result = await OpenSubtitles.SearchSubtitlesAsync(parms.ToArray(), cancellationToken).ConfigureAwait(false);
+ if (!(result is MethodResponseSubtitleSearch))
+ {
+ _logger.Debug("Invalid response type");
+ return new List<RemoteSubtitleInfo>();
+ }
+
+ Predicate<SubtitleSearchResult> mediaFilter =
+ x =>
+ request.ContentType == VideoContentType.Episode
+ ? !string.IsNullOrEmpty(x.SeriesSeason) && !string.IsNullOrEmpty(x.SeriesEpisode) &&
+ int.Parse(x.SeriesSeason, _usCulture) == request.ParentIndexNumber &&
+ int.Parse(x.SeriesEpisode, _usCulture) == request.IndexNumber
+ : !string.IsNullOrEmpty(x.IDMovieImdb) && long.Parse(x.IDMovieImdb, _usCulture) == imdbId;
+
+ var results = ((MethodResponseSubtitleSearch)result).Results;
+
+ // Avoid implicitly captured closure
+ var hasCopy = hash;
+
+ return results.Where(x => x.SubBad == "0" && mediaFilter(x))
+ .OrderBy(x => x.MovieHash == hash)
+ .ThenBy(x => Math.Abs(long.Parse(x.MovieByteSize, _usCulture) - movieByteSize))
+ .ThenByDescending(x => int.Parse(x.SubDownloadsCnt, _usCulture))
+ .ThenByDescending(x => double.Parse(x.SubRating, _usCulture))
+ .Select(i => new RemoteSubtitleInfo
+ {
+ Author = i.UserNickName,
+ Comment = i.SubAuthorComment,
+ CommunityRating = float.Parse(i.SubRating, _usCulture),
+ DownloadCount = int.Parse(i.SubDownloadsCnt, _usCulture),
+ Format = i.SubFormat,
+ ProviderName = Name,
+ ThreeLetterISOLanguageName = i.SubLanguageID,
+
+ Id = i.SubFormat + "-" + i.SubLanguageID + "-" + i.IDSubtitleFile,
+
+ Name = i.SubFileName,
+ DateCreated = DateTime.Parse(i.SubAddDate, _usCulture),
+ IsHashMatch = i.MovieHash == hasCopy
+ });
+ }
+
+ public void Dispose()
+ {
+ _config.ConfigurationUpdating -= _config_ConfigurationUpdating;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
new file mode 100644
index 000000000..2d5445653
--- /dev/null
+++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
@@ -0,0 +1,143 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Controller.Subtitles;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+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.Subtitles
+{
+ public class SubtitleManager : ISubtitleManager
+ {
+ private ISubtitleProvider[] _subtitleProviders;
+ private readonly ILogger _logger;
+ private readonly IFileSystem _fileSystem;
+ private readonly ILibraryMonitor _monitor;
+
+ public SubtitleManager(ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor)
+ {
+ _logger = logger;
+ _fileSystem = fileSystem;
+ _monitor = monitor;
+ }
+
+ public void AddParts(IEnumerable<ISubtitleProvider> subtitleProviders)
+ {
+ _subtitleProviders = subtitleProviders.ToArray();
+ }
+
+ public async Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(SubtitleSearchRequest request, CancellationToken cancellationToken)
+ {
+ var providers = _subtitleProviders
+ .Where(i => i.SupportedMediaTypes.Contains(request.ContentType))
+ .ToList();
+
+ var tasks = providers.Select(async i =>
+ {
+ try
+ {
+ return await i.Search(request, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error downloading subtitles from {0}", ex, i.Name);
+ return new List<RemoteSubtitleInfo>();
+ }
+ });
+
+ var results = await Task.WhenAll(tasks).ConfigureAwait(false);
+
+ return results.SelectMany(i => i);
+ }
+
+ public async Task DownloadSubtitles(Video video,
+ string subtitleId,
+ string providerName,
+ CancellationToken cancellationToken)
+ {
+ var provider = _subtitleProviders.First(i => string.Equals(i.Name, providerName, StringComparison.OrdinalIgnoreCase));
+
+ var response = await provider.GetSubtitles(subtitleId, cancellationToken).ConfigureAwait(false);
+
+ using (var stream = response.Stream)
+ {
+ var savePath = Path.Combine(Path.GetDirectoryName(video.Path),
+ Path.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower() + "." + response.Format.ToLower());
+
+ _logger.Info("Saving subtitles to {0}", savePath);
+
+ _monitor.ReportFileSystemChangeBeginning(savePath);
+
+ try
+ {
+ using (var fs = _fileSystem.GetFileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ {
+ await stream.CopyToAsync(fs).ConfigureAwait(false);
+ }
+ }
+ finally
+ {
+ _monitor.ReportFileSystemChangeComplete(savePath, false);
+ }
+ }
+ }
+
+ public Task<IEnumerable<RemoteSubtitleInfo>> SearchSubtitles(Video video, string language, CancellationToken cancellationToken)
+ {
+ if (video.LocationType != LocationType.FileSystem ||
+ video.VideoType != VideoType.VideoFile)
+ {
+ return Task.FromResult<IEnumerable<RemoteSubtitleInfo>>(new List<RemoteSubtitleInfo>());
+ }
+
+ VideoContentType mediaType;
+
+ if (video is Episode)
+ {
+ mediaType = VideoContentType.Episode;
+ }
+ else if (video is Movie)
+ {
+ mediaType = VideoContentType.Movie;
+ }
+ else
+ {
+ // These are the only supported types
+ return Task.FromResult<IEnumerable<RemoteSubtitleInfo>>(new List<RemoteSubtitleInfo>());
+ }
+
+ var request = new SubtitleSearchRequest
+ {
+ ContentType = mediaType,
+ IndexNumber = video.IndexNumber,
+ Language = language,
+ MediaPath = video.Path,
+ Name = video.Name,
+ ParentIndexNumber = video.ParentIndexNumber,
+ ProductionYear = video.ProductionYear,
+ ProviderIds = video.ProviderIds,
+ RuntimeTicks = video.RunTimeTicks
+ };
+
+ var episode = video as Episode;
+
+ if (episode != null)
+ {
+ request.IndexNumberEnd = episode.IndexNumberEnd;
+ request.SeriesName = episode.SeriesName;
+ }
+
+ return SearchSubtitles(request, cancellationToken);
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs b/MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs
index 5a4408f1b..93231e1e3 100644
--- a/MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs
+++ b/MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs
@@ -266,7 +266,7 @@ namespace MediaBrowser.Providers.Xbmc
public string Name
{
- get { return "MB3/Plex/Xbmc Images"; }
+ get { return "Media Browser/Plex/Xbmc Images"; }
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index e028065c3..748bc4b9c 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -11,6 +11,7 @@ using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
+using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
@@ -23,6 +24,7 @@ namespace MediaBrowser.Server.Implementations.Channels
public class ChannelManager : IChannelManager
{
private IChannel[] _channels;
+ private IChannelFactory[] _factories;
private List<Channel> _channelEntities = new List<Channel>();
private readonly IUserManager _userManager;
@@ -32,8 +34,9 @@ namespace MediaBrowser.Server.Implementations.Channels
private readonly ILogger _logger;
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
+ private readonly IJsonSerializer _jsonSerializer;
- public ChannelManager(IUserManager userManager, IDtoService dtoService, ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IUserDataManager userDataManager)
+ public ChannelManager(IUserManager userManager, IDtoService dtoService, ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IUserDataManager userDataManager, IJsonSerializer jsonSerializer)
{
_userManager = userManager;
_dtoService = dtoService;
@@ -42,11 +45,32 @@ namespace MediaBrowser.Server.Implementations.Channels
_config = config;
_fileSystem = fileSystem;
_userDataManager = userDataManager;
+ _jsonSerializer = jsonSerializer;
}
- public void AddParts(IEnumerable<IChannel> channels)
+ public void AddParts(IEnumerable<IChannel> channels, IEnumerable<IChannelFactory> factories)
{
_channels = channels.ToArray();
+ _factories = factories.ToArray();
+ }
+
+ private IEnumerable<IChannel> GetAllChannels()
+ {
+ return _factories
+ .SelectMany(i =>
+ {
+ try
+ {
+ return i.GetChannels().ToList();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error getting channel list", ex);
+ return new List<IChannel>();
+ }
+ })
+ .Concat(_channels)
+ .OrderBy(i => i.Name);
}
public Task<QueryResult<BaseItemDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken)
@@ -82,7 +106,7 @@ namespace MediaBrowser.Server.Implementations.Channels
public async Task RefreshChannels(IProgress<double> progress, CancellationToken cancellationToken)
{
- var allChannelsList = _channels.ToList();
+ var allChannelsList = GetAllChannels().ToList();
var list = new List<Channel>();
@@ -196,47 +220,123 @@ namespace MediaBrowser.Server.Implementations.Channels
? null
: _userManager.GetUserById(new Guid(query.UserId));
- var id = new Guid(query.ChannelId);
- var channel = _channelEntities.First(i => i.Id == id);
- var channelProvider = GetChannelProvider(channel);
+ var queryChannelId = query.ChannelId;
+ var channels = string.IsNullOrWhiteSpace(queryChannelId)
+ ? _channelEntities
+ : _channelEntities.Where(i => i.Id == new Guid(queryChannelId));
+
+ var itemTasks = channels.Select(async channel =>
+ {
+ var channelProvider = GetChannelProvider(channel);
+
+ var items = await GetChannelItems(channelProvider, user, query.CategoryId, cancellationToken)
+ .ConfigureAwait(false);
+
+ var channelId = channel.Id.ToString("N");
+
+ var tasks = items.Select(i => GetChannelItemEntity(i, channelId, cancellationToken));
+
+ return await Task.WhenAll(tasks).ConfigureAwait(false);
+ });
- var items = await GetChannelItems(channelProvider, user, query.CategoryId, cancellationToken)
- .ConfigureAwait(false);
+ var results = await Task.WhenAll(itemTasks).ConfigureAwait(false);
- return await GetReturnItems(items, user, query, cancellationToken).ConfigureAwait(false);
+ return await GetReturnItems(results.SelectMany(i => i), user, query, cancellationToken).ConfigureAwait(false);
}
+ private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1);
private async Task<IEnumerable<ChannelItemInfo>> GetChannelItems(IChannel channel, User user, string categoryId, CancellationToken cancellationToken)
{
- // TODO: Put some caching in here
+ var cachePath = GetChannelDataCachePath(channel, user, categoryId);
- var query = new InternalChannelItemQuery
+ try
{
- User = user,
- CategoryId = categoryId
- };
+ var channelItemResult = _jsonSerializer.DeserializeFromFile<ChannelItemResult>(cachePath);
+
+ if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(channelItemResult.CacheLength) > DateTime.UtcNow)
+ {
+ return channelItemResult.Items;
+ }
+ }
+ catch (FileNotFoundException)
+ {
+
+ }
+ catch (DirectoryNotFoundException)
+ {
+
+ }
+
+ await _resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
- var result = await channel.GetChannelItems(query, cancellationToken).ConfigureAwait(false);
+ try
+ {
+ try
+ {
+ var channelItemResult = _jsonSerializer.DeserializeFromFile<ChannelItemResult>(cachePath);
+
+ if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(channelItemResult.CacheLength) > DateTime.UtcNow)
+ {
+ return channelItemResult.Items;
+ }
+ }
+ catch (FileNotFoundException)
+ {
- return result.Items;
+ }
+ catch (DirectoryNotFoundException)
+ {
+
+ }
+
+ var query = new InternalChannelItemQuery
+ {
+ User = user,
+ CategoryId = categoryId
+ };
+
+ var result = await channel.GetChannelItems(query, cancellationToken).ConfigureAwait(false);
+
+ CacheResponse(result, cachePath);
+
+ return result.Items;
+ }
+ finally
+ {
+ _resourcePool.Release();
+ }
}
- private async Task<QueryResult<BaseItemDto>> GetReturnItems(IEnumerable<ChannelItemInfo> items, User user, ChannelItemQuery query, CancellationToken cancellationToken)
+ private void CacheResponse(ChannelItemResult result, string path)
{
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields))
- .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
- .ToList();
+ try
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
- var tasks = items.Select(i => GetChannelItemEntity(i, cancellationToken));
+ _jsonSerializer.SerializeToFile(result, path);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error writing to channel cache file: {0}", ex, path);
+ }
+ }
- IEnumerable<BaseItem> entities = await Task.WhenAll(tasks).ConfigureAwait(false);
+ private string GetChannelDataCachePath(IChannel channel, User user, string categoryId)
+ {
+ var channelId = GetInternalChannelId(channel.Name).ToString("N");
- entities = ApplyFilters(entities, query.Filters, user);
+ var categoryKey = string.IsNullOrWhiteSpace(categoryId) ? "root" : categoryId.GetMD5().ToString("N");
- entities = _libraryManager.Sort(entities, user, query.SortBy, query.SortOrder ?? SortOrder.Ascending);
+ return Path.Combine(_config.ApplicationPaths.CachePath, "channels", channelId, categoryKey, user.Id.ToString("N") + ".json");
+ }
- var all = entities.ToList();
+ private async Task<QueryResult<BaseItemDto>> GetReturnItems(IEnumerable<BaseItem> items, User user, ChannelItemQuery query, CancellationToken cancellationToken)
+ {
+ items = ApplyFilters(items, query.Filters, user);
+
+ items = _libraryManager.Sort(items, user, query.SortBy, query.SortOrder ?? SortOrder.Ascending);
+
+ var all = items.ToList();
var totalCount = all.Count;
if (query.StartIndex.HasValue)
@@ -250,6 +350,11 @@ namespace MediaBrowser.Server.Implementations.Channels
await RefreshIfNeeded(all, cancellationToken).ConfigureAwait(false);
+ // Get everything
+ var fields = Enum.GetNames(typeof(ItemFields))
+ .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
+ .ToList();
+
var returnItemArray = all.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
.ToArray();
@@ -263,10 +368,10 @@ namespace MediaBrowser.Server.Implementations.Channels
private string GetIdToHash(string externalId)
{
// Increment this as needed to force new downloads
- return externalId + "3";
+ return externalId + "4";
}
- private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info, CancellationToken cancellationToken)
+ private async Task<BaseItem> GetChannelItemEntity(ChannelItemInfo info, string internalChannnelId, CancellationToken cancellationToken)
{
BaseItem item;
Guid id;
@@ -339,6 +444,7 @@ namespace MediaBrowser.Server.Implementations.Channels
channelItem.OriginalImageUrl = info.ImageUrl;
channelItem.ExternalId = info.Id;
+ channelItem.ChannelId = internalChannnelId;
channelItem.ChannelItemType = info.Type;
var channelMediaItem = item as IChannelMediaItem;
@@ -380,7 +486,7 @@ namespace MediaBrowser.Server.Implementations.Channels
internal IChannel GetChannelProvider(Channel channel)
{
- return _channels.First(i => string.Equals(i.Name, channel.OriginalChannelName, StringComparison.OrdinalIgnoreCase));
+ return GetAllChannels().First(i => string.Equals(i.Name, channel.OriginalChannelName, StringComparison.OrdinalIgnoreCase));
}
private IEnumerable<BaseItem> ApplyFilters(IEnumerable<BaseItem> items, IEnumerable<ItemFilter> filters, User user)
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
index 653cbacb6..adcf3edba 100644
--- a/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
+++ b/MediaBrowser.Server.Implementations/Collections/CollectionManager.cs
@@ -93,7 +93,13 @@ namespace MediaBrowser.Server.Implementations.Collections
// Find an actual physical folder
if (folder is CollectionFolder)
{
- return _libraryManager.RootFolder.Children.OfType<Folder>().First(i => folder.PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase));
+ var child = _libraryManager.RootFolder.Children.OfType<Folder>()
+ .FirstOrDefault(i => folder.PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase));
+
+ if (child != null)
+ {
+ return child;
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs b/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs
index 834fbcd31..915a27c11 100644
--- a/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs
+++ b/MediaBrowser.Server.Implementations/Collections/CollectionsDynamicFolder.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities;
using System.IO;
-using System.Linq;
namespace MediaBrowser.Server.Implementations.Collections
{
@@ -26,30 +25,4 @@ namespace MediaBrowser.Server.Implementations.Collections
};
}
}
-
- public class ManualCollectionsFolder : BasePluginFolder
- {
- public ManualCollectionsFolder()
- {
- Name = "Collections";
- }
-
- public override bool IsVisible(User user)
- {
- if (!GetChildren(user, true).Any())
- {
- return false;
- }
-
- return base.IsVisible(user);
- }
-
- public override bool IsHidden
- {
- get
- {
- return !ActualChildren.Any() || base.IsHidden;
- }
- }
- }
}
diff --git a/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
new file mode 100644
index 000000000..e36c63b1c
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Collections/ManualCollectionsFolder.cs
@@ -0,0 +1,31 @@
+using System.Linq;
+using MediaBrowser.Controller.Entities;
+
+namespace MediaBrowser.Server.Implementations.Collections
+{
+ public class ManualCollectionsFolder : BasePluginFolder
+ {
+ public ManualCollectionsFolder()
+ {
+ Name = "Collections";
+ }
+
+ public override bool IsVisible(User user)
+ {
+ if (!GetChildren(user, true).Any())
+ {
+ return false;
+ }
+
+ return base.IsVisible(user);
+ }
+
+ public override bool IsHidden
+ {
+ get
+ {
+ return !ActualChildren.Any() || base.IsHidden;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
index da3861682..59267e856 100644
--- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
+++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
@@ -1,8 +1,10 @@
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Events;
using MediaBrowser.Common.Implementations.Configuration;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System;
@@ -29,6 +31,8 @@ namespace MediaBrowser.Server.Implementations.Configuration
UpdateMetadataPath();
}
+ public event EventHandler<GenericEventArgs<ServerConfiguration>> ConfigurationUpdating;
+
/// <summary>
/// Gets the type of the configuration.
/// </summary>
@@ -73,8 +77,8 @@ namespace MediaBrowser.Server.Implementations.Configuration
/// </summary>
private void UpdateItemsByNamePath()
{
- ((ServerApplicationPaths) ApplicationPaths).ItemsByNamePath = string.IsNullOrEmpty(Configuration.ItemsByNamePath) ?
- null :
+ ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = string.IsNullOrEmpty(Configuration.ItemsByNamePath) ?
+ null :
Configuration.ItemsByNamePath;
}
@@ -105,13 +109,15 @@ namespace MediaBrowser.Server.Implementations.Configuration
/// <exception cref="System.IO.DirectoryNotFoundException"></exception>
public override void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration)
{
- var newConfig = (ServerConfiguration) newConfiguration;
+ var newConfig = (ServerConfiguration)newConfiguration;
ValidateItemByNamePath(newConfig);
ValidateTranscodingTempPath(newConfig);
ValidatePathSubstitutions(newConfig);
ValidateMetadataPath(newConfig);
+ EventHelper.FireEventIfNotNull(ConfigurationUpdating, this, new GenericEventArgs<ServerConfiguration> { Argument = newConfig }, Logger);
+
base.ReplaceConfiguration(newConfiguration);
}
diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
index c6c1ec050..38f812809 100644
--- a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
+++ b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
@@ -649,7 +649,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
/// <param name="image">The image.</param>
/// <returns>Guid.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
- public Guid GetImageCacheTag(IHasImages item, ItemImageInfo image)
+ public string GetImageCacheTag(IHasImages item, ItemImageInfo image)
{
if (item == null)
{
@@ -676,7 +676,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
/// <param name="imageEnhancers">The image enhancers.</param>
/// <returns>Guid.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
- public Guid GetImageCacheTag(IHasImages item, ImageType imageType, string originalImagePath, DateTime dateModified, List<IImageEnhancer> imageEnhancers)
+ public string GetImageCacheTag(IHasImages item, ImageType imageType, string originalImagePath, DateTime dateModified, List<IImageEnhancer> imageEnhancers)
{
if (item == null)
{
@@ -696,14 +696,14 @@ namespace MediaBrowser.Server.Implementations.Drawing
// Optimization
if (imageEnhancers.Count == 0)
{
- return (originalImagePath + dateModified.Ticks).GetMD5();
+ return (originalImagePath + dateModified.Ticks).GetMD5().ToString("N");
}
// Cache name is created with supported enhancers combined with the last config change so we pick up new config changes
var cacheKeys = imageEnhancers.Select(i => i.GetConfigurationCacheKey(item, imageType)).ToList();
cacheKeys.Add(originalImagePath + dateModified.Ticks);
- return string.Join("|", cacheKeys.ToArray()).GetMD5();
+ return string.Join("|", cacheKeys.ToArray()).GetMD5().ToString("N");
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index c88cefdb3..4bcbfaf95 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -326,7 +326,7 @@ namespace MediaBrowser.Server.Implementations.Dto
/// </summary>
/// <param name="item">The item.</param>
/// <returns>List{System.String}.</returns>
- private List<Guid> GetBackdropImageTags(BaseItem item)
+ private List<string> GetBackdropImageTags(BaseItem item)
{
return GetCacheTags(item, ImageType.Backdrop).ToList();
}
@@ -336,26 +336,25 @@ namespace MediaBrowser.Server.Implementations.Dto
/// </summary>
/// <param name="item">The item.</param>
/// <returns>List{Guid}.</returns>
- private List<Guid> GetScreenshotImageTags(BaseItem item)
+ private List<string> GetScreenshotImageTags(BaseItem item)
{
var hasScreenshots = item as IHasScreenshots;
if (hasScreenshots == null)
{
- return new List<Guid>();
+ return new List<string>();
}
return GetCacheTags(item, ImageType.Screenshot).ToList();
}
- private IEnumerable<Guid> GetCacheTags(BaseItem item, ImageType type)
+ private IEnumerable<string> GetCacheTags(BaseItem item, ImageType type)
{
return item.GetImages(type)
.Select(p => GetImageCacheTag(item, p))
- .Where(i => i.HasValue)
- .Select(i => i.Value)
+ .Where(i => i != null)
.ToList();
}
- private Guid? GetImageCacheTag(BaseItem item, ImageType type)
+ private string GetImageCacheTag(BaseItem item, ImageType type)
{
try
{
@@ -368,7 +367,7 @@ namespace MediaBrowser.Server.Implementations.Dto
}
}
- private Guid? GetImageCacheTag(BaseItem item, ItemImageInfo image)
+ private string GetImageCacheTag(BaseItem item, ItemImageInfo image)
{
try
{
@@ -430,6 +429,7 @@ namespace MediaBrowser.Server.Implementations.Dto
if (dictionary.TryGetValue(person.Name, out entity))
{
baseItemPerson.PrimaryImageTag = GetImageCacheTag(entity, ImageType.Primary);
+ baseItemPerson.Id = entity.Id.ToString("N");
}
dto.People[i] = baseItemPerson;
@@ -677,7 +677,7 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.Genres = item.Genres;
}
- dto.ImageTags = new Dictionary<ImageType, Guid>();
+ dto.ImageTags = new Dictionary<ImageType, string>();
// Prevent implicitly captured closure
var currentItem = item;
@@ -685,9 +685,9 @@ namespace MediaBrowser.Server.Implementations.Dto
{
var tag = GetImageCacheTag(item, image);
- if (tag.HasValue)
+ if (tag != null)
{
- dto.ImageTags[image.Type] = tag.Value;
+ dto.ImageTags[image.Type] = tag;
}
}
@@ -1166,7 +1166,7 @@ namespace MediaBrowser.Server.Implementations.Dto
}).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0)
.ThenByDescending(i =>
{
- var stream = i.MediaStreams.FirstOrDefault(m => m.Type == MediaStreamType.Video);
+ var stream = i.VideoStream;
return stream == null || stream.Width == null ? 0 : stream.Width.Value;
})
@@ -1216,7 +1216,7 @@ namespace MediaBrowser.Server.Implementations.Dto
}
}
- var bitrate = i.TotalBitrate ??
+ var bitrate = i.TotalBitrate ??
info.MediaStreams.Where(m => m.Type != MediaStreamType.Subtitle && !string.Equals(m.Codec, "mjpeg", StringComparison.OrdinalIgnoreCase))
.Select(m => m.BitRate ?? 0)
.Sum();
@@ -1420,7 +1420,6 @@ namespace MediaBrowser.Server.Implementations.Dto
/// <returns>Task.</returns>
private void SetSpecialCounts(Folder folder, User user, BaseItemDto dto, List<ItemFields> fields)
{
- var rcentlyAddedItemCount = 0;
var recursiveItemCount = 0;
var unplayed = 0;
long runtime = 0;
@@ -1457,12 +1456,6 @@ namespace MediaBrowser.Server.Implementations.Dto
recursiveItemCount++;
- // Check is recently added
- //if (child.IsRecentlyAdded())
- //{
- // rcentlyAddedItemCount++;
- //}
-
var isUnplayed = true;
// Incrememt totalPercentPlayed
@@ -1491,7 +1484,6 @@ namespace MediaBrowser.Server.Implementations.Dto
}
dto.RecursiveItemCount = recursiveItemCount;
- dto.RecentlyAddedItemCount = rcentlyAddedItemCount;
dto.RecursiveUnplayedItemCount = unplayed;
if (recursiveItemCount > 0)
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
index 59fa78a00..40eeea651 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
@@ -252,15 +252,15 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
return new LibraryUpdateInfo
{
- ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id).Distinct().ToList(),
+ ItemsAdded = itemsAdded.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
- ItemsUpdated = itemsUpdated.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id).Distinct().ToList(),
+ ItemsUpdated = itemsUpdated.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
- ItemsRemoved = itemsRemoved.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren, true)).Select(i => i.Id).Distinct().ToList(),
+ ItemsRemoved = itemsRemoved.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren, true)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
- FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id).Distinct().ToList(),
+ FoldersAddedTo = foldersAddedTo.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id.ToString("N")).Distinct().ToList(),
- FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id).Distinct().ToList()
+ FoldersRemovedFrom = foldersRemovedFrom.SelectMany(i => TranslatePhysicalItemToUserLibrary(i, user, collections, allRecursiveChildren)).Select(i => i.Id.ToString("N")).Distinct().ToList()
};
}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs
index 1e3f8b0b0..242e81d1f 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifier.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs
@@ -1,25 +1,28 @@
-using MediaBrowser.Common.Events;
+using System.Globalization;
+using MediaBrowser.Common.Events;
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;
using MediaBrowser.Model.Notifications;
using MediaBrowser.Model.Tasks;
+using MediaBrowser.Model.Updates;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Model.Updates;
namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
{
@@ -40,6 +43,9 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
private readonly ISessionManager _sessionManager;
private readonly IServerApplicationHost _appHost;
+ 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)
{
_installationManager = installationManager;
@@ -81,7 +87,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
notification.Variables["Version"] = e.Argument.versionStr;
notification.Variables["ReleaseNotes"] = e.Argument.description;
-
+
await SendNotification(notification).ConfigureAwait(false);
}
@@ -134,7 +140,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
var notification = new NotificationRequest
{
- Description = "Please see mediabrowser3.com for details.",
+ Description = "Please see mediabrowser.tv for details.",
NotificationType = type
};
@@ -164,7 +170,13 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
var item = e.MediaInfo;
- if (e.Item !=null && e.Item.Parent == null)
+ if (item == null)
+ {
+ _logger.Warn("PlaybackStart reported with null media info.");
+ return;
+ }
+
+ if (e.Item != null && e.Item.Parent == null)
{
// Don't report theme song or local trailer playback
// TODO: This will also cause movie specials to not be reported
@@ -185,7 +197,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
await SendNotification(notification).ConfigureAwait(false);
}
-
+
private string GetPlaybackNotificationType(string mediaType)
{
if (string.Equals(mediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase))
@@ -204,23 +216,88 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
return null;
}
- async void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
+ private readonly List<BaseItem> _itemsAdded = new List<BaseItem>();
+ void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
{
- if (e.Item.LocationType == LocationType.FileSystem)
+ if (e.Item.LocationType == LocationType.FileSystem && !e.Item.IsFolder)
{
- var type = NotificationType.NewLibraryContent.ToString();
+ lock (_libraryChangedSyncLock)
+ {
+ if (LibraryUpdateTimer == null)
+ {
+ LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, 5000,
+ Timeout.Infinite);
+ }
+ else
+ {
+ LibraryUpdateTimer.Change(5000, Timeout.Infinite);
+ }
+
+ _itemsAdded.Add(e.Item);
+ }
+ }
+ }
- var item = e.Item;
+ private async void LibraryUpdateTimerCallback(object state)
+ {
+ List<BaseItem> items;
+
+ lock (_libraryChangedSyncLock)
+ {
+ items = _itemsAdded.ToList();
+ _itemsAdded.Clear();
+ DisposeLibraryUpdateTimer();
+ }
+
+ if (items.Count == 1)
+ {
+ var item = items.First();
var notification = new NotificationRequest
{
- NotificationType = type
+ NotificationType = NotificationType.NewLibraryContent.ToString()
};
- notification.Variables["Name"] = item.Name;
-
+ notification.Variables["Name"] = GetItemName(item);
+
await SendNotification(notification).ConfigureAwait(false);
}
+ else
+ {
+ var notification = new NotificationRequest
+ {
+ NotificationType = NotificationType.NewLibraryContentMultiple.ToString()
+ };
+
+ notification.Variables["ItemCount"] = items.Count.ToString(CultureInfo.InvariantCulture);
+
+ await SendNotification(notification).ConfigureAwait(false);
+ }
+ }
+
+ private string GetItemName(BaseItem item)
+ {
+ var name = item.Name;
+
+ var hasSeries = item as IHasSeries;
+
+ if (hasSeries != null)
+ {
+ name = hasSeries.SeriesName + " - " + name;
+ }
+
+ var hasArtist = item as IHasArtist;
+ if (hasArtist != null)
+ {
+ var artists = hasArtist.AllArtists;
+
+ if (artists.Count > 0)
+ {
+ name = hasArtist.AllArtists[0] + " - " + name;
+ }
+ }
+
+ return name;
}
async void _userManager_UserCreated(object sender, GenericEventArgs<User> e)
@@ -235,9 +312,9 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
await SendNotification(notification).ConfigureAwait(false);
}
- async void _taskManager_TaskCompleted(object sender, GenericEventArgs<TaskResult> e)
+ async void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e)
{
- var result = e.Argument;
+ var result = e.Result;
if (result.Status == TaskCompletionStatus.Failed)
{
@@ -250,8 +327,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
NotificationType = type
};
- notification.Variables["Name"] = e.Argument.Name;
- notification.Variables["ErrorMessage"] = e.Argument.ErrorMessage;
+ notification.Variables["Name"] = result.Name;
+ notification.Variables["ErrorMessage"] = result.ErrorMessage;
await SendNotification(notification).ConfigureAwait(false);
}
@@ -260,7 +337,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
async void _installationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
{
var type = NotificationType.PluginUninstalled.ToString();
-
+
var plugin = e.Argument;
var notification = new NotificationRequest
@@ -270,7 +347,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
notification.Variables["Name"] = plugin.Name;
notification.Variables["Version"] = plugin.Version.ToString();
-
+
await SendNotification(notification).ConfigureAwait(false);
}
@@ -307,6 +384,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
public void Dispose()
{
+ DisposeLibraryUpdateTimer();
+
_installationManager.PluginInstalled -= _installationManager_PluginInstalled;
_installationManager.PluginUpdated -= _installationManager_PluginUpdated;
_installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed;
@@ -322,5 +401,14 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
_appHost.HasUpdateAvailableChanged -= _appHost_HasUpdateAvailableChanged;
_appHost.ApplicationUpdated -= _appHost_ApplicationUpdated;
}
+
+ private void DisposeLibraryUpdateTimer()
+ {
+ if (LibraryUpdateTimer != null)
+ {
+ LibraryUpdateTimer.Dispose();
+ LibraryUpdateTimer = null;
+ }
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs
index 0925ca86c..d6ad7771b 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/ServerEventNotifier.cs
@@ -1,5 +1,4 @@
-using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Net;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Common.Updates;
@@ -9,6 +8,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Tasks;
using System;
using System.Threading;
@@ -53,8 +53,12 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// Initializes a new instance of the <see cref="ServerEventNotifier" /> class.
/// </summary>
/// <param name="serverManager">The server manager.</param>
- /// <param name="logger">The logger.</param>
+ /// <param name="appHost">The application host.</param>
/// <param name="userManager">The user manager.</param>
+ /// <param name="installationManager">The installation manager.</param>
+ /// <param name="taskManager">The task manager.</param>
+ /// <param name="dtoService">The dto service.</param>
+ /// <param name="sessionManager">The session manager.</param>
public ServerEventNotifier(IServerManager serverManager, IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, IDtoService dtoService, ISessionManager sessionManager)
{
_serverManager = serverManager;
@@ -79,7 +83,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
_installationManager.PackageInstallationCompleted += _installationManager_PackageInstallationCompleted;
_installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed;
- _taskManager.TaskExecuting += _taskManager_TaskExecuting;
_taskManager.TaskCompleted += _taskManager_TaskCompleted;
}
@@ -103,15 +106,9 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
_serverManager.SendWebSocketMessage("PackageInstallationFailed", e.InstallationInfo);
}
- void _taskManager_TaskCompleted(object sender, GenericEventArgs<TaskResult> e)
+ void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e)
{
- _serverManager.SendWebSocketMessage("ScheduledTaskEnded", e.Argument);
- }
-
- void _taskManager_TaskExecuting(object sender, EventArgs e)
- {
- var task = (IScheduledTask)sender;
- _serverManager.SendWebSocketMessage("ScheduledTaskStarted", task.Name);
+ _serverManager.SendWebSocketMessage("ScheduledTaskEnded", e.Result);
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/HttpServer/DelReceiveWebRequest.cs b/MediaBrowser.Server.Implementations/HttpServer/DelReceiveWebRequest.cs
new file mode 100644
index 000000000..235910fed
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/DelReceiveWebRequest.cs
@@ -0,0 +1,6 @@
+using System.Net;
+
+namespace MediaBrowser.Server.Implementations.HttpServer
+{
+ public delegate void DelReceiveWebRequest(HttpListenerContext context);
+} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/HttpServer/GetSwaggerResource.cs b/MediaBrowser.Server.Implementations/HttpServer/GetSwaggerResource.cs
new file mode 100644
index 000000000..36a257f63
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/GetSwaggerResource.cs
@@ -0,0 +1,17 @@
+using ServiceStack;
+
+namespace MediaBrowser.Server.Implementations.HttpServer
+{
+ /// <summary>
+ /// Class GetDashboardResource
+ /// </summary>
+ [Route("/swagger-ui/{ResourceName*}", "GET")]
+ public class GetSwaggerResource
+ {
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string ResourceName { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
index cfe5ef4f0..0fc9265f6 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -25,8 +25,6 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.HttpServer
{
- public delegate void DelReceiveWebRequest(HttpListenerContext context);
-
public class HttpListenerHost : ServiceStackHost, IHttpServer
{
private string ServerName { get; set; }
diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerLogFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerLogFactory.cs
new file mode 100644
index 000000000..40af3f3b0
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/HttpServer/ServerLogFactory.cs
@@ -0,0 +1,46 @@
+using System;
+using MediaBrowser.Model.Logging;
+using ServiceStack.Logging;
+
+namespace MediaBrowser.Server.Implementations.HttpServer
+{
+ /// <summary>
+ /// Class ServerLogFactory
+ /// </summary>
+ public class ServerLogFactory : ILogFactory
+ {
+ /// <summary>
+ /// The _log manager
+ /// </summary>
+ private readonly ILogManager _logManager;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ServerLogFactory"/> class.
+ /// </summary>
+ /// <param name="logManager">The log manager.</param>
+ public ServerLogFactory(ILogManager logManager)
+ {
+ _logManager = logManager;
+ }
+
+ /// <summary>
+ /// Gets the logger.
+ /// </summary>
+ /// <param name="typeName">Name of the type.</param>
+ /// <returns>ILog.</returns>
+ public ILog GetLogger(string typeName)
+ {
+ return new ServerLogger(_logManager.GetLogger(typeName));
+ }
+
+ /// <summary>
+ /// Gets the logger.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ /// <returns>ILog.</returns>
+ public ILog GetLogger(Type type)
+ {
+ return GetLogger(type.Name);
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs b/MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs
index 011e64df2..bf7924784 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/ServerLogger.cs
@@ -5,46 +5,6 @@ using System;
namespace MediaBrowser.Server.Implementations.HttpServer
{
/// <summary>
- /// Class ServerLogFactory
- /// </summary>
- public class ServerLogFactory : ILogFactory
- {
- /// <summary>
- /// The _log manager
- /// </summary>
- private readonly ILogManager _logManager;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ServerLogFactory"/> class.
- /// </summary>
- /// <param name="logManager">The log manager.</param>
- public ServerLogFactory(ILogManager logManager)
- {
- _logManager = logManager;
- }
-
- /// <summary>
- /// Gets the logger.
- /// </summary>
- /// <param name="typeName">Name of the type.</param>
- /// <returns>ILog.</returns>
- public ILog GetLogger(string typeName)
- {
- return new ServerLogger(_logManager.GetLogger(typeName));
- }
-
- /// <summary>
- /// Gets the logger.
- /// </summary>
- /// <param name="type">The type.</param>
- /// <returns>ILog.</returns>
- public ILog GetLogger(Type type)
- {
- return GetLogger(type.Name);
- }
- }
-
- /// <summary>
/// Class ServerLogger
/// </summary>
public class ServerLogger : ILog
@@ -206,7 +166,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="message">The message.</param>
public void Warn(object message)
{
- _logger.Warn(GetMesssage(message));
+ // Hide StringMapTypeDeserializer messages
+ // _logger.Warn(GetMesssage(message));
}
/// <summary>
@@ -216,7 +177,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <param name="args">The args.</param>
public void WarnFormat(string format, params object[] args)
{
- _logger.Warn(format, args);
+ // Hide StringMapTypeDeserializer messages
+ // _logger.Warn(format, args);
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SwaggerService.cs b/MediaBrowser.Server.Implementations/HttpServer/SwaggerService.cs
index 8f8505933..3764697f1 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/SwaggerService.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/SwaggerService.cs
@@ -1,24 +1,10 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Net;
-using ServiceStack;
using ServiceStack.Web;
using System.IO;
namespace MediaBrowser.Server.Implementations.HttpServer
{
- /// <summary>
- /// Class GetDashboardResource
- /// </summary>
- [Route("/swagger-ui/{ResourceName*}", "GET")]
- public class GetSwaggerResource
- {
- /// <summary>
- /// Gets or sets the name.
- /// </summary>
- /// <value>The name.</value>
- public string ResourceName { get; set; }
- }
-
public class SwaggerService : IHasResultFactory, IRestfulService
{
private readonly IApplicationPaths _appPaths;
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/BaseItemResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/ItemResolver.cs
index a03eda263..a03eda263 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/BaseItemResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/ItemResolver.cs
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
index 558087a25..905e6e676 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
@@ -381,7 +381,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
{
firstMovie.IsMultiPart = true;
- _logger.Info("Multi-part video found: " + firstMovie.Path);
+ _logger.Debug("Multi-part video found: " + firstMovie.Path);
return firstMovie;
}
@@ -411,7 +411,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
{
firstMovie.HasLocalAlternateVersions = true;
- _logger.Info("Multi-version video found: " + firstMovie.Path);
+ _logger.Debug("Multi-version video found: " + firstMovie.Path);
return firstMovie;
}
diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs
index 2ee843f09..23303c41f 100644
--- a/MediaBrowser.Server.Implementations/Library/UserManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/BoxSetPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/BoxSetPostScanTask.cs
index f02c907c6..86d88f7e0 100644
--- a/MediaBrowser.Server.Implementations/Library/Validators/BoxSetPostScanTask.cs
+++ b/MediaBrowser.Server.Implementations/Library/Validators/BoxSetPostScanTask.cs
@@ -27,7 +27,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
foreach (var boxset in boxsets)
{
- foreach (var child in boxset.GetLinkedChildren().OfType<ISupportsBoxSetGrouping>())
+ foreach (var child in boxset.Children.Concat(boxset.GetLinkedChildren()).OfType<ISupportsBoxSetGrouping>())
{
var boxsetIdList = child.BoxSetIdList.ToList();
if (!boxsetIdList.Contains(boxset.Id))
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/CountHelpers.cs b/MediaBrowser.Server.Implementations/Library/Validators/CountHelpers.cs
deleted file mode 100644
index edb4e7382..000000000
--- a/MediaBrowser.Server.Implementations/Library/Validators/CountHelpers.cs
+++ /dev/null
@@ -1,171 +0,0 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Model.Dto;
-using System;
-using System.Collections.Generic;
-
-namespace MediaBrowser.Server.Implementations.Library.Validators
-{
- /// <summary>
- /// Class CountHelpers
- /// </summary>
- internal static class CountHelpers
- {
- private static CountType? GetCountType(BaseItem item)
- {
- if (item is Movie)
- {
- return CountType.Movie;
- }
- if (item is Episode)
- {
- return CountType.Episode;
- }
- if (item is Game)
- {
- return CountType.Game;
- }
- if (item is Audio)
- {
- return CountType.Song;
- }
- if (item is Trailer)
- {
- return CountType.Trailer;
- }
- if (item is Series)
- {
- return CountType.Series;
- }
- if (item is MusicAlbum)
- {
- return CountType.MusicAlbum;
- }
- if (item is MusicVideo)
- {
- return CountType.MusicVideo;
- }
- if (item is AdultVideo)
- {
- return CountType.AdultVideo;
- }
-
- return null;
- }
-
- /// <summary>
- /// Increments the count.
- /// </summary>
- /// <param name="counts">The counts.</param>
- /// <param name="key">The key.</param>
- internal static void IncrementCount(Dictionary<CountType, int> counts, CountType key)
- {
- int count;
-
- if (counts.TryGetValue(key, out count))
- {
- count++;
- counts[key] = count;
- }
- else
- {
- counts.Add(key, 1);
- }
- }
-
- /// <summary>
- /// Gets the counts.
- /// </summary>
- /// <param name="counts">The counts.</param>
- /// <returns>ItemByNameCounts.</returns>
- internal static ItemByNameCounts GetCounts(Dictionary<CountType, int> counts)
- {
- return new ItemByNameCounts
- {
- AdultVideoCount = GetCount(counts, CountType.AdultVideo),
- AlbumCount = GetCount(counts, CountType.MusicAlbum),
- EpisodeCount = GetCount(counts, CountType.Episode),
- GameCount = GetCount(counts, CountType.Game),
- MovieCount = GetCount(counts, CountType.Movie),
- MusicVideoCount = GetCount(counts, CountType.MusicVideo),
- SeriesCount = GetCount(counts, CountType.Series),
- SongCount = GetCount(counts, CountType.Song),
- TrailerCount = GetCount(counts, CountType.Trailer),
- TotalCount = GetCount(counts, CountType.Total)
- };
- }
-
- /// <summary>
- /// Gets the count.
- /// </summary>
- /// <param name="counts">The counts.</param>
- /// <param name="key">The key.</param>
- /// <returns>System.Int32.</returns>
- internal static int GetCount(Dictionary<CountType, int> counts, CountType key)
- {
- int count;
-
- if (counts.TryGetValue(key, out count))
- {
- return count;
- }
-
- return 0;
- }
-
- /// <summary>
- /// Sets the item counts.
- /// </summary>
- /// <param name="userId">The user id.</param>
- /// <param name="media">The media.</param>
- /// <param name="names">The names.</param>
- /// <param name="masterDictionary">The master dictionary.</param>
- internal static void SetItemCounts(Guid userId, BaseItem media, IEnumerable<string> names, Dictionary<string, Dictionary<Guid, Dictionary<CountType, int>>> masterDictionary)
- {
- var countType = GetCountType(media);
-
- foreach (var name in names)
- {
- Dictionary<Guid, Dictionary<CountType, int>> libraryCounts;
-
- if (!masterDictionary.TryGetValue(name, out libraryCounts))
- {
- libraryCounts = new Dictionary<Guid, Dictionary<CountType, int>>();
- masterDictionary.Add(name, libraryCounts);
- }
-
- var userLibId = userId/* ?? Guid.Empty*/;
- Dictionary<CountType, int> userDictionary;
-
- if (!libraryCounts.TryGetValue(userLibId, out userDictionary))
- {
- userDictionary = new Dictionary<CountType, int>();
- libraryCounts.Add(userLibId, userDictionary);
- }
-
- if (countType.HasValue)
- {
- IncrementCount(userDictionary, countType.Value);
- }
-
- IncrementCount(userDictionary, CountType.Total);
- }
- }
- }
-
- internal enum CountType
- {
- AdultVideo,
- MusicAlbum,
- Episode,
- Game,
- Movie,
- MusicVideo,
- Series,
- Song,
- Trailer,
- Total
- }
-}
diff --git a/MediaBrowser.Server.Implementations/Library/Validators/PeoplePostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/PeoplePostScanTask.cs
deleted file mode 100644
index d11e62a1a..000000000
--- a/MediaBrowser.Server.Implementations/Library/Validators/PeoplePostScanTask.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Logging;
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Server.Implementations.Library.Validators
-{
- class PeoplePostScanTask : ILibraryPostScanTask
- {
- /// <summary>
- /// The _library manager
- /// </summary>
- private readonly ILibraryManager _libraryManager;
-
- /// <summary>
- /// The _logger
- /// </summary>
- private readonly ILogger _logger;
-
- public PeoplePostScanTask(ILibraryManager libraryManager, ILogger logger)
- {
- _libraryManager = libraryManager;
- _logger = logger;
- }
-
- /// <summary>
- /// Runs the specified progress.
- /// </summary>
- /// <param name="progress">The progress.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
- {
- return new PeopleValidator(_libraryManager, _logger).ValidatePeople(cancellationToken, new MetadataRefreshOptions
- {
- ImageRefreshMode = ImageRefreshMode.ValidationOnly,
- MetadataRefreshMode = MetadataRefreshMode.None
-
- }, progress);
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
index cf7358cce..7bf484689 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs
@@ -241,9 +241,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var imageTag = GetImageTag(recording);
- if (imageTag.HasValue)
+ if (imageTag != null)
{
- dto.ImageTags[ImageType.Primary] = imageTag.Value;
+ dto.ImageTags[ImageType.Primary] = imageTag;
}
if (user != null)
@@ -328,9 +328,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var imageTag = GetImageTag(info);
- if (imageTag.HasValue)
+ if (imageTag != null)
{
- dto.ImageTags[ImageType.Primary] = imageTag.Value;
+ dto.ImageTags[ImageType.Primary] = imageTag;
}
if (currentProgram != null)
@@ -389,9 +389,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var imageTag = GetImageTag(item);
- if (imageTag.HasValue)
+ if (imageTag != null)
{
- dto.ImageTags[ImageType.Primary] = imageTag.Value;
+ dto.ImageTags[ImageType.Primary] = imageTag;
}
if (user != null)
@@ -404,7 +404,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
return dto;
}
- private Guid? GetImageTag(IHasImages info)
+ private string GetImageTag(IHasImages info)
{
try
{
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json
new file mode 100644
index 000000000..fee6f74a6
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json
@@ -0,0 +1,30 @@
+{
+ "SettingsSaved": "Indstillinger er gemt",
+ "AddUser": "Tilf\u00f8j bruger",
+ "Users": "Brugere",
+ "Delete": "Slet",
+ "Administrator": "Administrator",
+ "Password": "Kode",
+ "DeleteImage": "Slet Image",
+ "DeleteImageConfirmation": "Er du sikker p\u00e5 du vil slette dette image?",
+ "FileReadCancelled": "The file read has been canceled.",
+ "FileNotFound": "Filen blev ikke fundet",
+ "FileReadError": "An error occurred while reading the file.",
+ "DeleteUser": "Slet bruger",
+ "DeleteUserConfirmation": "Er du sikker p\u00e5 du \u00f8nsker at slette {0}?",
+ "PasswordResetHeader": "Nulstil kode",
+ "PasswordResetComplete": "Koden er blevet nulstillet",
+ "PasswordResetConfirmation": "Er du sikker p\u00e5 at koden skal nulstilles",
+ "PasswordSaved": "Koden er gemt",
+ "PasswordMatchError": "Password and password confirmation must match.",
+ "OptionOff": "Off",
+ "OptionOn": "On",
+ "OptionRelease": "Official Release",
+ "OptionBeta": "Beta",
+ "OptionDev": "Dev (Ustabil)",
+ "UninstallPluginHeader": "Afinstaller plugin",
+ "UninstallPluginConfirmation": "Are you sure you wish to uninstall {0}?",
+ "NoPluginConfigurationMessage": "Der er igenting at konfigurere i dette plugin.",
+ "NoPluginsInstalledMessage": "Der er ikke installeret nogle plugins",
+ "BrowsePluginCatalogMessage": "Browse our plugin catalog to view available plugins."
+} \ 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 c464b2534..52ddcd795 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
@@ -17,8 +17,6 @@
"PasswordResetConfirmation": "Are you sure you wish to reset the password?",
"PasswordSaved": "Password saved.",
"PasswordMatchError": "Password and password confirmation must match.",
- "OptionOff": "Off",
- "OptionOn": "On",
"OptionRelease": "Official Release",
"OptionBeta": "Beta",
"OptionDev": "Dev (Unstable)",
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json
index f3d4d88f8..86ffe5863 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json
@@ -26,5 +26,5 @@
"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": "\u0414\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043d\u0435\u0447\u0435\u0433\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c.",
"NoPluginsInstalledMessage": "\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 \u043d\u0430\u0448 \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."
+ "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."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
index 629d21df6..1888d14fd 100644
--- a/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
+++ b/MediaBrowser.Server.Implementations/Localization/LocalizationManager.cs
@@ -5,7 +5,6 @@ using MediaBrowser.Controller.Localization;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Serialization;
-using MoreLinq;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -106,16 +105,13 @@ namespace MediaBrowser.Server.Implementations.Localization
/// <returns>IEnumerable{CultureDto}.</returns>
public IEnumerable<CultureDto> GetCultures()
{
- return CultureInfo.GetCultures(CultureTypes.AllCultures)
- .OrderBy(c => c.DisplayName)
- .DistinctBy(c => c.TwoLetterISOLanguageName + c.ThreeLetterISOLanguageName)
- .Select(c => new CultureDto
- {
- Name = c.Name,
- DisplayName = c.DisplayName,
- ThreeLetterISOLanguageName = c.ThreeLetterISOLanguageName,
- TwoLetterISOLanguageName = c.TwoLetterISOLanguageName
- });
+ var type = GetType();
+ var path = type.Namespace + ".cultures.json";
+
+ using (var stream = type.Assembly.GetManifestResourceStream(path))
+ {
+ return _jsonSerializer.DeserializeFromStream<List<CultureDto>>(stream);
+ }
}
/// <summary>
@@ -124,28 +120,13 @@ namespace MediaBrowser.Server.Implementations.Localization
/// <returns>IEnumerable{CountryInfo}.</returns>
public IEnumerable<CountryInfo> GetCountries()
{
- return CultureInfo.GetCultures(CultureTypes.SpecificCultures)
- .Select(c =>
- {
- try
- {
- return new RegionInfo(c.LCID);
- }
- catch (CultureNotFoundException)
- {
- return null;
- }
- })
- .Where(i => i != null)
- .OrderBy(c => c.DisplayName)
- .DistinctBy(c => c.TwoLetterISORegionName)
- .Select(c => new CountryInfo
- {
- Name = c.Name,
- DisplayName = c.DisplayName,
- TwoLetterISORegionName = c.TwoLetterISORegionName,
- ThreeLetterISORegionName = c.ThreeLetterISORegionName
- });
+ var type = GetType();
+ var path = type.Namespace + ".countries.json";
+
+ using (var stream = type.Assembly.GetManifestResourceStream(path))
+ {
+ return _jsonSerializer.DeserializeFromStream<List<CountryInfo>>(stream);
+ }
}
/// <summary>
@@ -350,6 +331,7 @@ namespace MediaBrowser.Server.Implementations.Localization
new LocalizatonOption{ Name="Catalan", Value="ca"},
new LocalizatonOption{ Name="Chinese Traditional", Value="zh-TW"},
new LocalizatonOption{ Name="Czech", Value="cs"},
+ new LocalizatonOption{ Name="Danish", Value="da"},
new LocalizatonOption{ Name="Dutch", Value="nl"},
new LocalizatonOption{ Name="French", Value="fr"},
new LocalizatonOption{ Name="German", Value="de"},
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ar.json b/MediaBrowser.Server.Implementations/Localization/Server/ar.json
index 5372bdfe4..2bf2edeb2 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ar.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ar.json
@@ -76,6 +76,7 @@
"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:",
"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": "\u0627\u0632\u0627\u0644\u0629 \u0635\u0648\u0631\u0629",
"LabelSelectUsers": "Select users:",
"ButtonUpload": "\u062a\u062d\u0645\u064a\u0644",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Scheduled Tasks",
"TabMyPlugins": "My Plugins",
"TabCatalog": "Catalog",
- "TabUpdates": "Updates",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Automatic Updates",
- "HeaderUpdateLevel": "Update Level",
"HeaderNowPlaying": "Now Playing",
"HeaderLatestAlbums": "Latest Albums",
"HeaderLatestSongs": "Latest Songs",
@@ -267,7 +266,7 @@
"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 language:",
+ "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.",
@@ -515,7 +514,7 @@
"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": "Down mix audio boost scale:",
+ "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",
@@ -565,6 +564,7 @@
"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",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Plugin failure",
"ButtonVolumeUp": "Volume up",
"ButtonVolumeDown": "Volume down",
- "ButtonMute": "Mute"
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 657c3ca42..59649d7ca 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ca.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ca.json
@@ -22,9 +22,9 @@
"MoreUsersCanBeAddedLater": "M\u00e9s usuaris es poden afegir m\u00e9s tard en el tauler d'instruments.",
"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.",
"LabelWindowsService": "Servei de Windows",
- "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.",
+ "AWindowsServiceHasBeenInstalled": "El servei de Windows s'ha instal \u00b7 lat.",
+ "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.",
+ "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.",
"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",
@@ -76,6 +76,7 @@
"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",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Scheduled Tasks",
"TabMyPlugins": "My Plugins",
"TabCatalog": "Catalog",
- "TabUpdates": "Updates",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Automatic Updates",
- "HeaderUpdateLevel": "Update Level",
"HeaderNowPlaying": "Now Playing",
"HeaderLatestAlbums": "Latest Albums",
"HeaderLatestSongs": "Latest Songs",
@@ -267,7 +266,7 @@
"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 language:",
+ "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.",
@@ -515,7 +514,7 @@
"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": "Down mix audio boost scale:",
+ "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",
@@ -565,6 +564,7 @@
"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",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Plugin failure",
"ButtonVolumeUp": "Volume up",
"ButtonVolumeDown": "Volume down",
- "ButtonMute": "Mute"
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 5d75c1d46..59a02e6ec 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/cs.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/cs.json
@@ -16,7 +16,7 @@
"LabelYoureDone": "Hotovo!",
"WelcomeToMediaBrowser": "V\u00edtejte v programu Media Browser!",
"TitleMediaBrowser": "Media Browser",
- "ThisWizardWillGuideYou": "Tento pr\u016fvodce V\u00e1m pom\u016f\u017ee proj\u00edt procesem nastaven\u00ed.",
+ "ThisWizardWillGuideYou": "Tento pr\u016fvodce V\u00e1m pom\u016f\u017ee proj\u00edt procesem nastaven\u00ed. Pro za\u010d\u00e1tek vyberte jazyk.",
"TellUsAboutYourself": "\u0158ekn\u011bte n\u00e1m n\u011bco o sob\u011b",
"LabelYourFirstName": "Va\u0161e k\u0159estn\u00ed jm\u00e9no:",
"MoreUsersCanBeAddedLater": "Dal\u0161\u00ed u\u017eivatele m\u016f\u017eete p\u0159idat pozd\u011bji na n\u00e1st\u011bnce.",
@@ -76,6 +76,7 @@
"LabelMaxParentalRating": "Maxim\u00e1ln\u00ed povolen\u00e9 rodi\u010dovsk\u00e9 hodnocen\u00ed:",
"MaxParentalRatingHelp": "Obsah s vy\u0161\u0161\u00edm hodnocen\u00edm bude tomuto u\u017eivateli blokov\u00e1n.",
"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.",
+ "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
"ButtonDeleteImage": "Odstranit obr\u00e1zek",
"LabelSelectUsers": "Select users:",
"ButtonUpload": "Nahr\u00e1t",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Rozvrh \u00faloh",
"TabMyPlugins": "Moje pluginy",
"TabCatalog": "Katalog",
- "TabUpdates": "Aktualizace",
"PluginsTitle": "Pluginy",
"HeaderAutomaticUpdates": "Automatick\u00e9 aktualizace",
- "HeaderUpdateLevel": "Level aktualizace",
"HeaderNowPlaying": "Pr\u00e1v\u011b hraje",
"HeaderLatestAlbums": "Posledn\u00ed alba",
"HeaderLatestSongs": "Posledn\u00ed skladby",
@@ -278,7 +277,7 @@
"HeaderPleaseSignIn": "Pros\u00edme, p\u0159ihlaste se",
"LabelUser": "U\u017eivatel:",
"LabelPassword": "Heslo:",
- "ButtonManualLogin": "Manu\u00e1ln\u00ed p\u0159ihl\u00e1\u0161en\u00ed:",
+ "ButtonManualLogin": "Manu\u00e1ln\u00ed p\u0159ihl\u00e1\u0161en\u00ed",
"PasswordLocalhostMessage": "Heslo nen\u00ed nutn\u00e9, pokud se p\u0159ihla\u0161ujete z m\u00edstn\u00edho PC-",
"TabGuide": "Pr\u016fvodce",
"TabChannels": "Kan\u00e1ly",
@@ -515,7 +514,7 @@
"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": "Down mix audio boost scale:",
+ "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",
@@ -565,6 +564,7 @@
"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",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Plugin failure",
"ButtonVolumeUp": "Volume up",
"ButtonVolumeDown": "Volume down",
- "ButtonMute": "Mute"
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/da.json b/MediaBrowser.Server.Implementations/Localization/Server/da.json
new file mode 100644
index 000000000..0f782994f
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Localization/Server/da.json
@@ -0,0 +1,715 @@
+{
+ "LabelExit": "Exit",
+ "LabelVisitCommunity": "Visit Community",
+ "LabelGithubWiki": "Github Wiki",
+ "LabelSwagger": "Swagger",
+ "LabelStandard": "Standard",
+ "LabelViewApiDocumentation": "Se Api dokumentation",
+ "LabelBrowseLibrary": "Gennemse biblitek",
+ "LabelConfigureMediaBrowser": "Konfigurere Media Browser",
+ "LabelOpenLibraryViewer": "Open Library Viewer",
+ "LabelRestartServer": "Genstart Server",
+ "LabelShowLogWindow": "Show Log Window",
+ "LabelPrevious": "Tidligere",
+ "LabelFinish": "Slut",
+ "LabelNext": "N\u00e6ste",
+ "LabelYoureDone": "Du er f\u00e6rdig!",
+ "WelcomeToMediaBrowser": "Welcome to Media Browser!",
+ "TitleMediaBrowser": "Media Browser",
+ "ThisWizardWillGuideYou": "Denne guide vil hj\u00e6lpe dig igennem ops\u00e6tningen. For at begynde, venligst v\u00e6lg dit fortrukne sprog.",
+ "TellUsAboutYourself": "Fort\u00e6l os lidt om dig selv",
+ "LabelYourFirstName": "Dit fornavn",
+ "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:",
+ "LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
+ "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:",
+ "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",
+ "PismoMessage": "Utilizing Pismo File Mount through a donated license.",
+ "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 (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",
+ "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 - MB3\/Plex\/Xbmc",
+ "OptionImageSavingStandard": "Standard - MB3\/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",
+ "HeaderChannels": "Channels",
+ "TabRecordings": "Recordings",
+ "TabScheduled": "Scheduled",
+ "TabSeries": "Series",
+ "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",
+ "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.",
+ "HeaderCustomizeOptionsPerMediaType": "Customize options per 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",
+ "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",
+ "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": "MB3 Key Missing or Invalid",
+ "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be an MB3 Supporter. Please donate and support the continued development of the core product. Thank you.",
+ "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",
+ "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",
+ "NotificationOptionAudioPlayback": "Audio playback",
+ "NotificationOptionGamePlayback": "Game playback",
+ "NotificationOptionTaskFailed": "Scheduled task failure",
+ "NotificationOptionInstallationFailed": "Installation failure",
+ "NotificationOptionNewLibraryContent": "New content added",
+ "NotificationOptionNewLibraryContentMultiple": "Nyt indhold tilf\u00f8jet (flere)",
+ "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": "Program",
+ "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": "Op",
+ "ButtonArrowDown": "Ned",
+ "ButtonArrowLeft": "Venstre",
+ "ButtonArrowRight": "H\u00f8jre",
+ "ButtonBack": "Tilbage",
+ "ButtonInfo": "Info",
+ "ButtonPageUp": "Side op",
+ "ButtonPageDown": "Side ned",
+ "PageAbbreviation": "PG",
+ "ButtonHome": "Hjem",
+ "ButtonSettings": "Indstillinger",
+ "ButtonTakeScreenshot": "Capture Screenshot",
+ "ButtonLetterUp": "Bogstav op",
+ "ButtonLetterDown": "Bogstav ned",
+ "PageButtonAbbreviation": "PG",
+ "LetterButtonAbbreviation": "A",
+ "TabNowPlaying": "Spiler nu",
+ "TabNavigation": "Navigation",
+ "TabControls": "Controls",
+ "ButtonFullscreen": "Skift til fuldsk\u00e6rm",
+ "ButtonScenes": "Scener",
+ "ButtonSubtitles": "Undertekster",
+ "ButtonAudioTracks": "Lyd filer",
+ "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 fejl",
+ "ButtonVolumeUp": "Volume up",
+ "ButtonVolumeDown": "Volume down",
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "Ingen undertekster",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "Mit bibliotek",
+ "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": "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": "Lyd",
+ "OptionProfileVideoAudio": "Video lyd",
+ "OptionProfilePhoto": "Foto",
+ "LabelUserLibrary": "bruger 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.",
+ "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": "System venligt navn",
+ "LabelManufacturer": "Producent",
+ "LabelManufacturerUrl": "Producent url",
+ "LabelModelName": "Model navn",
+ "LabelModelNumber": "Model 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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Spring over hvis videioen allerede indeholder grafiske undertekster",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Undertekster",
+ "LabelOpenSubtitlesUsername": "Open Subtitles brugernavn:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles kode:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck dette for at sikre at alle videoer har undertekster, uanset hvilket sprog lydsporet anvender.",
+ "HeaderSendMessage": "Send besked",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Tekst besked"
+} \ 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 cafc4d647..6e8c072bd 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/de.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/de.json
@@ -76,6 +76,7 @@
"LabelMaxParentalRating": "H\u00f6chste erlaubte elterlich Bewertung:",
"MaxParentalRatingHelp": "Inhalt mit einer h\u00f6heren Bewertung wird dem User nicht angezeigt.",
"LibraryAccessHelp": "W\u00e4hlen Sie die Medienordner die Sie mit diesem Benutzer teilen m\u00f6chten. Administratoren k\u00f6nnen den Metadata-Manager verwenden um alle Ordner zu bearbeiten.",
+ "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
"ButtonDeleteImage": "L\u00f6sche Bild",
"LabelSelectUsers": "W\u00e4hle Benutzer:",
"ButtonUpload": "Hochladen",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Geplante Aufgaben",
"TabMyPlugins": "Meine Plugins",
"TabCatalog": "Katalog",
- "TabUpdates": "Updates",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Automatische Updates",
- "HeaderUpdateLevel": "Update Level",
"HeaderNowPlaying": "Aktuelle Wiedergabe",
"HeaderLatestAlbums": "Neueste Alben",
"HeaderLatestSongs": "Neueste Songs",
@@ -267,7 +266,7 @@
"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.",
- "LabelMetadataDownloadLanguage": "Bevorzugte Sprache:",
+ "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.",
@@ -515,7 +514,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": "Down mix audio boost scale:",
+ "LabelDownMixAudioScale": "Audio boost when 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",
@@ -565,6 +564,7 @@
"NotificationOptionTaskFailed": "Scheduled task failure",
"NotificationOptionInstallationFailed": "Installation failure",
"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.",
"NotificationOptionServerRestartRequired": "Serverneustart notwendig",
"LabelNotificationEnabled": "Aktiviere diese Benachrichtigung",
@@ -574,7 +574,7 @@
"LabelUseNotificationServices": "Use the following services:",
"CategoryUser": "Benutzer",
"CategorySystem": "System",
- "CategoryApplication": "Application",
+ "CategoryApplication": "Anwendung",
"CategoryPlugin": "Plugin",
"LabelMessageTitle": "Message title:",
"LabelAvailableTokens": "Available tokens:",
@@ -593,7 +593,7 @@
"PageAbbreviation": "PG",
"ButtonHome": "Home",
"ButtonSettings": "Einstellungen",
- "ButtonTakeScreenshot": "Capture Screenshot",
+ "ButtonTakeScreenshot": "Bildschirmfoto aufnehmen",
"ButtonLetterUp": "Letter Up",
"ButtonLetterDown": "Letter Down",
"PageButtonAbbreviation": "PG",
@@ -611,8 +611,105 @@
"ButtonPause": "Pause",
"LabelGroupMoviesIntoCollections": "Gruppiere Filme in 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"
+ "NotificationOptionPluginError": "Plugin Fehler",
+ "ButtonVolumeUp": "Lauter",
+ "ButtonVolumeDown": "Leiser",
+ "ButtonMute": "Stumm",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 1533c7217..082850a6b 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/el.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/el.json
@@ -16,7 +16,7 @@
"LabelYoureDone": "\u03a4\u03b5\u03bb\u03b5\u03b9\u03ce\u03c3\u03b1\u03c4\u03b5",
"WelcomeToMediaBrowser": "\u039a\u03b1\u03bb\u03ce\u03c2 \u03ae\u03c1\u03b8\u03b1\u03c4\u03b5 \u03c3\u03c4\u03bf Media Browser",
"TitleMediaBrowser": "Media Browser",
- "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",
+ "ThisWizardWillGuideYou": "\u0391\u03c5\u03c4\u03cc\u03c2 \u03bf \u03bf\u03b4\u03b7\u03b3\u03cc\u03c2 \u03b8\u03b1 \u03c3\u03b1\u03c2 \u03ba\u03b1\u03b8\u03bf\u03b4\u03b7\u03b3\u03ae\u03c3\u03b5\u03b9 \u03bc\u03ad\u03c3\u03c9 \u03c4\u03b7\u03c2 \u03b4\u03b9\u03b1\u03b4\u03b9\u03ba\u03b1\u03c3\u03af\u03b1\u03c2 \u03b5\u03b3\u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7\u03c2. \u0393\u03b9\u03b1 \u03bd\u03b1 \u03be\u03b5\u03ba\u03b9\u03bd\u03ae\u03c3\u03b5\u03c4\u03b5, \u03b5\u03c0\u03b9\u03bb\u03ad\u03be\u03c4\u03b5 \u03c4\u03b7 \u03b3\u03bb\u03ce\u03c3\u03c3\u03b1 \u03c4\u03b7\u03c2 \u03c0\u03c1\u03bf\u03c4\u03af\u03bc\u03b7\u03c3\u03ae\u03c2 \u03c3\u03b1\u03c2.",
"TellUsAboutYourself": "\u03a0\u03b5\u03af\u03c4\u03b5 \u03bc\u03b1\u03c2 \u03b3\u03b9\u03b1 \u03b5\u03c3\u03ac\u03c2",
"LabelYourFirstName": "\u03a4\u03bf \u03cc\u03bd\u03bf\u03bc\u03ac \u03c3\u03b1\u03c2",
"MoreUsersCanBeAddedLater": "\u03a0\u03b5\u03c1\u03b9\u03c3\u03c3\u03cc\u03c4\u03b5\u03c1\u03bf\u03c5\u03c2 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b5\u03c2 \u03bc\u03c0\u03bf\u03c1\u03bf\u03cd\u03bd \u03bd\u03b1 \u03c0\u03c1\u03bf\u03c3\u03c4\u03b5\u03b8\u03bf\u03cd\u03bd \u03b1\u03c1\u03b3\u03cc\u03c4\u03b5\u03c1\u03b1 \u03bc\u03b5 \u03c4\u03bf \u03c4\u03b1\u03bc\u03c0\u03bb\u03cc",
@@ -26,57 +26,58 @@
"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. ",
"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",
+ "LabelConfigureSettings": "\u03b4\u03b9\u03b1\u03bc\u03bf\u03c1\u03c6\u03ce\u03c3\u03b5\u03c4\u03b5 \u03c4\u03b9\u03c2 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2",
"LabelEnableVideoImageExtraction": "Enable video image extraction",
"VideoImageExtractionHelp": "For videos that don't already have images, and that we're unable to find internet images for. This will add some additional time to the initial library scan but will result in a more pleasing presentation.",
"LabelEnableChapterImageExtractionForMovies": "Extract chapter image extraction for Movies",
"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",
+ "LabelEnableAutomaticPortMapping": "\u0395\u03bd\u03b5\u03c1\u03b3\u03bf\u03c0\u03bf\u03af\u03b7\u03c3\u03b7 \u03bb\u03b9\u03bc\u03ac\u03bd\u03b9 \u03b1\u03c5\u03c4\u03cc\u03bc\u03b1\u03c4\u03b7 \u03c7\u03b1\u03c1\u03c4\u03bf\u03b3\u03c1\u03ac\u03c6\u03b7\u03c3\u03b7",
"LabelEnableAutomaticPortMappingHelp": "UPnP allows automated router configuration for easy remote access. This may not work with some router models.",
- "ButtonOk": "Ok",
- "ButtonCancel": "Cancel",
+ "ButtonOk": "\u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9",
+ "ButtonCancel": "\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7 ",
"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",
+ "ButtonAddMediaFolder": "\u03a0\u03c1\u03bf\u03c3\u03b8\u03ad\u03c3\u03c4\u03b5 \u03c4\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03c4\u03bf\u03c5 Media",
+ "LabelFolderType": "\u03a4\u03cd\u03c0\u03bf \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5 ",
+ "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.",
+ "ReferToMediaLibraryWiki": "\u0391\u03bd\u03b1\u03c4\u03c1\u03b5\u03be\u03c4\u03b5 \u03c3\u03c4\u03bf media \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7 wiki",
+ "LabelCountry": "T\u03b7 \u03c7\u03ce\u03c1\u03b1",
+ "LabelLanguage": "\u03a4\u03b7 \u03b3\u03bb\u03ce\u03c3\u03c3\u03b1",
+ "HeaderPreferredMetadataLanguage": "\u03a0\u03c1\u03bf\u03c4\u03b9\u03bc\u03ce\u03bc\u03b5\u03bd\u03b7 \u03b3\u03bb\u03ce\u03c3\u03c3\u03b1 \u03bc\u03b5\u03c4\u03b1",
+ "LabelSaveLocalMetadata": "\u0391\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c3\u03b5\u03c4\u03b5 \u03c4\u03bf \u03ad\u03c1\u03b3\u03bf \u03c4\u03ad\u03c7\u03bd\u03b7\u03c2 \u03ba\u03b1\u03b9 \u03c4\u03b1 \u03bc\u03b5\u03c4\u03b1\u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1 \u03c3\u03b5 \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5\u03c2 \u03c0\u03bf\u03bb\u03c5\u03bc\u03ad\u03c3\u03c9\u03bd",
"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",
+ "LabelDownloadInternetMetadata": "\u039a\u03b1\u03c4\u03b5\u03b2\u03ac\u03c3\u03c4\u03b5 \u03ad\u03c1\u03b3\u03b1 \u03c4\u03ad\u03c7\u03bd\u03b7\u03c2 \u03ba\u03b1\u03b9 \u03c4\u03b1 \u03bc\u03b5\u03c4\u03b1-\u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1 \u03b1\u03c0\u03cc \u03c4\u03bf internet ",
"LabelDownloadInternetMetadataHelp": "Media Browser can download information about your media to enable rich presentations.",
- "TabPreferences": "Preferences",
- "TabPassword": "Password",
- "TabLibraryAccess": "Library Access",
- "TabImage": "Image",
- "TabProfile": "Profile",
+ "TabPreferences": "\u03a0\u03c1\u03bf\u03c4\u03b9\u03bc\u03ae\u03c3\u03b5\u03b9\u03c2 ",
+ "TabPassword": "\u03c4\u03bf\u03bd \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc",
+ "TabLibraryAccess": "\u03a0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7 \u03c3\u03c4\u03b7 \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7",
+ "TabImage": "\u03b5\u03b9\u03ba\u03cc\u03bd\u03b1",
+ "TabProfile": "\u03c0\u03c1\u03bf\u03c6\u03af\u03bb ",
"TabMetadata": "Metadata",
"TabImages": "Images",
"TabNotifications": "Notifications",
"TabCollectionTitles": "Titles",
- "LabelDisplayMissingEpisodesWithinSeasons": "Display missing episodes within seasons",
+ "LabelDisplayMissingEpisodesWithinSeasons": "\u0391\u03c0\u03b5\u03b9\u03ba\u03cc\u03bd\u03b9\u03c3\u03b7 \u03bb\u03b5\u03af\u03c0\u03b5\u03b9 \u03b5\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1 \u03bc\u03b5 \u03b5\u03c0\u03bf\u03c7\u03ad\u03c2",
"LabelUnairedMissingEpisodesWithinSeasons": "Display unaired episodes within seasons",
"HeaderVideoPlaybackSettings": "Video Playback Settings",
"HeaderPlaybackSettings": "Playback Settings",
"LabelAudioLanguagePreference": "Audio language preference:",
"LabelSubtitleLanguagePreference": "Subtitle language preference:",
"LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
- "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:",
+ "TabProfiles": "\u03c4\u03b1 \u03c0\u03c1\u03bf\u03c6\u03af\u03bb",
+ "TabSecurity": "A\u03c3\u03c6\u03ac\u03bb\u03b5\u03b9\u03b1 ",
+ "ButtonAddUser": "\u03a0\u03c1\u03bf\u03c3\u03b8\u03ae\u03ba\u03b7 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7",
+ "ButtonSave": "\u0391\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c3\u03c4\u03b5",
+ "ButtonResetPassword": "\u0395\u03c0\u03b1\u03bd\u03b1\u03c6\u03bf\u03c1\u03ac \u03c4\u03bf\u03c5 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03cd \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
+ "LabelNewPassword": "\u039d\u03ad\u03bf \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2 ",
+ "LabelNewPasswordConfirm": "\u0395\u03c0\u03b9\u03b2\u03b5\u03b2\u03b1\u03b9\u03ce\u03c3\u03c4\u03b5 \u03c4\u03bf \u03bd\u03ad\u03bf \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2 ",
+ "HeaderCreatePassword": "\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03af\u03b1 \u03ba\u03c9\u03b4\u03b9\u03ba\u03bf\u03cd \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2 ",
+ "LabelCurrentPassword": "\u03a4\u03c1\u03ad\u03c7\u03bf\u03bd\u03c4\u03b1 \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
"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.",
- "ButtonDeleteImage": "Delete Image",
+ "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
+ "ButtonDeleteImage": "\u0394\u03b9\u03b1\u03b3\u03c1\u03b1\u03c6\u03ae \u03b5\u03b9\u03ba\u03cc\u03bd\u03b1\u03c2",
"LabelSelectUsers": "Select users:",
"ButtonUpload": "\u0391\u03bd\u03b5\u03b2\u03ac\u03c3\u03c4\u03b5 ",
"HeaderUploadNewImage": "\u0391\u03bd\u03b5\u03b2\u03ac\u03c3\u03c4\u03b5 \u03bd\u03ad\u03b1 \u03b5\u03b9\u03ba\u03cc\u03bd\u03b1",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Scheduled Tasks",
"TabMyPlugins": "My Plugins",
"TabCatalog": "Catalog",
- "TabUpdates": "Updates",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Automatic Updates",
- "HeaderUpdateLevel": "Update Level",
"HeaderNowPlaying": "Now Playing",
"HeaderLatestAlbums": "Latest Albums",
"HeaderLatestSongs": "Latest Songs",
@@ -267,7 +266,7 @@
"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 language:",
+ "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.",
@@ -515,7 +514,7 @@
"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": "Down mix audio boost scale:",
+ "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",
@@ -565,6 +564,7 @@
"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",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Plugin failure",
"ButtonVolumeUp": "Volume up",
"ButtonVolumeDown": "Volume down",
- "ButtonMute": "Mute"
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 02ec28ac5..4b9914f29 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json
@@ -76,6 +76,7 @@
"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",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Scheduled Tasks",
"TabMyPlugins": "My Plugins",
"TabCatalog": "Catalog",
- "TabUpdates": "Updates",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Automatic Updates",
- "HeaderUpdateLevel": "Update Level",
"HeaderNowPlaying": "Now Playing",
"HeaderLatestAlbums": "Latest Albums",
"HeaderLatestSongs": "Latest Songs",
@@ -267,7 +266,7 @@
"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 language:",
+ "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.",
@@ -515,7 +514,7 @@
"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": "Down mix audio boost scale:",
+ "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",
@@ -565,6 +564,7 @@
"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",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Plugin failure",
"ButtonVolumeUp": "Volume up",
"ButtonVolumeDown": "Volume down",
- "ButtonMute": "Mute"
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 85740bc6b..35596c401 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json
@@ -76,6 +76,7 @@
"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",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Scheduled Tasks",
"TabMyPlugins": "My Plugins",
"TabCatalog": "Catalog",
- "TabUpdates": "Updates",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Automatic Updates",
- "HeaderUpdateLevel": "Update Level",
"HeaderNowPlaying": "Now Playing",
"HeaderLatestAlbums": "Latest Albums",
"HeaderLatestSongs": "Latest Songs",
@@ -267,7 +266,7 @@
"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 language:",
+ "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.",
@@ -515,7 +514,7 @@
"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": "Down mix audio boost scale:",
+ "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",
@@ -565,6 +564,7 @@
"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",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Plugin failure",
"ButtonVolumeUp": "Volume up",
"ButtonVolumeDown": "Volume down",
- "ButtonMute": "Mute"
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 36bf3cf45..f699ef62c 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/es.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/es.json
@@ -76,6 +76,7 @@
"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",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Tareas programadas",
"TabMyPlugins": "Mis Plugins",
"TabCatalog": "Cat\u00e1logo",
- "TabUpdates": "Actualizaciones",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Actualizaciones autom\u00e1ticas",
- "HeaderUpdateLevel": "Nivel de actualizaci\u00f3n",
"HeaderNowPlaying": "Reproduciendo ahora",
"HeaderLatestAlbums": "\u00dcltimos Albums",
"HeaderLatestSongs": "\u00daltimas canciones",
@@ -565,6 +564,7 @@
"NotificationOptionTaskFailed": "La tarea programada ha fallado",
"NotificationOptionInstallationFailed": "Fallo en la instalaci\u00f3n",
"NotificationOptionNewLibraryContent": "Nuevo contenido a\u00f1adido",
+ "NotificationOptionNewLibraryContentMultiple": "New content added (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",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Error en plugin",
"ButtonVolumeUp": "Subir volumen",
"ButtonVolumeDown": "Bajar volumen",
- "ButtonMute": "Silencio"
+ "ButtonMute": "Silencio",
+ "HeaderLatestMedia": "\u00daltimos medios",
+ "OptionNoSubtitles": "Sin subt\u00edtulos",
+ "OptionSpecialFeatures": "Caracter\u00edsticas especiales",
+ "HeaderCollections": "Colecciones",
+ "HeaderMyLibrary": "Mi librer\u00eda",
+ "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:",
+ "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": "Subt\u00edtulos",
+ "LabelOpenSubtitlesUsername": "Usuario de Open Subtitles:",
+ "LabelOpenSubtitlesPassword": "Contrase\u00f1a de Open Subtitles:",
+ "LabelAudioLanguagePreferenceHelp": "Si est\u00e1 vac\u00edo, se seleccionar\u00e1 la pista de audio por defecto, sin importar el idioma.",
+ "LabelDownloadLanguages": "Idiomas de descarga:",
+ "ButtonRegister": "Registrar",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 af72ac203..b3b803fa9 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json
@@ -76,6 +76,7 @@
"LabelMaxParentalRating": "M\u00e1xima clasificaci\u00f3n parental 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 administrador de metadatos.",
+ "ChannelAccessHelp": "Seleccione los canales a compartir con este usuario. Los administradores podr\u00e1n editar todos los canales empleando el administrador de metadatos.",
"ButtonDeleteImage": "Eliminar Imagen",
"LabelSelectUsers": "Seleccionar Usuarios:",
"ButtonUpload": "Subir",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Tareas Programadas",
"TabMyPlugins": "Mis Complementos",
"TabCatalog": "Cat\u00e1logo",
- "TabUpdates": "Actualizaciones",
"PluginsTitle": "Complementos",
"HeaderAutomaticUpdates": "Actualizaciones Autom\u00e1ticas",
- "HeaderUpdateLevel": "Nivel de Actualizaci\u00f3n",
"HeaderNowPlaying": "Reproduciendo Ahora",
"HeaderLatestAlbums": "\u00daltimos \u00c1lbums",
"HeaderLatestSongs": "Canciones Recientes",
@@ -267,7 +266,7 @@
"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.",
- "LabelMetadataDownloadLanguage": "Lenguaje preferido:",
+ "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.",
@@ -515,7 +514,7 @@
"ErrorConnectingToMediaBrowserRepository": "Ocurri\u00f3 un error al conectarse remotamente al repositorio de Media Browser,",
"LabelComponentsUpdated": "Los siguientes componentes han sido instalados o actualizados:",
"MessagePleaseRestartServerToFinishUpdating": "Por favor reinicie el servidor para completar la aplicaci\u00f3n de las actualizaciones.",
- "LabelDownMixAudioScale": "Escala de fortalecimiento de audio para down mix:",
+ "LabelDownMixAudioScale": "Fortalecimiento de audio durante el downmix:",
"LabelDownMixAudioScaleHelp": "Fortalezca el audio cuando se hace down mix. Coloque 1 para preservar el valor del volumen original.",
"ButtonLinkKeys": "Ligar Claves:",
"LabelOldSupporterKey": "Clave de aficionado vieja",
@@ -565,6 +564,7 @@
"NotificationOptionTaskFailed": "Falla de tarea programada",
"NotificationOptionInstallationFailed": "Falla de instalaci\u00f3n",
"NotificationOptionNewLibraryContent": "Adici\u00f3n de nuevos contenidos",
+ "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
"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",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Falla de complemento",
"ButtonVolumeUp": "Subir Volumen",
"ButtonVolumeDown": "Bajar Volumen",
- "ButtonMute": "Mudo"
+ "ButtonMute": "Mudo",
+ "HeaderLatestMedia": "\u00daltimos Medios",
+ "OptionNoSubtitles": "Sin Subtitulos",
+ "OptionSpecialFeatures": "Caracter\u00edsticas Especiales",
+ "HeaderCollections": "Colecciones",
+ "HeaderMyLibrary": "Mi Biblioteca",
+ "LabelProfileCodecsHelp": "Separados por comas. Puede dejarse vaci\u00f3 para aplicarlo a todos los codecs.",
+ "LabelProfileContainersHelp": "Separados por comas. Puede dejarse vaci\u00f3 para aplicarlo 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 Codecs",
+ "HeaderCodecProfileHelp": "Los perfiles de codificaci\u00f3n indican las limitaciones de un dispositivo al reproducir con codecs espec\u00edficos. Si aplica una limitaci\u00f3n el medio ser\u00e1 transcodificado, a\u00fan si el codec ha sido configurado para reproduci\u00f3n directa.",
+ "HeaderContainerProfile": "Perfil del Contenedor",
+ "HeaderContainerProfileHelp": "Los perfiles de contenedor indican las limitaciones de un dispositivo al reproducir formatos espec\u00edficos. Si aplica una limitaci\u00f3n el medio ser\u00e1 transcodificado, a\u00fan si el formato ha sifo configurado para reproducci\u00f3n directa.",
+ "OptionProfileVideo": "Video",
+ "OptionProfileAudio": "Audio",
+ "OptionProfileVideoAudio": "Audio del Video",
+ "OptionProfilePhoto": "Foto",
+ "LabelUserLibrary": "Biblioteca del Usuario:",
+ "LabelUserLibraryHelp": "Seleccione la biblioteca de usuario a desplegar en el dispositivo. Deje vac\u00edo para heredar la configuraci\u00f3n por defecto.",
+ "OptionPlainStorageFolders": "Desplegar todas las carpetas como carpetas de almacenamiento simples.",
+ "OptionPlainStorageFoldersHelp": "Si se habilita, todos las carpetas ser\u00e1n representadas en DIDL como \"object.container.storageFolder\" en lugar de un tipo m\u00e1s espec\u00edfico, como \"object.container.person.musicArtist\".",
+ "OptionPlainVideoItems": "Desplegar todos los videos como elemenos de video simples",
+ "OptionPlainVideoItemsHelp": "Se se habilita, todos los videos ser\u00e1n representados en DIDL como \"object.item.videoItem\" en lugar de un tipo m\u00e1s espec\u00edfico, como \"object.item.videoItem.movie\".",
+ "LabelSupportedMediaTypes": "Tipos de Medios Soportados:",
+ "TabIdentification": "Identificaci\u00f3n",
+ "TabDirectPlay": "Reproducci\u00f3n Directa",
+ "TabContainers": "Contenedores",
+ "TabCodecs": "Codecs",
+ "TabResponses": "Respuestas",
+ "HeaderProfileInformation": "Informaci\u00f3n de Perfil",
+ "LabelEmbedAlbumArtDidl": "Incrustar arte del \u00e1lbum en DIDL",
+ "LabelEmbedAlbumArtDidlHelp": "Algunos dispositivos prefieren este m\u00e9todo para obtener arte del \u00e1lbum. Otros podr\u00edan fallar al reproducir con esta opci\u00f3n habilitada.",
+ "LabelAlbumArtPN": "PN para arte del \u00e1lbum:",
+ "LabelAlbumArtHelp": "PN usado para arte del \u00e1lbum, dento del atributo dlna:profileID en upnp:albumArtURI. Algunos clientes requeren valores espec\u00edficos, independientemente del tama\u00f1o de la imagen.",
+ "LabelAlbumArtMaxWidth": "Ancho m\u00e1ximo para arte del \u00e1lbum:",
+ "LabelAlbumArtMaxWidthHelp": "M\u00e1xima resoluci\u00f3n para arte del album expuesta via upnp:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "Altura m\u00e1xima para arte del \u00e1lbum:",
+ "LabelAlbumArtMaxHeightHelp": "M\u00e1xima resoluci\u00f3n para arte del album expuesta via upnp:albumArtURI.",
+ "LabelIconMaxWidth": "Ancho m\u00e1ximo de \u00efcono:",
+ "LabelIconMaxWidthHelp": "M\u00e1xima resoluci\u00f3n para iconos expuesta via upnp:icon.",
+ "LabelIconMaxHeight": "Altura m\u00e1xima de \u00efcono:",
+ "LabelIconMaxHeightHelp": "M\u00e1xima resoluci\u00f3n para iconos expuesta via upnp:icon.",
+ "LabelIdentificationFieldHelp": "Una subcadena insensible a la diferencia entre min\u00fasculas y may\u00fasculas o expresi\u00f3n regex.",
+ "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.",
+ "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:",
+ "LabelManufacturer": "Fabricante:",
+ "LabelManufacturerUrl": "URL del fabricante:",
+ "LabelModelName": "Nombre del modelo:",
+ "LabelModelNumber": "N\u00famero del modelo:",
+ "LabelModelDescription": "Descripci\u00f3n del modelo:",
+ "LabelModelUrl": "URL del modelo:",
+ "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.",
+ "HeaderResponseProfileHelp": "Los perfiles de respuesta proporcionan un medio para personalizar la informaci\u00f3n enviada a un dispositivo cuando se reproducen ciertos tipos de medios.",
+ "LabelXDlnaCap": "X-DLNA cap:",
+ "LabelXDlnaCapHelp": "Determina el contenido del elemento X_DLNACAP em el namespace urn:schemas-dlna-org:device-1-0.",
+ "LabelXDlnaDoc": "X-DLNA Doc:",
+ "LabelXDlnaDocHelp": "Determina el contenido del elemento X_DLNADOC en el namespace urn:schemas-dlna-org:device-1-0.",
+ "LabelSonyAggregationFlags": "Banderas de agregaci\u00f3n Sony:",
+ "LabelSonyAggregationFlagsHelp": "Determina el contenido del elemento aggregationFlags in el namespace urn:schemas-sonycom:av",
+ "LabelTranscodingContainer": "Contenedor:",
+ "LabelTranscodingVideoCodec": "Codec de video:",
+ "LabelTranscodingVideoProfile": "Perfil de video:",
+ "LabelTranscodingAudioCodec": "Codec de audio:",
+ "OptionEnableM2tsMode": "Habilitar modo M2ts:",
+ "OptionEnableM2tsModeHelp": "Habilita el modo m2ts cuando se codifican mpegs.",
+ "OptionEstimateContentLength": "Estimar la duraci\u00f3n del contenido cuando se transcodifica",
+ "OptionReportByteRangeSeekingWhenTranscoding": "Reportar que el servidor soporta busqueda de bytes al transcodificar",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "Esto es requerido para algunos dispositivos que no pueden hacer b\u00fasquedas por tiempo muy bien.",
+ "HeaderSubtitleDownloadingHelp": "Cuando Media Browser examina sus archivos de video puede buscar los subt\u00edtulos faltantes, y descargarlos usando un proveedor de subt\u00edtulos como OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "Descargar subt\u00edtulos para:",
+ "LabelSkipIfGraphicalSubsPresent": "Omitir si el video ya contiene subt\u00edtulos gr\u00e1ficos",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Mantener versiones de texto de los subt\u00edtulos resultar\u00e1 en una entrega m\u00e1s eficiente para clientes m\u00f3viles.",
+ "TabSubtitles": "Subt\u00edtulos",
+ "LabelOpenSubtitlesUsername": "Nombre de usuario de Open Subtitles:",
+ "LabelOpenSubtitlesPassword": "Contrase\u00f1a de Open Subtitles:",
+ "LabelAudioLanguagePreferenceHelp": "Si se deja vac\u00edo, la pista de audio por defecto ser\u00e1 seleccionada, independientemente del lenguaje.",
+ "LabelDownloadLanguages": "Descargar lenguajes:",
+ "ButtonRegister": "Registrar",
+ "LabelSkipIfAudioTrackPresent": "Omitir si la pista de audio por defecto coincide con el lenguaje de descarga",
+ "LabelSkipIfAudioTrackPresentHelp": "Desactive esto para asegurar que todos los videos tengan subt\u00edtulos, independientemente del lenguaje del audio.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 fd3c8d888..ce3447a88 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/fr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/fr.json
@@ -76,8 +76,9 @@
"LabelMaxParentalRating": "Note maximale d'\u00e9valuation de contr\u00f4le parental:",
"MaxParentalRatingHelp": "Le contenu avec une note d'\u00e9valuation de contr\u00f4le parental plus \u00e9lev\u00e9e ne sera pas visible par cet utilisateur.",
"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.",
+ "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.",
"ButtonDeleteImage": "Supprimer Image",
- "LabelSelectUsers": "Select users:",
+ "LabelSelectUsers": "S\u00e9lectionner utilisateurs:",
"ButtonUpload": "Envoyer",
"HeaderUploadNewImage": "Envoyer nouvelle image",
"LabelDropImageHere": "Placer image ici",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "T\u00e2ches programm\u00e9es",
"TabMyPlugins": "Mes Plugins",
"TabCatalog": "Catalogue",
- "TabUpdates": "Mises \u00e0 jour",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Mises \u00e0 jour automatiques",
- "HeaderUpdateLevel": "Niveau de mise \u00e0 jour",
"HeaderNowPlaying": "Lecture en cours",
"HeaderLatestAlbums": "Derniers albums",
"HeaderLatestSongs": "Derni\u00e8res chansons",
@@ -267,7 +266,7 @@
"LabelAutomaticUpdatesTmdbHelp": "Si activ\u00e9, les nouvelles images seront t\u00e9l\u00e9charg\u00e9es automatiquement lorsqu'elles seront ajout\u00e9es dans TheMovieDB.org. Les images existantes ne seront pas remplac\u00e9es.",
"LabelAutomaticUpdatesTvdbHelp": "Si activ\u00e9, les nouvelles images seront t\u00e9l\u00e9charg\u00e9es automatiquement lorsqu'elles seront ajout\u00e9es dans TheTVDB.com. Les images existantes ne seront pas remplac\u00e9es.",
"ExtractChapterImagesHelp": "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.",
- "LabelMetadataDownloadLanguage": "Langue pr\u00e9f\u00e9r\u00e9e",
+ "LabelMetadataDownloadLanguage": "Langue t\u00e9l\u00e9charg\u00e9e pr\u00e9f\u00e9r\u00e9e: ",
"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.",
@@ -416,10 +415,10 @@
"LabelEnableDlnaDebugLoggingHelp": "Ceci va g\u00e9n\u00e9rer de gros fichiers de journal d'\u00e9v\u00e9nements et ne devrait \u00eatre utiliser seulement pour des besoins de diagnostique de probl\u00e8mes...",
"LabelEnableDlnaClientDiscoveryInterval": "Intervalle de d\u00e9couverte des clients (secondes)",
"LabelEnableDlnaClientDiscoveryIntervalHelp": "D\u00e9terminez la dur\u00e9e en secondes de l\u2019intervalle entre les recherches SSDP effectu\u00e9es par Media Browser.",
- "HeaderCustomDlnaProfiles": "Profiles personnalis\u00e9s",
+ "HeaderCustomDlnaProfiles": "Profils personnalis\u00e9s",
"HeaderSystemDlnaProfiles": "Profils syst\u00e8mes",
- "CustomDlnaProfilesHelp": "Cr\u00e9er un profile personnalis\u00e9 pour cibler un appareil ou remplacer un profile syst\u00e8me.",
- "SystemDlnaProfilesHelp": "Les profils syst\u00e8mes sont en lecture seule. Pour remplacer un profile syst\u00e8me, cr\u00e9ez un profil personnalis\u00e9 ciblant le m\u00eame appareil.",
+ "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",
"TabInfo": "Info",
@@ -515,13 +514,13 @@
"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.",
- "LabelDownMixAudioScale": "Down mix audio boost scale:",
- "LabelDownMixAudioScaleHelp": "Boost audio when downmixing. Set to 1 to preserve original volume value.",
+ "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",
"LabelOldSupporterKey": "Ancienne cl\u00e9 de supporteur",
"LabelNewSupporterKey": "Nouvelle cl\u00e9 de supporteur",
"HeaderMultipleKeyLinking": "Lien de cl\u00e9s multiples",
- "MultipleKeyLinkingHelp": "If you have more than one supporter key, use this form to link the old key's registrations with your new one.",
+ "MultipleKeyLinkingHelp": "Si vous avez plus qu'une cl\u00e9 de supporteur, utilisez ce formulaire pour lier l'ancienne cl\u00e9 d'enregistrement avec la nouvelle.",
"LabelCurrentEmailAddress": "Adresse courriel actuelle",
"LabelCurrentEmailAddressHelp": "L'adresse courriel actuelle \u00e0 laquelle votre nouvelle cl\u00e9 a \u00e9t\u00e9 envoy\u00e9e.",
"HeaderForgotKey": "Oubli\u00e9 cl\u00e9",
@@ -529,19 +528,19 @@
"LabelSupporterEmailAddress": "L'adresse courriel avec laquelle la cl\u00e9 a \u00e9t\u00e9 achet\u00e9e.",
"ButtonRetrieveKey": "obtenir la cl\u00e9",
"LabelSupporterKey": "Cl\u00e9 de supporteur (coller du courriel)",
- "LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
+ "LabelSupporterKeyHelp": "Entrez votre cl\u00e9 du supporteur pour commencer \u00e0 profiter des b\u00e9n\u00e9fices additionnels que la communaut\u00e9 a d\u00e9velopp\u00e9 pour Media Browser.",
"MessageInvalidKey": "Cl\u00e9 MB3 manquante ou invalide",
- "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be an MB3 Supporter. Please donate and support the continued development of the core product. Thank you.",
+ "ErrorMessageInvalidKey": "Pour que le contenu premium soit enregistr\u00e9, vous devez aussi \u00eatre supporteur MB3. S'il vous plait effectuez des dons et soutenez la continuation du d\u00e9veloppement de Media Browser.",
"HeaderDisplaySettings": "Param\u00e8tres d'affichage",
"TabPlayTo": "Lire sur",
"LabelEnableDlnaServer": "Activer le serveur DLNA",
- "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.",
+ "LabelEnableDlnaServerHelp": "Authorise les appareils UPnP sur le r\u00e9seau \u00e0 naviguer et lire le contenu Media Browser.",
+ "LabelEnableBlastAliveMessages": "Diffuser des message de pr\u00e9sence",
+ "LabelEnableBlastAliveMessagesHelp": "Activer cette option si le serveur n'est pas d\u00e9tect\u00e9 correctement ou par intermittence par d'autre appareil UPnP sur le r\u00e9seau. ",
+ "LabelBlastMessageInterval": "Intervalles des messages de pr\u00e9sence (secondes):",
+ "LabelBlastMessageIntervalHelp": "D\u00e9termine la dur\u00e9e en secondes entre les message de pr\u00e9sences.",
"LabelDefaultUser": "Utilisateur par d\u00e9faut:",
- "LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.",
+ "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",
"HeaderServerSettings": "Param\u00e8tres du serveur",
"LabelWeatherDisplayLocation": "Emplacement de l'affichage de la m\u00e9t\u00e9o:",
@@ -565,6 +564,7 @@
"NotificationOptionTaskFailed": "\u00c9chec de t\u00e2che programm\u00e9e",
"NotificationOptionInstallationFailed": "\u00c9chec d'installation",
"NotificationOptionNewLibraryContent": "Nouveau contenu ajout\u00e9",
+ "NotificationOptionNewLibraryContentMultiple": "Nouveau contenu ajout\u00e9 (multiple)",
"SendNotificationHelp": "Par d\u00e9faut, les notifications sont d\u00e9livr\u00e9es dans la bo\u00eete de r\u00e9ception du tableau de bord. Consultez le catalogue de plugins pour installer des options de notifications suppl\u00e9mentaires.",
"NotificationOptionServerRestartRequired": "Un red\u00e9marrage du serveur est requis",
"LabelNotificationEnabled": "Activer cette notification",
@@ -576,43 +576,140 @@
"CategorySystem": "Syst\u00e8me",
"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",
+ "LabelMessageTitle": "Titre du message:",
+ "LabelAvailableTokens": "Jetons disponibles:",
+ "AdditionalNotificationServices": "Visitez le catalogue de plugins pour installer des service de notifications suppl\u00e9mentaires.",
+ "OptionAllUsers": "Tous les utilisateurs",
+ "OptionAdminUsers": "Administrateurs",
+ "OptionCustomUsers": "Personnalis\u00e9",
+ "ButtonArrowUp": "Haut",
+ "ButtonArrowDown": "Bas",
+ "ButtonArrowLeft": "Gauche",
+ "ButtonArrowRight": "Droite",
+ "ButtonBack": "Retour arri\u00e8re",
"ButtonInfo": "Info",
- "ButtonPageUp": "Page Up",
- "ButtonPageDown": "Page Down",
+ "ButtonPageUp": "Page suivante",
+ "ButtonPageDown": "Page pr\u00e9c\u00e9dante",
"PageAbbreviation": "PG",
- "ButtonHome": "Home",
- "ButtonSettings": "Settings",
- "ButtonTakeScreenshot": "Capture Screenshot",
- "ButtonLetterUp": "Letter Up",
- "ButtonLetterDown": "Letter Down",
+ "ButtonHome": "Principal",
+ "ButtonSettings": "Param\u00e8tres",
+ "ButtonTakeScreenshot": "Capture d'\u00e9cran",
+ "ButtonLetterUp": "Lettre haut",
+ "ButtonLetterDown": "Lettre bas",
"PageButtonAbbreviation": "PG",
"LetterButtonAbbreviation": "A",
- "TabNowPlaying": "Now Playing",
+ "TabNowPlaying": "En cours de lecture",
"TabNavigation": "Navigation",
- "TabControls": "Controls",
- "ButtonFullscreen": "Toggle fullscreen",
- "ButtonScenes": "Scenes",
- "ButtonSubtitles": "Subtitles",
- "ButtonAudioTracks": "Audio tracks",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "ButtonStop": "Stop",
+ "TabControls": "Contr\u00f4les",
+ "ButtonFullscreen": "Plein \u00e9cran",
+ "ButtonScenes": "Sc\u00e8nes",
+ "ButtonSubtitles": "Sous-titres",
+ "ButtonAudioTracks": "Piste audio",
+ "ButtonPreviousTrack": "Piste pr\u00e9c\u00e9dante",
+ "ButtonNextTrack": "Piste suivante",
+ "ButtonStop": "Arr\u00eat",
"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"
+ "LabelGroupMoviesIntoCollections": "Grouper les films en collections",
+ "LabelGroupMoviesIntoCollectionsHelp": "Dans l'affichage des listes de films, les films faisant partie d'une collection seront affich\u00e9s comme un item de groupe.",
+ "NotificationOptionPluginError": "\u00c9chec de plugin",
+ "ButtonVolumeUp": "Volume haut",
+ "ButtonVolumeDown": "Volume bas",
+ "ButtonMute": "Sourdine",
+ "HeaderLatestMedia": "Derniers m\u00e9dias",
+ "OptionNoSubtitles": "Aucun sous-titre",
+ "OptionSpecialFeatures": "\u00c9v\u00eanements sp\u00e9ciaux",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "Ma biblioth\u00e8que",
+ "LabelProfileCodecsHelp": "S\u00e9par\u00e9s par des virgules. Peut \u00eatre laiss\u00e9 vide pour appliquer tous les codecs.",
+ "LabelProfileContainersHelp": "S\u00e9par\u00e9s par des virgules. Peut \u00eatre laiss\u00e9 vide pour appliquer tous les conteneurs.",
+ "HeaderResponseProfile": "Profil de r\u00e9ponse",
+ "LabelType": "Type:",
+ "LabelProfileContainer": "Conteneur:",
+ "LabelProfileVideoCodecs": "Codecs vid\u00e9os:",
+ "LabelProfileAudioCodecs": "Codecs audios:",
+ "LabelProfileCodecs": "Codecs:",
+ "HeaderDirectPlayProfile": "Profil de lecture directe (Direct Play):",
+ "HeaderTranscodingProfile": "Profil de transcodage:",
+ "HeaderCodecProfile": "Profil de codecs",
+ "HeaderCodecProfileHelp": "Les profils de codecs sp\u00e9cifient les limites de lecture de codecs sp\u00e9cifiques d'un appareil. Si la limite s'applique, le m\u00e9dia sera transcod\u00e9, m\u00eame si le codec est configur\u00e9 pour des lectures directes.",
+ "HeaderContainerProfile": "Profil de conteneur",
+ "HeaderContainerProfileHelp": "Les profils de conteneur indique les limites d'un appareil lors de lectures de formats sp\u00e9cifiques. Si la limite s'applique au m\u00e9dia, ce dernier sera transcod\u00e9, m\u00eame si le format est configur\u00e9 pour faire de la lecture directe.",
+ "OptionProfileVideo": "Vid\u00e9o",
+ "OptionProfileAudio": "Audio",
+ "OptionProfileVideoAudio": "Vid\u00e9o Audio",
+ "OptionProfilePhoto": "Photo",
+ "LabelUserLibrary": "Biblioth\u00e8que de l'utilisateur:",
+ "LabelUserLibraryHelp": "S\u00e9lectionner quelle biblioth\u00e8que d'utilisateur \u00e0 afficher sur l'appareil. Laisser vide pour h\u00e9riter des param\u00e8tres par d\u00e9faut.",
+ "OptionPlainStorageFolders": "Afficher tous les r\u00e9pertoires en tant que simple r\u00e9pertoires de stockage.",
+ "OptionPlainStorageFoldersHelp": "Si activ\u00e9, tous les r\u00e9pertoires seront affich\u00e9s en DIDL en tant que \"object.container.storageFolder\" au lieu de formats plus sp\u00e9cifiques comme, par exemple \"object.container.person.musicArtist\".",
+ "OptionPlainVideoItems": "Afficher les vid\u00e9os en tant que simple items vid\u00e9os.",
+ "OptionPlainVideoItemsHelp": "Si activ\u00e9, tous les vid\u00e9os seront affich\u00e9s en DIDL en tant que \"object.item.videoItem\" au lieu de formats plus sp\u00e9cifiques comme, par exemple \"object.item.videoItem.movie\".",
+ "LabelSupportedMediaTypes": "Types de m\u00e9dias support\u00e9s:",
+ "TabIdentification": "Indentification",
+ "TabDirectPlay": "Lecture directe",
+ "TabContainers": "Conteneur",
+ "TabCodecs": "Codecs",
+ "TabResponses": "R\u00e9ponses",
+ "HeaderProfileInformation": "Information de profil",
+ "LabelEmbedAlbumArtDidl": "Int\u00e9grer les images d'album dans Didl",
+ "LabelEmbedAlbumArtDidlHelp": "Certains appareils pr\u00e9f\u00e8rent cette m\u00e9thode pour obtenir les images d'album. D'autre, par contre, pourraient ne pas pouvoir les lire avec cette options activ\u00e9e.",
+ "LabelAlbumArtPN": "PN d'images d'album:",
+ "LabelAlbumArtHelp": "PN utilis\u00e9 pour les images d'album, dans l\u2019attribut dlna:profileID de upnp:albumArtURi. Certains client n\u00e9cessite une valeur sp\u00e9cifique, peu importe la grosseur de l'image.",
+ "LabelAlbumArtMaxWidth": "Largeur maximum des images d'album:",
+ "LabelAlbumArtMaxWidthHelp": "R\u00e9solution maximum des images d'album expos\u00e9e par upnp:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "Hauteur maximum des images d'album:",
+ "LabelAlbumArtMaxHeightHelp": "R\u00e9solution maximum des images d'album expos\u00e9e par upnp:albumArtURI.",
+ "LabelIconMaxWidth": "Largeur maximum des ic\u00f4nes:",
+ "LabelIconMaxWidthHelp": "R\u00e9solution maximum des ic\u00f4nes expos\u00e9e par upnp:icon.",
+ "LabelIconMaxHeight": "hauteur maximum des ic\u00f4nes:",
+ "LabelIconMaxHeightHelp": "R\u00e9solution maximum des ic\u00f4nes expos\u00e9e par upnp:icon.",
+ "LabelIdentificationFieldHelp": "Une sous-cha\u00eene ou expression regex insensible \u00e0 la diff\u00e9rence minuscules-majuscules.",
+ "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.",
+ "OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
+ "OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
+ "LabelFriendlyName": "Surnom d'affichage",
+ "LabelManufacturer": "Manufacturier",
+ "LabelManufacturerUrl": "URL du manufacturier",
+ "LabelModelName": "Nom de mod\u00e8le",
+ "LabelModelNumber": "Num\u00e9ro de mod\u00e8le",
+ "LabelModelDescription": "Description de mod\u00e8le",
+ "LabelModelUrl": "URL de mod\u00e8le",
+ "LabelSerialNumber": "Num\u00e9ro de s\u00e9rie",
+ "LabelDeviceDescription": "Description de l'appareil",
+ "HeaderIdentificationCriteriaHelp": "Entrer au moins un crit\u00e8re d'identification.",
+ "HeaderDirectPlayProfileHelp": "Ajoutez des profils de lecture directe pour sp\u00e9cifier quels formats l'appareil peut lire nativement.",
+ "HeaderTranscodingProfileHelp": "Ajoutez des profils de transcodage pour sp\u00e9cifier quels formats doit \u00eatre transcod\u00e9.",
+ "HeaderResponseProfileHelp": "Les profils de r\u00e9ponse permettent de personnaliser l'information envoy\u00e9e \u00e0 l'appareil lors de lecture de certains formats de m\u00e9dia.",
+ "LabelXDlnaCap": "Cap X-Dlna:",
+ "LabelXDlnaCapHelp": "D\u00e9termine le contenu des \u00e9l\u00e9ments X_DLNACAP dans l'espace de nom urn:schemas-dlna-org:device-1-0.",
+ "LabelXDlnaDoc": "Doc X-Dlna:",
+ "LabelXDlnaDocHelp": "D\u00e9termine le contenu des \u00e9l\u00e9ments X_DLNADOC dans l'espace de nom urn:schemas-dlna-org:device-1-0.",
+ "LabelSonyAggregationFlags": "Sony aggregation flags:",
+ "LabelSonyAggregationFlagsHelp": "D\u00e9termine le contenu des \u00e9l\u00e9ments aggregationFlags dans l'espace de nom urn:schemas-sonycom:av .",
+ "LabelTranscodingContainer": "Conteneur:",
+ "LabelTranscodingVideoCodec": "Codec vid\u00e9o:",
+ "LabelTranscodingVideoProfile": "Profil vid\u00e9o:",
+ "LabelTranscodingAudioCodec": "Codec audio:",
+ "OptionEnableM2tsMode": "Activer le mode M2ts",
+ "OptionEnableM2tsModeHelp": "Activ\u00e9 le mode m2ts lors d'encodage en mpegts.",
+ "OptionEstimateContentLength": "Estimer la dur\u00e9e du contenu lors d'encodage",
+ "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": "Lorsque Media Browser balaye vos fichiers vid\u00e9os, le serveur peut rechercher des sous-titres manquants et les t\u00e9l\u00e9charger en utilisant un fournisseur de sous-titre comme OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "T\u00e9l\u00e9charger les sous-titres pour:",
+ "LabelSkipIfGraphicalSubsPresent": "Sauter le vid\u00e9o contient d\u00e9j\u00e0 des sous-titres graphiques",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Garder des versions textes des sous-titres va \u00eatre plus efficace avec les appareils mobiles.",
+ "TabSubtitles": "Sous-titres:",
+ "LabelOpenSubtitlesUsername": "Nom d'utilisateur de Open Subtitles:",
+ "LabelOpenSubtitlesPassword": "Mot de passe de Open Subtitles:",
+ "LabelAudioLanguagePreferenceHelp": "Si laiss\u00e9 vide, la piste audio par d\u00e9faut sera s\u00e9lectionn\u00e9e, peu importe la langue.",
+ "LabelDownloadLanguages": "Langes de t\u00e9l\u00e9chargement:",
+ "ButtonRegister": "S'enregistrer",
+ "LabelSkipIfAudioTrackPresent": "Sauter si la piste audio correspond \u00e0 la langue de t\u00e9l\u00e9chargement",
+ "LabelSkipIfAudioTrackPresentHelp": "D\u00e9cocher cette option va assurer que tous les vid\u00e9os ont des sous-titres, peu importe la langue audio.",
+ "HeaderSendMessage": "Envoyer message",
+ "ButtonSend": "Envoyer",
+ "LabelMessageText": "Texte du message:"
} \ 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 bd288060c..bf0398382 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/he.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/he.json
@@ -76,6 +76,7 @@
"LabelMaxParentalRating": "\u05d3\u05d9\u05e8\u05d5\u05d2 \u05d4\u05d5\u05e8\u05d9\u05dd \u05de\u05e7\u05e1\u05d9\u05de\u05d0\u05dc\u05d9:",
"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.",
"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.",
+ "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
"ButtonDeleteImage": "\u05de\u05d7\u05e7 \u05ea\u05de\u05d5\u05e0\u05d4",
"LabelSelectUsers": "\u05d1\u05d7\u05e8 \u05de\u05e9\u05ea\u05de\u05e9\u05d9\u05dd:",
"ButtonUpload": "\u05d4\u05e2\u05dc\u05d4",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "\u05de\u05e9\u05d9\u05de\u05d5\u05ea \u05de\u05ea\u05d5\u05d6\u05de\u05e0\u05d5\u05ea",
"TabMyPlugins": "\u05d4\u05ea\u05d5\u05e1\u05e4\u05d9\u05dd \u05e9\u05dc\u05d9",
"TabCatalog": "\u05e7\u05d8\u05dc\u05d5\u05d2",
- "TabUpdates": "\u05e2\u05d9\u05d3\u05db\u05d5\u05e0\u05d9\u05dd",
"PluginsTitle": "\u05ea\u05d5\u05e1\u05e4\u05d9\u05dd",
"HeaderAutomaticUpdates": "\u05e2\u05d9\u05d3\u05db\u05d5\u05e0\u05d9\u05dd \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05dd",
- "HeaderUpdateLevel": "\u05e8\u05de\u05ea \u05d4\u05e2\u05d9\u05d3\u05db\u05d5\u05df",
"HeaderNowPlaying": "\u05de\u05e0\u05d2\u05df \u05e2\u05db\u05e9\u05d9\u05d5",
"HeaderLatestAlbums": "\u05d0\u05dc\u05d1\u05d5\u05de\u05d9\u05dd \u05d0\u05d7\u05e8\u05d5\u05e0\u05d9\u05dd",
"HeaderLatestSongs": "\u05e9\u05d9\u05e8\u05d9\u05dd \u05d0\u05d7\u05e8\u05d5\u05e0\u05d9\u05dd",
@@ -267,7 +266,7 @@
"LabelAutomaticUpdatesTmdbHelp": "\u05d0\u05dd \u05de\u05d5\u05e4\u05e2\u05dc, \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05d7\u05d3\u05e9\u05d5\u05ea \u05d9\u05e8\u05d3\u05d5 \u05d1\u05e6\u05d5\u05e8\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea \u05db\u05d0\u05e9\u05e8 \u05d4\u05df \u05e0\u05d5\u05e1\u05e4\u05d5\u05ea \u05dc- TheMovieDB.org. \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05e7\u05d9\u05d9\u05de\u05d5\u05ea \u05dc\u05d0 \u05d9\u05d5\u05d7\u05dc\u05e4\u05d5.",
"LabelAutomaticUpdatesTvdbHelp": "\u05d0\u05dd \u05de\u05d5\u05e4\u05e2\u05dc, \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05d7\u05d3\u05e9\u05d5\u05ea \u05d9\u05e8\u05d3\u05d5 \u05d1\u05e6\u05d5\u05e8\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea \u05db\u05d0\u05e9\u05e8 \u05d4\u05df \u05e0\u05d5\u05e1\u05e4\u05d5\u05ea \u05dc- TVDB.com. \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05e7\u05d9\u05d9\u05de\u05d5\u05ea \u05dc\u05d0 \u05d9\u05d5\u05d7\u05dc\u05e4\u05d5.",
"ExtractChapterImagesHelp": "\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 \u05d7\u05dc\u05d5\u05df \u05d1\u05d7\u05d9\u05e8\u05ea \u05e1\u05e6\u05d9\u05e0\u05d5\u05ea \u05d2\u05e8\u05e4\u05d9. \u05d4\u05ea\u05d4\u05dc\u05d9\u05da \u05d4\u05d6\u05d4 \u05d9\u05db\u05d5\u05dc \u05dc\u05d4\u05d9\u05d5\u05ea \u05d0\u05d9\u05d8\u05d9, \u05dc\u05d3\u05e8\u05d5\u05e9 \u05db\u05d5\u05d7 \u05e2\u05d9\u05d1\u05d5\u05d3 \u05e8\u05d1 \u05d5\u05e9\u05d8\u05d7 \u05d0\u05d9\u05d7\u05e1\u05d5\u05df \u05d2\u05d3\u05d5\u05dc. \u05d4\u05d5\u05d0 \u05e8\u05e5 \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. \u05dc\u05de\u05e8\u05d5\u05ea \u05e9\u05e0\u05d9\u05ea\u05df \u05dc\u05d4\u05d2\u05d3\u05d9\u05e8 \u05d0\u05d5\u05ea\u05d5 \u05d1\u05d0\u05d6\u05d5\u05e8 \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\u05e8\u05d9\u05e5 \u05d0\u05d5\u05ea\u05d5 \u05d1\u05e9\u05e2\u05d5\u05ea \u05d4\u05e9\u05d9\u05de\u05d5\u05e9 \u05d4\u05de\u05d7\u05e9\u05d1.",
- "LabelMetadataDownloadLanguage": "\u05e9\u05e4\u05d4 \u05de\u05d5\u05e2\u05d3\u05e4\u05ea:",
+ "LabelMetadataDownloadLanguage": "\u05e9\u05e4\u05ea \u05d4\u05d5\u05e8\u05d3\u05d4 \u05de\u05d5\u05e2\u05d3\u05e4\u05ea:",
"ButtonAutoScroll": "\u05d2\u05dc\u05d9\u05dc\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea",
"LabelImageSavingConvention": "\u05e9\u05d9\u05d8\u05ea \u05e9\u05de\u05d9\u05e8\u05ea \u05ea\u05de\u05d5\u05e0\u05d4:",
"LabelImageSavingConventionHelp": "Media Browser \u05de\u05d6\u05d4\u05d4 \u05ea\u05de\u05d5\u05e0\u05d5\u05ea \u05de\u05e8\u05d5\u05d1 \u05ea\u05d5\u05db\u05e0\u05d5\u05ea \u05d4\u05de\u05d3\u05d9\u05d4 \u05d4\u05d2\u05d3\u05d5\u05dc\u05d5\u05ea. \u05d1\u05d7\u05d9\u05e8\u05ea \u05e9\u05d9\u05d8\u05ea \u05d4\u05d4\u05d5\u05e8\u05d3\u05d4 \u05d9\u05e2\u05d9\u05dc\u05d4 \u05db\u05e9\u05d0\u05e8 \u05d0\u05ea\u05d4 \u05de\u05e9\u05ea\u05de\u05e9 \u05d1\u05de\u05d5\u05e6\u05e8\u05d9\u05dd \u05d0\u05d7\u05e8\u05d9\u05dd.",
@@ -565,6 +564,7 @@
"NotificationOptionTaskFailed": "\u05de\u05e9\u05d9\u05de\u05d4 \u05de\u05ea\u05d5\u05d6\u05de\u05e0\u05ea \u05e0\u05db\u05e9\u05dc\u05d4",
"NotificationOptionInstallationFailed": "\u05d4\u05ea\u05e7\u05e0\u05d4 \u05e0\u05db\u05e9\u05dc\u05d4",
"NotificationOptionNewLibraryContent": "\u05ea\u05d5\u05db\u05df \u05d7\u05d3\u05e9 \u05e0\u05d5\u05e1\u05e3",
+ "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
"SendNotificationHelp": "\u05d1\u05e8\u05d9\u05e8\u05ea \u05d4\u05de\u05d7\u05d3\u05dc \u05d4\u05d9\u05d0 \u05e9\u05d4\u05ea\u05e8\u05d0\u05d5\u05ea \u05de\u05d2\u05d9\u05e2\u05d5\u05ea \u05dc\u05ea\u05d9\u05d1\u05ea \u05d4\u05d3\u05d5\u05d0\u05e8 \u05d4\u05e0\u05db\u05e0\u05e1 \u05e9\u05dc \u05dc\u05d5\u05d7 \u05d4\u05d1\u05e7\u05e8\u05d4. \u05e2\u05d9\u05d9\u05df \u05d1\u05e7\u05d8\u05dc\u05d5\u05d2 \u05d4\u05ea\u05d5\u05e1\u05e4\u05d9\u05dd \u05db\u05d3\u05d9 \u05dc\u05d4\u05ea\u05e7\u05d9\u05df \u05d0\u05e4\u05e9\u05e8\u05d5\u05d9\u05d5\u05ea \u05e0\u05d5\u05e1\u05e4\u05d5\u05ea \u05dc\u05e7\u05d1\u05dc\u05ea \u05d4\u05ea\u05e8\u05d0\u05d5\u05ea",
"NotificationOptionServerRestartRequired": "\u05e0\u05d3\u05e8\u05e9\u05ea \u05d4\u05e4\u05e2\u05dc\u05d4 \u05de\u05d7\u05d3\u05e9 \u05e9\u05dc \u05d4\u05e9\u05e8\u05ea",
"LabelNotificationEnabled": "\u05d0\u05e4\u05e9\u05e8 \u05d4\u05ea\u05e8\u05d0\u05d4 \u05d6\u05d5",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Plugin failure",
"ButtonVolumeUp": "Volume up",
"ButtonVolumeDown": "Volume down",
- "ButtonMute": "Mute"
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 673c73530..e9ca91b55 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/it.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/it.json
@@ -76,6 +76,7 @@
"LabelMaxParentalRating": "Massima valutazione dei genitori consentita:",
"MaxParentalRatingHelp": "Contento di un punteggio pi\u00f9 elevato sar\u00e0 nascosto da questo utente.",
"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.",
+ "ChannelAccessHelp": "Selezionare i canali da condividere con questo utente. Gli amministratori saranno in grado di modificare tutti i canali usando il gestore dei metadati",
"ButtonDeleteImage": "Elimina immagine",
"LabelSelectUsers": "Seleziona Utenti:",
"ButtonUpload": "Carica",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Operazioni Pianificate",
"TabMyPlugins": "Plugins Installati",
"TabCatalog": "Catalogo",
- "TabUpdates": "Aggiornamenti",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Aggiornamenti Automatici",
- "HeaderUpdateLevel": "Livello",
"HeaderNowPlaying": "Riproducendo",
"HeaderLatestAlbums": "Ultimi Albums Aggiunti",
"HeaderLatestSongs": "Ultime Canzoni",
@@ -267,7 +266,7 @@
"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.",
- "LabelMetadataDownloadLanguage": "Lingua preferita:",
+ "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.",
@@ -565,6 +564,7 @@
"NotificationOptionTaskFailed": "Fallimento operazione pianificata",
"NotificationOptionInstallationFailed": "errore di installazione",
"NotificationOptionNewLibraryContent": "Nuovo contenuto aggiunto",
+ "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
"SendNotificationHelp": "Per impostazione predefinita, le notifiche vengono consegnate al cruscotto della Posta in arrivo . Sfoglia il catalogo plugin da installare opzioni di notifica aggiuntive.",
"NotificationOptionServerRestartRequired": "Riavvio del server necessaria",
"LabelNotificationEnabled": "Abilita questa notifica",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Plugin fallito",
"ButtonVolumeUp": "Aumenta Volume",
"ButtonVolumeDown": "Diminuisci volume",
- "ButtonMute": "Muto"
+ "ButtonMute": "Muto",
+ "HeaderLatestMedia": "Ultimi Media",
+ "OptionNoSubtitles": "Nessun Sottotitolo",
+ "OptionSpecialFeatures": "caratteristiche Speciali",
+ "HeaderCollections": "Collezioni",
+ "HeaderMyLibrary": "Mia Libereria",
+ "LabelProfileCodecsHelp": "Separati da virgola. Questo pu\u00f2 essere lasciato vuoto da applicare a tutti i codec.",
+ "LabelProfileContainersHelp": "Separati da virgola. Questo pu\u00f2 essere lasciato vuoto da applicare a tutti i contenitori.",
+ "HeaderResponseProfile": "Risposta Profilo",
+ "LabelType": "Tipo:",
+ "LabelProfileContainer": "Contenitore:",
+ "LabelProfileVideoCodecs": "Video codecs:",
+ "LabelProfileAudioCodecs": "Audio codecs:",
+ "LabelProfileCodecs": "Codecs:",
+ "HeaderDirectPlayProfile": "Direct Play profilo",
+ "HeaderTranscodingProfile": "transcodifica profilo",
+ "HeaderCodecProfile": "Codec Profilo",
+ "HeaderCodecProfileHelp": "Profili Codec indicano i limiti di un dispositivo durante la riproduzione di codec specifici. Se una limitazione si applica poi saranno trascodificati media, anche se il codec \u00e8 configurato per riproduzione diretta.",
+ "HeaderContainerProfile": "Profilo Contenitore",
+ "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": "Foto",
+ "LabelUserLibrary": "Libreria utente:",
+ "LabelUserLibraryHelp": "Selezionare quale libreria utente da visualizzare sul dispositivo. Lasciare vuoto per ereditare l'impostazione predefinita.",
+ "OptionPlainStorageFolders": "Visualizzare tutte le cartelle come cartelle di archiviazione pianura",
+ "OptionPlainStorageFoldersHelp": "Se abilitato, tutte le cartelle sono rappresentati in didl come \"object.container.storageFolder\" invece di tipo pi\u00f9 specifico, come \"object.container.person.musicArtist\".",
+ "OptionPlainVideoItems": "Display all videos as plain video items",
+ "OptionPlainVideoItemsHelp": "Se attivato, tutti i video sono rappresentati in didl come \"object.item.videoItem\" invece di tipo pi\u00f9 specifico, come \"object.item.videoItem.movie\".",
+ "LabelSupportedMediaTypes": "Tipi di media supportati:",
+ "TabIdentification": "identificazione",
+ "TabDirectPlay": "Direct Play",
+ "TabContainers": "contenitori",
+ "TabCodecs": "Codecs",
+ "TabResponses": "Risposte",
+ "HeaderProfileInformation": "Informazioni sul profilo",
+ "LabelEmbedAlbumArtDidl": "Embed album art in Didl",
+ "LabelEmbedAlbumArtDidlHelp": "Alcuni dispositivi preferiscono questo metodo per ottenere le copertine degli album. Altri possono non riuscire a giocare con questa opzione abilitata.",
+ "LabelAlbumArtPN": "Album art PN:",
+ "LabelAlbumArtHelp": "PN utilizzato per le copertine degli album, all'interno del DLNA: attributo di ProfileId su UPnP: albumArtURI. Alcuni clienti richiedono un valore specifico, indipendentemente dalla dimensione dell'immagine.",
+ "LabelAlbumArtMaxWidth": "Album art Larghezza max:",
+ "LabelAlbumArtMaxWidthHelp": "Risoluzione max di album esposta tramite UPnP: albumArtURI",
+ "LabelAlbumArtMaxHeight": "Art Album Altezza max:",
+ "LabelAlbumArtMaxHeightHelp": "Risoluzione max di album esposta tramite UPnP: albumArtURI",
+ "LabelIconMaxWidth": "Larghezza max Icon:",
+ "LabelIconMaxWidthHelp": "Risoluzione max delle icone esposto tramite UPnP: icona.",
+ "LabelIconMaxHeight": "Altezza Icon max:",
+ "LabelIconMaxHeightHelp": "Risoluzione max delle icone esposto tramite UPnP: icona.",
+ "LabelIdentificationFieldHelp": "Una stringa o regex espressione maiuscole e minuscole.",
+ "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.",
+ "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",
+ "LabelManufacturer": "fabbricante",
+ "LabelManufacturerUrl": "fabbricante Url",
+ "LabelModelName": "Modello Nome",
+ "LabelModelNumber": "Modello Numero",
+ "LabelModelDescription": "Modello Descrizione",
+ "LabelModelUrl": "Modello Url",
+ "LabelSerialNumber": "Numero di serie",
+ "LabelDeviceDescription": "Descrizione dispositivo",
+ "HeaderIdentificationCriteriaHelp": "Inserire almeno un criterio di identificazione.",
+ "HeaderDirectPlayProfileHelp": "Add direct play profiles to indicate which formats the device can handle natively.",
+ "HeaderTranscodingProfileHelp": "Aggiungere i profili di transcodifica per indicare quali formati da utilizzare quando \u00e8 richiesta la transcodifica.",
+ "HeaderResponseProfileHelp": "Profili di risposta forniscono un modo per personalizzare le informazioni inviate al dispositivo durante la riproduzione di alcuni tipi di 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": "Determina il contenuto dell'elemento aggregationFlags nel urn: schemas-sonycom: namespace av.",
+ "LabelTranscodingContainer": "contenitore:",
+ "LabelTranscodingVideoCodec": "Video codec:",
+ "LabelTranscodingVideoProfile": "Video profile:",
+ "LabelTranscodingAudioCodec": "Audio codec:",
+ "OptionEnableM2tsMode": "Attiva modalit\u00e0 M2TS",
+ "OptionEnableM2tsModeHelp": "Attivare la modalit\u00e0 m2ts durante la codifica di mpegts.",
+ "OptionEstimateContentLength": "Stimare la lunghezza contenuto quando transcodifica",
+ "OptionReportByteRangeSeekingWhenTranscoding": "Segnala che il server supporta la ricerca di byte quando transcodifica",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "Questo \u00e8 necessario per alcuni dispositivi che il tempo non cercano molto bene.",
+ "HeaderSubtitleDownloadingHelp": "When Media Browser scans your video files it can search for missing subtitles, and download them using a subtitle provider such as OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "Download subtitles for:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 a2ac0e623..948569cf7 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/kk.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/kk.json
@@ -76,6 +76,7 @@
"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:",
"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",
"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\u0442\u0435\u0440 \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.",
+ "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
"ButtonDeleteImage": "\u0421\u0443\u0440\u0435\u0442\u0442\u0456 \u0436\u043e\u044e",
"LabelSelectUsers": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440\u0434\u044b \u0442\u0430\u04a3\u0434\u0430\u0443:",
"ButtonUpload": "\u041a\u0435\u0440\u0456 \u049b\u043e\u0442\u0430\u0440\u0443",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "\u0416\u043e\u0441\u043f\u0430\u0440\u043b\u0430\u0493\u0430\u043d \u0442\u0430\u043f\u0441\u044b\u0440\u043c\u0430\u043b\u0430\u0440",
"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",
- "TabUpdates": "\u0416\u0430\u04a3\u0430\u0440\u0442\u0443\u043b\u0430\u0440",
"PluginsTitle": "\u041f\u043b\u0430\u0433\u0438\u043d\u0434\u0435\u0440",
"HeaderAutomaticUpdates": "\u0410\u0432\u0442\u043e\u0436\u0430\u04a3\u0430\u0440\u0442\u0443\u043b\u0430\u0440",
- "HeaderUpdateLevel": "\u0416\u0430\u04a3\u0430\u0440\u0442\u0443 \u0434\u0435\u04a3\u0433\u0435\u0439\u0456",
"HeaderNowPlaying": "\u049a\u0430\u0437\u0456\u0440 \u043e\u0439\u043d\u0430\u0442\u044b\u043b\u0443\u0434\u0430",
"HeaderLatestAlbums": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u04a3\u0433\u0456 \u0430\u043b\u044c\u0431\u043e\u043c\u0434\u0430\u0440",
"HeaderLatestSongs": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u04a3\u0433\u0456 \u04d9\u043d\u0434\u0435\u0440",
@@ -565,6 +564,7 @@
"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": "New content added (multiple)",
"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.",
"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",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "\u041f\u043b\u0430\u0433\u0438\u043d \u0441\u04d9\u0442\u0441\u0456\u0437\u0434\u0456\u0433\u0456",
"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"
+ "ButtonMute": "\u0414\u044b\u0431\u044b\u0441\u0442\u044b \u04e9\u0448\u0456\u0440\u0443",
+ "HeaderLatestMedia": "\u0415\u04a3 \u043a\u0435\u0439\u0456\u043d\u0433\u0456 \u0442\u0430\u0441\u0443\u0448\u044b\u043b\u0430\u0440",
+ "OptionNoSubtitles": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u043b\u0435\u0440 \u0436\u043e\u049b",
+ "OptionSpecialFeatures": "\u0410\u0440\u043d\u0430\u0439\u044b \u049b\u043e\u0441\u044b\u043c\u0448\u0430\u043b\u0430\u0440",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "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": "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 801a45956..1ea974568 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ms.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ms.json
@@ -76,6 +76,7 @@
"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",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Scheduled Tasks",
"TabMyPlugins": "My Plugins",
"TabCatalog": "Catalog",
- "TabUpdates": "Updates",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Automatic Updates",
- "HeaderUpdateLevel": "Update Level",
"HeaderNowPlaying": "Now Playing",
"HeaderLatestAlbums": "Latest Albums",
"HeaderLatestSongs": "Latest Songs",
@@ -267,7 +266,7 @@
"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 language:",
+ "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.",
@@ -515,7 +514,7 @@
"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": "Down mix audio boost scale:",
+ "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",
@@ -565,6 +564,7 @@
"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",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Plugin failure",
"ButtonVolumeUp": "Volume up",
"ButtonVolumeDown": "Volume down",
- "ButtonMute": "Mute"
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 30ddaf6ac..f1e208a95 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/nb.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/nb.json
@@ -76,6 +76,7 @@
"LabelMaxParentalRating": "Maximum allowed parental rating:",
"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.",
"ButtonDeleteImage": "Slett bilde",
"LabelSelectUsers": "Select users:",
"ButtonUpload": "Last opp",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Scheduled Tasks",
"TabMyPlugins": "My Plugins",
"TabCatalog": "Katalog",
- "TabUpdates": "Oppdateringer",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Automatiske oppdateringer",
- "HeaderUpdateLevel": "Oppdaterings-niv\u00e5",
"HeaderNowPlaying": "Spiller n\u00e5",
"HeaderLatestAlbums": "Siste album",
"HeaderLatestSongs": "siste l\u00e5ter",
@@ -267,7 +266,7 @@
"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 language:",
+ "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.",
@@ -515,7 +514,7 @@
"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": "Down mix audio boost scale:",
+ "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",
@@ -565,6 +564,7 @@
"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",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Plugin failure",
"ButtonVolumeUp": "Volume up",
"ButtonVolumeDown": "Volume down",
- "ButtonMute": "Mute"
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 f5834fe87..a08d54633 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/nl.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/nl.json
@@ -76,6 +76,7 @@
"LabelMaxParentalRating": "Leeftijdsgrens",
"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.",
"ButtonDeleteImage": "Verwijder afbeelding",
"LabelSelectUsers": "Selecteer gebruikers:",
"ButtonUpload": "Uploaden",
@@ -85,7 +86,7 @@
"MessageNothingHere": "Lijst is leeg.",
"MessagePleaseEnsureInternetMetadata": "Zorg ervoor dat het downloaden van metagegevens van het internet is ingeschakeld.",
"TabSuggested": "Aanbevolen",
- "TabLatest": "Nieuwste",
+ "TabLatest": "Nieuw",
"TabUpcoming": "Binnenkort",
"TabShows": "Series",
"TabEpisodes": "Afleveringen",
@@ -103,7 +104,7 @@
"OptionDirectors": "Regiseurs",
"OptionWriters": "Schrijvers",
"OptionProducers": "Producenten",
- "HeaderResume": "Hervatten",
+ "HeaderResume": "Hervat",
"HeaderNextUp": "Eerstvolgende",
"NoNextUpItemsMessage": "Niets gevonden. Start met kijken!",
"HeaderLatestEpisodes": "Nieuwste Afleveringen",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Geplande taken",
"TabMyPlugins": "Mijn Plug-ins",
"TabCatalog": "Catalogus",
- "TabUpdates": "Updates",
"PluginsTitle": "Plug-ins",
"HeaderAutomaticUpdates": "Automatische updates",
- "HeaderUpdateLevel": "Update Niveau",
"HeaderNowPlaying": "Wordt nu afgespeeld",
"HeaderLatestAlbums": "Nieuwste Albums",
"HeaderLatestSongs": "Nieuwste Songs",
@@ -303,7 +302,7 @@
"OptionRecordOnlyNewEpisodes": "Alleen nieuwe afleveringen opnemen",
"HeaderDays": "Dagen",
"HeaderActiveRecordings": "Actieve Opnames",
- "HeaderLatestRecordings": "Nieuwste Opnames",
+ "HeaderLatestRecordings": "Nieuwe Opnames",
"HeaderAllRecordings": "Alle Opnames",
"ButtonPlay": "Afspelen",
"ButtonEdit": "Bewerken",
@@ -352,7 +351,7 @@
"LabelEveryXMinutes": "Iedere:",
"HeaderTvTuners": "Tuners",
"HeaderGallery": "Galerij",
- "HeaderLatestGames": "Nieuwste Games",
+ "HeaderLatestGames": "Nieuwe Games",
"HeaderRecentlyPlayedGames": "Recent gespeelde Games",
"TabGameSystems": "Game Systemen",
"TitleMediaLibrary": "Media Bibliotheek",
@@ -428,7 +427,7 @@
"LinkCommunity": "Gemeenschap",
"LinkGithub": "Github",
"LinkApiDocumentation": "Api Documentatie",
- "LabelFriendlyServerName": "Vriendelijke servernaam:",
+ "LabelFriendlyServerName": "Aangepaste servernaam",
"LabelFriendlyServerNameHelp": "Deze naam wordt gebruikt om deze server te identificeren. Indien leeg gelaten, zal de naam van de computer worden gebruikt.",
"LabelPreferredDisplayLanguage": "Voorkeurs weergavetaal",
"LabelPreferredDisplayLanguageHelp": "Het vertalen van Media Browser is een doorlopend project en is nog niet voltooid.",
@@ -499,7 +498,7 @@
"OptionCopy": "Kopie",
"OptionMove": "Verplaats",
"LabelTransferMethodHelp": "Bestanden kopi\u00ebren of verplaatsen van de bewaakte map",
- "HeaderLatestNews": "Laatste Nieuws",
+ "HeaderLatestNews": "Nieuws",
"HeaderHelpImproveMediaBrowser": "Help Media Browser te verbeteren",
"HeaderRunningTasks": "Actieve taken",
"HeaderActiveDevices": "Actieve apparaten",
@@ -565,7 +564,8 @@
"NotificationOptionTaskFailed": "Mislukken van de geplande taak",
"NotificationOptionInstallationFailed": "Mislukken van de installatie",
"NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd",
- "SendNotificationHelp": "Meldingen worden geplaatst in de dashboard inbox. Blader door de Plug-ins catalogus om aanvullende opties voor meldingen te installeren.",
+ "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
+ "SendNotificationHelp": "Meldingen worden geplaatst in de inbox op het dashboard. Blader door de Plug-ins catalogus om aanvullende opties voor meldingen te installeren.",
"NotificationOptionServerRestartRequired": "Server herstart nodig",
"LabelNotificationEnabled": "Deze melding inschakelen",
"LabelMonitorUsers": "Monitor activiteit van:",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Plug-in fout",
"ButtonVolumeUp": "Volume omhoog",
"ButtonVolumeDown": "Volume omlaag",
- "ButtonMute": "Dempen"
+ "ButtonMute": "Dempen",
+ "HeaderLatestMedia": "Nieuw in bibliotheek",
+ "OptionNoSubtitles": "Geen ondertitels",
+ "OptionSpecialFeatures": "Extra's",
+ "HeaderCollections": "Collecties",
+ "HeaderMyLibrary": "Mijn Bibliotheek",
+ "LabelProfileCodecsHelp": "Gescheiden door een komma. Deze kan leeg gelaten worden om te laten gelden voor alle codecs.",
+ "LabelProfileContainersHelp": "Gescheiden door een komma. Deze kan leeg gelaten worden om te laten gelden voor alle containers.",
+ "HeaderResponseProfile": "Antwoord Profiel",
+ "LabelType": "Type:",
+ "LabelProfileContainer": "Container:",
+ "LabelProfileVideoCodecs": "Video codecs:",
+ "LabelProfileAudioCodecs": "Audio codecs:",
+ "LabelProfileCodecs": "Codecs:",
+ "HeaderDirectPlayProfile": "Direct Afspelen Profiel",
+ "HeaderTranscodingProfile": "Direct Afspelen Profiel",
+ "HeaderCodecProfile": "Codec Profiel",
+ "HeaderCodecProfileHelp": "Codec profielen geven de beperkingen van een apparaat bij het afspelen van bepaalde codecs. Als een beperking geldt dan zal de media getranscodeerd worden, zelfs indien de codec is geconfigureerd voor direct afspelen.",
+ "HeaderContainerProfile": "Container Profiel",
+ "HeaderContainerProfileHelp": "Container profielen geven de beperkingen van een apparaat bij het afspelen van bepaalde formaten. Als een beperking geldt dan zal de media getranscodeerd worden, zelfs indien het formaat is geconfigureerd voor direct afspelen.",
+ "OptionProfileVideo": "Video",
+ "OptionProfileAudio": "Audio",
+ "OptionProfileVideoAudio": "Video Audio",
+ "OptionProfilePhoto": "Foto",
+ "LabelUserLibrary": "Gebruikers Bibliotheek:",
+ "LabelUserLibraryHelp": "Selecteer welke gebruikers bibliotheek weergegeven moet worden op het apparaat. Laat leeg standaardinstelling te gebruiken.",
+ "OptionPlainStorageFolders": "Alle mappen weergeven als gewone opslagmappen",
+ "OptionPlainStorageFoldersHelp": "Wanneer ingeschakeld dan worden alle mappen in DIDL weergegeven als 'object.container.storageFolder' in plaats van een meer specifiek type, zoals 'object.container.person.musicArtist'.",
+ "OptionPlainVideoItems": "Alle video's weergeven als gewone video items",
+ "OptionPlainVideoItemsHelp": "Indien ingeschakeld dan worden alle video's in DIDL weergegeven als 'object.item.videoItem' in plaats van een meer specifiek type, zoals 'object.item.videoItem.movie'.",
+ "LabelSupportedMediaTypes": "Ondersteunde Media Types:",
+ "TabIdentification": "Identificatie",
+ "TabDirectPlay": "Direct Afspelen",
+ "TabContainers": "Containers",
+ "TabCodecs": "Codecs",
+ "TabResponses": "Reacties",
+ "HeaderProfileInformation": "Profiel Informatie",
+ "LabelEmbedAlbumArtDidl": "Insluiten van albumhoezen in Didl",
+ "LabelEmbedAlbumArtDidlHelp": "Sommige apparaten prefereren deze methode voor het verkrijgen van albumhoezen. Anderen kunnen falen om af te spelen met deze optie ingeschakeld.",
+ "LabelAlbumArtPN": "Albumhoes PN:",
+ "LabelAlbumArtHelp": "PN gebruikt voor albumhoes, binnen het kenmerk van de dlna:profileID op upnp:albumArtURI. Sommige Cli\u00ebnts eisen een specifieke waarde, ongeacht de grootte van de afbeelding",
+ "LabelAlbumArtMaxWidth": "Albumhoes max. breedte:",
+ "LabelAlbumArtMaxWidthHelp": "Max. resolutie van albumhoezen weergegeven via upnp:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "Albumhoes max. hoogte:",
+ "LabelAlbumArtMaxHeightHelp": "Max. resolutie van albumhoezen weergegeven via upnp:albumArtURI.",
+ "LabelIconMaxWidth": "Pictogram max breedte:",
+ "LabelIconMaxWidthHelp": "Max. resolutie van pictogrammen weergegeven via upnp:icon.",
+ "LabelIconMaxHeight": "Pictogram max. hoogte:\n",
+ "LabelIconMaxHeightHelp": "Max. resolutie van pictogrammen weergegeven via upnp:icon.",
+ "LabelIdentificationFieldHelp": "Een niet-hoofdlettergevoelige subtekenreeks of regex expressie.",
+ "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.",
+ "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",
+ "LabelManufacturer": "Fabrikant",
+ "LabelManufacturerUrl": "Url Fabrikant",
+ "LabelModelName": "Modelnaam",
+ "LabelModelNumber": "Modelnummer",
+ "LabelModelDescription": "Model omschrijving",
+ "LabelModelUrl": "Model url",
+ "LabelSerialNumber": "Serienummer",
+ "LabelDeviceDescription": "Apparaat omschrijving",
+ "HeaderIdentificationCriteriaHelp": "Voer ten minste \u00e9\u00e9n identificatiecriteria in.",
+ "HeaderDirectPlayProfileHelp": "Toevoegen direct afspelen profielen om aan te geven welke formaten het apparaat standaard aankan.",
+ "HeaderTranscodingProfileHelp": "Transcoding profielen toevoegen om aan te geven welke indelingen moeten worden gebruikt wanneer transcoding vereist is.",
+ "HeaderResponseProfileHelp": "Responsprofielen bieden een manier om informatie, verzonden naar het apparaat bij het afspelen van bepaalde soorten media aan te passen.",
+ "LabelXDlnaCap": "X-Dlna cap:",
+ "LabelXDlnaCapHelp": "Bepaalt de inhoud van het X_DLNACAP element in de urn: schemas-dlna-org:device-1-0 namespace. \n",
+ "LabelXDlnaDoc": "X-Dlna doc:",
+ "LabelXDlnaDocHelp": "Bepaalt de inhoud van het X_DLNADOC element in de urn: schemas-dlna-org:device-1-0 namespace. ",
+ "LabelSonyAggregationFlags": "Sony aggregatie vlaggen:",
+ "LabelSonyAggregationFlagsHelp": "Bepaalt de inhoud van het aggregationFlags element in de urn schemas-sonycom av namespace.",
+ "LabelTranscodingContainer": "Container:",
+ "LabelTranscodingVideoCodec": "Video codec:",
+ "LabelTranscodingVideoProfile": "Video profile:",
+ "LabelTranscodingAudioCodec": "Audio codec:",
+ "OptionEnableM2tsMode": "M2ts-modus inschakelen",
+ "OptionEnableM2tsModeHelp": "m2ts-modus bij het encoderen naar mpegts inschakelen",
+ "OptionEstimateContentLength": "Lengte schatten van de inhoud bij het transcoderen",
+ "OptionReportByteRangeSeekingWhenTranscoding": "Rapporteer dat de server byte zoeken tijdens transcoderen ondersteunt",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "Dit is vereist voor bepaalde apparaten die zo goed op tijd zoeken.",
+ "HeaderSubtitleDownloadingHelp": "Bij het scannen van je films kan Media Browser naar ontbrekende ondertiteling zoeken en deze downloaden bij ondertiteling providers zoals OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "Download ondertiteling voor:",
+ "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",
+ "LabelOpenSubtitlesUsername": "Gebruikersnaam Open Subtitles:",
+ "LabelOpenSubtitlesPassword": "Wachtwoord Open Subtitles:",
+ "LabelAudioLanguagePreferenceHelp": "Indien niet ingevuld zal het standaard audio spoor geselecteerd worden, ongeacht de taal.",
+ "LabelDownloadLanguages": "Download talen:",
+ "ButtonRegister": "Aanmelden",
+ "LabelSkipIfAudioTrackPresent": "Overslaan als de standaard audio track overeenkomt met de taal van de download",
+ "LabelSkipIfAudioTrackPresentHelp": "Uitvinken om ervoor te zorgen dat alle video's ondertitels krijgen, ongeacht de gesproken taal.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 a234fe6dc..16e8ba74e 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json
@@ -76,6 +76,7 @@
"LabelMaxParentalRating": "Classifica\u00e7\u00e3o parental m\u00e1xima permitida:",
"MaxParentalRatingHelp": "Conte\u00fado com classifica\u00e7\u00e3o maior ser\u00e1 ocultado do usu\u00e1rio.",
"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.",
+ "ChannelAccessHelp": "Selecione os canais a compartilhar com este usu\u00e1rio. Administradores poder\u00e3o editar todos os canais usando o gerenciador de metadados.",
"ButtonDeleteImage": "Apagar Imagem",
"LabelSelectUsers": "Selecionar usu\u00e1rios:",
"ButtonUpload": "Carregar",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Tarefas Agendadas",
"TabMyPlugins": "Meus Plugins",
"TabCatalog": "Cat\u00e1logo",
- "TabUpdates": "Atualiza\u00e7\u00f5es",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Atualiza\u00e7\u00f5es Autom\u00e1ticas",
- "HeaderUpdateLevel": "N\u00edvel de Atualiza\u00e7\u00e3o",
"HeaderNowPlaying": "Reproduzindo Agora",
"HeaderLatestAlbums": "\u00c1lbuns Recentes",
"HeaderLatestSongs": "M\u00fasicas Recentes",
@@ -267,7 +266,7 @@
"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 mostrar 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 \u00e9 executado \u00e0s 4 hs da madrugada, 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.",
- "LabelMetadataDownloadLanguage": "Idioma preferido:",
+ "LabelMetadataDownloadLanguage": "Idioma preferido para transfer\u00eancia:",
"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 transfer\u00eancia \u00e9 \u00fatil se voc\u00ea usa tamb\u00e9m outros produtos.",
@@ -515,7 +514,7 @@
"ErrorConnectingToMediaBrowserRepository": "Ocorreu um erro ao conectar com o reposit\u00f3rio remoto do Media Browser",
"LabelComponentsUpdated": "Os seguintes componentes foram instalados ou atualizados:",
"MessagePleaseRestartServerToFinishUpdating": "Por favor, reinicie o servidor para terminar de aplicar as atualiza\u00e7\u00f5es.",
- "LabelDownMixAudioScale": "Escala do aumento de \u00e1udio ao executar downmix.",
+ "LabelDownMixAudioScale": "Aumento do \u00e1udio ao executar downmix:",
"LabelDownMixAudioScaleHelp": "Aumentar o \u00e1udio quando executar downmix. Defina como 1 para preservar o volume original.",
"ButtonLinkKeys": "Unir as chaves.",
"LabelOldSupporterKey": "Chave antiga de colaborador",
@@ -565,6 +564,7 @@
"NotificationOptionTaskFailed": "Falha na tarefa agendada",
"NotificationOptionInstallationFailed": "Falha na instala\u00e7\u00e3o",
"NotificationOptionNewLibraryContent": "Adicionado novo conte\u00fado",
+ "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
"SendNotificationHelp": "Por padr\u00e3o, notifica\u00e7\u00f5es s\u00e3o entregues \u00e0 caixa de entrada do painel. Navegue pelo cat\u00e1logo de plugins para instalar op\u00e7\u00f5es adicionais de notifica\u00e7\u00f5es.",
"NotificationOptionServerRestartRequired": "Necessidade de reiniciar servidor",
"LabelNotificationEnabled": "Ativar esta notifica\u00e7\u00e3o",
@@ -600,7 +600,7 @@
"LetterButtonAbbreviation": "A",
"TabNowPlaying": "Reproduzindo Agora",
"TabNavigation": "Navega\u00e7\u00e3o",
- "TabControls": "Controls",
+ "TabControls": "Controles",
"ButtonFullscreen": "Alternar tela cheia",
"ButtonScenes": "Cenas",
"ButtonSubtitles": "Legendas",
@@ -612,7 +612,104 @@
"LabelGroupMoviesIntoCollections": "Agrupar filmes nas cole\u00e7\u00f5es",
"LabelGroupMoviesIntoCollectionsHelp": "Ao exibir listas de filmes, filmes que perten\u00e7am a uma cole\u00e7\u00e3o ser\u00e3o exibidos como um \u00fanico item agrupado.",
"NotificationOptionPluginError": "Falha no plugin",
- "ButtonVolumeUp": "Volume up",
- "ButtonVolumeDown": "Volume down",
- "ButtonMute": "Mute"
+ "ButtonVolumeUp": "Aumentar volume",
+ "ButtonVolumeDown": "Diminuir volume",
+ "ButtonMute": "Mudo",
+ "HeaderLatestMedia": "\u00daltima m\u00eddia",
+ "OptionNoSubtitles": "Nenhuma legenda",
+ "OptionSpecialFeatures": "Caracter\u00edsticas Especiais",
+ "HeaderCollections": "Cole\u00e7\u00f5es",
+ "HeaderMyLibrary": "Minha Biblioteca",
+ "LabelProfileCodecsHelp": "Separados por v\u00edrgula. Pode ser deixado em branco para usar com todos os codecs.",
+ "LabelProfileContainersHelp": "Separados por v\u00edrgula. Pode ser deixado em branco para usar com todos os containers.",
+ "HeaderResponseProfile": "Perfil de Resposta",
+ "LabelType": "Tipo:",
+ "LabelProfileContainer": "Container:",
+ "LabelProfileVideoCodecs": "Codecs de v\u00eddeo:",
+ "LabelProfileAudioCodecs": "Codecs de \u00e1udio:",
+ "LabelProfileCodecs": "Codecs:",
+ "HeaderDirectPlayProfile": "Perfil da Reprodu\u00e7\u00e3o Direta",
+ "HeaderTranscodingProfile": "Perfil da Transcodifica\u00e7\u00e3o",
+ "HeaderCodecProfile": "Perfil do Codec",
+ "HeaderCodecProfileHelp": "Perfis do Codec indicam as limita\u00e7\u00f5es de um dispositivo ao reproduzir codecs espec\u00edficos. Se uma limita\u00e7\u00e3o ocorre, a m\u00eddia ser\u00e1 transcodificada, mesmo se o codec estiver configurado para reprodu\u00e7\u00e3o direta.",
+ "HeaderContainerProfile": "Perfil do Container",
+ "HeaderContainerProfileHelp": "Perfis do Container indicam as limita\u00e7\u00f5es de um dispositivo ao reproduzir formatos espec\u00edficos. Se uma limita\u00e7\u00e3o ocorre, a m\u00eddia ser\u00e1 transcodificada, mesmo se o formato estiver configurado para reprodu\u00e7\u00e3o direta.",
+ "OptionProfileVideo": "V\u00eddeo",
+ "OptionProfileAudio": "\u00c1udio",
+ "OptionProfileVideoAudio": "\u00c1udio do V\u00eddeo",
+ "OptionProfilePhoto": "Foto",
+ "LabelUserLibrary": "Biblioteca do usu\u00e1rio:",
+ "LabelUserLibraryHelp": "Selecione qual biblioteca de usu\u00e1rio ser\u00e1 exibida no dispositivo. Deixa em branco para usar a configura\u00e7\u00e3o padr\u00e3o.",
+ "OptionPlainStorageFolders": "Exibir todas as pastas como pastas de armazenamento simples",
+ "OptionPlainStorageFoldersHelp": "Se ativado, todas as pastas s\u00e3o representadas no DIDL como \"object.container.storageFolder\" ao inv\u00e9s de um tipo mais espec\u00edfico como, por exemplo, \"object.container.person.musicArtist\".",
+ "OptionPlainVideoItems": "Exibir todos os v\u00eddeos como itens de v\u00eddeo simples",
+ "OptionPlainVideoItemsHelp": "Se ativado, todos os v\u00eddeos s\u00e3o representados no DIDL como \"object.item.videoItem\" ao inv\u00e9s de um tipo mais espec\u00edfico como, por exemplo, \"object.item.videoItem.movie\".",
+ "LabelSupportedMediaTypes": "Tipos de M\u00eddia Suportados:",
+ "TabIdentification": "Identifica\u00e7\u00e3o",
+ "TabDirectPlay": "Reprodu\u00e7\u00e3o Direta",
+ "TabContainers": "Containers",
+ "TabCodecs": "Codecs",
+ "TabResponses": "Respostas",
+ "HeaderProfileInformation": "Informa\u00e7\u00e3o do Perfil",
+ "LabelEmbedAlbumArtDidl": "Embutir a capa do \u00e1lbum no Didl",
+ "LabelEmbedAlbumArtDidlHelp": "Alguns dispositivos preferem este m\u00e9todo para obter a capa do \u00e1lbum. Outros podem falhar para reproduzir com esta op\u00e7\u00e3o ativada",
+ "LabelAlbumArtPN": "PN da capa do \u00e1lbum:",
+ "LabelAlbumArtHelp": "O PN usado para a capa do album, dentro do atributo dlna:profileID em upnp:albumArtURI. Alguns clientes requerem um valor espec\u00edfico, independente do tamanho da imagem.",
+ "LabelAlbumArtMaxWidth": "Largura m\u00e1xima da capa do \u00e1lbum:",
+ "LabelAlbumArtMaxWidthHelp": "Resolu\u00e7\u00e3o m\u00e1xima da capa do \u00e1lbum que \u00e9 exposta via upnp:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "Altura m\u00e1xima da capa do \u00e1lbum:",
+ "LabelAlbumArtMaxHeightHelp": "Resolu\u00e7\u00e3o m\u00e1xima da capa do \u00e1lbum que \u00e9 exposta via upnp:albumArtURI.",
+ "LabelIconMaxWidth": "Largura m\u00e1xima do \u00edcone:",
+ "LabelIconMaxWidthHelp": "Resolu\u00e7\u00e3o m\u00e1xima do \u00edcone que \u00e9 exposto via upnp:icon.",
+ "LabelIconMaxHeight": "Altura m\u00e1xima do \u00edcone:",
+ "LabelIconMaxHeightHelp": "Resolu\u00e7\u00e3o m\u00e1xima do \u00edcone que \u00e9 exposto via upnp:icon.",
+ "LabelIdentificationFieldHelp": "Uma substring ou express\u00e3o regex que n\u00e3o diferencia mai\u00fascula de min\u00fasculas.",
+ "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.",
+ "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.",
+ "LabelFriendlyName": "Nome amig\u00e1vel",
+ "LabelManufacturer": "Fabricante",
+ "LabelManufacturerUrl": "Url do fabricante",
+ "LabelModelName": "Nome do modelo",
+ "LabelModelNumber": "N\u00famero do modelo",
+ "LabelModelDescription": "Descri\u00e7\u00e3o do modelo",
+ "LabelModelUrl": "Url do modelo",
+ "LabelSerialNumber": "N\u00famero de s\u00e9rie",
+ "LabelDeviceDescription": "Descri\u00e7\u00e3o do dispositivo",
+ "HeaderIdentificationCriteriaHelp": "Digite, ao menos, um crit\u00e9rio de identifica\u00e7\u00e3o.",
+ "HeaderDirectPlayProfileHelp": "Adicionar perfis de reprodu\u00e7\u00e3o direta que indiquem que formatos o dispositivo pode suportar nativamente.",
+ "HeaderTranscodingProfileHelp": "Adicionar perfis de transcodifica\u00e7\u00e3o que indiquem que formatos dever\u00e3o ser usados quando a transcodifica\u00e7\u00e3o \u00e9 necess\u00e1ria.",
+ "HeaderResponseProfileHelp": "Perfis de resposta oferecem uma forma de personalizar a informa\u00e7\u00e3o enviada para o dispositivo ao executar certos tipos de m\u00eddia.",
+ "LabelXDlnaCap": "X-Dlna cap:",
+ "LabelXDlnaCapHelp": "Determina o conte\u00fado do elemento X_DLNACAP no namespace urn:schemas-dlna-org:device-1-0.",
+ "LabelXDlnaDoc": "X-Dlna doc:",
+ "LabelXDlnaDocHelp": "Determina o conte\u00fado do elemento X_DLNADOC no namespace urn:schemas-dlna-org:device-1-0",
+ "LabelSonyAggregationFlags": "Flags de agrega\u00e7\u00e3o da Sony:",
+ "LabelSonyAggregationFlagsHelp": "Determina o conte\u00fado do elemento aggregationFlags no namespace urn:schemas-sonycom:av.",
+ "LabelTranscodingContainer": "Container:",
+ "LabelTranscodingVideoCodec": "Codec do v\u00eddeo:",
+ "LabelTranscodingVideoProfile": "Perfil do v\u00eddeo:",
+ "LabelTranscodingAudioCodec": "Codec do \u00c1udio:",
+ "OptionEnableM2tsMode": "Ativar modo M2ts",
+ "OptionEnableM2tsModeHelp": "Ative o modo m2ts quando codificar para mpegts.",
+ "OptionEstimateContentLength": "Estimar o tamanho do conte\u00fado quando transcodificar",
+ "OptionReportByteRangeSeekingWhenTranscoding": "Reportar que o servidor suporta busca de byte quando transcodificar",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "Isto \u00e9 necess\u00e1rio para alguns dispositivos que n\u00e3o buscam o tempo muito bem.",
+ "HeaderSubtitleDownloadingHelp": "Quando o Media Browser verificar seus arquivos de v\u00eddeo, ele pode buscar legendas que n\u00e3o existam e transferi-las usando um provedor de legendas como, por exemplo, o OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "Transferir legendas para:",
+ "LabelSkipIfGraphicalSubsPresent": "Pular se o v\u00eddeo j\u00e1 possuir legendas gr\u00e1ficas",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Manter vers\u00f5es das legendas em texto resultar\u00e1 em uma entrega mais eficiente para os clientes m\u00f3veis.",
+ "TabSubtitles": "Legendas",
+ "LabelOpenSubtitlesUsername": "Nome do usu\u00e1rio do Open Subtitles:",
+ "LabelOpenSubtitlesPassword": "Senha do Open Subtitles:",
+ "LabelAudioLanguagePreferenceHelp": "Se estiver em branco, a faixa de \u00e1udio padr\u00e3o ser\u00e1 selecionada, independente do idioma.",
+ "LabelDownloadLanguages": "Idiomas para transfer\u00eancia:",
+ "ButtonRegister": "Registrar",
+ "LabelSkipIfAudioTrackPresent": "Pular se a faixa de \u00e1udio padr\u00e3o coincidir com o idioma de transfer\u00eancia",
+ "LabelSkipIfAudioTrackPresentHelp": "Desmarque esta op\u00e7\u00e3o para garantir que todos os v\u00eddeos t\u00eam legendas, independente do idioma do \u00e1udio.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 6278e220e..5d9f6aa75 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json
@@ -76,8 +76,9 @@
"LabelMaxParentalRating": "Controlo Parental m\u00e1ximo permitido:",
"MaxParentalRatingHelp": "Conte\u00fado com classifica\u00e7\u00e3o mais elevada ser\u00e1 escondida deste utilizador.",
"LibraryAccessHelp": "Escolha as pastas de media a partilha com este utilizador. Os Administradores poder\u00e3o editar todas as pastas, usando o Gestor de Metadados.",
+ "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
"ButtonDeleteImage": "Apagar imagem",
- "LabelSelectUsers": "Select users:",
+ "LabelSelectUsers": "Selecionar utilizadores:",
"ButtonUpload": "Carregar",
"HeaderUploadNewImage": "Carregar Nova Imagem",
"LabelDropImageHere": "Largar imagem aqui",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Tarefas Agendadas",
"TabMyPlugins": "As minhas extens\u00f5es",
"TabCatalog": "Cat\u00e1logo",
- "TabUpdates": "Atualiza\u00e7\u00f5es",
"PluginsTitle": "Extens\u00f5es",
"HeaderAutomaticUpdates": "Atualiza\u00e7\u00f5es autom\u00e1ticas",
- "HeaderUpdateLevel": "N\u00edvel de atualiza\u00e7\u00e3o",
"HeaderNowPlaying": "A reproduzir",
"HeaderLatestAlbums": "\u00daltimos \u00c1lbuns",
"HeaderLatestSongs": "\u00daltimas m\u00fasicas",
@@ -515,7 +514,7 @@
"ErrorConnectingToMediaBrowserRepository": "Ocorreu um erro ao conectar ao reposit\u00f3rio remoto do Media Browser.",
"LabelComponentsUpdated": "Os componentes seguintes foram instalados ou atualizados:",
"MessagePleaseRestartServerToFinishUpdating": "Por favor reinicie o servidor para terminar a aplica\u00e7\u00e3o das atualiza\u00e7\u00f5es.",
- "LabelDownMixAudioScale": "Escala do aumento de \u00e1udio ao fazer downmix.",
+ "LabelDownMixAudioScale": "Escala do aumento de \u00e1udio ao fazer downmix:",
"LabelDownMixAudioScaleHelp": "Aumentar o \u00e1udio ao fazer downmix. Defina como 1 para preservar o volume original.",
"ButtonLinkKeys": "Unir Chaves",
"LabelOldSupporterKey": "Chave de apoiante antiga",
@@ -536,9 +535,9 @@
"TabPlayTo": "Play To",
"LabelEnableDlnaServer": "Ativar servidor DLNA",
"LabelEnableDlnaServerHelp": "Permite aos dispositivos UPnP da sua rede, navegar e reproduzir conte\u00fado do Media Browser.",
- "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)",
+ "LabelEnableBlastAliveMessages": "Propagar mensagens de reconhecimento",
+ "LabelEnableBlastAliveMessagesHelp": "Ativar isto se o servidor n\u00e3o \u00e9 detetado convenientemente por outros dispositivos UPnP na sua rede.",
+ "LabelBlastMessageInterval": "Intervalo das mensagens de reconhecimento (segundos)",
"LabelBlastMessageIntervalHelp": "Determines the duration in seconds between server alive messages.",
"LabelDefaultUser": "Utilizador padr\u00e3o:",
"LabelDefaultUserHelp": "Determines which user library should be displayed on connected devices. This can be overridden for each device using profiles.",
@@ -565,54 +564,152 @@
"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",
+ "LabelNotificationEnabled": "Ativar esta notifica\u00e7\u00e3o",
"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",
+ "CategoryUser": "Utilizador",
+ "CategorySystem": "Sistema",
+ "CategoryApplication": "Aplica\u00e7\u00e3o",
"CategoryPlugin": "Plugin",
- "LabelMessageTitle": "Message title:",
+ "LabelMessageTitle": "Titulo da mensagem:",
"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",
+ "OptionAllUsers": "Todos os utilizadores",
+ "OptionAdminUsers": "Administradores",
+ "OptionCustomUsers": "Personalizado",
+ "ButtonArrowUp": "Cima",
+ "ButtonArrowDown": "Baixo",
+ "ButtonArrowLeft": "Esquerda",
+ "ButtonArrowRight": "Direita",
+ "ButtonBack": "Voltar",
"ButtonInfo": "Info",
"ButtonPageUp": "Page Up",
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
- "ButtonHome": "Home",
+ "ButtonHome": "In\u00edcio",
"ButtonSettings": "Settings",
"ButtonTakeScreenshot": "Capture Screenshot",
"ButtonLetterUp": "Letter Up",
"ButtonLetterDown": "Letter Down",
"PageButtonAbbreviation": "PG",
"LetterButtonAbbreviation": "A",
- "TabNowPlaying": "Now Playing",
- "TabNavigation": "Navigation",
+ "TabNowPlaying": "A reproduzir agora",
+ "TabNavigation": "Navega\u00e7\u00e3o",
"TabControls": "Controls",
"ButtonFullscreen": "Toggle fullscreen",
- "ButtonScenes": "Scenes",
- "ButtonSubtitles": "Subtitles",
- "ButtonAudioTracks": "Audio tracks",
- "ButtonPreviousTrack": "Previous track",
- "ButtonNextTrack": "Next track",
- "ButtonStop": "Stop",
- "ButtonPause": "Pause",
+ "ButtonScenes": "Cenas",
+ "ButtonSubtitles": "Legendas",
+ "ButtonAudioTracks": "Faixas de \u00e1udio",
+ "ButtonPreviousTrack": "Faixa anterior",
+ "ButtonNextTrack": "Pr\u00f3xima faixa",
+ "ButtonStop": "Parar",
+ "ButtonPause": "Pausar",
"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"
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Tipo:",
+ "LabelProfileContainer": "Contentor:",
+ "LabelProfileVideoCodecs": "Codecs do v\u00eddeo:",
+ "LabelProfileAudioCodecs": "Codecs do \u00e1udio:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 bac157d74..71deb596c 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ru.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ru.json
@@ -1,15 +1,15 @@
{
"LabelExit": "\u0412\u044b\u0445\u043e\u0434",
- "LabelVisitCommunity": "\u041f\u043e\u0441\u0435\u0442\u0438\u0442\u044c \u0421\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e",
+ "LabelVisitCommunity": "\u041f\u043e\u0441\u0435\u0449\u0435\u043d\u0438\u0435 \u0421\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430",
"LabelGithubWiki": "\u0412\u0438\u043a\u0438 \u043d\u0430 Github",
"LabelSwagger": "\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Swagger",
"LabelStandard": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442",
"LabelViewApiDocumentation": "\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e API",
"LabelBrowseLibrary": "\u041e\u0431\u0437\u043e\u0440 \u041c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438",
- "LabelConfigureMediaBrowser": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c Media Browser",
+ "LabelConfigureMediaBrowser": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 Media Browser",
"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",
- "LabelRestartServer": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440",
- "LabelShowLogWindow": "\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u0416\u0443\u0440\u043d\u0430\u043b \u0432 \u043e\u043a\u043d\u0435",
+ "LabelRestartServer": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430",
+ "LabelShowLogWindow": "\u041e\u0442\u043a\u0440\u044b\u0442\u0438\u0435 \u0416\u0443\u0440\u043d\u0430\u043b\u0430 \u0432 \u043e\u043a\u043d\u0435",
"LabelPrevious": "\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435",
"LabelFinish": "\u0417\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c",
"LabelNext": "\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435",
@@ -24,15 +24,15 @@
"LabelWindowsService": "\u0421\u043b\u0443\u0436\u0431\u0430 Windows",
"AWindowsServiceHasBeenInstalled": "\u0421\u043b\u0443\u0436\u0431\u0430 Windows \u0431\u044b\u043b\u0430 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430.",
"WindowsServiceIntro1": "\u041e\u0431\u044b\u0447\u043d\u043e Media Browser Server \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \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 \u0435\u0441\u043b\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0435\u0433\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \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\u0442\u0438\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.",
- "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 \u0442\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 <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>.",
+ "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 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \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>.",
"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",
"LabelEnableVideoImageExtraction": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0430 \u0438\u0437 \u0432\u0438\u0434\u0435\u043e",
"VideoImageExtractionHelp": "\u0414\u043b\u044f \u0432\u0438\u0434\u0435\u043e, \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.",
"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\u0451\u043d\u043d\u044b\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0441\u0446\u0435\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043c\u0435\u043d\u044e \u0432\u044b\u0431\u043e\u0440\u0430 \u0441\u0446\u0435\u043d\u044b. \u042d\u0442\u043e\u0442 \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. \u0420\u0430\u0431\u043e\u0442\u0430 \u0434\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 4:00 \u0443\u0442\u0440\u0430, \u043e\u0434\u043d\u0430\u043a\u043e, \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\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 \u044d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 \u0447\u0430\u0441 \u043f\u0438\u043a.",
- "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. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432.",
+ "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.",
"ButtonOk": "\u041e\u041a",
"ButtonCancel": "\u041e\u0442\u043c\u0435\u043d\u0430",
"ButtonNew": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c",
@@ -47,7 +47,7 @@
"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.",
"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": "Media Browser \u0441\u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043c\u0435\u0434\u0438\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0435 \u0434\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 \u0434\u0430\u043d\u043d\u044b\u0445.",
+ "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.",
"TabPreferences": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438",
"TabPassword": "\u041f\u0430\u0440\u043e\u043b\u044c",
"TabLibraryAccess": "\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435",
@@ -73,11 +73,12 @@
"LabelNewPasswordConfirm": "\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f",
"HeaderCreatePassword": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c",
"LabelCurrentPassword": "\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u043f\u0430\u0440\u043e\u043b\u044c",
- "LabelMaxParentalRating": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \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:",
+ "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",
"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 \u0441\u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0432\u0441\u0435 \u043f\u0430\u043f\u043a\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0414\u0438\u0441\u043f\u0435\u0442\u0447\u0435\u0440 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445.",
+ "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
"ButtonDeleteImage": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0440\u0438\u0441\u0443\u043d\u043e\u043a",
- "LabelSelectUsers": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439:",
+ "LabelSelectUsers": "\u0412\u044b\u0431\u043e\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439:",
"ButtonUpload": "\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c",
"HeaderUploadNewImage": "\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043d\u043e\u0432\u043e\u0433\u043e \u0440\u0438\u0441\u0443\u043d\u043a\u0430",
"LabelDropImageHere": "\u041f\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442\u0435 \u0440\u0438\u0441\u0443\u043d\u043e\u043a \u0441\u044e\u0434\u0430",
@@ -146,16 +147,14 @@
"ScheduledTasksTitle": "\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u043d\u0438\u044f",
"TabMyPlugins": "\u041c\u043e\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u044b",
"TabCatalog": "\u041a\u0430\u0442\u0430\u043b\u043e\u0433",
- "TabUpdates": "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f",
"PluginsTitle": "\u041f\u043b\u0430\u0433\u0438\u043d\u044b",
- "HeaderAutomaticUpdates": "\u0410\u0432\u0442\u043e-\u043e\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",
+ "HeaderAutomaticUpdates": "\u0410\u0432\u0442\u043e\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f",
"HeaderNowPlaying": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f",
"HeaderLatestAlbums": "\u0421\u0432\u0435\u0436\u0438\u0435 \u0430\u043b\u044c\u0431\u043e\u043c\u044b",
"HeaderLatestSongs": "\u0421\u0432\u0435\u0436\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u0438",
"HeaderRecentlyPlayed": "\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0435",
"HeaderFrequentlyPlayed": "\u0427\u0430\u0441\u0442\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u044b\u0435",
- "DevBuildWarning": "\u0421\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f \u0420\u0430\u0437\u0440\u0430\u0431[\u043e\u0442\u043a\u0438] \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0438\u0441\u043f\u044b\u0442\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c\u0438. \u0412\u044b\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u043e, \u044d\u0442\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u043d\u0435 \u0431\u044b\u043b\u0438 \u043e\u0442\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0434\u043e \u043a\u043e\u043d\u0446\u0430. \u0420\u0430\u0431\u043e\u0442\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0430\u0432\u0430\u0440\u0438\u0439\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c\u0441\u044f, \u0430 \u043c\u043d\u043e\u0433\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u043e\u0433\u0443\u0442 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e\u0432\u0441\u0435\u043c.",
+ "DevBuildWarning": "\u0421\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f \u0420\u0430\u0437\u0440\u0430\u0431[\u043e\u0442\u043a\u0438] \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u044b\u0440\u044b\u043c\u0438. \u0412\u044b\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u043e, \u044d\u0442\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u043d\u0435 \u0431\u044b\u043b\u0438 \u043e\u0442\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0434\u043e \u043a\u043e\u043d\u0446\u0430. \u0420\u0430\u0431\u043e\u0442\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0430\u0432\u0430\u0440\u0438\u0439\u043d\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c\u0441\u044f, \u0430 \u043c\u043d\u043e\u0433\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043c\u043e\u0433\u0443\u0442 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u043e\u0432\u0441\u0435\u043c.",
"LabelVideoType": "\u0422\u0438\u043f \u0432\u0438\u0434\u0435\u043e:",
"OptionBluray": "BluRay",
"OptionDvd": "DVD",
@@ -200,7 +199,7 @@
"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 \u043d\u0430\u0448\u0435\u0439 \u0431\u0430\u0437\u043e\u0439 \u0437\u043d\u0430\u043d\u0438\u0439 \u043f\u043e \u043e\u043a\u0430\u0437\u0430\u043d\u0438\u044e \u043f\u043e\u043c\u043e\u0449\u0438 \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u0442\u0434\u0430\u0447\u0438 \u043e\u0442 Media Browser.",
+ "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.",
"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",
@@ -212,7 +211,7 @@
"LabelName": "\u0418\u043c\u044f:",
"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\u044f\u0442\u044c \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 \u043d\u043e\u0441\u0442\u0435\u043b\u0435\u0439",
"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\u044f\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435 \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",
@@ -231,12 +230,12 @@
"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\u043e\u0435",
- "LabelAutomaticUpdateLevel": "\u0421\u0442\u0435\u043f\u0435\u043d\u044c \u0430\u0432\u0442\u043e-\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f",
+ "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",
"OptionDev": "\u0420\u0430\u0437\u0440\u0430\u0431 (\u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e)",
"LabelAllowServerAutoRestart": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0430\u0432\u0442\u043e\u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439",
- "LabelAllowServerAutoRestartHelp": "\u0421\u0435\u0440\u0432\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u044f, \u043a\u043e\u0433\u0434\u0430 \u043d\u0438 \u043e\u0434\u0438\u043d \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u0435\u043d.",
+ "LabelAllowServerAutoRestartHelp": "\u0421\u0435\u0440\u0432\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u044f, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u0442 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.",
"LabelEnableDebugLogging": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0416\u0443\u0440\u043d\u0430\u043b\u0435",
"LabelRunServerAtStartup": "\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439",
"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.",
@@ -249,26 +248,26 @@
"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.",
"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 \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.",
"TabBasics": "\u041e\u0441\u043d\u043e\u0432\u044b",
"TabTV": "\u0422\u0412",
"TabGames": "\u0418\u0433\u0440\u044b",
"TabMusic": "\u041c\u0443\u0437\u044b\u043a\u0430",
"TabOthers": "\u0414\u0440\u0443\u0433\u0438\u0435",
- "HeaderExtractChapterImagesFor": "\u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0442\u044c \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0441\u0446\u0435\u043d \u0434\u043b\u044f:",
+ "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",
"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\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \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\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \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\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441 TheTVDB.com",
+ "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 \u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c \u0434\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \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. \u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u043f\u043b\u0430\u043d\u043e\u0432\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u0441 4:00 \u0443\u0442\u0440\u0430, \u043e\u0434\u043d\u0430\u043a\u043e, \u0435\u0451 \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\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\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 \u0447\u0430\u0441 \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:",
- "ButtonAutoScroll": "\u0410\u0432\u0442\u043e-\u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0430",
+ "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": "Media Browser \u0432\u043e\u0441\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u043e\u0442 \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043c\u0443\u043b\u044c\u0442\u0438\u043c\u0435\u0434\u0438\u0430. \u0412\u044b\u0431\u043e\u0440 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u043f\u043e\u043b\u0435\u0437\u0435\u043d, \u043a\u043e\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u0430\u043a\u0436\u0435 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b.",
"OptionImageSavingCompatible": "\u0421\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 - MB3\/Plex\/Xbmc",
@@ -316,10 +315,10 @@
"LabelNumberOfGuideDays": "\u0427\u0438\u0441\u043b\u043e \u0434\u043d\u0435\u0439 \u0442\u0435\u043b\u0435\u0433\u0438\u0434\u0430 \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0434\u0430\u043d\u043d\u044b\u0445:",
"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 \u0442\u0435\u043b\u0435\u0433\u0438\u0434\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\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": "\u041c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \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 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u043d\u0438\u0445 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0430\u043a\u0442\u0438\u0432\u0435\u043d \u0432 \u0442\u043e\u0442 \u0436\u0435 \u0441\u0430\u043c\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442.",
+ "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.",
"OptionAutomatic": "\u0410\u0432\u0442\u043e",
"LiveTvPluginRequired": "\u041f\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 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c.",
- "LiveTvPluginRequiredHelp": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043e\u0434\u0438\u043d \u0438\u0437 \u043d\u0430\u0448\u0438\u0445 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a NextPVR \u0438\u043b\u0438 ServerWMC.",
+ "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, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a NextPVR \u0438\u043b\u0438 ServerWMC.",
"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",
"OptionDownloadThumbImage": "\u0411\u0435\u0433\u0443\u043d\u043e\u043a",
"OptionDownloadMenuImage": "\u041c\u0435\u043d\u044e",
@@ -330,12 +329,12 @@
"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": "\u0414\u0435\u043b\u0430\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u043a\u0443 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432:",
+ "HeaderFetchImages": "\u0412\u044b\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",
"LabelMaxBackdropsPerItem": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0437\u0430\u0434\u043d\u0438\u043a\u043e\u0432 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442:",
- "LabelMaxScreenshotsPerItem": "\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0441\u043d\u0438\u043c\u043a\u043e\u0432 \u044d\u043a\u0440\u0430\u043d\u0430 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442:",
- "LabelMinBackdropDownloadWidth": "\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0448\u0438\u0440\u0438\u043d\u0430 \u0437\u0430\u0434\u043d\u0438\u043a\u0430 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438:",
- "LabelMinScreenshotDownloadWidth": "\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0448\u0438\u0440\u0438\u043d\u0430 \u0441\u043d\u0438\u043c\u043a\u0430 \u044d\u043a\u0440\u0430\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438:",
+ "LabelMaxScreenshotsPerItem": "\u041c\u0430\u043a\u0441. \u0447\u0438\u0441\u043b\u043e \u0441\u043d\u0438\u043c\u043a\u043e\u0432 \u044d\u043a\u0440\u0430\u043d\u0430 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442:",
+ "LabelMinBackdropDownloadWidth": "\u041c\u0438\u043d. \u0448\u0438\u0440\u0438\u043d\u0430 \u0437\u0430\u0434\u043d\u0438\u043a\u0430 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438:",
+ "LabelMinScreenshotDownloadWidth": "\u041c\u0438\u043d\u0438. \u0448\u0438\u0440\u0438\u043d\u0430 \u0441\u043d\u0438\u043c\u043a\u0430 \u044d\u043a\u0440\u0430\u043d\u0430 \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438:",
"ButtonAddScheduledTaskTrigger": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u0440\u0438\u0433\u0433\u0435\u0440 \u0437\u0430\u0434\u0430\u043d\u0438\u044f",
"HeaderAddScheduledTaskTrigger": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430 \u0437\u0430\u0434\u0430\u043d\u0438\u044f",
"ButtonAdd": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c",
@@ -360,7 +359,7 @@
"TabPathSubstitution": "\u041f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \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 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \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 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u0436\u0435.",
"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",
@@ -382,7 +381,7 @@
"ButtonPlayTrailer": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440",
"LabelMissing": "\u041f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043e",
"LabelOffline": "\u0410\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e",
- "PathSubstitutionHelp": "\u041f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u0443\u0442\u0435\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0443\u0442\u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043d\u0430 \u0441\u0435\u0442\u0435\u0432\u043e\u0439 \u043f\u0443\u0442\u044c, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043a\u043b\u0438\u0435\u043d\u0442\u044b \u0438\u043c\u0435\u0435\u044e\u0442 \u0434\u043e\u0441\u0442\u0443\u043f. \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\u0444\u0430\u0439\u043b\u0430\u043c \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u043e\u043d\u0438 \u0441\u043c\u043e\u0433\u0443\u0442 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0435\u0445 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u043e \u0441\u0435\u0442\u0438 \u0438 \u043d\u0435 \u0442\u0440\u0430\u0442\u0438\u0442\u044c \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\u0435 \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.",
"HeaderFrom": "\u041e\u0442\u043a\u0443\u0434\u0430",
"HeaderTo": "\u041a\u0443\u0434\u0430",
"LabelFrom": "\u041e\u0442\u043a\u0443\u0434\u0430:",
@@ -411,7 +410,7 @@
"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 \u0441\u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0442\u044c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0432 \u0432\u0430\u0448\u0435\u0439 \u0441\u0435\u0442\u0438 \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u043c\u0438.",
+ "LabelEnableDlnaPlayToHelp": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0432 \u0441\u0435\u0442\u0438 \u043c\u043e\u0433\u0443\u0442 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f Media Browser \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \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",
@@ -430,7 +429,7 @@
"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 \u044f\u0437\u044b\u043a\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f",
+ "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.",
"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",
@@ -439,7 +438,7 @@
"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. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432.",
+ "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.",
"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.",
"TabResume": "\u0412\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435",
@@ -451,7 +450,7 @@
"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\u043b\u044f\u0435\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",
+ "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",
"HeaderDate": "\u0414\u0430\u0442\u0430",
@@ -473,7 +472,7 @@
"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.",
"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.",
- "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.",
+ "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 \u043f\u0430\u043f\u043a\u0438 \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u0435\u0439.",
"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:",
@@ -493,7 +492,7 @@
"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",
"LabelDeleteEmptyFoldersHelp": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u044d\u0442\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0447\u0438\u0441\u0442\u044b\u043c.",
"LabelDeleteLeftOverFiles": "\u0423\u0434\u0430\u043b\u044f\u0442\u044c \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0444\u0430\u0439\u043b\u044b \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438:",
- "LabelDeleteLeftOverFilesHelp": "\u041e\u0442\u0434\u0435\u043b\u044f\u0439\u0442\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e ;. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: .nfo;.txt",
+ "LabelDeleteLeftOverFilesHelp": "\u041e\u0442\u0434\u0435\u043b\u044f\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \";\". \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: .nfo;.txt",
"OptionOverwriteExistingEpisodes": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u044d\u043f\u0438\u0437\u043e\u0434\u044b",
"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",
@@ -565,10 +564,11 @@
"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": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435",
- "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": "New content added (multiple)",
+ "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.",
"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\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441:",
+ "LabelMonitorUsers": "\u0421\u043b\u0435\u0436\u0435\u043d\u0438\u0435 \u0437\u0430 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u043c\u0438 \u0441:",
"LabelSendNotificationToUsers": "\u041f\u043e\u0441\u044b\u043b\u0430\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043a:",
"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\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u043b\u0443\u0436\u0431\u044b:",
@@ -614,5 +614,102 @@
"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"
+ "ButtonMute": "\u041e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0437\u0432\u0443\u043a",
+ "HeaderLatestMedia": "\u0421\u0432\u0435\u0436\u0438\u0435 \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u0438",
+ "OptionNoSubtitles": "\u041d\u0435\u0442 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u043e\u0432",
+ "OptionSpecialFeatures": "\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ 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 8e2fa18b9..258d7bff2 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/server.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json
@@ -147,10 +147,8 @@
"ScheduledTasksTitle": "Scheduled Tasks",
"TabMyPlugins": "My Plugins",
"TabCatalog": "Catalog",
- "TabUpdates": "Updates",
"PluginsTitle": "Plugins",
"HeaderAutomaticUpdates": "Automatic Updates",
- "HeaderUpdateLevel": "Update Level",
"HeaderNowPlaying": "Now Playing",
"HeaderLatestAlbums": "Latest Albums",
"HeaderLatestSongs": "Latest Songs",
@@ -163,6 +161,10 @@
"OptionIso": "Iso",
"Option3D": "3D",
"LabelFeatures": "Features:",
+ "LabelService": "Service:",
+ "LabelStatus": "Status:",
+ "LabelVersion": "Version:",
+ "LabelLastResult": "Last result:",
"OptionHasSubtitles": "Subtitles",
"OptionHasTrailer": "Trailer",
"OptionHasThemeSong": "Theme Song",
@@ -272,8 +274,8 @@
"ButtonAutoScroll": "Auto-scroll",
"LabelImageSavingConvention": "Image saving convention:",
"LabelImageSavingConventionHelp": "Media Browser recognizes images from most major media applications. Choosing your downloading convention is useful if you also use other products.",
- "OptionImageSavingCompatible": "Compatible - MB3/Plex/Xbmc",
- "OptionImageSavingStandard": "Standard - MB3/MB2",
+ "OptionImageSavingCompatible": "Compatible - Media Browser/Plex/Xbmc",
+ "OptionImageSavingStandard": "Standard - MB2",
"ButtonSignIn": "Sign In",
"TitleSignIn": "Sign In",
"HeaderPleaseSignIn": "Please sign in",
@@ -283,10 +285,13 @@
"PasswordLocalhostMessage": "Passwords are not required when logging in from localhost.",
"TabGuide": "Guide",
"TabChannels": "Channels",
+ "TabCollections": "Collections",
"HeaderChannels": "Channels",
"TabRecordings": "Recordings",
"TabScheduled": "Scheduled",
"TabSeries": "Series",
+ "TabFavorites": "Favorites",
+ "TabMyLibrary": "My Library",
"ButtonCancelRecording": "Cancel Recording",
"HeaderPrePostPadding": "Pre/Post Padding",
"LabelPrePaddingMinutes": "Pre-padding minutes:",
@@ -520,7 +525,7 @@
"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": "Down mix audio boost scale:",
+ "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",
@@ -535,8 +540,8 @@
"ButtonRetrieveKey": "Retrieve Key",
"LabelSupporterKey": "Supporter Key (paste from email)",
"LabelSupporterKeyHelp": "Enter your supporter key to start enjoying additional benefits the community has developed for Media Browser.",
- "MessageInvalidKey": "MB3 Key Missing or Invalid",
- "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be an MB3 Supporter. Please donate and support the continued development of the core product. Thank you.",
+ "MessageInvalidKey": "Supporter key is missing or invalid.",
+ "ErrorMessageInvalidKey": "In order for any premium content to be registered, you must also be a Media Browser Supporter. Please donate and support the continued development of the core product. Thank you.",
"HeaderDisplaySettings": "Display Settings",
"TabPlayTo": "Play To",
"LabelEnableDlnaServer": "Enable Dlna server",
@@ -570,6 +575,7 @@
"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",
@@ -593,6 +599,7 @@
"ButtonArrowRight": "Right",
"ButtonBack": "Back",
"ButtonInfo": "Info",
+ "ButtonOsd": "On screen display",
"ButtonPageUp": "Page Up",
"ButtonPageDown": "Page Down",
"PageAbbreviation": "PG",
@@ -624,5 +631,119 @@
"ButtonMute": "Mute",
"HeaderLatestMedia": "Latest Media",
"OptionNoSubtitles": "No Subtitles",
- "OptionSpecialFeatures": "Special Features"
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderChannels": "Channels",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:",
+ "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"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/sv.json b/MediaBrowser.Server.Implementations/Localization/Server/sv.json
index 445916646..2a90f55cf 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/sv.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/sv.json
@@ -16,7 +16,7 @@
"LabelYoureDone": "Klart!",
"WelcomeToMediaBrowser": "V\u00e4lkommen till Media Browser!",
"TitleMediaBrowser": "Media Browser",
- "ThisWizardWillGuideYou": "Den h\u00e4r guiden kommer att guida dig igenom installationsprocessen.",
+ "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.",
"TellUsAboutYourself": "Ber\u00e4tta om dig sj\u00e4lv",
"LabelYourFirstName": "Ditt f\u00f6rnamn:",
"MoreUsersCanBeAddedLater": "Flera anv\u00e4ndare kan skapas senare i Kontrollpanelen.",
@@ -24,7 +24,7 @@
"LabelWindowsService": "Windows-tj\u00e4nst",
"AWindowsServiceHasBeenInstalled": "En Windows-tj\u00e4nst har installerats.",
"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).",
- "WindowsServiceIntro2": "Om Media Browser k\u00f6rs som 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.",
+ "WindowsServiceIntro2": "Om Media Browser k\u00f6rs som 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.",
"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>.",
"LabelConfigureSettings": "Inst\u00e4llningar",
"LabelEnableVideoImageExtraction": "Ta fram bildrutor ur videofiler",
@@ -76,6 +76,7 @@
"LabelMaxParentalRating": "H\u00f6gsta till\u00e5tna \u00e5ldersgr\u00e4ns",
"MaxParentalRatingHelp": "Inneh\u00e5ll med h\u00f6gre gr\u00e4ns visas ej f\u00f6r den h\u00e4r anv\u00e4ndaren.",
"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.",
+ "ChannelAccessHelp": "V\u00e4lj kanaler kanaler att dela med denna anv\u00e4ndaren. Administrat\u00f6rer kan redigera alla kanaler med hj\u00e4lp av metadata hanteraren.",
"ButtonDeleteImage": "Ta bort bild",
"LabelSelectUsers": "V\u00e4lj anv\u00e4ndare:",
"ButtonUpload": "Ladda upp",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "Schemalagda aktiviteter",
"TabMyPlugins": "Mina till\u00e4gg",
"TabCatalog": "Katalog",
- "TabUpdates": "Uppdateringar",
"PluginsTitle": "Till\u00e4gg",
"HeaderAutomaticUpdates": "Automatiska uppdateringar",
- "HeaderUpdateLevel": "Uppdatera versionsniv\u00e5",
"HeaderNowPlaying": "Nu spelas",
"HeaderLatestAlbums": "Nytillkomna album",
"HeaderLatestSongs": "Nytillkomna l\u00e5tar",
@@ -541,7 +540,7 @@
"LabelBlastMessageInterval": "S\u00e4ndningsintervall i sekunder f\u00f6r \"jag lever\"-meddelanden",
"LabelBlastMessageIntervalHelp": "Anger tid i sekunder mellan varje \"jag lever\"-meddelande.",
"LabelDefaultUser": "F\u00f6rvald anv\u00e4ndare:",
- "LabelDefaultUserHelp": "Anger vilket anv\u00e4ndarbibliotek som skall visas p\u00e5 anslutna enheter. Denna inst\u00e4llning kan \u00e4ndras med hj\u00e4lp av en enhetsprofil.",
+ "LabelDefaultUserHelp": "Anger vilket anv\u00e4ndarbibliotek som skall visas p\u00e5 anslutna enheter. Denna inst\u00e4llning kan \u00e4ndras p\u00e5 enhets basis med hj\u00e4lp av en enhetsprofiler.",
"TitleDlna": "DLNA",
"HeaderServerSettings": "Serverinst\u00e4llningar",
"LabelWeatherDisplayLocation": "Geografisk plats f\u00f6r v\u00e4derdata:",
@@ -565,7 +564,8 @@
"NotificationOptionTaskFailed": "Schemalagd uppgift misslyckades",
"NotificationOptionInstallationFailed": "Installationen misslyckades",
"NotificationOptionNewLibraryContent": "Nytt inneh\u00e5ll har tillkommit",
- "SendNotificationHelp": "Meddelanden visas i kontrollpanelens inkorg. S\u00f6k efter fler meddelandetill\u00e4gg i pluginkatalogen.",
+ "NotificationOptionNewLibraryContentMultiple": "Nytillkommet inneh\u00e5ll finns (flera objekt)",
+ "SendNotificationHelp": "Meddelanden visas som standard i kontrollpanelens inkorg. S\u00f6k efter fler meddelandetill\u00e4gg i pluginkatalogen.",
"NotificationOptionServerRestartRequired": "Servern m\u00e5ste startas om",
"LabelNotificationEnabled": "Aktivera denna meddelandetyp",
"LabelMonitorUsers": "\u00d6vervaka aktivitet fr\u00e5n:",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Fel uppstod med till\u00e4gget",
"ButtonVolumeUp": "H\u00f6j Volymen",
"ButtonVolumeDown": "S\u00e4nk Volymen",
- "ButtonMute": "Tyst"
+ "ButtonMute": "Tyst",
+ "HeaderLatestMedia": "Nytillkommet",
+ "OptionNoSubtitles": "Inga undertexter",
+ "OptionSpecialFeatures": "Extramaterial",
+ "HeaderCollections": "Samling",
+ "HeaderMyLibrary": "Mitt Bibliotek",
+ "LabelProfileCodecsHelp": "Separerade med kommatecken, Detta kan l\u00e4mnas tomt f\u00f6r att g\u00e4lla f\u00f6r alla codecs.",
+ "LabelProfileContainersHelp": "Separerade med kommatecken, Detta kan l\u00e4mnas tomt f\u00f6r att g\u00e4lla f\u00f6r alla beh\u00e5llare.",
+ "HeaderResponseProfile": "Svars Profil",
+ "LabelType": "Typ:",
+ "LabelProfileContainer": "Beh\u00e5llare:",
+ "LabelProfileVideoCodecs": "Video codecs:",
+ "LabelProfileAudioCodecs": "Ljud codecs:",
+ "LabelProfileCodecs": "Codecs:",
+ "HeaderDirectPlayProfile": "Spela Direkt Profil",
+ "HeaderTranscodingProfile": "Transcoding Profile",
+ "HeaderCodecProfile": "Codec Profil",
+ "HeaderCodecProfileHelp": "Avkodarprofiler best\u00e4mmer begr\u00e4nsningarna hos en enhet n\u00e4r den spelar upp olika kodningstyper. Om en begr\u00e4nsning \u00e4r aktuell kommer inneh\u00e5llet att kodas om, \u00e4ven om kodningstypen sig \u00e4r inst\u00e4lld f\u00f6r direkt avspelning.",
+ "HeaderContainerProfile": "Beh\u00e5llar profil",
+ "HeaderContainerProfileHelp": "Beh\u00e5llareprofiler best\u00e4mmer begr\u00e4nsningarna hos en enhet n\u00e4r den spelar upp olika filformat. Om en begr\u00e4nsning \u00e4r aktuell kommer inneh\u00e5llet att kodas om, \u00e4ven om formatet i sig \u00e4r inst\u00e4llt f\u00f6r direkt avspelning.",
+ "OptionProfileVideo": "Video",
+ "OptionProfileAudio": "Ljud",
+ "OptionProfileVideoAudio": "Video Ljud",
+ "OptionProfilePhoto": "Foto",
+ "LabelUserLibrary": "Anv\u00e4ndar bibliotek:",
+ "LabelUserLibraryHelp": "V\u00e4lj vilken anv\u00e4ndares bibliotek som skall visas p\u00e5 enheten. L\u00e4mna detta tomt f\u00f6r att standard biblioteket skall anv\u00e4ndas.",
+ "OptionPlainStorageFolders": "Visa alla mappar som enkla lagrings mappar",
+ "OptionPlainStorageFoldersHelp": "Om aktiverad representeras alla mappar i DIDL som \"object.container.storageFolder\" i st\u00e4llet f\u00f6r en mera specifik typ, t ex \"object.container.person.musicArtist\".",
+ "OptionPlainVideoItems": "Visa alla videor som objekt utan specifikt format",
+ "OptionPlainVideoItemsHelp": "Om aktiverad representeras alla videor i DIDL som \"object.item.videoItem\" i st\u00e4llet f\u00f6r en mera specifik typ, t ex \"object.item.videoItem.movie\".",
+ "LabelSupportedMediaTypes": "Media Format som St\u00f6ds:",
+ "TabIdentification": "Identifiering",
+ "TabDirectPlay": "Spela Direkt",
+ "TabContainers": "Beh\u00e5llare",
+ "TabCodecs": "Codecs",
+ "TabResponses": "Svar",
+ "HeaderProfileInformation": "Profil Information",
+ "LabelEmbedAlbumArtDidl": "B\u00e4dda in omslagsbilder i Didl",
+ "LabelEmbedAlbumArtDidlHelp": "Vissa enheter f\u00f6redrar den h\u00e4r metoden att ta fram omslagsbilder. Andra kanske avbryter avspelningen om detta val \u00e4r aktiverat.",
+ "LabelAlbumArtPN": "PN f\u00f6r omslagsbilder:",
+ "LabelAlbumArtHelp": "Det PN som anv\u00e4nds f\u00f6r omslagsbilder, inom attributet dlna:profileID hos upnp:albumArtURI. Vissa klienter kr\u00e4ver ett specifikt v\u00e4rde, oavsett bildens storlek.",
+ "LabelAlbumArtMaxWidth": "Maximal bredd f\u00f6r omslagsbilder:",
+ "LabelAlbumArtMaxWidthHelp": "H\u00f6gsta uppl\u00f6sning hos omslagsbilder presenterade via upnp:albumArtURI.",
+ "LabelAlbumArtMaxHeight": "Skivomslagens max h\u00f6jd:",
+ "LabelAlbumArtMaxHeightHelp": "H\u00f6gsta uppl\u00f6sning hos omslagsbilder presenterade via upnp:albumArtURI.",
+ "LabelIconMaxWidth": "Ikoners max bredd:",
+ "LabelIconMaxWidthHelp": "Max uppl\u00f6sning p\u00e5 ikoner som visas via upnp:ikon.",
+ "LabelIconMaxHeight": "Ikon max h\u00f6jd:",
+ "LabelIconMaxHeightHelp": "H\u00f6gsta uppl\u00f6sning hos ikoner presenterade via upnp:icon.",
+ "LabelIdentificationFieldHelp": "En skiftl\u00e4gesok\u00e4nslig delstr\u00e4ng eller regex-uttryck.",
+ "HeaderProfileServerSettingsHelp": "Dessa v\u00e4rden styr hur Media Browser presenterar sig f\u00f6r enheten.",
+ "LabelMaxBitrate": "Max bitrate:",
+ "LabelMaxBitrateHelp": "Ange en h\u00f6gsta bithastighet i bandbreddsbegr\u00e4nsade milj\u00f6er, eller i fall d\u00e4r enheten har sina egna begr\u00e4nsningar.",
+ "OptionIgnoreTranscodeByteRangeRequests": "Ignorera beg\u00e4ran om \"byte range\" vid omkodning",
+ "OptionIgnoreTranscodeByteRangeRequestsHelp": "Om aktiverad kommer beg\u00e4ran att uppfyllas, men \"byte range\"-rubriken ignoreras.",
+ "LabelFriendlyName": "L\u00e4ttl\u00e4st namn",
+ "LabelManufacturer": "Tillverkare",
+ "LabelManufacturerUrl": "Tillverkarens webaddress",
+ "LabelModelName": "Modell Namn",
+ "LabelModelNumber": "Modell nummer",
+ "LabelModelDescription": "Modell beskrivning",
+ "LabelModelUrl": "L\u00e4nk till Modellen",
+ "LabelSerialNumber": "Serie nummer",
+ "LabelDeviceDescription": "Enhets beskrivning",
+ "HeaderIdentificationCriteriaHelp": "Var god skriv in minst ett identifierings kriterium",
+ "HeaderDirectPlayProfileHelp": "Ange direktuppspelningsprofiler f\u00f6r att indikera vilka format enheten kan spela upp utan omkodning.",
+ "HeaderTranscodingProfileHelp": "Ange omkodningsprofiler f\u00f6r att indikera vilka format som ska anv\u00e4ndas d\u00e5 omkodning kr\u00e4vs.",
+ "HeaderResponseProfileHelp": "Svarsprofiler \u00e4r ett s\u00e4tt att anpassa den information som s\u00e4nds till enheten d\u00e5 olika typer av media spelas upp.",
+ "LabelXDlnaCap": "X-Dlna cap:",
+ "LabelXDlnaCapHelp": "Anger inneh\u00e5llet i elementet X_DLNACAP i namnutrymmet urn:schemas-dlna-org:device-1-0.",
+ "LabelXDlnaDoc": "X-Dlna doc:",
+ "LabelXDlnaDocHelp": "Anger inneh\u00e5llet i elementet X_DLNADOC i namnutrymmet urn:schemas-dlna-org:device-1-0.",
+ "LabelSonyAggregationFlags": "Sony sammanst\u00e4llnings flaggor:",
+ "LabelSonyAggregationFlagsHelp": "Anger inneh\u00e5llet i elementet aggregationFlags i namnutrymmet urn:schemas-sonycom:av.",
+ "LabelTranscodingContainer": "Beh\u00e5llare:",
+ "LabelTranscodingVideoCodec": "Video codec:",
+ "LabelTranscodingVideoProfile": "Video profil:",
+ "LabelTranscodingAudioCodec": "Audio codec:",
+ "OptionEnableM2tsMode": "Till\u00e5t M2ts l\u00e4ge",
+ "OptionEnableM2tsModeHelp": "Aktivera m2ts-l\u00e4ge n\u00e4r omkodning sker till mpegts.",
+ "OptionEstimateContentLength": "Upskattad inneh\u00e5lls l\u00e4ngd vid omkonvertering",
+ "OptionReportByteRangeSeekingWhenTranscoding": "Meddela att servern st\u00f6djer bytebaserad s\u00f6kning vid omkodning",
+ "OptionReportByteRangeSeekingWhenTranscodingHelp": "Detta kr\u00e4vs f\u00f6r vissa enheter som inte hanterar tids-s\u00f6kning bra.",
+ "HeaderSubtitleDownloadingHelp": "N\u00e4r Media Browser s\u00f6ker igenom dina videofiler kan den identifiera saknade undertexter och ladda ner dem fr\u00e5n en onlinetj\u00e4nst, t ex OpenSubtitles.org.",
+ "HeaderDownloadSubtitlesFor": "Ladda ner undertexter f\u00f6r:",
+ "LabelSkipIfGraphicalSubsPresent": "Hoppa \u00f6ver om videon redan inneh\u00e5ller grafiska undertexter",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Om du sparar textversioner av undertexterna f\u00e5r du ett b\u00e4ttre resultat vid anv\u00e4ndning av mobila enheter.",
+ "TabSubtitles": "Undertexter",
+ "LabelOpenSubtitlesUsername": "Inloggnings-ID hos Open Subtitles:",
+ "LabelOpenSubtitlesPassword": "L\u00f6senord hos Open Subtitles:",
+ "LabelAudioLanguagePreferenceHelp": "Om ej angivet kommer det f\u00f6rvalda ljudsp\u00e5ret att v\u00e4ljas, oavsett spr\u00e5k.",
+ "LabelDownloadLanguages": "Spr\u00e5k att ladda ner:",
+ "ButtonRegister": "Registrera",
+ "LabelSkipIfAudioTrackPresent": "Hoppa \u00f6ver om det f\u00f6rvalda ljudsp\u00e5rets spr\u00e5k \u00e4r samma som det nerladdade",
+ "LabelSkipIfAudioTrackPresentHelp": "Bocka ur denna f\u00f6r att ge undertexter \u00e5t alla videor oavsett ljudsp\u00e5rets spr\u00e5k.",
+ "HeaderSendMessage": "Skicka meddelande",
+ "ButtonSend": "Skicka",
+ "LabelMessageText": "Meddelandetext"
} \ 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 faa74a115..431bb9b24 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json
@@ -76,6 +76,7 @@
"LabelMaxParentalRating": "\u6700\u5927\u5141\u8a31\u7684\u5bb6\u9577\u8a55\u7d1a\uff1a",
"MaxParentalRatingHelp": "\u5177\u6709\u8f03\u9ad8\u7684\u5bb6\u9577\u8a55\u7d1a\u5167\u5bb9\u5c07\u5f9e\u9019\u7528\u6236\u88ab\u96b1\u85cf",
"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",
+ "ChannelAccessHelp": "Select the channels to share with this user. Administrators will be able to edit all channels using the metadata manager.",
"ButtonDeleteImage": "\u522a\u9664\u5716\u50cf",
"LabelSelectUsers": "Select users:",
"ButtonUpload": "\u4e0a\u8f09",
@@ -146,10 +147,8 @@
"ScheduledTasksTitle": "\u5df2\u8a08\u5283\u4efb\u52d9",
"TabMyPlugins": "\u6211\u7684\u63d2\u4ef6",
"TabCatalog": "\u76ee\u9304",
- "TabUpdates": "\u66f4\u65b0",
"PluginsTitle": "\u63d2\u4ef6",
"HeaderAutomaticUpdates": "\u81ea\u52d5\u66f4\u65b0",
- "HeaderUpdateLevel": "\u66f4\u65b0\u7d1a\u5225",
"HeaderNowPlaying": "\u6b63\u5728\u64ad\u653e",
"HeaderLatestAlbums": "\u6700\u65b0\u5c08\u8f2f",
"HeaderLatestSongs": "\u6700\u65b0\u6b4c\u66f2",
@@ -515,7 +514,7 @@
"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": "Down mix audio boost scale:",
+ "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",
@@ -565,6 +564,7 @@
"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",
@@ -614,5 +614,102 @@
"NotificationOptionPluginError": "Plugin failure",
"ButtonVolumeUp": "Volume up",
"ButtonVolumeDown": "Volume down",
- "ButtonMute": "Mute"
+ "ButtonMute": "Mute",
+ "HeaderLatestMedia": "Latest Media",
+ "OptionNoSubtitles": "No Subtitles",
+ "OptionSpecialFeatures": "Special Features",
+ "HeaderCollections": "Collections",
+ "HeaderMyLibrary": "My Library",
+ "LabelProfileCodecsHelp": "Separated by comma. This can be left empty to apply to all codecs.",
+ "LabelProfileContainersHelp": "Separated by comma. This can be left empty to apply to all containers.",
+ "HeaderResponseProfile": "Response Profile",
+ "LabelType": "Type:",
+ "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.",
+ "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:",
+ "LabelSkipIfGraphicalSubsPresent": "Skip if the video already contains graphical subtitles",
+ "LabelSkipIfGraphicalSubsPresentHelp": "Keeping text versions of subtitles will result in more efficient delivery to mobile clients.",
+ "TabSubtitles": "Subtitles",
+ "LabelOpenSubtitlesUsername": "Open Subtitles username:",
+ "LabelOpenSubtitlesPassword": "Open Subtitles password:",
+ "LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
+ "LabelDownloadLanguages": "Download languages:",
+ "ButtonRegister": "Register",
+ "LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",
+ "LabelSkipIfAudioTrackPresentHelp": "Uncheck this to ensure all videos have subtitles, regardless of audio language.",
+ "HeaderSendMessage": "Send Message",
+ "ButtonSend": "Send",
+ "LabelMessageText": "Message text:"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/countries.json b/MediaBrowser.Server.Implementations/Localization/countries.json
new file mode 100644
index 000000000..e671b3685
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Localization/countries.json
@@ -0,0 +1 @@
+[{"Name":"AF","DisplayName":"Afghanistan","TwoLetterISORegionName":"AF","ThreeLetterISORegionName":"AFG"},{"Name":"AL","DisplayName":"Albania","TwoLetterISORegionName":"AL","ThreeLetterISORegionName":"ALB"},{"Name":"DZ","DisplayName":"Algeria","TwoLetterISORegionName":"DZ","ThreeLetterISORegionName":"DZA"},{"Name":"AR","DisplayName":"Argentina","TwoLetterISORegionName":"AR","ThreeLetterISORegionName":"ARG"},{"Name":"AM","DisplayName":"Armenia","TwoLetterISORegionName":"AM","ThreeLetterISORegionName":"ARM"},{"Name":"AU","DisplayName":"Australia","TwoLetterISORegionName":"AU","ThreeLetterISORegionName":"AUS"},{"Name":"AT","DisplayName":"Austria","TwoLetterISORegionName":"AT","ThreeLetterISORegionName":"AUT"},{"Name":"AZ","DisplayName":"Azerbaijan","TwoLetterISORegionName":"AZ","ThreeLetterISORegionName":"AZE"},{"Name":"BH","DisplayName":"Bahrain","TwoLetterISORegionName":"BH","ThreeLetterISORegionName":"BHR"},{"Name":"BD","DisplayName":"Bangladesh","TwoLetterISORegionName":"BD","ThreeLetterISORegionName":"BGD"},{"Name":"BY","DisplayName":"Belarus","TwoLetterISORegionName":"BY","ThreeLetterISORegionName":"BLR"},{"Name":"BE","DisplayName":"Belgium","TwoLetterISORegionName":"BE","ThreeLetterISORegionName":"BEL"},{"Name":"BZ","DisplayName":"Belize","TwoLetterISORegionName":"BZ","ThreeLetterISORegionName":"BLZ"},{"Name":"VE","DisplayName":"Bolivarian Republic of Venezuela","TwoLetterISORegionName":"VE","ThreeLetterISORegionName":"VEN"},{"Name":"BO","DisplayName":"Bolivia","TwoLetterISORegionName":"BO","ThreeLetterISORegionName":"BOL"},{"Name":"BA","DisplayName":"Bosnia and Herzegovina","TwoLetterISORegionName":"BA","ThreeLetterISORegionName":"BIH"},{"Name":"BW","DisplayName":"Botswana","TwoLetterISORegionName":"BW","ThreeLetterISORegionName":"BWA"},{"Name":"BR","DisplayName":"Brazil","TwoLetterISORegionName":"BR","ThreeLetterISORegionName":"BRA"},{"Name":"BN","DisplayName":"Brunei Darussalam","TwoLetterISORegionName":"BN","ThreeLetterISORegionName":"BRN"},{"Name":"BG","DisplayName":"Bulgaria","TwoLetterISORegionName":"BG","ThreeLetterISORegionName":"BGR"},{"Name":"KH","DisplayName":"Cambodia","TwoLetterISORegionName":"KH","ThreeLetterISORegionName":"KHM"},{"Name":"CM","DisplayName":"Cameroon","TwoLetterISORegionName":"CM","ThreeLetterISORegionName":"CMR"},{"Name":"CA","DisplayName":"Canada","TwoLetterISORegionName":"CA","ThreeLetterISORegionName":"CAN"},{"Name":"029","DisplayName":"Caribbean","TwoLetterISORegionName":"029","ThreeLetterISORegionName":"029"},{"Name":"CL","DisplayName":"Chile","TwoLetterISORegionName":"CL","ThreeLetterISORegionName":"CHL"},{"Name":"CO","DisplayName":"Colombia","TwoLetterISORegionName":"CO","ThreeLetterISORegionName":"COL"},{"Name":"CD","DisplayName":"Congo [DRC]","TwoLetterISORegionName":"CD","ThreeLetterISORegionName":"COD"},{"Name":"CR","DisplayName":"Costa Rica","TwoLetterISORegionName":"CR","ThreeLetterISORegionName":"CRI"},{"Name":"HR","DisplayName":"Croatia","TwoLetterISORegionName":"HR","ThreeLetterISORegionName":"HRV"},{"Name":"CZ","DisplayName":"Czech Republic","TwoLetterISORegionName":"CZ","ThreeLetterISORegionName":"CZE"},{"Name":"DK","DisplayName":"Denmark","TwoLetterISORegionName":"DK","ThreeLetterISORegionName":"DNK"},{"Name":"DO","DisplayName":"Dominican Republic","TwoLetterISORegionName":"DO","ThreeLetterISORegionName":"DOM"},{"Name":"EC","DisplayName":"Ecuador","TwoLetterISORegionName":"EC","ThreeLetterISORegionName":"ECU"},{"Name":"EG","DisplayName":"Egypt","TwoLetterISORegionName":"EG","ThreeLetterISORegionName":"EGY"},{"Name":"SV","DisplayName":"El Salvador","TwoLetterISORegionName":"SV","ThreeLetterISORegionName":"SLV"},{"Name":"ER","DisplayName":"Eritrea","TwoLetterISORegionName":"ER","ThreeLetterISORegionName":"ERI"},{"Name":"EE","DisplayName":"Estonia","TwoLetterISORegionName":"EE","ThreeLetterISORegionName":"EST"},{"Name":"ET","DisplayName":"Ethiopia","TwoLetterISORegionName":"ET","ThreeLetterISORegionName":"ETH"},{"Name":"FO","DisplayName":"Faroe Islands","TwoLetterISORegionName":"FO","ThreeLetterISORegionName":"FRO"},{"Name":"FI","DisplayName":"Finland","TwoLetterISORegionName":"FI","ThreeLetterISORegionName":"FIN"},{"Name":"FR","DisplayName":"France","TwoLetterISORegionName":"FR","ThreeLetterISORegionName":"FRA"},{"Name":"GE","DisplayName":"Georgia","TwoLetterISORegionName":"GE","ThreeLetterISORegionName":"GEO"},{"Name":"DE","DisplayName":"Germany","TwoLetterISORegionName":"DE","ThreeLetterISORegionName":"DEU"},{"Name":"GR","DisplayName":"Greece","TwoLetterISORegionName":"GR","ThreeLetterISORegionName":"GRC"},{"Name":"GL","DisplayName":"Greenland","TwoLetterISORegionName":"GL","ThreeLetterISORegionName":"GRL"},{"Name":"GT","DisplayName":"Guatemala","TwoLetterISORegionName":"GT","ThreeLetterISORegionName":"GTM"},{"Name":"HT","DisplayName":"Haiti","TwoLetterISORegionName":"HT","ThreeLetterISORegionName":"HTI"},{"Name":"HN","DisplayName":"Honduras","TwoLetterISORegionName":"HN","ThreeLetterISORegionName":"HND"},{"Name":"HK","DisplayName":"Hong Kong S.A.R.","TwoLetterISORegionName":"HK","ThreeLetterISORegionName":"HKG"},{"Name":"HU","DisplayName":"Hungary","TwoLetterISORegionName":"HU","ThreeLetterISORegionName":"HUN"},{"Name":"IS","DisplayName":"Iceland","TwoLetterISORegionName":"IS","ThreeLetterISORegionName":"ISL"},{"Name":"IN","DisplayName":"India","TwoLetterISORegionName":"IN","ThreeLetterISORegionName":"IND"},{"Name":"ID","DisplayName":"Indonesia","TwoLetterISORegionName":"ID","ThreeLetterISORegionName":"IDN"},{"Name":"IR","DisplayName":"Iran","TwoLetterISORegionName":"IR","ThreeLetterISORegionName":"IRN"},{"Name":"IQ","DisplayName":"Iraq","TwoLetterISORegionName":"IQ","ThreeLetterISORegionName":"IRQ"},{"Name":"IE","DisplayName":"Ireland","TwoLetterISORegionName":"IE","ThreeLetterISORegionName":"IRL"},{"Name":"PK","DisplayName":"Islamic Republic of Pakistan","TwoLetterISORegionName":"PK","ThreeLetterISORegionName":"PAK"},{"Name":"IL","DisplayName":"Israel","TwoLetterISORegionName":"IL","ThreeLetterISORegionName":"ISR"},{"Name":"IT","DisplayName":"Italy","TwoLetterISORegionName":"IT","ThreeLetterISORegionName":"ITA"},{"Name":"CI","DisplayName":"Ivory Coast","TwoLetterISORegionName":"CI","ThreeLetterISORegionName":"CIV"},{"Name":"JM","DisplayName":"Jamaica","TwoLetterISORegionName":"JM","ThreeLetterISORegionName":"JAM"},{"Name":"JP","DisplayName":"Japan","TwoLetterISORegionName":"JP","ThreeLetterISORegionName":"JPN"},{"Name":"JO","DisplayName":"Jordan","TwoLetterISORegionName":"JO","ThreeLetterISORegionName":"JOR"},{"Name":"KZ","DisplayName":"Kazakhstan","TwoLetterISORegionName":"KZ","ThreeLetterISORegionName":"KAZ"},{"Name":"KE","DisplayName":"Kenya","TwoLetterISORegionName":"KE","ThreeLetterISORegionName":"KEN"},{"Name":"KR","DisplayName":"Korea","TwoLetterISORegionName":"KR","ThreeLetterISORegionName":"KOR"},{"Name":"KW","DisplayName":"Kuwait","TwoLetterISORegionName":"KW","ThreeLetterISORegionName":"KWT"},{"Name":"KG","DisplayName":"Kyrgyzstan","TwoLetterISORegionName":"KG","ThreeLetterISORegionName":"KGZ"},{"Name":"LA","DisplayName":"Lao P.D.R.","TwoLetterISORegionName":"LA","ThreeLetterISORegionName":"LAO"},{"Name":"419","DisplayName":"Latin America","TwoLetterISORegionName":"419","ThreeLetterISORegionName":"419"},{"Name":"LV","DisplayName":"Latvia","TwoLetterISORegionName":"LV","ThreeLetterISORegionName":"LVA"},{"Name":"LB","DisplayName":"Lebanon","TwoLetterISORegionName":"LB","ThreeLetterISORegionName":"LBN"},{"Name":"LY","DisplayName":"Libya","TwoLetterISORegionName":"LY","ThreeLetterISORegionName":"LBY"},{"Name":"LI","DisplayName":"Liechtenstein","TwoLetterISORegionName":"LI","ThreeLetterISORegionName":"LIE"},{"Name":"LT","DisplayName":"Lithuania","TwoLetterISORegionName":"LT","ThreeLetterISORegionName":"LTU"},{"Name":"LU","DisplayName":"Luxembourg","TwoLetterISORegionName":"LU","ThreeLetterISORegionName":"LUX"},{"Name":"MO","DisplayName":"Macao S.A.R.","TwoLetterISORegionName":"MO","ThreeLetterISORegionName":"MAC"},{"Name":"MK","DisplayName":"Macedonia (FYROM)","TwoLetterISORegionName":"MK","ThreeLetterISORegionName":"MKD"},{"Name":"MY","DisplayName":"Malaysia","TwoLetterISORegionName":"MY","ThreeLetterISORegionName":"MYS"},{"Name":"MV","DisplayName":"Maldives","TwoLetterISORegionName":"MV","ThreeLetterISORegionName":"MDV"},{"Name":"ML","DisplayName":"Mali","TwoLetterISORegionName":"ML","ThreeLetterISORegionName":"MLI"},{"Name":"MT","DisplayName":"Malta","TwoLetterISORegionName":"MT","ThreeLetterISORegionName":"MLT"},{"Name":"MX","DisplayName":"Mexico","TwoLetterISORegionName":"MX","ThreeLetterISORegionName":"MEX"},{"Name":"MN","DisplayName":"Mongolia","TwoLetterISORegionName":"MN","ThreeLetterISORegionName":"MNG"},{"Name":"ME","DisplayName":"Montenegro","TwoLetterISORegionName":"ME","ThreeLetterISORegionName":"MNE"},{"Name":"MA","DisplayName":"Morocco","TwoLetterISORegionName":"MA","ThreeLetterISORegionName":"MAR"},{"Name":"NP","DisplayName":"Nepal","TwoLetterISORegionName":"NP","ThreeLetterISORegionName":"NPL"},{"Name":"NL","DisplayName":"Netherlands","TwoLetterISORegionName":"NL","ThreeLetterISORegionName":"NLD"},{"Name":"NZ","DisplayName":"New Zealand","TwoLetterISORegionName":"NZ","ThreeLetterISORegionName":"NZL"},{"Name":"NI","DisplayName":"Nicaragua","TwoLetterISORegionName":"NI","ThreeLetterISORegionName":"NIC"},{"Name":"NG","DisplayName":"Nigeria","TwoLetterISORegionName":"NG","ThreeLetterISORegionName":"NGA"},{"Name":"NO","DisplayName":"Norway","TwoLetterISORegionName":"NO","ThreeLetterISORegionName":"NOR"},{"Name":"OM","DisplayName":"Oman","TwoLetterISORegionName":"OM","ThreeLetterISORegionName":"OMN"},{"Name":"PA","DisplayName":"Panama","TwoLetterISORegionName":"PA","ThreeLetterISORegionName":"PAN"},{"Name":"PY","DisplayName":"Paraguay","TwoLetterISORegionName":"PY","ThreeLetterISORegionName":"PRY"},{"Name":"CN","DisplayName":"People's Republic of China","TwoLetterISORegionName":"CN","ThreeLetterISORegionName":"CHN"},{"Name":"PE","DisplayName":"Peru","TwoLetterISORegionName":"PE","ThreeLetterISORegionName":"PER"},{"Name":"PH","DisplayName":"Philippines","TwoLetterISORegionName":"PH","ThreeLetterISORegionName":"PHL"},{"Name":"PL","DisplayName":"Poland","TwoLetterISORegionName":"PL","ThreeLetterISORegionName":"POL"},{"Name":"PT","DisplayName":"Portugal","TwoLetterISORegionName":"PT","ThreeLetterISORegionName":"PRT"},{"Name":"MC","DisplayName":"Principality of Monaco","TwoLetterISORegionName":"MC","ThreeLetterISORegionName":"MCO"},{"Name":"PR","DisplayName":"Puerto Rico","TwoLetterISORegionName":"PR","ThreeLetterISORegionName":"PRI"},{"Name":"QA","DisplayName":"Qatar","TwoLetterISORegionName":"QA","ThreeLetterISORegionName":"QAT"},{"Name":"MD","DisplayName":"Republica Moldova","TwoLetterISORegionName":"MD","ThreeLetterISORegionName":"MDA"},{"Name":"RE","DisplayName":"Réunion","TwoLetterISORegionName":"RE","ThreeLetterISORegionName":"REU"},{"Name":"RO","DisplayName":"Romania","TwoLetterISORegionName":"RO","ThreeLetterISORegionName":"ROU"},{"Name":"RU","DisplayName":"Russia","TwoLetterISORegionName":"RU","ThreeLetterISORegionName":"RUS"},{"Name":"RW","DisplayName":"Rwanda","TwoLetterISORegionName":"RW","ThreeLetterISORegionName":"RWA"},{"Name":"SA","DisplayName":"Saudi Arabia","TwoLetterISORegionName":"SA","ThreeLetterISORegionName":"SAU"},{"Name":"SN","DisplayName":"Senegal","TwoLetterISORegionName":"SN","ThreeLetterISORegionName":"SEN"},{"Name":"RS","DisplayName":"Serbia","TwoLetterISORegionName":"RS","ThreeLetterISORegionName":"SRB"},{"Name":"CS","DisplayName":"Serbia and Montenegro (Former)","TwoLetterISORegionName":"CS","ThreeLetterISORegionName":"SCG"},{"Name":"SG","DisplayName":"Singapore","TwoLetterISORegionName":"SG","ThreeLetterISORegionName":"SGP"},{"Name":"SK","DisplayName":"Slovakia","TwoLetterISORegionName":"SK","ThreeLetterISORegionName":"SVK"},{"Name":"SI","DisplayName":"Slovenia","TwoLetterISORegionName":"SI","ThreeLetterISORegionName":"SVN"},{"Name":"SO","DisplayName":"Soomaaliya","TwoLetterISORegionName":"SO","ThreeLetterISORegionName":"SOM"},{"Name":"ZA","DisplayName":"South Africa","TwoLetterISORegionName":"ZA","ThreeLetterISORegionName":"ZAF"},{"Name":"ES","DisplayName":"Spain","TwoLetterISORegionName":"ES","ThreeLetterISORegionName":"ESP"},{"Name":"LK","DisplayName":"Sri Lanka","TwoLetterISORegionName":"LK","ThreeLetterISORegionName":"LKA"},{"Name":"SE","DisplayName":"Sweden","TwoLetterISORegionName":"SE","ThreeLetterISORegionName":"SWE"},{"Name":"CH","DisplayName":"Switzerland","TwoLetterISORegionName":"CH","ThreeLetterISORegionName":"CHE"},{"Name":"SY","DisplayName":"Syria","TwoLetterISORegionName":"SY","ThreeLetterISORegionName":"SYR"},{"Name":"TW","DisplayName":"Taiwan","TwoLetterISORegionName":"TW","ThreeLetterISORegionName":"TWN"},{"Name":"TJ","DisplayName":"Tajikistan","TwoLetterISORegionName":"TJ","ThreeLetterISORegionName":"TAJ"},{"Name":"TH","DisplayName":"Thailand","TwoLetterISORegionName":"TH","ThreeLetterISORegionName":"THA"},{"Name":"TT","DisplayName":"Trinidad and Tobago","TwoLetterISORegionName":"TT","ThreeLetterISORegionName":"TTO"},{"Name":"TN","DisplayName":"Tunisia","TwoLetterISORegionName":"TN","ThreeLetterISORegionName":"TUN"},{"Name":"TR","DisplayName":"Turkey","TwoLetterISORegionName":"TR","ThreeLetterISORegionName":"TUR"},{"Name":"TM","DisplayName":"Turkmenistan","TwoLetterISORegionName":"TM","ThreeLetterISORegionName":"TKM"},{"Name":"AE","DisplayName":"U.A.E.","TwoLetterISORegionName":"AE","ThreeLetterISORegionName":"ARE"},{"Name":"UA","DisplayName":"Ukraine","TwoLetterISORegionName":"UA","ThreeLetterISORegionName":"UKR"},{"Name":"GB","DisplayName":"United Kingdom","TwoLetterISORegionName":"GB","ThreeLetterISORegionName":"GBR"},{"Name":"US","DisplayName":"United States","TwoLetterISORegionName":"US","ThreeLetterISORegionName":"USA"},{"Name":"UY","DisplayName":"Uruguay","TwoLetterISORegionName":"UY","ThreeLetterISORegionName":"URY"},{"Name":"UZ","DisplayName":"Uzbekistan","TwoLetterISORegionName":"UZ","ThreeLetterISORegionName":"UZB"},{"Name":"VN","DisplayName":"Vietnam","TwoLetterISORegionName":"VN","ThreeLetterISORegionName":"VNM"},{"Name":"YE","DisplayName":"Yemen","TwoLetterISORegionName":"YE","ThreeLetterISORegionName":"YEM"},{"Name":"ZW","DisplayName":"Zimbabwe","TwoLetterISORegionName":"ZW","ThreeLetterISORegionName":"ZWE"}] \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/cultures.json b/MediaBrowser.Server.Implementations/Localization/cultures.json
new file mode 100644
index 000000000..e9732fda8
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Localization/cultures.json
@@ -0,0 +1 @@
+[{"Name":"af","DisplayName":"Afrikaans","TwoLetterISOLanguageName":"af","ThreeLetterISOLanguageName":"afr"},{"Name":"sq","DisplayName":"Albanian","TwoLetterISOLanguageName":"sq","ThreeLetterISOLanguageName":"sqi"},{"Name":"gsw","DisplayName":"Alsatian","TwoLetterISOLanguageName":"gsw","ThreeLetterISOLanguageName":"gsw"},{"Name":"am","DisplayName":"Amharic","TwoLetterISOLanguageName":"am","ThreeLetterISOLanguageName":"amh"},{"Name":"ar","DisplayName":"Arabic","TwoLetterISOLanguageName":"ar","ThreeLetterISOLanguageName":"ara"},{"Name":"hy","DisplayName":"Armenian","TwoLetterISOLanguageName":"hy","ThreeLetterISOLanguageName":"hye"},{"Name":"as","DisplayName":"Assamese","TwoLetterISOLanguageName":"as","ThreeLetterISOLanguageName":"asm"},{"Name":"az","DisplayName":"Azeri","TwoLetterISOLanguageName":"az","ThreeLetterISOLanguageName":"aze"},{"Name":"jv","DisplayName":"Basa Jawa","TwoLetterISOLanguageName":"jv","ThreeLetterISOLanguageName":"jav"},{"Name":"ba","DisplayName":"Bashkir","TwoLetterISOLanguageName":"ba","ThreeLetterISOLanguageName":"bak"},{"Name":"eu","DisplayName":"Basque","TwoLetterISOLanguageName":"eu","ThreeLetterISOLanguageName":"eus"},{"Name":"be","DisplayName":"Belarusian","TwoLetterISOLanguageName":"be","ThreeLetterISOLanguageName":"bel"},{"Name":"bn","DisplayName":"Bengali","TwoLetterISOLanguageName":"bn","ThreeLetterISOLanguageName":"bng"},{"Name":"bs","DisplayName":"Bosnian","TwoLetterISOLanguageName":"bs","ThreeLetterISOLanguageName":"bsb"},{"Name":"bs-Cyrl","DisplayName":"Bosnian (Cyrillic)","TwoLetterISOLanguageName":"bs","ThreeLetterISOLanguageName":"bsc"},{"Name":"br","DisplayName":"Breton","TwoLetterISOLanguageName":"br","ThreeLetterISOLanguageName":"bre"},{"Name":"bg","DisplayName":"Bulgarian","TwoLetterISOLanguageName":"bg","ThreeLetterISOLanguageName":"bul"},{"Name":"my","DisplayName":"Burmese","TwoLetterISOLanguageName":"my","ThreeLetterISOLanguageName":"mya"},{"Name":"ca","DisplayName":"Catalan","TwoLetterISOLanguageName":"ca","ThreeLetterISOLanguageName":"cat"},{"Name":"tzm-Tfng-MA","DisplayName":"Central Atlas Tamazight (Tifinagh, Morocco)","TwoLetterISOLanguageName":"tzm","ThreeLetterISOLanguageName":"tzm"},{"Name":"ku","DisplayName":"Central Kurdish","TwoLetterISOLanguageName":"ku","ThreeLetterISOLanguageName":"kur"},{"Name":"chr","DisplayName":"Cherokee","TwoLetterISOLanguageName":"chr","ThreeLetterISOLanguageName":"chr"},{"Name":"zh","DisplayName":"Chinese","TwoLetterISOLanguageName":"zh","ThreeLetterISOLanguageName":"zho"},{"Name":"sn","DisplayName":"chiShona","TwoLetterISOLanguageName":"sn","ThreeLetterISOLanguageName":"sna"},{"Name":"co","DisplayName":"Corsican","TwoLetterISOLanguageName":"co","ThreeLetterISOLanguageName":"cos"},{"Name":"hr","DisplayName":"Croatian","TwoLetterISOLanguageName":"hr","ThreeLetterISOLanguageName":"hrv"},{"Name":"hr-BA","DisplayName":"Croatian (Latin, Bosnia and Herzegovina)","TwoLetterISOLanguageName":"hr","ThreeLetterISOLanguageName":"hrb"},{"Name":"cs","DisplayName":"Czech","TwoLetterISOLanguageName":"cs","ThreeLetterISOLanguageName":"ces"},{"Name":"da","DisplayName":"Danish","TwoLetterISOLanguageName":"da","ThreeLetterISOLanguageName":"dan"},{"Name":"prs","DisplayName":"Dari","TwoLetterISOLanguageName":"prs","ThreeLetterISOLanguageName":"prs"},{"Name":"dv","DisplayName":"Divehi","TwoLetterISOLanguageName":"dv","ThreeLetterISOLanguageName":"div"},{"Name":"nl","DisplayName":"Dutch","TwoLetterISOLanguageName":"nl","ThreeLetterISOLanguageName":"nld"},{"Name":"en","DisplayName":"English","TwoLetterISOLanguageName":"en","ThreeLetterISOLanguageName":"eng"},{"Name":"et","DisplayName":"Estonian","TwoLetterISOLanguageName":"et","ThreeLetterISOLanguageName":"est"},{"Name":"fo","DisplayName":"Faroese","TwoLetterISOLanguageName":"fo","ThreeLetterISOLanguageName":"fao"},{"Name":"fil","DisplayName":"Filipino","TwoLetterISOLanguageName":"fil","ThreeLetterISOLanguageName":"fil"},{"Name":"fi","DisplayName":"Finnish","TwoLetterISOLanguageName":"fi","ThreeLetterISOLanguageName":"fin"},{"Name":"fr","DisplayName":"French","TwoLetterISOLanguageName":"fr","ThreeLetterISOLanguageName":"fra"},{"Name":"fy","DisplayName":"Frisian","TwoLetterISOLanguageName":"fy","ThreeLetterISOLanguageName":"fry"},{"Name":"ff","DisplayName":"Fulah","TwoLetterISOLanguageName":"ff","ThreeLetterISOLanguageName":"ful"},{"Name":"gl","DisplayName":"Galician","TwoLetterISOLanguageName":"gl","ThreeLetterISOLanguageName":"glg"},{"Name":"ka","DisplayName":"Georgian","TwoLetterISOLanguageName":"ka","ThreeLetterISOLanguageName":"kat"},{"Name":"de","DisplayName":"German","TwoLetterISOLanguageName":"de","ThreeLetterISOLanguageName":"deu"},{"Name":"el","DisplayName":"Greek","TwoLetterISOLanguageName":"el","ThreeLetterISOLanguageName":"ell"},{"Name":"kl","DisplayName":"Greenlandic","TwoLetterISOLanguageName":"kl","ThreeLetterISOLanguageName":"kal"},{"Name":"gn","DisplayName":"Guarani","TwoLetterISOLanguageName":"gn","ThreeLetterISOLanguageName":"grn"},{"Name":"gu","DisplayName":"Gujarati","TwoLetterISOLanguageName":"gu","ThreeLetterISOLanguageName":"guj"},{"Name":"ha","DisplayName":"Hausa","TwoLetterISOLanguageName":"ha","ThreeLetterISOLanguageName":"hau"},{"Name":"haw","DisplayName":"Hawaiian","TwoLetterISOLanguageName":"haw","ThreeLetterISOLanguageName":"haw"},{"Name":"he","DisplayName":"Hebrew","TwoLetterISOLanguageName":"he","ThreeLetterISOLanguageName":"heb"},{"Name":"hi","DisplayName":"Hindi","TwoLetterISOLanguageName":"hi","ThreeLetterISOLanguageName":"hin"},{"Name":"hu","DisplayName":"Hungarian","TwoLetterISOLanguageName":"hu","ThreeLetterISOLanguageName":"hun"},{"Name":"is","DisplayName":"Icelandic","TwoLetterISOLanguageName":"is","ThreeLetterISOLanguageName":"isl"},{"Name":"ig","DisplayName":"Igbo","TwoLetterISOLanguageName":"ig","ThreeLetterISOLanguageName":"ibo"},{"Name":"id","DisplayName":"Indonesian","TwoLetterISOLanguageName":"id","ThreeLetterISOLanguageName":"ind"},{"Name":"iu","DisplayName":"Inuktitut","TwoLetterISOLanguageName":"iu","ThreeLetterISOLanguageName":"iku"},{"Name":"ga","DisplayName":"Irish","TwoLetterISOLanguageName":"ga","ThreeLetterISOLanguageName":"gle"},{"Name":"xh","DisplayName":"isiXhosa","TwoLetterISOLanguageName":"xh","ThreeLetterISOLanguageName":"xho"},{"Name":"zu","DisplayName":"isiZulu","TwoLetterISOLanguageName":"zu","ThreeLetterISOLanguageName":"zul"},{"Name":"it","DisplayName":"Italian","TwoLetterISOLanguageName":"it","ThreeLetterISOLanguageName":"ita"},{"Name":"ja","DisplayName":"Japanese","TwoLetterISOLanguageName":"ja","ThreeLetterISOLanguageName":"jpn"},{"Name":"kn","DisplayName":"Kannada","TwoLetterISOLanguageName":"kn","ThreeLetterISOLanguageName":"kan"},{"Name":"kk","DisplayName":"Kazakh","TwoLetterISOLanguageName":"kk","ThreeLetterISOLanguageName":"kaz"},{"Name":"km","DisplayName":"Khmer","TwoLetterISOLanguageName":"km","ThreeLetterISOLanguageName":"khm"},{"Name":"qut","DisplayName":"K'iche","TwoLetterISOLanguageName":"qut","ThreeLetterISOLanguageName":"qut"},{"Name":"rw","DisplayName":"Kinyarwanda","TwoLetterISOLanguageName":"rw","ThreeLetterISOLanguageName":"kin"},{"Name":"sw","DisplayName":"Kiswahili","TwoLetterISOLanguageName":"sw","ThreeLetterISOLanguageName":"swa"},{"Name":"kok","DisplayName":"Konkani","TwoLetterISOLanguageName":"kok","ThreeLetterISOLanguageName":"kok"},{"Name":"ko","DisplayName":"Korean","TwoLetterISOLanguageName":"ko","ThreeLetterISOLanguageName":"kor"},{"Name":"ky","DisplayName":"Kyrgyz","TwoLetterISOLanguageName":"ky","ThreeLetterISOLanguageName":"kir"},{"Name":"lo","DisplayName":"Lao","TwoLetterISOLanguageName":"lo","ThreeLetterISOLanguageName":"lao"},{"Name":"lv","DisplayName":"Latvian","TwoLetterISOLanguageName":"lv","ThreeLetterISOLanguageName":"lav"},{"Name":"lt","DisplayName":"Lithuanian","TwoLetterISOLanguageName":"lt","ThreeLetterISOLanguageName":"lit"},{"Name":"dsb","DisplayName":"Lower Sorbian","TwoLetterISOLanguageName":"dsb","ThreeLetterISOLanguageName":"dsb"},{"Name":"lb","DisplayName":"Luxembourgish","TwoLetterISOLanguageName":"lb","ThreeLetterISOLanguageName":"ltz"},{"Name":"mk-MK","DisplayName":"Macedonian (Former Yugoslav Republic of Macedonia)","TwoLetterISOLanguageName":"mk","ThreeLetterISOLanguageName":"mkd"},{"Name":"mg","DisplayName":"Malagasy","TwoLetterISOLanguageName":"mg","ThreeLetterISOLanguageName":"mlg"},{"Name":"ms","DisplayName":"Malay","TwoLetterISOLanguageName":"ms","ThreeLetterISOLanguageName":"msa"},{"Name":"ml","DisplayName":"Malayalam","TwoLetterISOLanguageName":"ml","ThreeLetterISOLanguageName":"mym"},{"Name":"mt","DisplayName":"Maltese","TwoLetterISOLanguageName":"mt","ThreeLetterISOLanguageName":"mlt"},{"Name":"mi","DisplayName":"Maori","TwoLetterISOLanguageName":"mi","ThreeLetterISOLanguageName":"mri"},{"Name":"arn","DisplayName":"Mapudungun","TwoLetterISOLanguageName":"arn","ThreeLetterISOLanguageName":"arn"},{"Name":"mr","DisplayName":"Marathi","TwoLetterISOLanguageName":"mr","ThreeLetterISOLanguageName":"mar"},{"Name":"moh","DisplayName":"Mohawk","TwoLetterISOLanguageName":"moh","ThreeLetterISOLanguageName":"moh"},{"Name":"mn","DisplayName":"Mongolian","TwoLetterISOLanguageName":"mn","ThreeLetterISOLanguageName":"mon"},{"Name":"ne","DisplayName":"Nepali","TwoLetterISOLanguageName":"ne","ThreeLetterISOLanguageName":"nep"},{"Name":"no","DisplayName":"Norwegian","TwoLetterISOLanguageName":"nb","ThreeLetterISOLanguageName":"nob"},{"Name":"nn","DisplayName":"Norwegian (Nynorsk)","TwoLetterISOLanguageName":"nn","ThreeLetterISOLanguageName":"nno"},{"Name":"oc","DisplayName":"Occitan","TwoLetterISOLanguageName":"oc","ThreeLetterISOLanguageName":"oci"},{"Name":"or","DisplayName":"Oriya","TwoLetterISOLanguageName":"or","ThreeLetterISOLanguageName":"ori"},{"Name":"om","DisplayName":"Oromo","TwoLetterISOLanguageName":"om","ThreeLetterISOLanguageName":"orm"},{"Name":"ps","DisplayName":"Pashto","TwoLetterISOLanguageName":"ps","ThreeLetterISOLanguageName":"pus"},{"Name":"fa","DisplayName":"Persian","TwoLetterISOLanguageName":"fa","ThreeLetterISOLanguageName":"fas"},{"Name":"pl","DisplayName":"Polish","TwoLetterISOLanguageName":"pl","ThreeLetterISOLanguageName":"pol"},{"Name":"pt-AO","DisplayName":"português (Angola)","TwoLetterISOLanguageName":"pt","ThreeLetterISOLanguageName":"por"},{"Name":"pa","DisplayName":"Punjabi","TwoLetterISOLanguageName":"pa","ThreeLetterISOLanguageName":"pan"},{"Name":"quz","DisplayName":"Quechua","TwoLetterISOLanguageName":"quz","ThreeLetterISOLanguageName":"qub"},{"Name":"quz-EC","DisplayName":"Quechua (Ecuador)","TwoLetterISOLanguageName":"quz","ThreeLetterISOLanguageName":"que"},{"Name":"quz-PE","DisplayName":"Quechua (Peru)","TwoLetterISOLanguageName":"quz","ThreeLetterISOLanguageName":"qup"},{"Name":"ro","DisplayName":"Romanian","TwoLetterISOLanguageName":"ro","ThreeLetterISOLanguageName":"ron"},{"Name":"rm","DisplayName":"Romansh","TwoLetterISOLanguageName":"rm","ThreeLetterISOLanguageName":"roh"},{"Name":"ru","DisplayName":"Russian","TwoLetterISOLanguageName":"ru","ThreeLetterISOLanguageName":"rus"},{"Name":"sah","DisplayName":"Sakha","TwoLetterISOLanguageName":"sah","ThreeLetterISOLanguageName":"sah"},{"Name":"smn","DisplayName":"Sami (Inari)","TwoLetterISOLanguageName":"smn","ThreeLetterISOLanguageName":"smn"},{"Name":"smj","DisplayName":"Sami (Lule)","TwoLetterISOLanguageName":"smj","ThreeLetterISOLanguageName":"smj"},{"Name":"se","DisplayName":"Sami (Northern)","TwoLetterISOLanguageName":"se","ThreeLetterISOLanguageName":"sme"},{"Name":"sms","DisplayName":"Sami (Skolt)","TwoLetterISOLanguageName":"sms","ThreeLetterISOLanguageName":"sms"},{"Name":"sma","DisplayName":"Sami (Southern)","TwoLetterISOLanguageName":"sma","ThreeLetterISOLanguageName":"sma"},{"Name":"sa","DisplayName":"Sanskrit","TwoLetterISOLanguageName":"sa","ThreeLetterISOLanguageName":"san"},{"Name":"gd","DisplayName":"Scottish Gaelic","TwoLetterISOLanguageName":"gd","ThreeLetterISOLanguageName":"gla"},{"Name":"sr","DisplayName":"Serbian","TwoLetterISOLanguageName":"sr","ThreeLetterISOLanguageName":"srp"},{"Name":"sr-Cyrl-BA","DisplayName":"Serbian (Cyrillic, Bosnia and Herzegovina)","TwoLetterISOLanguageName":"sr","ThreeLetterISOLanguageName":"srn"},{"Name":"sr-Latn-BA","DisplayName":"Serbian (Latin, Bosnia and Herzegovina)","TwoLetterISOLanguageName":"sr","ThreeLetterISOLanguageName":"srs"},{"Name":"nso","DisplayName":"Sesotho sa Leboa","TwoLetterISOLanguageName":"nso","ThreeLetterISOLanguageName":"nso"},{"Name":"tn","DisplayName":"Setswana","TwoLetterISOLanguageName":"tn","ThreeLetterISOLanguageName":"tsn"},{"Name":"sd","DisplayName":"Sindhi","TwoLetterISOLanguageName":"sd","ThreeLetterISOLanguageName":"sin"},{"Name":"si","DisplayName":"Sinhala","TwoLetterISOLanguageName":"si","ThreeLetterISOLanguageName":"sin"},{"Name":"sk","DisplayName":"Slovak","TwoLetterISOLanguageName":"sk","ThreeLetterISOLanguageName":"slk"},{"Name":"sl","DisplayName":"Slovenian","TwoLetterISOLanguageName":"sl","ThreeLetterISOLanguageName":"slv"},{"Name":"so","DisplayName":"Somali","TwoLetterISOLanguageName":"so","ThreeLetterISOLanguageName":"som"},{"Name":"st","DisplayName":"Southern Sotho","TwoLetterISOLanguageName":"st","ThreeLetterISOLanguageName":"sot"},{"Name":"es","DisplayName":"Spanish","TwoLetterISOLanguageName":"es","ThreeLetterISOLanguageName":"spa"},{"Name":"zgh","DisplayName":"Standard Morrocan Tamazight","TwoLetterISOLanguageName":"zgh","ThreeLetterISOLanguageName":"zgh"},{"Name":"sv","DisplayName":"Swedish","TwoLetterISOLanguageName":"sv","ThreeLetterISOLanguageName":"swe"},{"Name":"syr","DisplayName":"Syriac","TwoLetterISOLanguageName":"syr","ThreeLetterISOLanguageName":"syr"},{"Name":"tg","DisplayName":"Tajik","TwoLetterISOLanguageName":"tg","ThreeLetterISOLanguageName":"tgk"},{"Name":"ta","DisplayName":"Tamil","TwoLetterISOLanguageName":"ta","ThreeLetterISOLanguageName":"tam"},{"Name":"tt","DisplayName":"Tatar","TwoLetterISOLanguageName":"tt","ThreeLetterISOLanguageName":"tat"},{"Name":"te","DisplayName":"Telugu","TwoLetterISOLanguageName":"te","ThreeLetterISOLanguageName":"tel"},{"Name":"th","DisplayName":"Thai","TwoLetterISOLanguageName":"th","ThreeLetterISOLanguageName":"tha"},{"Name":"bo","DisplayName":"Tibetan","TwoLetterISOLanguageName":"bo","ThreeLetterISOLanguageName":"bod"},{"Name":"ti","DisplayName":"Tigrinya","TwoLetterISOLanguageName":"ti","ThreeLetterISOLanguageName":"tir"},{"Name":"ts","DisplayName":"Tsonga","TwoLetterISOLanguageName":"ts","ThreeLetterISOLanguageName":"tso"},{"Name":"tr","DisplayName":"Turkish","TwoLetterISOLanguageName":"tr","ThreeLetterISOLanguageName":"tur"},{"Name":"tk","DisplayName":"Turkmen","TwoLetterISOLanguageName":"tk","ThreeLetterISOLanguageName":"tuk"},{"Name":"uk","DisplayName":"Ukrainian","TwoLetterISOLanguageName":"uk","ThreeLetterISOLanguageName":"ukr"},{"Name":"hsb","DisplayName":"Upper Sorbian","TwoLetterISOLanguageName":"hsb","ThreeLetterISOLanguageName":"hsb"},{"Name":"ur","DisplayName":"Urdu","TwoLetterISOLanguageName":"ur","ThreeLetterISOLanguageName":"urd"},{"Name":"ug","DisplayName":"Uyghur","TwoLetterISOLanguageName":"ug","ThreeLetterISOLanguageName":"uig"},{"Name":"uz","DisplayName":"Uzbek","TwoLetterISOLanguageName":"uz","ThreeLetterISOLanguageName":"uzb"},{"Name":"vi","DisplayName":"Vietnamese","TwoLetterISOLanguageName":"vi","ThreeLetterISOLanguageName":"vie"},{"Name":"cy","DisplayName":"Welsh","TwoLetterISOLanguageName":"cy","ThreeLetterISOLanguageName":"cym"},{"Name":"wo","DisplayName":"Wolof","TwoLetterISOLanguageName":"wo","ThreeLetterISOLanguageName":"wol"},{"Name":"ii","DisplayName":"Yi","TwoLetterISOLanguageName":"ii","ThreeLetterISOLanguageName":"iii"},{"Name":"yo","DisplayName":"Yoruba","TwoLetterISOLanguageName":"yo","ThreeLetterISOLanguageName":"yor"}] \ 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 6e5e58d26..21fcd736f 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -64,6 +64,7 @@
<Reference Include="System.Drawing" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
+ <Reference Include="System.Security" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
<Reference Include="MoreLinq">
@@ -103,6 +104,7 @@
<Compile Include="Channels\RefreshChannelsScheduledTask.cs" />
<Compile Include="Collections\CollectionManager.cs" />
<Compile Include="Collections\CollectionsDynamicFolder.cs" />
+ <Compile Include="Collections\ManualCollectionsFolder.cs" />
<Compile Include="Configuration\ServerConfigurationManager.cs" />
<Compile Include="Drawing\ImageHeader.cs" />
<Compile Include="Drawing\PercentPlayedDrawer.cs" />
@@ -113,7 +115,7 @@
<Compile Include="EntryPoints\ExternalPortForwarding.cs" />
<Compile Include="EntryPoints\LibraryChangedNotifier.cs" />
<Compile Include="EntryPoints\LoadRegistrations.cs" />
- <Compile Include="EntryPoints\Notifications\Notifier.cs" />
+ <Compile Include="EntryPoints\Notifications\Notifications.cs" />
<Compile Include="EntryPoints\Notifications\RemoteNotifications.cs" />
<Compile Include="EntryPoints\Notifications\WebSocketNotifier.cs" />
<Compile Include="EntryPoints\RefreshUsersMetadata.cs" />
@@ -127,6 +129,8 @@
<Compile Include="EntryPoints\UserDataChangeNotifier.cs" />
<Compile Include="FileOrganization\OrganizerScheduledTask.cs" />
<Compile Include="HttpServer\ContainerAdapter.cs" />
+ <Compile Include="HttpServer\DelReceiveWebRequest.cs" />
+ <Compile Include="HttpServer\GetSwaggerResource.cs" />
<Compile Include="HttpServer\HttpListenerHost.cs" />
<Compile Include="HttpServer\HttpResultFactory.cs" />
<Compile Include="HttpServer\LoggerUtils.cs" />
@@ -134,6 +138,7 @@
<Compile Include="HttpServer\RangeRequestWriter.cs" />
<Compile Include="HttpServer\ResponseFilter.cs" />
<Compile Include="HttpServer\ServerFactory.cs" />
+ <Compile Include="HttpServer\ServerLogFactory.cs" />
<Compile Include="HttpServer\ServerLogger.cs" />
<Compile Include="HttpServer\StreamWriter.cs" />
<Compile Include="HttpServer\SwaggerService.cs" />
@@ -148,7 +153,7 @@
<Compile Include="Library\Resolvers\Audio\AudioResolver.cs" />
<Compile Include="Library\Resolvers\Audio\MusicAlbumResolver.cs" />
<Compile Include="Library\Resolvers\Audio\MusicArtistResolver.cs" />
- <Compile Include="Library\Resolvers\BaseItemResolver.cs" />
+ <Compile Include="Library\Resolvers\ItemResolver.cs" />
<Compile Include="Library\Resolvers\FolderResolver.cs" />
<Compile Include="Library\Resolvers\LocalTrailerResolver.cs" />
<Compile Include="Library\Resolvers\Movies\BoxSetResolver.cs" />
@@ -162,14 +167,12 @@
<Compile Include="Library\Validators\ArtistsPostScanTask.cs" />
<Compile Include="Library\Validators\ArtistsValidator.cs" />
<Compile Include="Library\Validators\BoxSetPostScanTask.cs" />
- <Compile Include="Library\Validators\CountHelpers.cs" />
<Compile Include="Library\Validators\GameGenresPostScanTask.cs" />
<Compile Include="Library\Validators\GameGenresValidator.cs" />
<Compile Include="Library\Validators\GenresPostScanTask.cs" />
<Compile Include="Library\Validators\GenresValidator.cs" />
<Compile Include="Library\Validators\MusicGenresPostScanTask.cs" />
<Compile Include="Library\Validators\MusicGenresValidator.cs" />
- <Compile Include="Library\Validators\PeoplePostScanTask.cs" />
<Compile Include="Library\Validators\PeopleValidator.cs" />
<Compile Include="Library\Validators\StudiosPostScanTask.cs" />
<Compile Include="Library\Validators\StudiosValidator.cs" />
@@ -202,6 +205,7 @@
<Compile Include="ScheduledTasks\ChapterImagesTask.cs" />
<Compile Include="ScheduledTasks\RefreshIntrosTask.cs" />
<Compile Include="ScheduledTasks\RefreshMediaLibraryTask.cs" />
+ <Compile Include="Security\EncryptionManager.cs" />
<Compile Include="ServerApplicationPaths.cs" />
<Compile Include="ServerManager\ServerManager.cs" />
<Compile Include="ServerManager\WebSocketConnection.cs" />
@@ -224,6 +228,7 @@
<Compile Include="Sorting\DatePlayedComparer.cs" />
<Compile Include="Sorting\GameSystemComparer.cs" />
<Compile Include="Sorting\IsFolderComparer.cs" />
+ <Compile Include="Sorting\IsPlayedComparer.cs" />
<Compile Include="Sorting\IsUnplayedComparer.cs" />
<Compile Include="Sorting\MetascoreComparer.cs" />
<Compile Include="Sorting\NameComparer.cs" />
@@ -328,6 +333,8 @@
<EmbeddedResource Include="Localization\Server\ms.json" />
<EmbeddedResource Include="Localization\JavaScript\kk.json" />
<EmbeddedResource Include="Localization\Server\kk.json" />
+ <EmbeddedResource Include="Localization\countries.json" />
+ <EmbeddedResource Include="Localization\cultures.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
diff --git a/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs b/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs
index f712949d9..012b5ae92 100644
--- a/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs
+++ b/MediaBrowser.Server.Implementations/Notifications/CoreNotificationTypes.cs
@@ -92,6 +92,13 @@ namespace MediaBrowser.Server.Implementations.Notifications
new NotificationTypeInfo
{
+ Type = NotificationType.NewLibraryContentMultiple.ToString(),
+ DefaultTitle = "{ItemCount} new items have been added to your media library.",
+ Variables = new List<string>{"ItemCount"}
+ },
+
+ new NotificationTypeInfo
+ {
Type = NotificationType.AudioPlayback.ToString(),
DefaultTitle = "{UserName} is playing {ItemName} on {DeviceName}.",
Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs
index 9f6ec0f24..ac1c5ef55 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -111,7 +112,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
throw new ArgumentNullException("displayPreferences");
}
- if (displayPreferences.Id == Guid.Empty)
+ if (string.IsNullOrWhiteSpace(displayPreferences.Id))
{
throw new ArgumentNullException("displayPreferences.Id");
}
@@ -132,7 +133,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
cmd.CommandText = "replace into userdisplaypreferences (id, userid, client, data) values (@1, @2, @3, @4)";
- cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = displayPreferences.Id;
+ cmd.Parameters.Add(cmd, "@1", DbType.Guid).Value = new Guid(displayPreferences.Id);
cmd.Parameters.Add(cmd, "@2", DbType.Guid).Value = userId;
cmd.Parameters.Add(cmd, "@3", DbType.String).Value = client;
cmd.Parameters.Add(cmd, "@4", DbType.Binary).Value = serialized;
@@ -183,17 +184,19 @@ namespace MediaBrowser.Server.Implementations.Persistence
/// <param name="client">The client.</param>
/// <returns>Task{DisplayPreferences}.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
- public DisplayPreferences GetDisplayPreferences(Guid displayPreferencesId, Guid userId, string client)
+ public DisplayPreferences GetDisplayPreferences(string displayPreferencesId, Guid userId, string client)
{
- if (displayPreferencesId == Guid.Empty)
+ if (string.IsNullOrWhiteSpace(displayPreferencesId))
{
throw new ArgumentNullException("displayPreferencesId");
}
+ var guidId = displayPreferencesId.GetMD5();
+
var cmd = _connection.CreateCommand();
cmd.CommandText = "select data from userdisplaypreferences where id = @id and userId=@userId and client=@client";
- cmd.Parameters.Add(cmd, "@id", DbType.Guid).Value = displayPreferencesId;
+ cmd.Parameters.Add(cmd, "@id", DbType.Guid).Value = guidId;
cmd.Parameters.Add(cmd, "@userId", DbType.Guid).Value = userId;
cmd.Parameters.Add(cmd, "@client", DbType.String).Value = client;
@@ -208,7 +211,10 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
- return new DisplayPreferences { Id = displayPreferencesId };
+ return new DisplayPreferences
+ {
+ Id = guidId.ToString("N")
+ };
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/Roku/RokuSessionController.cs b/MediaBrowser.Server.Implementations/Roku/RokuSessionController.cs
index cdaf03fbe..ad9db947a 100644
--- a/MediaBrowser.Server.Implementations/Roku/RokuSessionController.cs
+++ b/MediaBrowser.Server.Implementations/Roku/RokuSessionController.cs
@@ -56,16 +56,6 @@ namespace MediaBrowser.Server.Implementations.Roku
return Task.FromResult(true);
}
- public Task SendMessageCommand(MessageCommand command, CancellationToken cancellationToken)
- {
- return SendCommand(new WebSocketMessage<MessageCommand>
- {
- MessageType = "MessageCommand",
- Data = command
-
- }, cancellationToken);
- }
-
public Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken)
{
return SendCommand(new WebSocketMessage<PlayRequest>
diff --git a/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs b/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs
new file mode 100644
index 000000000..73a4e3004
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Security/EncryptionManager.cs
@@ -0,0 +1,36 @@
+using MediaBrowser.Controller.Security;
+using System;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace MediaBrowser.Server.Implementations.Security
+{
+ public class EncryptionManager : IEncryptionManager
+ {
+ /// <summary>
+ /// Encrypts the string.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>System.String.</returns>
+ /// <exception cref="System.ArgumentNullException">value</exception>
+ public string EncryptString(string value)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+
+ return Encoding.Default.GetString(ProtectedData.Protect(Encoding.Default.GetBytes(value), null, DataProtectionScope.LocalMachine));
+ }
+
+ /// <summary>
+ /// Decrypts the string.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns>System.String.</returns>
+ /// <exception cref="System.ArgumentNullException">value</exception>
+ public string DecryptString(string value)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+
+ return Encoding.Default.GetString(ProtectedData.Unprotect(Encoding.Default.GetBytes(value), null, DataProtectionScope.LocalMachine));
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index 5a800eae7..d2a047b42 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Events;
+using System.Globalization;
+using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
@@ -48,6 +49,7 @@ namespace MediaBrowser.Server.Implementations.Session
private readonly IMusicManager _musicManager;
private readonly IDtoService _dtoService;
private readonly IImageProcessor _imageProcessor;
+ private readonly IItemRepository _itemRepo;
/// <summary>
/// Gets or sets the configuration manager.
@@ -90,7 +92,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)
+ public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo)
{
_userDataRepository = userDataRepository;
_configurationManager = configurationManager;
@@ -101,6 +103,7 @@ namespace MediaBrowser.Server.Implementations.Session
_musicManager = musicManager;
_dtoService = dtoService;
_imageProcessor = imageProcessor;
+ _itemRepo = itemRepo;
}
/// <summary>
@@ -279,7 +282,18 @@ namespace MediaBrowser.Server.Implementations.Session
if (!string.IsNullOrWhiteSpace(info.ItemId) && libraryItem != null)
{
- info.Item = GetItemInfo(libraryItem, runtimeTicks);
+ 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;
+ }
+
+ info.Item.RunTimeTicks = runtimeTicks;
}
session.NowPlayingItem = info.Item;
@@ -710,12 +724,20 @@ namespace MediaBrowser.Server.Implementations.Session
public Task SendMessageCommand(string controllingSessionId, string sessionId, MessageCommand command, CancellationToken cancellationToken)
{
- var session = GetSessionForRemoteControl(sessionId);
+ var generalCommand = new GeneralCommand
+ {
+ Name = GeneralCommandType.DisplayMessage.ToString()
+ };
- var controllingSession = GetSession(controllingSessionId);
- AssertCanControl(session, controllingSession);
+ generalCommand.Arguments["Header"] = command.Header;
+ generalCommand.Arguments["Text"] = command.Text;
- return session.SessionController.SendMessageCommand(command, cancellationToken);
+ if (command.TimeoutMs.HasValue)
+ {
+ generalCommand.Arguments["TimeoutMs"] = command.TimeoutMs.Value.ToString(CultureInfo.InvariantCulture);
+ }
+
+ return SendGeneralCommand(controllingSessionId, sessionId, generalCommand, cancellationToken);
}
public Task SendGeneralCommand(string controllingSessionId, string sessionId, GeneralCommand command, CancellationToken cancellationToken)
@@ -1171,10 +1193,11 @@ namespace MediaBrowser.Server.Implementations.Session
/// Converts a BaseItem to a BaseItemInfo
/// </summary>
/// <param name="item">The item.</param>
- /// <param name="runtimeTicks">The now playing runtime ticks.</param>
+ /// <param name="chapterOwner">The chapter owner.</param>
+ /// <param name="mediaSourceId">The media source identifier.</param>
/// <returns>BaseItemInfo.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
- private BaseItemInfo GetItemInfo(BaseItem item, long? runtimeTicks)
+ private BaseItemInfo GetItemInfo(BaseItem item, BaseItem chapterOwner, string mediaSourceId)
{
if (item == null)
{
@@ -1187,7 +1210,7 @@ namespace MediaBrowser.Server.Implementations.Session
Name = item.Name,
MediaType = item.MediaType,
Type = item.GetClientTypeName(),
- RunTimeTicks = runtimeTicks,
+ RunTimeTicks = item.RunTimeTicks,
IndexNumber = item.IndexNumber,
ParentIndexNumber = item.ParentIndexNumber,
PremiereDate = item.PremiereDate,
@@ -1195,7 +1218,7 @@ namespace MediaBrowser.Server.Implementations.Session
};
info.PrimaryImageTag = GetImageCacheTag(item, ImageType.Primary);
- if (info.PrimaryImageTag.HasValue)
+ if (info.PrimaryImageTag != null)
{
info.PrimaryImageItemId = GetDtoId(item);
}
@@ -1233,14 +1256,14 @@ namespace MediaBrowser.Server.Implementations.Session
info.Album = audio.Album;
info.Artists = audio.Artists;
- if (!info.PrimaryImageTag.HasValue)
+ if (info.PrimaryImageTag == null)
{
var album = audio.Parents.OfType<MusicAlbum>().FirstOrDefault();
if (album != null && album.HasImage(ImageType.Primary))
{
info.PrimaryImageTag = GetImageCacheTag(album, ImageType.Primary);
- if (info.PrimaryImageTag.HasValue)
+ if (info.PrimaryImageTag != null)
{
info.PrimaryImageItemId = GetDtoId(album);
}
@@ -1322,10 +1345,26 @@ namespace MediaBrowser.Server.Implementations.Session
info.LogoItemId = GetDtoId(logoItem);
}
+ if (chapterOwner != null)
+ {
+ info.ChapterImagesItemId = chapterOwner.Id.ToString("N");
+
+ info.Chapters = _itemRepo.GetChapters(chapterOwner.Id).Select(i => _dtoService.GetChapterInfoDto(i, chapterOwner)).ToList();
+ }
+
+ if (!string.IsNullOrWhiteSpace(mediaSourceId))
+ {
+ info.MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery
+ {
+ ItemId = new Guid(mediaSourceId)
+
+ }).ToList();
+ }
+
return info;
}
- private Guid? GetImageCacheTag(BaseItem item, ImageType type)
+ private string GetImageCacheTag(BaseItem item, ImageType type)
{
try
{
@@ -1347,7 +1386,7 @@ namespace MediaBrowser.Server.Implementations.Session
{
var item = _libraryManager.GetItemById(new Guid(itemId));
- var info = GetItemInfo(item, item.RunTimeTicks);
+ var info = GetItemInfo(item, null, null);
ReportNowViewingItem(sessionId, info);
}
diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
index 4b0c25a87..3b6ecd21e 100644
--- a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
+++ b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
@@ -57,18 +57,6 @@ namespace MediaBrowser.Server.Implementations.Session
return socket;
}
- public Task SendMessageCommand(MessageCommand command, CancellationToken cancellationToken)
- {
- var socket = GetActiveSocket();
-
- return socket.SendAsync(new WebSocketMessage<MessageCommand>
- {
- MessageType = "MessageCommand",
- Data = command
-
- }, cancellationToken);
- }
-
public Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken)
{
var socket = GetActiveSocket();
diff --git a/MediaBrowser.Server.Implementations/Sorting/IsPlayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/IsPlayedComparer.cs
new file mode 100644
index 000000000..aebfbdb1c
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Sorting/IsPlayedComparer.cs
@@ -0,0 +1,58 @@
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Sorting;
+using MediaBrowser.Model.Querying;
+
+namespace MediaBrowser.Server.Implementations.Sorting
+{
+ public class IsPlayedComparer : IUserBaseItemComparer
+ {
+ /// <summary>
+ /// Gets or sets the user.
+ /// </summary>
+ /// <value>The user.</value>
+ public User User { get; set; }
+
+ /// <summary>
+ /// Compares the specified x.
+ /// </summary>
+ /// <param name="x">The x.</param>
+ /// <param name="y">The y.</param>
+ /// <returns>System.Int32.</returns>
+ public int Compare(BaseItem x, BaseItem y)
+ {
+ return GetValue(x).CompareTo(GetValue(y));
+ }
+
+ /// <summary>
+ /// Gets the date.
+ /// </summary>
+ /// <param name="x">The x.</param>
+ /// <returns>DateTime.</returns>
+ private int GetValue(BaseItem x)
+ {
+ return x.IsPlayed(User) ? 0 : 1;
+ }
+
+ /// <summary>
+ /// Gets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name
+ {
+ get { return ItemSortBy.IsUnplayed; }
+ }
+
+ /// <summary>
+ /// Gets or sets the user data repository.
+ /// </summary>
+ /// <value>The user data repository.</value>
+ public IUserDataManager UserDataRepository { get; set; }
+
+ /// <summary>
+ /// Gets or sets the user manager.
+ /// </summary>
+ /// <value>The user manager.</value>
+ public IUserManager UserManager { get; set; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Sorting/IsUnplayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/IsUnplayedComparer.cs
index e3053155f..f1c6a5a4e 100644
--- a/MediaBrowser.Server.Implementations/Sorting/IsUnplayedComparer.cs
+++ b/MediaBrowser.Server.Implementations/Sorting/IsUnplayedComparer.cs
@@ -55,55 +55,4 @@ namespace MediaBrowser.Server.Implementations.Sorting
/// <value>The user manager.</value>
public IUserManager UserManager { get; set; }
}
-
- public class IsPlayedComparer : IUserBaseItemComparer
- {
- /// <summary>
- /// Gets or sets the user.
- /// </summary>
- /// <value>The user.</value>
- public User User { get; set; }
-
- /// <summary>
- /// Compares the specified x.
- /// </summary>
- /// <param name="x">The x.</param>
- /// <param name="y">The y.</param>
- /// <returns>System.Int32.</returns>
- public int Compare(BaseItem x, BaseItem y)
- {
- return GetValue(x).CompareTo(GetValue(y));
- }
-
- /// <summary>
- /// Gets the date.
- /// </summary>
- /// <param name="x">The x.</param>
- /// <returns>DateTime.</returns>
- private int GetValue(BaseItem x)
- {
- return x.IsPlayed(User) ? 0 : 1;
- }
-
- /// <summary>
- /// Gets the name.
- /// </summary>
- /// <value>The name.</value>
- public string Name
- {
- get { return ItemSortBy.IsUnplayed; }
- }
-
- /// <summary>
- /// Gets or sets the user data repository.
- /// </summary>
- /// <value>The user data repository.</value>
- public IUserDataManager UserDataRepository { get; set; }
-
- /// <summary>
- /// Gets or sets the user manager.
- /// </summary>
- /// <value>The user manager.</value>
- public IUserManager UserManager { get; set; }
- }
}
diff --git a/MediaBrowser.Server.Mono/Native/NativeApp.cs b/MediaBrowser.Server.Mono/Native/NativeApp.cs
index deff79b4b..1cf217910 100644
--- a/MediaBrowser.Server.Mono/Native/NativeApp.cs
+++ b/MediaBrowser.Server.Mono/Native/NativeApp.cs
@@ -51,5 +51,10 @@ namespace MediaBrowser.ServerApplication.Native
{
get { return false; }
}
+
+ public static void PreventSystemStandby()
+ {
+
+ }
}
}
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index 0740feece..2bae497ff 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -29,13 +29,14 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
+using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.Sorting;
+using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Controller.Themes;
using MediaBrowser.Dlna;
using MediaBrowser.Dlna.Eventing;
using MediaBrowser.Dlna.Main;
-using MediaBrowser.Dlna.PlayTo;
using MediaBrowser.Dlna.Server;
using MediaBrowser.MediaEncoding.BdInfo;
using MediaBrowser.MediaEncoding.Encoder;
@@ -44,6 +45,7 @@ using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.System;
using MediaBrowser.Model.Updates;
using MediaBrowser.Providers.Manager;
+using MediaBrowser.Providers.Subtitles;
using MediaBrowser.Server.Implementations;
using MediaBrowser.Server.Implementations.Channels;
using MediaBrowser.Server.Implementations.Collections;
@@ -60,6 +62,7 @@ using MediaBrowser.Server.Implementations.Localization;
using MediaBrowser.Server.Implementations.MediaEncoder;
using MediaBrowser.Server.Implementations.Notifications;
using MediaBrowser.Server.Implementations.Persistence;
+using MediaBrowser.Server.Implementations.Security;
using MediaBrowser.Server.Implementations.ServerManager;
using MediaBrowser.Server.Implementations.Session;
using MediaBrowser.Server.Implementations.Themes;
@@ -193,6 +196,7 @@ namespace MediaBrowser.ServerApplication
private IProviderRepository ProviderRepository { get; set; }
private INotificationManager NotificationManager { get; set; }
+ private ISubtitleManager SubtitleManager { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationHost"/> class.
@@ -492,7 +496,7 @@ namespace MediaBrowser.ServerApplication
DtoService = new DtoService(Logger, LibraryManager, UserManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager);
RegisterSingleInstance(DtoService);
- SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor);
+ SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository);
RegisterSingleInstance(SessionManager);
var newsService = new Server.Implementations.News.NewsService(ApplicationPaths, JsonSerializer);
@@ -507,7 +511,7 @@ namespace MediaBrowser.ServerApplication
MediaEncoder);
RegisterSingleInstance(EncodingManager);
- ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, Logger, ServerConfigurationManager, FileSystemManager, UserDataManager);
+ ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, Logger, ServerConfigurationManager, FileSystemManager, UserDataManager, JsonSerializer);
RegisterSingleInstance(ChannelManager);
var appThemeManager = new AppThemeManager(ApplicationPaths, FileSystemManager, JsonSerializer, Logger);
@@ -531,6 +535,11 @@ namespace MediaBrowser.ServerApplication
NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager);
RegisterSingleInstance(NotificationManager);
+ RegisterSingleInstance<IEncryptionManager>(new EncryptionManager());
+
+ SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor);
+ RegisterSingleInstance(SubtitleManager);
+
var displayPreferencesTask = Task.Run(async () => await ConfigureDisplayPreferencesRepositories().ConfigureAwait(false));
var itemsTask = Task.Run(async () => await ConfigureItemRepositories().ConfigureAwait(false));
var userdataTask = Task.Run(async () => await ConfigureUserDataRepositories().ConfigureAwait(false));
@@ -566,7 +575,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.Path, info.ProbePath, info.Version, FileSystemManager);
+ MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ApplicationPaths, JsonSerializer, info.EncoderPath, info.ProbePath, info.Version, FileSystemManager);
RegisterSingleInstance(MediaEncoder);
}
@@ -710,9 +719,11 @@ namespace MediaBrowser.ServerApplication
LiveTvManager.AddParts(GetExports<ILiveTvService>());
+ SubtitleManager.AddParts(GetExports<ISubtitleProvider>());
+
SessionManager.AddParts(GetExports<ISessionControllerFactory>());
- ChannelManager.AddParts(GetExports<IChannel>());
+ ChannelManager.AddParts(GetExports<IChannel>(), GetExports<IChannelFactory>());
NotificationManager.AddParts(GetExports<INotificationService>(), GetExports<INotificationTypeFactory>());
}
@@ -1026,16 +1037,12 @@ namespace MediaBrowser.ServerApplication
/// <returns>Task{CheckForUpdateResult}.</returns>
public override async Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress)
{
-#if DEBUG
- return new CheckForUpdateResult { AvailableVersion = ApplicationVersion, IsUpdateAvailable = false };
-#endif
-
var availablePackages = await InstallationManager.GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, Constants.MbServerPkgName, null, ApplicationVersion,
ConfigurationManager.CommonConfiguration.SystemUpdateLevel);
- HasUpdateAvailable = version != null;
+ HasUpdateAvailable = version != null && version.version >= ApplicationVersion;
return version != null ? new CheckForUpdateResult { AvailableVersion = version.version, IsUpdateAvailable = version.version > ApplicationVersion, Package = version } :
new CheckForUpdateResult { AvailableVersion = ApplicationVersion, IsUpdateAvailable = false };
diff --git a/MediaBrowser.ServerApplication/EntryPoints/KeepServerAwake.cs b/MediaBrowser.ServerApplication/EntryPoints/KeepServerAwake.cs
new file mode 100644
index 000000000..9881bdf18
--- /dev/null
+++ b/MediaBrowser.ServerApplication/EntryPoints/KeepServerAwake.cs
@@ -0,0 +1,57 @@
+using MediaBrowser.Controller.Plugins;
+using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.ServerApplication.Native;
+using System;
+using System.Linq;
+using System.Threading;
+
+namespace MediaBrowser.ServerApplication.EntryPoints
+{
+ public class KeepServerAwake : IServerEntryPoint
+ {
+ private readonly ISessionManager _sessionManager;
+ private readonly ILogger _logger;
+ private Timer _timer;
+
+ public KeepServerAwake(ISessionManager sessionManager, ILogger logger)
+ {
+ _sessionManager = sessionManager;
+ _logger = logger;
+ }
+
+ public void Run()
+ {
+ _timer = new Timer(obj =>
+ {
+ var now = DateTime.UtcNow;
+ if (_sessionManager.Sessions.Any(i => (now - i.LastActivityDate).TotalMinutes < 5))
+ {
+ KeepAlive();
+ }
+
+ }, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5));
+ }
+
+ private void KeepAlive()
+ {
+ try
+ {
+ NativeApp.PreventSystemStandby();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error resetting system standby timer", ex);
+ }
+ }
+
+ 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 c4f529754..b4fc47d02 100644
--- a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs
+++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs
@@ -4,6 +4,8 @@ using Mono.Unix.Native;
using System.Text.RegularExpressions;
using System.IO;
#endif
+using System.IO;
+using System.Text.RegularExpressions;
namespace MediaBrowser.ServerApplication.FFMpeg
{
@@ -32,7 +34,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
switch (arg)
{
case "Version":
- return "20140304";
+ return "20140506";
case "FFMpegFilename":
return "ffmpeg.exe";
case "FFProbeFilename":
@@ -42,7 +44,6 @@ namespace MediaBrowser.ServerApplication.FFMpeg
}
break;
- #if __MonoCS__
case PlatformID.Unix:
if (PlatformDetection.IsMac)
{
@@ -69,7 +70,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
switch (arg)
{
case "Version":
- return "20140304";
+ return "20140506";
case "FFMpegFilename":
return "ffmpeg";
case "FFProbeFilename":
@@ -85,7 +86,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
switch (arg)
{
case "Version":
- return "20140304";
+ return "20140505";
case "FFMpegFilename":
return "ffmpeg";
case "FFProbeFilename":
@@ -98,7 +99,6 @@ namespace MediaBrowser.ServerApplication.FFMpeg
}
// Unsupported Unix platform
return "";
-#endif
}
return "";
}
@@ -106,18 +106,17 @@ namespace MediaBrowser.ServerApplication.FFMpeg
private static string[] GetDownloadUrls()
{
var pid = Environment.OSVersion.Platform;
-
+
switch (pid)
{
case PlatformID.Win32NT:
return new[]
{
- "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20140304-git-f34cceb-win32-static.7z",
- "https://www.dropbox.com/s/6brdetuzbld93jk/ffmpeg-20140304-git-f34cceb-win32-static.7z?dl=1"
+ "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20140506-git-2baf1c8-win32-static.7z",
+ "https://www.dropbox.com/s/lxlzxs0r83iatsv/ffmpeg-20140506-git-2baf1c8-win32-static.7z?dl=1"
};
-
- #if __MonoCS__
- case PlatformID.Unix:
+
+ case PlatformID.Unix:
if (PlatformDetection.IsMac && PlatformDetection.IsX86_64)
{
return new[]
@@ -132,8 +131,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg
{
return new[]
{
- "http://ffmpeg.gusari.org/static/32bit/ffmpeg.static.32bit.2014-03-04.tar.gz",
- "https://www.dropbox.com/s/0l76mcauqqkta31/ffmpeg.static.32bit.2014-03-04.tar.gz?dl=1"
+ "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"
};
}
@@ -141,22 +140,20 @@ namespace MediaBrowser.ServerApplication.FFMpeg
{
return new[]
{
- "http://ffmpeg.gusari.org/static/64bit/ffmpeg.static.64bit.2014-03-04.tar.gz",
- "https://www.dropbox.com/s/9wlxz440mdejuqe/ffmpeg.static.64bit.2014-03-04.tar.gz?dl=1"
+ "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"
};
}
}
//No Unix version available
- return new string[] {};
-#endif
+ return new string[] { };
}
- return new string[] {};
+ return new string[] { };
}
}
- #if __MonoCS__
public static class PlatformDetection
{
public readonly static bool IsWindows;
@@ -166,34 +163,52 @@ namespace MediaBrowser.ServerApplication.FFMpeg
public readonly static bool IsX86_64;
public readonly static bool IsArm;
- static PlatformDetection ()
+ static PlatformDetection()
{
IsWindows = Path.DirectorySeparatorChar == '\\';
//Don't call uname on windows
if (!IsWindows)
{
- Utsname uname;
- var callResult = Syscall.uname(out uname);
- if (callResult == 0)
- {
- IsMac = uname.sysname == "Darwin";
- IsLinux = !IsMac && uname.sysname == "Linux";
+ var uname = GetUnixName();
- Regex archX86 = new Regex("(i|I)[3-6]86");
- IsX86 = archX86.IsMatch(uname.machine);
- IsX86_64 = !IsX86 && uname.machine == "x86_64";
- IsArm = !IsX86 && !IsX86 && uname.machine.StartsWith("arm");
- }
+ IsMac = uname.sysname == "Darwin";
+ IsLinux = uname.sysname == "Linux";
+
+ var archX86 = new Regex("(i|I)[3-6]86");
+ IsX86 = archX86.IsMatch(uname.machine);
+ IsX86_64 = !IsX86 && uname.machine == "x86_64";
+ IsArm = !IsX86 && !IsX86_64 && uname.machine.StartsWith("arm");
}
else
{
- if (System.Environment.Is64BitOperatingSystem)
+ if (Environment.Is64BitOperatingSystem)
IsX86_64 = true;
else
IsX86 = true;
}
}
+
+ private static Uname GetUnixName()
+ {
+ var uname = new Uname();
+
+#if __MonoCS__
+ Utsname utsname;
+ var callResult = Syscall.uname(out utsname);
+ if (callResult == 0)
+ {
+ uname.sysname= utsname.sysname;
+ uname.machine= utsname.machine;
+ }
+#endif
+ return uname;
+ }
+ }
+
+ public class Uname
+ {
+ public string sysname = string.Empty;
+ public string machine = string.Empty;
}
- #endif
}
diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs
index b9c45e0d9..c550cb27f 100644
--- a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs
+++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs
@@ -42,63 +42,86 @@ namespace MediaBrowser.ServerApplication.FFMpeg
public async Task<FFMpegInfo> GetFFMpegInfo(IProgress<double> progress)
{
- var versionedDirectoryPath = Path.Combine(GetMediaToolsPath(true), FFMpegDownloadInfo.Version);
+ var rootEncoderPath = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg");
+ var versionedDirectoryPath = Path.Combine(rootEncoderPath, FFMpegDownloadInfo.Version);
var info = new FFMpegInfo
{
ProbePath = Path.Combine(versionedDirectoryPath, FFMpegDownloadInfo.FFProbeFilename),
- Path = Path.Combine(versionedDirectoryPath, FFMpegDownloadInfo.FFMpegFilename),
+ EncoderPath = Path.Combine(versionedDirectoryPath, FFMpegDownloadInfo.FFMpegFilename),
Version = FFMpegDownloadInfo.Version
};
Directory.CreateDirectory(versionedDirectoryPath);
- var tasks = new List<Task>();
-
- double ffmpegPercent = 0;
- double fontPercent = 0;
- var syncLock = new object();
-
- if (!File.Exists(info.ProbePath) || !File.Exists(info.Path))
+ if (!File.Exists(info.ProbePath) || !File.Exists(info.EncoderPath))
{
- var ffmpegProgress = new ActionableProgress<double>();
- ffmpegProgress.RegisterAction(p =>
- {
- ffmpegPercent = p;
+ // ffmpeg not present. See if there's an older version we can start with
+ var existingVersion = GetExistingVersion(info, rootEncoderPath);
- lock (syncLock)
- {
- progress.Report((ffmpegPercent / 2) + (fontPercent / 2));
- }
- });
+ // No older version. Need to download and block until complete
+ if (existingVersion == null)
+ {
+ await DownloadFFMpeg(versionedDirectoryPath, progress).ConfigureAwait(false);
+ }
+ else
+ {
+ // Older version found.
+ // Start with that. Download new version in the background.
+ var newPath = versionedDirectoryPath;
+ Task.Run(() => DownloadFFMpegInBackground(newPath));
- tasks.Add(DownloadFFMpeg(info, ffmpegProgress));
- }
- else
- {
- ffmpegPercent = 100;
- progress.Report(50);
+ info = existingVersion;
+ versionedDirectoryPath = Path.GetDirectoryName(info.EncoderPath);
+ }
}
- var fontProgress = new ActionableProgress<double>();
- fontProgress.RegisterAction(p =>
+ await DownloadFonts(versionedDirectoryPath).ConfigureAwait(false);
+
+ return info;
+ }
+
+ private FFMpegInfo GetExistingVersion(FFMpegInfo info, string rootEncoderPath)
+ {
+ var encoderFilename = Path.GetFileName(info.EncoderPath);
+ var probeFilename = Path.GetFileName(info.ProbePath);
+
+ foreach (var directory in Directory.EnumerateDirectories(rootEncoderPath, "*", SearchOption.TopDirectoryOnly)
+ .ToList())
{
- fontPercent = p;
+ var allFiles = Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories).ToList();
- lock (syncLock)
+ var encoder = allFiles.FirstOrDefault(i => string.Equals(Path.GetFileName(i), encoderFilename, StringComparison.OrdinalIgnoreCase));
+ var probe = allFiles.FirstOrDefault(i => string.Equals(Path.GetFileName(i), probeFilename, StringComparison.OrdinalIgnoreCase));
+
+ if (!string.IsNullOrWhiteSpace(encoder) &&
+ !string.IsNullOrWhiteSpace(probe))
{
- progress.Report((ffmpegPercent / 2) + (fontPercent / 2));
+ return new FFMpegInfo
+ {
+ EncoderPath = encoder,
+ ProbePath = probe,
+ Version = Path.GetFileNameWithoutExtension(Path.GetDirectoryName(probe))
+ };
}
- });
-
- tasks.Add(DownloadFonts(versionedDirectoryPath, fontProgress));
+ }
- await Task.WhenAll(tasks).ConfigureAwait(false);
+ return null;
+ }
- return info;
+ private async void DownloadFFMpegInBackground(string directory)
+ {
+ try
+ {
+ await DownloadFFMpeg(directory, new Progress<double>()).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error downloading ffmpeg", ex);
+ }
}
- private async Task DownloadFFMpeg(FFMpegInfo info, IProgress<double> progress)
+ private async Task DownloadFFMpeg(string directory, IProgress<double> progress)
{
foreach (var url in FFMpegDownloadInfo.FfMpegUrls)
{
@@ -114,7 +137,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
}).ConfigureAwait(false);
- ExtractFFMpeg(tempFile, Path.GetDirectoryName(info.Path));
+ ExtractFFMpeg(tempFile, directory);
return;
}
catch (HttpException ex)
@@ -132,7 +155,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg
private void ExtractFFMpeg(string tempFile, string targetFolder)
{
- _logger.Debug("Extracting ffmpeg from {0}", tempFile);
+ _logger.Info("Extracting ffmpeg from {0}", tempFile);
var tempFolder = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString());
@@ -171,6 +194,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg
private void ExtractArchive(string archivePath, string targetPath)
{
+ _logger.Info("Extracting {0} to {1}", archivePath, targetPath);
+
if (string.Equals(FFMpegDownloadInfo.ArchiveType, "7z", StringComparison.OrdinalIgnoreCase))
{
_zipClient.ExtractAllFrom7z(archivePath, targetPath, true);
@@ -182,6 +207,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg
}
private void Extract7zArchive(string archivePath, string targetPath)
{
+ _logger.Info("Extracting {0} to {1}", archivePath, targetPath);
+
_zipClient.ExtractAllFrom7z(archivePath, targetPath, true);
}
@@ -201,7 +228,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg
/// Extracts the fonts.
/// </summary>
/// <param name="targetPath">The target path.</param>
- private async Task DownloadFonts(string targetPath, IProgress<double> progress)
+ /// <returns>Task.</returns>
+ private async Task DownloadFonts(string targetPath)
{
try
{
@@ -213,12 +241,19 @@ namespace MediaBrowser.ServerApplication.FFMpeg
var fontFile = Path.Combine(fontsDirectory, fontFilename);
- if (!File.Exists(fontFile))
+ if (File.Exists(fontFile))
{
- await DownloadFontFile(fontsDirectory, fontFilename, progress).ConfigureAwait(false);
+ await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
+ }
+ else
+ {
+ // Kick this off, but no need to wait on it
+ Task.Run(async () =>
+ {
+ await DownloadFontFile(fontsDirectory, fontFilename, new Progress<double>()).ConfigureAwait(false);
+ await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
+ });
}
-
- await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false);
}
catch (HttpException ex)
{
@@ -230,8 +265,6 @@ namespace MediaBrowser.ServerApplication.FFMpeg
// Don't let the server crash because of this
_logger.ErrorException("Error writing ffmpeg font files", ex);
}
-
- progress.Report(100);
}
/// <summary>
@@ -325,19 +358,5 @@ namespace MediaBrowser.ServerApplication.FFMpeg
}
}
}
-
- /// <summary>
- /// Gets the media tools path.
- /// </summary>
- /// <param name="create">if set to <c>true</c> [create].</param>
- /// <returns>System.String.</returns>
- private string GetMediaToolsPath(bool create)
- {
- var path = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg");
-
- Directory.CreateDirectory(path);
-
- return path;
- }
}
}
diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs
index 147a9f771..1361277aa 100644
--- a/MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs
+++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs
@@ -9,7 +9,7 @@
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
- public string Path { get; set; }
+ public string EncoderPath { get; set; }
/// <summary>
/// Gets or sets the probe path.
/// </summary>
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs
index d8bd3938e..6dcbf00e3 100644
--- a/MediaBrowser.ServerApplication/MainStartup.cs
+++ b/MediaBrowser.ServerApplication/MainStartup.cs
@@ -111,6 +111,7 @@ namespace MediaBrowser.ServerApplication
/// <summary>
/// Determines whether [is already running] [the specified current process].
/// </summary>
+ /// <param name="applicationPath">The application path.</param>
/// <param name="currentProcess">The current process.</param>
/// <returns><c>true</c> if [is already running] [the specified current process]; otherwise, <c>false</c>.</returns>
private static bool IsAlreadyRunning(string applicationPath, Process currentProcess)
@@ -131,7 +132,7 @@ namespace MediaBrowser.ServerApplication
{
_logger.Info("Found a duplicate process. Giving it time to exit.");
- if (!duplicate.WaitForExit(5000))
+ if (!duplicate.WaitForExit(10000))
{
_logger.Info("The duplicate process did not exit.");
return true;
diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
index b49e100ab..7fdea66f6 100644
--- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
+++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
@@ -96,6 +96,7 @@
<Compile Include="BackgroundServiceInstaller.cs">
<SubType>Component</SubType>
</Compile>
+ <Compile Include="EntryPoints\KeepServerAwake.cs" />
<Compile Include="EntryPoints\ResourceEntryPoint.cs" />
<Compile Include="EntryPoints\StartupWizard.cs" />
<Compile Include="EntryPoints\WanAddressEntryPoint.cs" />
diff --git a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs
index 39beee563..77a543ad7 100644
--- a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs
+++ b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs
@@ -45,7 +45,7 @@ namespace MediaBrowser.ServerApplication.Native
/// <param name="logger">The logger.</param>
public static void OpenCommunity(ILogger logger)
{
- OpenUrl("http://mediabrowser3.com/community", logger);
+ OpenUrl("http://mediabrowser.tv/community", logger);
}
/// <summary>
diff --git a/MediaBrowser.ServerApplication/Native/NativeApp.cs b/MediaBrowser.ServerApplication/Native/NativeApp.cs
index 646a7bc98..2388b610b 100644
--- a/MediaBrowser.ServerApplication/Native/NativeApp.cs
+++ b/MediaBrowser.ServerApplication/Native/NativeApp.cs
@@ -1,4 +1,5 @@
-
+using System.Runtime.InteropServices;
+
namespace MediaBrowser.ServerApplication.Native
{
/// <summary>
@@ -57,5 +58,31 @@ namespace MediaBrowser.ServerApplication.Native
return MainStartup.CanSelfUpdate;
}
}
+
+ public static void PreventSystemStandby()
+ {
+ SystemHelper.ResetStandbyTimer();
+ }
+
+ internal enum EXECUTION_STATE : uint
+ {
+ ES_NONE = 0,
+ ES_SYSTEM_REQUIRED = 0x00000001,
+ ES_DISPLAY_REQUIRED = 0x00000002,
+ ES_USER_PRESENT = 0x00000004,
+ ES_AWAYMODE_REQUIRED = 0x00000040,
+ ES_CONTINUOUS = 0x80000000
+ }
+
+ public class SystemHelper
+ {
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
+
+ public static void ResetStandbyTimer()
+ {
+ EXECUTION_STATE es = SetThreadExecutionState(EXECUTION_STATE.ES_SYSTEM_REQUIRED);
+ }
+ }
}
}
diff --git a/MediaBrowser.Tests/MediaBrowser.Tests.csproj b/MediaBrowser.Tests/MediaBrowser.Tests.csproj
index 6ae7544b8..d31615952 100644
--- a/MediaBrowser.Tests/MediaBrowser.Tests.csproj
+++ b/MediaBrowser.Tests/MediaBrowser.Tests.csproj
@@ -50,6 +50,9 @@
</Otherwise>
</Choose>
<ItemGroup>
+ <Compile Include="MediaEncoding\Subtitles\SsaParserTests.cs" />
+ <Compile Include="MediaEncoding\Subtitles\SrtParserTests.cs" />
+ <Compile Include="MediaEncoding\Subtitles\VttWriterTest.cs" />
<Compile Include="Providers\MovieDbProviderTests.cs" />
<Compile Include="Resolvers\MovieResolverTests.cs" />
<Compile Include="Resolvers\TvUtilTests.cs" />
@@ -61,6 +64,10 @@
<Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
<Name>MediaBrowser.Controller</Name>
</ProjectReference>
+ <ProjectReference Include="..\MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj">
+ <Project>{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}</Project>
+ <Name>MediaBrowser.MediaEncoding</Name>
+ </ProjectReference>
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
<Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
<Name>MediaBrowser.Model</Name>
@@ -77,6 +84,17 @@
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
+ <ItemGroup>
+ <None Include="MediaEncoding\Subtitles\TestSubtitles\expected.vtt">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ <None Include="MediaEncoding\Subtitles\TestSubtitles\data.ssa">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ <None Include="MediaEncoding\Subtitles\TestSubtitles\unit.srt">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>
diff --git a/MediaBrowser.Tests/MediaEncoding/Subtitles/SrtParserTests.cs b/MediaBrowser.Tests/MediaEncoding/Subtitles/SrtParserTests.cs
new file mode 100644
index 000000000..0d86fbdcd
--- /dev/null
+++ b/MediaBrowser.Tests/MediaEncoding/Subtitles/SrtParserTests.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using MediaBrowser.MediaEncoding.Subtitles;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace MediaBrowser.Tests.MediaEncoding.Subtitles {
+
+ [TestClass]
+ public class SrtParserTests {
+
+ [TestMethod]
+ public void TestParse() {
+
+ var expectedSubs =
+ new SubtitleTrackInfo {
+ TrackEvents = new List<SubtitleTrackEvent> {
+ new SubtitleTrackEvent {
+ Id = "1",
+ StartPositionTicks = 24000000,
+ EndPositionTicks = 52000000,
+ Text =
+ "[Background Music Playing]"
+ },
+ new SubtitleTrackEvent {
+ Id = "2",
+ StartPositionTicks = 157120000,
+ EndPositionTicks = 173990000,
+ Text =
+ "Oh my god, Watch out!<br />It's coming!!"
+ },
+ new SubtitleTrackEvent {
+ Id = "3",
+ StartPositionTicks = 257120000,
+ EndPositionTicks = 303990000,
+ Text = "[Bird noises]"
+ },
+ new SubtitleTrackEvent {
+ Id = "4",
+ StartPositionTicks = 310000000,
+ EndPositionTicks = 319990000,
+ Text =
+ "This text is <font color=\"red\">RED</font> and has not been positioned."
+ },
+ new SubtitleTrackEvent {
+ Id = "5",
+ StartPositionTicks = 320000000,
+ EndPositionTicks = 329990000,
+ Text =
+ "This is a<br />new line, as is<br />this"
+ },
+ new SubtitleTrackEvent {
+ Id = "6",
+ StartPositionTicks = 330000000,
+ EndPositionTicks = 339990000,
+ Text =
+ "This contains nested <b>bold, <i>italic, <u>underline</u> and <s>strike-through</s></u></i></b> HTML tags"
+ },
+ new SubtitleTrackEvent {
+ Id = "7",
+ StartPositionTicks = 340000000,
+ EndPositionTicks = 349990000,
+ Text =
+ "Unclosed but <b>supported HTML tags are left in, SSA italics aren't"
+ },
+ new SubtitleTrackEvent {
+ Id = "8",
+ StartPositionTicks = 350000000,
+ EndPositionTicks = 359990000,
+ Text =
+ "&lt;ggg&gt;Unsupported&lt;/ggg&gt; HTML tags are escaped and left in, even if &lt;hhh&gt;not closed."
+ },
+ new SubtitleTrackEvent {
+ Id = "9",
+ StartPositionTicks = 360000000,
+ EndPositionTicks = 369990000,
+ Text =
+ "Multiple SSA tags are stripped"
+ },
+ new SubtitleTrackEvent {
+ Id = "10",
+ StartPositionTicks = 370000000,
+ EndPositionTicks = 379990000,
+ Text =
+ "Greater than (&lt;) and less than (&gt;) are shown"
+ }
+ }
+ };
+
+ var sut = new SrtParser();
+
+ var stream = File.OpenRead(@"MediaEncoding\Subtitles\TestSubtitles\unit.srt");
+
+ var result = sut.Parse(stream);
+
+ Assert.IsNotNull(result);
+ Assert.AreEqual(expectedSubs.TrackEvents.Count,result.TrackEvents.Count);
+ for (int i = 0; i < expectedSubs.TrackEvents.Count; i++)
+ {
+ Assert.AreEqual(expectedSubs.TrackEvents[i].Id, result.TrackEvents[i].Id);
+ Assert.AreEqual(expectedSubs.TrackEvents[i].StartPositionTicks, result.TrackEvents[i].StartPositionTicks);
+ Assert.AreEqual(expectedSubs.TrackEvents[i].EndPositionTicks, result.TrackEvents[i].EndPositionTicks);
+ Assert.AreEqual(expectedSubs.TrackEvents[i].Text, result.TrackEvents[i].Text);
+ }
+
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Tests/MediaEncoding/Subtitles/SsaParserTests.cs b/MediaBrowser.Tests/MediaEncoding/Subtitles/SsaParserTests.cs
new file mode 100644
index 000000000..51dc7f959
--- /dev/null
+++ b/MediaBrowser.Tests/MediaEncoding/Subtitles/SsaParserTests.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using MediaBrowser.MediaEncoding.Subtitles;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace MediaBrowser.Tests.MediaEncoding.Subtitles {
+
+ [TestClass]
+ public class SsaParserTests {
+
+ [TestMethod]
+ public void TestParse() {
+
+ var expectedSubs =
+ new SubtitleTrackInfo {
+ TrackEvents = new List<SubtitleTrackEvent> {
+ new SubtitleTrackEvent {
+ Id = "1",
+ StartPositionTicks = 24000000,
+ EndPositionTicks = 72000000,
+ Text =
+ "Senator, we're <br />making our final <br />approach into Coruscant."
+ },
+ new SubtitleTrackEvent {
+ Id = "2",
+ StartPositionTicks = 97100000,
+ EndPositionTicks = 133900000,
+ Text =
+ "Very good, Lieutenant."
+ },
+ new SubtitleTrackEvent {
+ Id = "3",
+ StartPositionTicks = 150400000,
+ EndPositionTicks = 180400000,
+ Text = "It's <br />a <br />trap!"
+ }
+ }
+ };
+
+ var sut = new SsaParser();
+
+ var stream = File.OpenRead(@"MediaEncoding\Subtitles\TestSubtitles\data.ssa");
+
+ var result = sut.Parse(stream);
+
+ Assert.IsNotNull(result);
+ Assert.AreEqual(expectedSubs.TrackEvents.Count,result.TrackEvents.Count);
+ for (int i = 0; i < expectedSubs.TrackEvents.Count; i++)
+ {
+ Assert.AreEqual(expectedSubs.TrackEvents[i].Id, result.TrackEvents[i].Id);
+ Assert.AreEqual(expectedSubs.TrackEvents[i].StartPositionTicks, result.TrackEvents[i].StartPositionTicks);
+ Assert.AreEqual(expectedSubs.TrackEvents[i].EndPositionTicks, result.TrackEvents[i].EndPositionTicks);
+ Assert.AreEqual(expectedSubs.TrackEvents[i].Text, result.TrackEvents[i].Text);
+ }
+
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/data.ssa b/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/data.ssa
new file mode 100644
index 000000000..3114a844a
--- /dev/null
+++ b/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/data.ssa
@@ -0,0 +1,23 @@
+[Script Info]
+Title: Testing subtitles for the SSA Format
+
+[V4 Styles]
+Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding
+Style: Default,Arial,20,65535,65535,65535,-2147483640,-1,0,1,3,0,2,30,30,30,0,0
+Style: Titre_episode,Akbar,140,15724527,65535,65535,986895,-1,0,1,1,0,3,30,30,30,0,0
+Style: Wolf main,Wolf_Rain,56,15724527,15724527,15724527,4144959,0,0,1,1,2,2,5,5,30,0,0
+
+
+
+[Events]
+Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
+Dialogue: 0,0:00:02.40,0:00:07.20,Default,,0000,0000,0000,,Senator, {\kf89}we're \Nmaking our final \napproach into Coruscant.
+Dialogue: 0,0:00:09.71,0:00:13.39,Default,,0000,0000,0000,,{\pos(400,570)}Very good, Lieutenant.
+Dialogue: 0,0:00:15.04,0:00:18.04,Default,,0000,0000,0000,,It's \Na \ntrap!
+
+
+[Pictures]
+This section will be ignored
+
+[Fonts]
+This section will be ignored \ No newline at end of file
diff --git a/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/expected.vtt b/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/expected.vtt
new file mode 100644
index 000000000..b6352e7b5
--- /dev/null
+++ b/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/expected.vtt
@@ -0,0 +1,32 @@
+WEBVTT
+
+00:00:02.400 --> 00:00:05.200
+[Background Music Playing]
+
+00:00:15.712 --> 00:00:17.399
+Oh my god, Watch out!<br />It's coming!!
+
+00:00:25.712 --> 00:00:30.399
+[Bird noises]
+
+00:00:31.000 --> 00:00:31.999
+This text is <font color="red">RED</font> and has not been positioned.
+
+00:00:32.000 --> 00:00:32.999
+This is a<br />new line, as is<br />this
+
+00:00:33.000 --> 00:00:33.999
+This contains nested <b>bold, <i>italic, <u>underline</u> and <s>strike-through</s></u></i></b> HTML tags
+
+00:00:34.000 --> 00:00:34.999
+Unclosed but <b>supported HTML tags are left in, SSA italics aren't
+
+00:00:35.000 --> 00:00:35.999
+&lt;ggg&gt;Unsupported&lt;/ggg&gt; HTML tags are escaped and left in, even if &lt;hhh&gt;not closed.
+
+00:00:36.000 --> 00:00:36.999
+Multiple SSA tags are stripped
+
+00:00:37.000 --> 00:00:37.999
+Greater than (&lt;) and less than (&gt;) are shown
+
diff --git a/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/unit.srt b/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/unit.srt
new file mode 100644
index 000000000..5f6e5636e
--- /dev/null
+++ b/MediaBrowser.Tests/MediaEncoding/Subtitles/TestSubtitles/unit.srt
@@ -0,0 +1,44 @@
+
+
+1
+00:00:02.400 --> 00:00:05.200
+[Background Music Playing]
+
+2
+00:00:15,712 --> 00:00:17,399 X1:000 X2:000 Y1:050 Y2:100
+Oh my god, Watch out!
+It's coming!!
+
+3
+00:00:25,712 --> 00:00:30,399
+[Bird noises]
+
+4
+00:00:31,000 --> 00:00:31,999
+This text is <font color="red">RED</font> and has not been {\pos(142,120)}positioned.
+
+5
+00:00:32,000 --> 00:00:32,999
+This is a\nnew line, as is\Nthis
+
+6
+00:00:33,000 --> 00:00:33,999
+This contains nested <b>bold, <i>italic, <u>underline</u> and <s>strike-through</s></u></i></b> HTML tags
+
+7
+00:00:34,000 --> 00:00:34,999
+Unclosed but <b>supported HTML tags are left in, {\i1} SSA italics aren't
+
+8
+00:00:35,000 --> 00:00:35,999
+<ggg>Unsupported</ggg> HTML tags are escaped and left in, even if <hhh>not closed.
+
+9
+00:00:36,000 --> 00:00:36,999
+Multiple {\pos(142,120)\b1}SSA tags are stripped
+
+10
+00:00:37,000 --> 00:00:37,999
+Greater than (<) and less than (>) are shown
+
+
diff --git a/MediaBrowser.Tests/MediaEncoding/Subtitles/VttWriterTest.cs b/MediaBrowser.Tests/MediaEncoding/Subtitles/VttWriterTest.cs
new file mode 100644
index 000000000..5292ad3d2
--- /dev/null
+++ b/MediaBrowser.Tests/MediaEncoding/Subtitles/VttWriterTest.cs
@@ -0,0 +1,103 @@
+using System.Collections.Generic;
+using System.IO;
+using MediaBrowser.MediaEncoding.Subtitles;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace MediaBrowser.Tests.MediaEncoding.Subtitles {
+
+ [TestClass]
+ public class VttWriterTest {
+ [TestMethod]
+ public void TestWrite() {
+ var infoSubs =
+ new SubtitleTrackInfo
+ {
+ TrackEvents = new List<SubtitleTrackEvent> {
+ new SubtitleTrackEvent {
+ Id = "1",
+ StartPositionTicks = 24000000,
+ EndPositionTicks = 52000000,
+ Text =
+ "[Background Music Playing]"
+ },
+ new SubtitleTrackEvent {
+ Id = "2",
+ StartPositionTicks = 157120000,
+ EndPositionTicks = 173990000,
+ Text =
+ "Oh my god, Watch out!<br />It's coming!!"
+ },
+ new SubtitleTrackEvent {
+ Id = "3",
+ StartPositionTicks = 257120000,
+ EndPositionTicks = 303990000,
+ Text = "[Bird noises]"
+ },
+ new SubtitleTrackEvent {
+ Id = "4",
+ StartPositionTicks = 310000000,
+ EndPositionTicks = 319990000,
+ Text =
+ "This text is <font color=\"red\">RED</font> and has not been positioned."
+ },
+ new SubtitleTrackEvent {
+ Id = "5",
+ StartPositionTicks = 320000000,
+ EndPositionTicks = 329990000,
+ Text =
+ "This is a<br />new line, as is<br />this"
+ },
+ new SubtitleTrackEvent {
+ Id = "6",
+ StartPositionTicks = 330000000,
+ EndPositionTicks = 339990000,
+ Text =
+ "This contains nested <b>bold, <i>italic, <u>underline</u> and <s>strike-through</s></u></i></b> HTML tags"
+ },
+ new SubtitleTrackEvent {
+ Id = "7",
+ StartPositionTicks = 340000000,
+ EndPositionTicks = 349990000,
+ Text =
+ "Unclosed but <b>supported HTML tags are left in, SSA italics aren't"
+ },
+ new SubtitleTrackEvent {
+ Id = "8",
+ StartPositionTicks = 350000000,
+ EndPositionTicks = 359990000,
+ Text =
+ "&lt;ggg&gt;Unsupported&lt;/ggg&gt; HTML tags are escaped and left in, even if &lt;hhh&gt;not closed."
+ },
+ new SubtitleTrackEvent {
+ Id = "9",
+ StartPositionTicks = 360000000,
+ EndPositionTicks = 369990000,
+ Text =
+ "Multiple SSA tags are stripped"
+ },
+ new SubtitleTrackEvent {
+ Id = "10",
+ StartPositionTicks = 370000000,
+ EndPositionTicks = 379990000,
+ Text =
+ "Greater than (&lt;) and less than (&gt;) are shown"
+ }
+ }
+ };
+
+ var sut = new VttWriter();
+
+ if(File.Exists("testVTT.vtt"))
+ File.Delete("testVTT.vtt");
+ using (var file = File.OpenWrite("testVTT.vtt"))
+ {
+ sut.Write(infoSubs,file);
+ }
+
+ var result = File.ReadAllText("testVTT.vtt");
+ var expectedText = File.ReadAllText(@"MediaEncoding\Subtitles\TestSubtitles\expected.vtt");
+
+ Assert.AreEqual(expectedText, result);
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs
index 2db493f02..047758f0d 100644
--- a/MediaBrowser.WebDashboard/Api/DashboardService.cs
+++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs
@@ -517,7 +517,7 @@ namespace MediaBrowser.WebDashboard.Api
"librarymenu.js",
"mediacontroller.js",
"chromecast.js",
- "contextmenu.js",
+ "backdrops.js",
"mediaplayer.js",
"mediaplayer-video.js",
@@ -585,6 +585,7 @@ namespace MediaBrowser.WebDashboard.Api
"medialibrarypage.js",
"metadataconfigurationpage.js",
"metadataimagespage.js",
+ "metadatasubtitles.js",
"moviegenres.js",
"moviecollections.js",
"movies.js",
@@ -605,7 +606,6 @@ namespace MediaBrowser.WebDashboard.Api
"playlist.js",
"plugincatalogpage.js",
"pluginspage.js",
- "pluginupdatespage.js",
"remotecontrol.js",
"scheduledtaskpage.js",
"scheduledtaskspage.js",
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index 03c77c227..a6a9183e1 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -166,6 +166,18 @@
<Content Include="dashboard-ui\css\images\favicon.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\css\images\headersearch.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\css\images\items\folders\edit.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <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>
@@ -211,6 +223,36 @@
<Content Include="dashboard-ui\css\images\items\detail\tv.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\css\images\items\folders\books.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\css\images\items\folders\channels.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\css\images\items\folders\folder.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\css\images\items\folders\games.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\css\images\items\folders\homevideos.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\css\images\items\folders\movies.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\css\images\items\folders\music.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\css\images\items\folders\musicvideos.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\css\images\items\folders\photos.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\css\images\items\folders\tv.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\css\images\items\list\remotesearch.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -223,6 +265,9 @@
<Content Include="dashboard-ui\css\images\media\tvflyout.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\css\images\remote.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\css\librarymenu.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -298,6 +343,9 @@
<Content Include="dashboard-ui\livetvtimers.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\metadatasubtitles.html">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\movieslatest.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -532,6 +580,9 @@
<Content Include="dashboard-ui\scripts\appsplayback.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\scripts\backdrops.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\scripts\channelitems.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -541,9 +592,6 @@
<Content Include="dashboard-ui\scripts\chromecast.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\scripts\contextmenu.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\scripts\dashboardgeneral.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -628,6 +676,9 @@
<Content Include="dashboard-ui\scripts\mediaplayer-video.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\scripts\metadatasubtitles.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\scripts\movieslatest.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -1752,16 +1803,6 @@
</Content>
</ItemGroup>
<ItemGroup>
- <Content Include="dashboard-ui\pluginupdates.html">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- </ItemGroup>
- <ItemGroup>
- <Content Include="dashboard-ui\scripts\pluginupdatespage.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- </ItemGroup>
- <ItemGroup>
<Content Include="dashboard-ui\addplugin.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -2043,9 +2084,6 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="packages.config" />
- <None Include="WebMarkupMin.Configuration.xsd">
- <SubType>Designer</SubType>
- </None>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index 7dc06fb0c..4eec81cff 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -43,6 +43,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Dlna", "MediaB
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSubtitlesHandler", "OpenSubtitlesHandler\OpenSubtitlesHandler.csproj", "{4A4402D4-E910-443B-B8FC-2C18286A2CA0}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -263,6 +265,20 @@ 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|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
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {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|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
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index 22c8a293c..1c90bdc87 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.360</version>
+ <version>3.0.366</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.360" />
+ <dependency id="MediaBrowser.Common" version="3.0.366" />
<dependency id="NLog" version="2.1.0" />
- <dependency id="SimpleInjector" version="2.4.1" />
+ <dependency id="SimpleInjector" version="2.5.0" />
<dependency id="sharpcompress" version="0.10.2" />
</dependencies>
</metadata>
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index e8debd820..72bd0cbc0 100644
--- a/Nuget/MediaBrowser.Common.nuspec
+++ b/Nuget/MediaBrowser.Common.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
- <version>3.0.360</version>
+ <version>3.0.366</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec
index 2cad4cbde..2fa54ab0d 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.360</version>
+ <version>3.0.366</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.360" />
+ <dependency id="MediaBrowser.Common" version="3.0.366" />
</dependencies>
</metadata>
<files>
diff --git a/OpenSubtitlesHandler/Console/OSHConsole.cs b/OpenSubtitlesHandler/Console/OSHConsole.cs
new file mode 100644
index 000000000..04c00bf25
--- /dev/null
+++ b/OpenSubtitlesHandler/Console/OSHConsole.cs
@@ -0,0 +1,92 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using System;
+
+namespace OpenSubtitlesHandler.Console
+{
+ public class OSHConsole
+ {
+ /// <summary>
+ /// Write line to the console and raise the "LineWritten" event
+ /// </summary>
+ ///
+ /// <param name="text">The debug line</param>
+ /// <param name="code">The status</param>
+ public static void WriteLine(string text, DebugCode code = DebugCode.None)
+ {
+ if (LineWritten != null)
+ LineWritten(null, new DebugEventArgs(text, code));
+ }
+ /// <summary>
+ /// Update the last written line
+ /// </summary>
+ /// <param name="text">The debug line</param>
+ /// <param name="code">The status</param>
+ public static void UpdateLine(string text, DebugCode code = DebugCode.None)
+ {
+ if (UpdateLastLine != null)
+ UpdateLastLine(null, new DebugEventArgs(text, code));
+ }
+
+ public static event EventHandler<DebugEventArgs> LineWritten;
+ public static event EventHandler<DebugEventArgs> UpdateLastLine;
+ }
+ public enum DebugCode
+ {
+ None,
+ Good,
+ Warning,
+ Error
+ }
+ /// <summary>
+ /// Console Debug Args
+ /// </summary>
+ public class DebugEventArgs : System.EventArgs
+ {
+ public DebugCode Code { get; private set; }
+ public string Text { get; private set; }
+
+ /// <summary>
+ /// Console Debug Args
+ /// </summary>
+ /// <param name="text">The debug line</param>
+ /// <param name="code">The status</param>
+ public DebugEventArgs(string text, DebugCode code)
+ {
+ this.Text = text;
+ this.Code = code;
+ }
+ }
+ public struct DebugLine
+ {
+ public DebugLine(string debugLine, DebugCode status)
+ {
+ this.debugLine = debugLine;
+ this.status = status;
+ }
+ string debugLine;
+ DebugCode status;
+
+ public string Text
+ { get { return debugLine; } set { debugLine = value; } }
+ public DebugCode Code
+ { get { return status; } set { status = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/Interfaces/IMethodResponse.cs b/OpenSubtitlesHandler/Interfaces/IMethodResponse.cs
new file mode 100644
index 000000000..b8e24f12b
--- /dev/null
+++ b/OpenSubtitlesHandler/Interfaces/IMethodResponse.cs
@@ -0,0 +1,62 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.ComponentModel;
+
+namespace OpenSubtitlesHandler
+{
+ /// <summary>
+ /// When you call a method to communicate with OpenSubtitles server, that method should return this response with the reuired information.
+ /// </summary>
+ public abstract class IMethodResponse
+ {
+ public IMethodResponse() { LoadAttributes(); }
+ public IMethodResponse(string name, string message)
+ {
+ this.name = name;
+ this.message = message;
+ }
+ protected string name;
+ protected string message;
+ protected double seconds;
+ protected string status;
+
+ protected virtual void LoadAttributes()
+ {
+ foreach (Attribute attr in Attribute.GetCustomAttributes(this.GetType()))
+ {
+ if (attr.GetType() == typeof(MethodResponseDescription))
+ {
+ this.name = ((MethodResponseDescription)attr).Name;
+ this.message = ((MethodResponseDescription)attr).Message;
+ break;
+ }
+ }
+ }
+
+ [Description("The name of this response"), Category("MethodResponse")]
+ public virtual string Name { get { return name; } set { name = value; } }
+ [Description("The message about this response"), Category("MethodResponse")]
+ public virtual string Message { get { return message; } set { message = value; } }
+ [Description("Time taken to execute this command on server"), Category("MethodResponse")]
+ public double Seconds { get { return seconds; } set { seconds = value; } }
+ [Description("The status"), Category("MethodResponse")]
+ public string Status { get { return status; } set { status = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/Interfaces/MethodResponseAttr.cs b/OpenSubtitlesHandler/Interfaces/MethodResponseAttr.cs
new file mode 100644
index 000000000..57f01d4d9
--- /dev/null
+++ b/OpenSubtitlesHandler/Interfaces/MethodResponseAttr.cs
@@ -0,0 +1,40 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ /// <summary>
+ /// Attributes to describe a method response object.
+ /// </summary>
+ public class MethodResponseDescription : Attribute
+ {
+ public MethodResponseDescription(string name, string message)
+ {
+ this.name = name;
+ this.message = message;
+ }
+
+ private string name;
+ private string message;
+
+ public string Name { get { return name; } set { name = value; } }
+ public string Message { get { return message; } set { message = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/Languages/DetectLanguageResult.cs b/OpenSubtitlesHandler/Languages/DetectLanguageResult.cs
new file mode 100644
index 000000000..9cc3cb8d8
--- /dev/null
+++ b/OpenSubtitlesHandler/Languages/DetectLanguageResult.cs
@@ -0,0 +1,31 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+namespace OpenSubtitlesHandler
+{
+ public struct DetectLanguageResult
+ {
+ private string inputSample;
+ private string languageID;
+
+ public string LanguageID
+ { get { return languageID; } set { languageID = value; } }
+ public string InputSample
+ { get { return inputSample; } set { inputSample = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseAddComment.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseAddComment.cs
new file mode 100644
index 000000000..4cfa11cc9
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseAddComment.cs
@@ -0,0 +1,32 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("AddComment method response",
+ "AddComment method response hold all expected values from server.")]
+ public class MethodResponseAddComment : IMethodResponse
+ {
+ public MethodResponseAddComment()
+ : base()
+ { }
+ public MethodResponseAddComment(string name, string message)
+ : base(name, message)
+ { }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseAddRequest.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseAddRequest.cs
new file mode 100644
index 000000000..8ea1c387c
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseAddRequest.cs
@@ -0,0 +1,35 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("AddRequest method response",
+ "AddRequest method response hold all expected values from server.")]
+ public class MethodResponseAddRequest : IMethodResponse
+ {
+ public MethodResponseAddRequest()
+ : base()
+ { }
+ public MethodResponseAddRequest(string name, string message)
+ : base(name, message)
+ { }
+ private string _request_url;
+
+ public string request_url { get { return _request_url; } set { _request_url = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseAutoUpdate.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseAutoUpdate.cs
new file mode 100644
index 000000000..26edf8b0e
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseAutoUpdate.cs
@@ -0,0 +1,60 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.ComponentModel;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("AutoUpdate method response",
+ "AutoUpdate method response hold all expected values from server.")]
+ public class MethodResponseAutoUpdate : IMethodResponse
+ {
+ public MethodResponseAutoUpdate()
+ : base()
+ { }
+ public MethodResponseAutoUpdate(string name, string message)
+ : base(name, message)
+ { }
+
+ private string _version;
+ private string _url_windows;
+ private string _comments;
+ private string _url_linux;
+ /// <summary>
+ /// Latest application version
+ /// </summary>
+ [Description("Latest application version"), Category("AutoUpdate")]
+ public string version { get { return _version; } set { _version = value; } }
+ /// <summary>
+ /// Download URL for Windows version
+ /// </summary>
+ [Description("Download URL for Windows version"), Category("AutoUpdate")]
+ public string url_windows { get { return _url_windows; } set { _url_windows = value; } }
+ /// <summary>
+ /// Application changelog and other comments
+ /// </summary>
+ [Description("Application changelog and other comments"), Category("AutoUpdate")]
+ public string comments { get { return _comments; } set { _comments = value; } }
+ /// <summary>
+ /// Download URL for Linux version
+ /// </summary>
+ [Description("Download URL for Linux version"), Category("AutoUpdate")]
+ public string url_linux { get { return _url_linux; } set { _url_linux = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash.cs
new file mode 100644
index 000000000..30ef075b9
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash.cs
@@ -0,0 +1,37 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("CheckMovieHash method response",
+ "CheckMovieHash method response hold all expected values from server.")]
+ public class MethodResponseCheckMovieHash : IMethodResponse
+ {
+ public MethodResponseCheckMovieHash()
+ : base()
+ { }
+ public MethodResponseCheckMovieHash(string name, string message)
+ : base(name, message)
+ { }
+ private List<CheckMovieHashResult> results = new List<CheckMovieHashResult>();
+ public List<CheckMovieHashResult> Results
+ { get { return results; } set { results = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash2.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash2.cs
new file mode 100644
index 000000000..78cdef0c4
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckMovieHash2.cs
@@ -0,0 +1,37 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("CheckMovieHash2 method response",
+ "CheckMovieHash2 method response hold all expected values from server.")]
+ public class MethodResponseCheckMovieHash2 : IMethodResponse
+ {
+ public MethodResponseCheckMovieHash2()
+ : base()
+ { }
+ public MethodResponseCheckMovieHash2(string name, string message)
+ : base(name, message)
+ { }
+ private List<CheckMovieHash2Result> results = new List<CheckMovieHash2Result>();
+ public List<CheckMovieHash2Result> Results
+ { get { return results; } set { results = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckSubHash.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckSubHash.cs
new file mode 100644
index 000000000..45c73631c
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseCheckSubHash.cs
@@ -0,0 +1,38 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("CheckSubHash method response",
+ "CheckSubHash method response hold all expected values from server.")]
+ public class MethodResponseCheckSubHash : IMethodResponse
+ {
+ public MethodResponseCheckSubHash()
+ : base()
+ { }
+ public MethodResponseCheckSubHash(string name, string message)
+ : base(name, message)
+ { }
+ private List<CheckSubHashResult> results = new List<CheckSubHashResult>();
+
+ public List<CheckSubHashResult> Results { get { return results; } set { results = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseDetectLanguage.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseDetectLanguage.cs
new file mode 100644
index 000000000..20b4d30f3
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseDetectLanguage.cs
@@ -0,0 +1,37 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System.Collections.Generic;
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("DetectLanguage method response",
+ "DetectLanguage method response hold all expected values from server.")]
+ public class MethodResponseDetectLanguage : IMethodResponse
+ {
+ public MethodResponseDetectLanguage()
+ : base()
+ { }
+ public MethodResponseDetectLanguage(string name, string message)
+ : base(name, message)
+ { }
+ private List<DetectLanguageResult> results = new List<DetectLanguageResult>();
+
+ public List<DetectLanguageResult> Results
+ { get { return results; } set { results = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseError.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseError.cs
new file mode 100644
index 000000000..273dfb1ad
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseError.cs
@@ -0,0 +1,36 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+namespace OpenSubtitlesHandler
+{
+ /// <summary>
+ /// Response that can be used for general error like internet connection fail.
+ /// </summary>
+ [MethodResponseDescription("Error method response",
+ "Error method response that describes error that occured")]
+ public class MethodResponseError : IMethodResponse
+ {
+ public MethodResponseError()
+ : base()
+ { }
+ public MethodResponseError(string name, string message)
+ : base(name, message)
+ { }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseGetAvailableTranslations.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseGetAvailableTranslations.cs
new file mode 100644
index 000000000..1ee4ea6c0
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseGetAvailableTranslations.cs
@@ -0,0 +1,37 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("GetAvailableTranslations method response",
+ "GetAvailableTranslations method response hold all expected values from server.")]
+ public class MethodResponseGetAvailableTranslations : IMethodResponse
+ {
+ public MethodResponseGetAvailableTranslations()
+ : base()
+ { }
+ public MethodResponseGetAvailableTranslations(string name, string message)
+ : base(name, message)
+ { }
+ private List<GetAvailableTranslationsResult> results = new List<GetAvailableTranslationsResult>();
+ public List<GetAvailableTranslationsResult> Results { get { return results; } set { results = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseGetComments.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseGetComments.cs
new file mode 100644
index 000000000..6a586d5ce
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseGetComments.cs
@@ -0,0 +1,41 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("GetComments method response",
+ "GetComments method response hold all expected values from server.")]
+ public class MethodResponseGetComments : IMethodResponse
+ {
+ public MethodResponseGetComments()
+ : base()
+ { }
+ public MethodResponseGetComments(string name, string message)
+ : base(name, message)
+ { }
+ private List<GetCommentsResult> results = new List<GetCommentsResult>();
+
+ public List<GetCommentsResult> Results
+ { get { return results; } set { results = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseGetSubLanguages.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseGetSubLanguages.cs
new file mode 100644
index 000000000..dc8100c92
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseGetSubLanguages.cs
@@ -0,0 +1,39 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("GetSubLanguages method response",
+ "GetSubLanguages method response hold all expected values from server.")]
+ public class MethodResponseGetSubLanguages : IMethodResponse
+ {
+ public MethodResponseGetSubLanguages()
+ : base()
+ { }
+ public MethodResponseGetSubLanguages(string name, string message)
+ : base(name, message)
+ { }
+ private List<SubtitleLanguage> languages = new List<SubtitleLanguage>();
+
+ public List<SubtitleLanguage> Languages
+ { get { return languages; } set { languages = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseGetTranslation.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseGetTranslation.cs
new file mode 100644
index 000000000..548246887
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseGetTranslation.cs
@@ -0,0 +1,37 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("GetTranslation method response",
+ "GetTranslation method response hold all expected values from server.")]
+ public class MethodResponseGetTranslation : IMethodResponse
+ {
+ public MethodResponseGetTranslation()
+ : base()
+ { }
+ public MethodResponseGetTranslation(string name, string message)
+ : base(name, message)
+ { }
+ private string data;
+
+ public string ContentData { get { return data; } set { data = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovie.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovie.cs
new file mode 100644
index 000000000..b53aad5a9
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovie.cs
@@ -0,0 +1,37 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("InsertMovie method response",
+ "InsertMovie method response hold all expected values from server.")]
+ public class MethodResponseInsertMovie : IMethodResponse
+ {
+ public MethodResponseInsertMovie()
+ : base()
+ { }
+ public MethodResponseInsertMovie(string name, string message)
+ : base(name, message)
+ { }
+ private string _ID;
+ public string ID
+ { get { return _ID; } set { _ID = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovieHash.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovieHash.cs
new file mode 100644
index 000000000..fe9196de8
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseInsertMovieHash.cs
@@ -0,0 +1,38 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System.Collections.Generic;
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("InsertMovieHash method response",
+ "InsertMovieHash method response hold all expected values from server.")]
+ public class MethodResponseInsertMovieHash : IMethodResponse
+ {
+ public MethodResponseInsertMovieHash()
+ : base()
+ { }
+ public MethodResponseInsertMovieHash(string name, string message)
+ : base(name, message)
+ { }
+ private List<string> _accepted_moviehashes = new List<string>();
+ private List<string> _new_imdbs = new List<string>();
+
+ public List<string> accepted_moviehashes { get { return _accepted_moviehashes; } set { _accepted_moviehashes = value; } }
+ public List<string> new_imdbs { get { return _new_imdbs; } set { _new_imdbs = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseLogIn.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseLogIn.cs
new file mode 100644
index 000000000..e7c23f61c
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseLogIn.cs
@@ -0,0 +1,40 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ /// <summary>
+ /// Response can be used for log in/out operation.
+ /// </summary>
+ [MethodResponseDescription("LogIn method response",
+ "LogIn method response hold all expected values from server.")]
+ public class MethodResponseLogIn : IMethodResponse
+ {
+ public MethodResponseLogIn()
+ : base()
+ { }
+ public MethodResponseLogIn(string name, string message)
+ : base(name, message)
+ { }
+ private string token;
+
+ public string Token { get { return token; } set { token = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseMovieDetails.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseMovieDetails.cs
new file mode 100644
index 000000000..29e19245c
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseMovieDetails.cs
@@ -0,0 +1,73 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("MovieDetails method response",
+ "MovieDetails method response hold all expected values from server.")]
+ public class MethodResponseMovieDetails : IMethodResponse
+ {
+ public MethodResponseMovieDetails()
+ : base()
+ { }
+ public MethodResponseMovieDetails(string name, string message)
+ : base(name, message)
+ { }
+ // Details
+ private string id;
+ private string title;
+ private string year;
+ private string coverLink;
+
+ private string duration;
+ private string tagline;
+ private string plot;
+ private string goofs;
+ private string trivia;
+ private List<string> cast = new List<string>();
+ private List<string> directors = new List<string>();
+ private List<string> writers = new List<string>();
+ private List<string> awards = new List<string>();
+ private List<string> genres = new List<string>();
+ private List<string> country = new List<string>();
+ private List<string> language = new List<string>();
+ private List<string> certification = new List<string>();
+
+ // Details
+ public string ID { get { return id; } set { id = value; } }
+ public string Title { get { return title; } set { title = value; } }
+ public string Year { get { return year; } set { year = value; } }
+ public string CoverLink { get { return coverLink; } set { coverLink = value; } }
+ public string Duration { get { return duration; } set { duration = value; } }
+ public string Tagline { get { return tagline; } set { tagline = value; } }
+ public string Plot { get { return plot; } set { plot = value; } }
+ public string Goofs { get { return goofs; } set { goofs = value; } }
+ public string Trivia { get { return trivia; } set { trivia = value; } }
+ public List<string> Cast { get { return cast; } set { cast = value; } }
+ public List<string> Directors { get { return directors; } set { directors = value; } }
+ public List<string> Writers { get { return writers; } set { writers = value; } }
+ public List<string> Genres { get { return genres; } set { genres = value; } }
+ public List<string> Awards { get { return awards; } set { awards = value; } }
+ public List<string> Country { get { return country; } set { country = value; } }
+ public List<string> Language { get { return language; } set { language = value; } }
+ public List<string> Certification { get { return certification; } set { certification = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseMovieSearch.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseMovieSearch.cs
new file mode 100644
index 000000000..c1beeeeea
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseMovieSearch.cs
@@ -0,0 +1,43 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("MovieSearch method response",
+ "MovieSearch method response hold all expected values from server.")]
+ public class MethodResponseMovieSearch : IMethodResponse
+ {
+ public MethodResponseMovieSearch()
+ : base()
+ {
+ results = new List<MovieSearchResult>();
+ }
+ public MethodResponseMovieSearch(string name, string message)
+ : base(name, message)
+ {
+ results = new List<MovieSearchResult>();
+ }
+ private List<MovieSearchResult> results;
+
+ public List<MovieSearchResult> Results
+ { get { return results; } set { results = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseNoOperation.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseNoOperation.cs
new file mode 100644
index 000000000..0b5b2f1aa
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseNoOperation.cs
@@ -0,0 +1,53 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("NoOperation method response",
+ "NoOperation method response hold all expected values from server.")]
+ public class MethodResponseNoOperation : IMethodResponse
+ {
+ public MethodResponseNoOperation()
+ : base() { }
+ public MethodResponseNoOperation(string name, string message)
+ : base(name, message)
+ { }
+
+ private string _global_wrh_download_limit;
+ private string _client_ip;
+ private string _limit_check_by;
+ private string _client_24h_download_count;
+ private string _client_downlaod_quota;
+ private string _client_24h_download_limit;
+
+ public string global_wrh_download_limit
+ { get { return _global_wrh_download_limit; } set { _global_wrh_download_limit = value; } }
+ public string client_ip
+ { get { return _client_ip; } set { _client_ip = value; } }
+ public string limit_check_by
+ { get { return _limit_check_by; } set { _limit_check_by = value; } }
+ public string client_24h_download_count
+ { get { return _client_24h_download_count; } set { _client_24h_download_count = value; } }
+ public string client_downlaod_quota
+ { get { return _client_downlaod_quota; } set { _client_downlaod_quota = value; } }
+ public string client_24h_download_limit
+ { get { return _client_24h_download_limit; } set { _client_24h_download_limit = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongImdbMovie.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongImdbMovie.cs
new file mode 100644
index 000000000..3c19fcf6e
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongImdbMovie.cs
@@ -0,0 +1,33 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("ReportWrongImdbMovie method response",
+ "ReportWrongImdbMovie method response hold all expected values from server.")]
+ public class MethodResponseReportWrongImdbMovie : IMethodResponse
+ {
+ public MethodResponseReportWrongImdbMovie()
+ : base()
+ { }
+ public MethodResponseReportWrongImdbMovie(string name, string message)
+ : base(name, message)
+ { }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongMovieHash.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongMovieHash.cs
new file mode 100644
index 000000000..94788b2c6
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseReportWrongMovieHash.cs
@@ -0,0 +1,34 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("ReportWrongMovieHash method response",
+ "ReportWrongMovieHash method response hold all expected values from server.")]
+ public class MethodResponseReportWrongMovieHash : IMethodResponse
+ {
+ public MethodResponseReportWrongMovieHash()
+ : base()
+ { }
+ public MethodResponseReportWrongMovieHash(string name, string message)
+ : base(name, message)
+ { }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseSearchToMail.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseSearchToMail.cs
new file mode 100644
index 000000000..9f195dea0
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseSearchToMail.cs
@@ -0,0 +1,32 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("SearchToMail method response",
+ "SearchToMail method response hold all expected values from server.")]
+ public class MethodResponseSearchToMail : IMethodResponse
+ {
+ public MethodResponseSearchToMail()
+ : base()
+ { }
+ public MethodResponseSearchToMail(string name, string message)
+ : base(name, message)
+ { }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseServerInfo.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseServerInfo.cs
new file mode 100644
index 000000000..fce5b4245
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseServerInfo.cs
@@ -0,0 +1,132 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("ServerInfo method response",
+ "ServerInfo method response hold all expected values from server.")]
+ public class MethodResponseServerInfo : IMethodResponse
+ {
+ public MethodResponseServerInfo()
+ : base()
+ { }
+ public MethodResponseServerInfo(string name, string message)
+ : base(name, message)
+ { }
+ private string _xmlrpc_version;
+ private string _xmlrpc_url;
+ private string _application;
+ private string _contact;
+ private string _website_url;
+ private int _users_online_total;
+ private int _users_online_program;
+ private int _users_loggedin;
+ private string _users_max_alltime;
+ private string _users_registered;
+ private string _subs_downloads;
+ private string _subs_subtitle_files;
+ private string _movies_total;
+ private string _movies_aka;
+ private string _total_subtitles_languages;
+ private List<string> _last_update_strings = new List<string>();
+
+ /// <summary>
+ /// Version of server's XML-RPC API implementation
+ /// </summary>
+ [Description("Version of server's XML-RPC API implementation"), Category("OS")]
+ public string xmlrpc_version { get { return _xmlrpc_version; } set { _xmlrpc_version = value; } }
+ /// <summary>
+ /// XML-RPC interface URL
+ /// </summary>
+ [Description("XML-RPC interface URL"), Category("OS")]
+ public string xmlrpc_url { get { return _xmlrpc_url; } set { _xmlrpc_url = value; } }
+ /// <summary>
+ /// Server's application name and version
+ /// </summary>
+ [Description("Server's application name and version"), Category("OS")]
+ public string application { get { return _application; } set { _application = value; } }
+ /// <summary>
+ /// Contact e-mail address for server related quuestions and problems
+ /// </summary>
+ [Description("Contact e-mail address for server related quuestions and problems"), Category("OS")]
+ public string contact { get { return _contact; } set { _contact = value; } }
+ /// <summary>
+ /// Main server URL
+ /// </summary>
+ [Description("Main server URL"), Category("OS")]
+ public string website_url { get { return _website_url; } set { _website_url = value; } }
+ /// <summary>
+ /// Number of users currently online
+ /// </summary>
+ [Description("Number of users currently online"), Category("OS")]
+ public int users_online_total { get { return _users_online_total; } set { _users_online_total = value; } }
+ /// <summary>
+ /// Number of users currently online using a client application (XML-RPC API)
+ /// </summary>
+ [Description("Number of users currently online using a client application (XML-RPC API)"), Category("OS")]
+ public int users_online_program { get { return _users_online_program; } set { _users_online_program = value; } }
+ /// <summary>
+ /// Number of currently logged-in users
+ /// </summary>
+ [Description("Number of currently logged-in users"), Category("OS")]
+ public int users_loggedin { get { return _users_loggedin; } set { _users_loggedin = value; } }
+ /// <summary>
+ /// Maximum number of users throughout the history
+ /// </summary>
+ [Description("Maximum number of users throughout the history"), Category("OS")]
+ public string users_max_alltime { get { return _users_max_alltime; } set { _users_max_alltime = value; } }
+ /// <summary>
+ /// Number of registered users
+ /// </summary>
+ [Description("Number of registered users"), Category("OS")]
+ public string users_registered { get { return _users_registered; } set { _users_registered = value; } }
+ /// <summary>
+ /// Total number of subtitle downloads
+ /// </summary>
+ [Description("Total number of subtitle downloads"), Category("OS")]
+ public string subs_downloads { get { return _subs_downloads; } set { _subs_downloads = value; } }
+ /// <summary>
+ /// Total number of subtitle files stored on the server
+ /// </summary>
+ [Description("Total number of subtitle files stored on the server"), Category("OS")]
+ public string subs_subtitle_files { get { return _subs_subtitle_files; } set { _subs_subtitle_files = value; } }
+ /// <summary>
+ /// Total number of movies in the database
+ /// </summary>
+ [Description("Total number of movies in the database"), Category("OS")]
+ public string movies_total { get { return _movies_total; } set { _movies_total = value; } }
+ /// <summary>
+ /// Total number of movie A.K.A. titles in the database
+ /// </summary>
+ [Description("Total number of movie A.K.A. titles in the database"), Category("OS")]
+ public string movies_aka { get { return _movies_aka; } set { _movies_aka = value; } }
+ /// <summary>
+ /// Total number of subtitle languages supported
+ /// </summary>
+ [Description("Total number of subtitle languages supported"), Category("OS")]
+ public string total_subtitles_languages { get { return _total_subtitles_languages; } set { _total_subtitles_languages = value; } }
+ /// <summary>
+ /// Structure containing information about last updates of translations.
+ /// </summary>
+ [Description("Structure containing information about last updates of translations"), Category("OS")]
+ public List<string> last_update_strings { get { return _last_update_strings; } set { _last_update_strings = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleDownload.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleDownload.cs
new file mode 100644
index 000000000..7ad9f38ec
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleDownload.cs
@@ -0,0 +1,44 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+namespace OpenSubtitlesHandler
+{
+ /// <summary>
+ /// The response that should be used by subtitle download methods.
+ /// </summary>
+ [MethodResponseDescription("SubtitleDownload method response",
+ "SubtitleDownload method response hold all expected values from server.")]
+ public class MethodResponseSubtitleDownload : IMethodResponse
+ {
+ public MethodResponseSubtitleDownload()
+ : base()
+ {
+ results = new List<SubtitleDownloadResult>();
+ }
+ public MethodResponseSubtitleDownload(string name, string message)
+ : base(name, message)
+ {
+ results = new List<SubtitleDownloadResult>();
+ }
+ private List<SubtitleDownloadResult> results;
+ public List<SubtitleDownloadResult> Results
+ { get { return results; } set { results = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleSearch.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleSearch.cs
new file mode 100644
index 000000000..c359c0ffd
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitleSearch.cs
@@ -0,0 +1,46 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace OpenSubtitlesHandler
+{
+ /// <summary>
+ /// Response to SearchSubtitle successed call.
+ /// </summary>
+ [MethodResponseDescription("SubtitleSearch method response",
+ "SubtitleSearch method response hold all expected values from server.")]
+ public class MethodResponseSubtitleSearch : IMethodResponse
+ {
+ public MethodResponseSubtitleSearch()
+ : base()
+ {
+ results = new List<SubtitleSearchResult>();
+ }
+ public MethodResponseSubtitleSearch(string name, string message)
+ : base(name, message)
+ {
+ results = new List<SubtitleSearchResult>();
+ }
+
+ private List<SubtitleSearchResult> results;
+ public List<SubtitleSearchResult> Results
+ { get { return results; } set { results = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitlesVote.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitlesVote.cs
new file mode 100644
index 000000000..1f5364f0c
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseSubtitlesVote.cs
@@ -0,0 +1,44 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("SubtitlesVote method response",
+ "SubtitlesVote method response hold all expected values from server.")]
+ public class MethodResponseSubtitlesVote : IMethodResponse
+ {
+ public MethodResponseSubtitlesVote()
+ : base()
+ { }
+ public MethodResponseSubtitlesVote(string name, string message)
+ : base(name, message)
+ { }
+ private string _SubRating;
+ private string _SubSumVotes;
+ private string _IDSubtitle;
+
+ public string SubRating
+ { get { return _SubRating; } set { _SubRating = value; } }
+ public string SubSumVotes
+ { get { return _SubSumVotes; } set { _SubSumVotes = value; } }
+ public string IDSubtitle
+ { get { return _IDSubtitle; } set { _IDSubtitle = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseTryUploadSubtitles.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseTryUploadSubtitles.cs
new file mode 100644
index 000000000..9dbf1576d
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseTryUploadSubtitles.cs
@@ -0,0 +1,40 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("TryUploadSubtitles method response",
+ "TryUploadSubtitles method response hold all expected values from server.")]
+ public class MethodResponseTryUploadSubtitles : IMethodResponse
+ {
+ public MethodResponseTryUploadSubtitles()
+ : base()
+ { }
+ public MethodResponseTryUploadSubtitles(string name, string message)
+ : base(name, message)
+ { }
+ private int alreadyindb;
+ private List<SubtitleSearchResult> results = new List<SubtitleSearchResult>();
+
+ public int AlreadyInDB { get { return alreadyindb; } set { alreadyindb = value; } }
+ public List<SubtitleSearchResult> Results { get { return results; } set { results = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/MethodResponses/MethodResponseUploadSubtitles.cs b/OpenSubtitlesHandler/MethodResponses/MethodResponseUploadSubtitles.cs
new file mode 100644
index 000000000..3b2320db2
--- /dev/null
+++ b/OpenSubtitlesHandler/MethodResponses/MethodResponseUploadSubtitles.cs
@@ -0,0 +1,39 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ [MethodResponseDescription("UploadSubtitles method response",
+ "UploadSubtitles method response hold all expected values from server.")]
+ public class MethodResponseUploadSubtitles : IMethodResponse
+ {
+ public MethodResponseUploadSubtitles()
+ : base()
+ { }
+ public MethodResponseUploadSubtitles(string name, string message)
+ : base(name, message)
+ { }
+ private string _data;
+ private bool _subtitles;
+
+ public string Data { get { return _data; } set { _data = value; } }
+ public bool SubTitles { get { return _subtitles; } set { _subtitles = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/Methods Implemeted.txt b/OpenSubtitlesHandler/Methods Implemeted.txt
new file mode 100644
index 000000000..5d7ae0d49
--- /dev/null
+++ b/OpenSubtitlesHandler/Methods Implemeted.txt
@@ -0,0 +1,39 @@
+List of available OpenSubtitles.org server XML-RPC methods.
+==========================================================
+Legends:
+* OK: this method is fully implemented, tested and works fine.
+* TODO: this method is in the plan to be added.
+* NOT TESTED: this method added and expected to work fine but never tested.
+* NOT WORK (x): this method added but not work. x= Description of the error.
+
+--------------------------------------------
+Method name | Status
+-------------------------|------------------
+LogIn | OK
+LogOut | OK
+NoOperation | OK
+SearchSubtitles | OK
+DownloadSubtitles | OK
+SearchToMail | OK
+TryUploadSubtitles | OK
+UploadSubtitles | OK
+SearchMoviesOnIMDB | OK
+GetIMDBMovieDetails | OK
+InsertMovie | OK
+InsertMovieHash | OK
+ServerInfo | OK
+ReportWrongMovieHash | OK
+ReportWrongImdbMovie | OK
+SubtitlesVote | OK
+AddComment | OK
+AddRequest | OK
+GetComments | OK
+GetSubLanguages | OK
+DetectLanguage | OK
+GetAvailableTranslations | OK
+GetTranslation | NOT WORK (Returns status of error 410 'Other or unknown error')
+AutoUpdate | NOT WORK (Returns status: 'parse error. not well formed')
+CheckMovieHash | OK
+CheckMovieHash2 | OK
+CheckSubHash | OK
+-------------------------------------------- \ No newline at end of file
diff --git a/OpenSubtitlesHandler/MovieHasher.cs b/OpenSubtitlesHandler/MovieHasher.cs
new file mode 100644
index 000000000..a14bd20f8
--- /dev/null
+++ b/OpenSubtitlesHandler/MovieHasher.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace OpenSubtitlesHandler
+{
+ public class MovieHasher
+ {
+ public static byte[] ComputeMovieHash(string filename)
+ {
+ byte[] result;
+ using (Stream input = File.OpenRead(filename))
+ {
+ result = ComputeMovieHash(input);
+ }
+ return result;
+ }
+
+ private static byte[] ComputeMovieHash(Stream input)
+ {
+ long lhash, streamsize;
+ streamsize = input.Length;
+ lhash = streamsize;
+
+ long i = 0;
+ byte[] buffer = new byte[sizeof(long)];
+ while (i < 65536 / sizeof(long) && (input.Read(buffer, 0, sizeof(long)) > 0))
+ {
+ i++;
+ lhash += BitConverter.ToInt64(buffer, 0);
+ }
+
+ input.Position = Math.Max(0, streamsize - 65536);
+ i = 0;
+ while (i < 65536 / sizeof(long) && (input.Read(buffer, 0, sizeof(long)) > 0))
+ {
+ i++;
+ lhash += BitConverter.ToInt64(buffer, 0);
+ }
+ input.Close();
+ byte[] result = BitConverter.GetBytes(lhash);
+ Array.Reverse(result);
+ return result;
+ }
+
+ public static string ToHexadecimal(byte[] bytes)
+ {
+ StringBuilder hexBuilder = new StringBuilder();
+ for (int i = 0; i < bytes.Length; i++)
+ {
+ hexBuilder.Append(bytes[i].ToString("x2"));
+ }
+ return hexBuilder.ToString();
+ }
+ }
+}
diff --git a/OpenSubtitlesHandler/Movies/CheckMovieHash2Data.cs b/OpenSubtitlesHandler/Movies/CheckMovieHash2Data.cs
new file mode 100644
index 000000000..4f6de82b1
--- /dev/null
+++ b/OpenSubtitlesHandler/Movies/CheckMovieHash2Data.cs
@@ -0,0 +1,42 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OpenSubtitlesHandler
+{
+ public struct CheckMovieHash2Data
+ {
+ private string _MovieHash;
+ private string _MovieImdbID;
+ private string _MovieName;
+ private string _MovieYear;
+ private string _MovieKind;
+ private string _SeriesSeason;
+ private string _SeriesEpisode;
+ private string _SeenCount;
+
+ public string MovieHash { get { return _MovieHash; } set { _MovieHash = value; } }
+ public string MovieImdbID { get { return _MovieImdbID; } set { _MovieImdbID = value; } }
+ public string MovieName { get { return _MovieName; } set { _MovieName = value; } }
+ public string MovieYear { get { return _MovieYear; } set { _MovieYear = value; } }
+ public string MovieKind { get { return _MovieKind; } set { _MovieKind = value; } }
+ public string SeriesSeason { get { return _SeriesSeason; } set { _SeriesSeason = value; } }
+ public string SeriesEpisode { get { return _SeriesEpisode; } set { _SeriesEpisode = value; } }
+ public string SeenCount { get { return _SeenCount; } set { _SeenCount = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/Movies/CheckMovieHash2Result.cs b/OpenSubtitlesHandler/Movies/CheckMovieHash2Result.cs
new file mode 100644
index 000000000..e91541c3c
--- /dev/null
+++ b/OpenSubtitlesHandler/Movies/CheckMovieHash2Result.cs
@@ -0,0 +1,37 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace OpenSubtitlesHandler
+{
+ public class CheckMovieHash2Result
+ {
+ private string name;
+ private List<CheckMovieHash2Data> data = new List<CheckMovieHash2Data>();
+
+ public string Name { get { return name; } set { name = value; } }
+ public List<CheckMovieHash2Data> Items { get { return data; } set { data = value; } }
+
+ public override string ToString()
+ {
+ return name;
+ }
+ }
+}
diff --git a/OpenSubtitlesHandler/Movies/CheckMovieHashResult.cs b/OpenSubtitlesHandler/Movies/CheckMovieHashResult.cs
new file mode 100644
index 000000000..b51181f23
--- /dev/null
+++ b/OpenSubtitlesHandler/Movies/CheckMovieHashResult.cs
@@ -0,0 +1,42 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ public struct CheckMovieHashResult
+ {
+ private string name;
+ private string _MovieHash;
+ private string _MovieImdbID;
+ private string _MovieName;
+ private string _MovieYear;
+
+ public string MovieHash { get { return _MovieHash; } set { _MovieHash = value; } }
+ public string MovieImdbID { get { return _MovieImdbID; } set { _MovieImdbID = value; } }
+ public string MovieName { get { return _MovieName; } set { _MovieName = value; } }
+ public string MovieYear { get { return _MovieYear; } set { _MovieYear = value; } }
+ public string Name { get { return name; } set { name = value; } }
+
+ public override string ToString()
+ {
+ return name;
+ }
+ }
+}
diff --git a/OpenSubtitlesHandler/Movies/InsertMovieHashParameters.cs b/OpenSubtitlesHandler/Movies/InsertMovieHashParameters.cs
new file mode 100644
index 000000000..58402324b
--- /dev/null
+++ b/OpenSubtitlesHandler/Movies/InsertMovieHashParameters.cs
@@ -0,0 +1,38 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OpenSubtitlesHandler
+{
+ public class InsertMovieHashParameters
+ {
+ private string _moviehash = "";
+ private string _moviebytesize = "";
+ private string _imdbid = "";
+ private string _movietimems = "";
+ private string _moviefps = "";
+ private string _moviefilename = "";
+
+ public string moviehash { get { return _moviehash; } set { _moviehash = value; } }
+ public string moviebytesize { get { return _moviebytesize; } set { _moviebytesize = value; } }
+ public string imdbid { get { return _imdbid; } set { _imdbid = value; } }
+ public string movietimems { get { return _movietimems; } set { _movietimems = value; } }
+ public string moviefps { get { return _moviefps; } set { _moviefps = value; } }
+ public string moviefilename { get { return _moviefilename; } set { _moviefilename = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/Movies/MovieSearchResult.cs b/OpenSubtitlesHandler/Movies/MovieSearchResult.cs
new file mode 100644
index 000000000..fe085acc4
--- /dev/null
+++ b/OpenSubtitlesHandler/Movies/MovieSearchResult.cs
@@ -0,0 +1,41 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ public struct MovieSearchResult
+ {
+ private string id;
+ private string title;
+
+ public string ID
+ { get { return id; } set { id = value; } }
+ public string Title
+ { get { return title; } set { title = value; } }
+ /// <summary>
+ /// Title
+ /// </summary>
+ /// <returns></returns>
+ public override string ToString()
+ {
+ return title;
+ }
+ }
+}
diff --git a/OpenSubtitlesHandler/Movies/SearchToMailMovieParameter.cs b/OpenSubtitlesHandler/Movies/SearchToMailMovieParameter.cs
new file mode 100644
index 000000000..d5e3fc4c6
--- /dev/null
+++ b/OpenSubtitlesHandler/Movies/SearchToMailMovieParameter.cs
@@ -0,0 +1,30 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace OpenSubtitlesHandler
+{
+ public struct SearchToMailMovieParameter
+ {
+ private string _moviehash;
+ private double _moviesize;
+
+ public string moviehash { get { return _moviehash; } set { _moviehash = value; } }
+ public double moviesize { get { return _moviesize; } set { _moviesize = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/OpenSubtitles.cs b/OpenSubtitlesHandler/OpenSubtitles.cs
new file mode 100644
index 000000000..9452c25ec
--- /dev/null
+++ b/OpenSubtitlesHandler/OpenSubtitles.cs
@@ -0,0 +1,2731 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Text;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using OpenSubtitlesHandler.Console;
+using XmlRpcHandler;
+
+namespace OpenSubtitlesHandler
+{
+ /// <summary>
+ /// The core of the OpenSubtitles Handler library. All members are static.
+ /// </summary>
+ public sealed class OpenSubtitles
+ {
+ private static string XML_PRC_USERAGENT = "";
+ // This is session id after log in, important value and MUST be set by LogIn before any other call.
+ private static string TOKEN = "";
+
+ /// <summary>
+ /// Set the useragent value. This must be called before doing anything else.
+ /// </summary>
+ /// <param name="agent">The useragent value</param>
+ public static void SetUserAgent(string agent)
+ {
+ XML_PRC_USERAGENT = agent;
+ }
+
+ /*Session handling*/
+ /// <summary>
+ /// Send a LogIn request, this must be called before anything else in this class.
+ /// </summary>
+ /// <param name="userName">The user name of OpenSubtitles</param>
+ /// <param name="password">The password</param>
+ /// <param name="language">The language, usally en</param>
+ /// <returns>Status of the login operation</returns>
+ public static IMethodResponse LogIn(string userName, string password, string language)
+ {
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(userName));
+ parms.Add(new XmlRpcValueBasic(password));
+ parms.Add(new XmlRpcValueBasic(language));
+ parms.Add(new XmlRpcValueBasic(XML_PRC_USERAGENT));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("LogIn", parms);
+ OSHConsole.WriteLine("Sending LogIn request to the server ...", DebugCode.Good);
+
+ //File.WriteAllText(".\\request.txt", Encoding.UTF8.GetString(XmlRpcGenerator.Generate(call)));
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response. We expect Struct here.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ MethodResponseLogIn re = new MethodResponseLogIn("Success", "Log in successful.");
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "token": re.Token = TOKEN = MEMBER.Data.Data.ToString(); OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": re.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "status": re.Status = MEMBER.Data.Data.ToString(); OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ }
+ }
+ return re;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "Log in failed !");
+ }
+
+ public static async Task<IMethodResponse> LogInAsync(string userName, string password, string language, CancellationToken cancellationToken)
+ {
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(userName));
+ parms.Add(new XmlRpcValueBasic(password));
+ parms.Add(new XmlRpcValueBasic(language));
+ parms.Add(new XmlRpcValueBasic(XML_PRC_USERAGENT));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("LogIn", parms);
+ OSHConsole.WriteLine("Sending LogIn request to the server ...", DebugCode.Good);
+
+ //File.WriteAllText(".\\request.txt", Encoding.UTF8.GetString(XmlRpcGenerator.Generate(call)));
+ // Send the request to the server
+ var stream = await Utilities.SendRequestAsync(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT, cancellationToken)
+ .ConfigureAwait(false);
+
+ string response = Utilities.GetStreamString(stream);
+
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response. We expect Struct here.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ MethodResponseLogIn re = new MethodResponseLogIn("Success", "Log in successful.");
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "token": re.Token = TOKEN = MEMBER.Data.Data.ToString(); OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": re.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "status": re.Status = MEMBER.Data.Data.ToString(); OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ }
+ }
+ return re;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "Log in failed !");
+ }
+
+ /// <summary>
+ /// Log out from the server. Call this to terminate the session.
+ /// </summary>
+ /// <returns></returns>
+ public static IMethodResponse LogOut()
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("LogOut", parms);
+
+ OSHConsole.WriteLine("Sending LogOut request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response. We expect Struct here.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct strct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ OSHConsole.WriteLine("STATUS=" + ((XmlRpcValueBasic)strct.Members[0].Data).Data.ToString());
+ OSHConsole.WriteLine("SECONDS=" + ((XmlRpcValueBasic)strct.Members[1].Data).Data.ToString());
+ MethodResponseLogIn re = new MethodResponseLogIn("Success", "Log out successful.");
+ re.Status = ((XmlRpcValueBasic)strct.Members[0].Data).Data.ToString();
+ re.Seconds = (double)((XmlRpcValueBasic)strct.Members[1].Data).Data;
+ return re;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "Log out failed !");
+ }
+ /// <summary>
+ /// keep-alive user's session, verify token/session validity
+ /// </summary>
+ /// <returns>Status of the call operation</returns>
+ public static IMethodResponse NoOperation()
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ parms.Add(new XmlRpcValueBasic(XML_PRC_USERAGENT, XmlRpcBasicValueType.String));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("NoOperation", parms);
+
+ OSHConsole.WriteLine("Sending NoOperation request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response. We expect Struct here.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ MethodResponseNoOperation R = new MethodResponseNoOperation();
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(MEMBER.Name + "= " + MEMBER.Data.Data); break;
+ case "download_limits":
+ XmlRpcValueStruct dlStruct = (XmlRpcValueStruct)MEMBER.Data;
+ foreach (XmlRpcStructMember dlmember in dlStruct.Members)
+ {
+ OSHConsole.WriteLine(" >" + dlmember.Name + "= " + dlmember.Data.Data.ToString());
+ switch (dlmember.Name)
+ {
+ case "global_wrh_download_limit": R.global_wrh_download_limit = dlmember.Data.Data.ToString(); break;
+ case "client_ip": R.client_ip = dlmember.Data.Data.ToString(); break;
+ case "limit_check_by": R.limit_check_by = dlmember.Data.Data.ToString(); break;
+ case "client_24h_download_count": R.client_24h_download_count = dlmember.Data.Data.ToString(); break;
+ case "client_downlaod_quota": R.client_downlaod_quota = dlmember.Data.Data.ToString(); break;
+ case "client_24h_download_limit": R.client_24h_download_limit = dlmember.Data.Data.ToString(); break;
+ }
+ }
+ break;
+ }
+ }
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "NoOperation call failed !");
+ }
+ /*Search and download*/
+ /// <summary>
+ /// Search for subtitle files matching your videos using either video file hashes or IMDb IDs.
+ /// </summary>
+ /// <param name="parameters">List of search subtitle parameters which each one represents 'struct parameter' as descriped at http://trac.opensubtitles.org/projects/opensubtitles/wiki/XmlRpcSearchSubtitles </param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseSubtitleSearch'</returns>
+ public static IMethodResponse SearchSubtitles(SubtitleSearchParameters[] parameters)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ if (parameters == null)
+ {
+ OSHConsole.UpdateLine("No subtitle search parameter passed !!", DebugCode.Error);
+ return new MethodResponseError("Fail", "No subtitle search parameter passed"); ;
+ }
+ if (parameters.Length == 0)
+ {
+ OSHConsole.UpdateLine("No subtitle search parameter passed !!", DebugCode.Error);
+ return new MethodResponseError("Fail", "No subtitle search parameter passed"); ;
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ // Add token param
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ // Add subtitle search parameters. Each one will be like 'array' of structs.
+ XmlRpcValueArray array = new XmlRpcValueArray();
+ foreach (SubtitleSearchParameters param in parameters)
+ {
+ XmlRpcValueStruct strct = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ // sublanguageid member
+ XmlRpcStructMember member = new XmlRpcStructMember("sublanguageid",
+ new XmlRpcValueBasic(param.SubLangaugeID, XmlRpcBasicValueType.String));
+ strct.Members.Add(member);
+ // moviehash member
+ if (param.MovieHash.Length > 0 && param.MovieByteSize > 0) {
+ member = new XmlRpcStructMember("moviehash",
+ new XmlRpcValueBasic(param.MovieHash, XmlRpcBasicValueType.String));
+ strct.Members.Add(member);
+ // moviehash member
+ member = new XmlRpcStructMember("moviebytesize",
+ new XmlRpcValueBasic(param.MovieByteSize, XmlRpcBasicValueType.Int));
+ strct.Members.Add(member);
+ }
+ if (param.Query.Length > 0) {
+ member = new XmlRpcStructMember("query",
+ new XmlRpcValueBasic(param.Query, XmlRpcBasicValueType.String));
+ strct.Members.Add(member);
+ }
+
+ if (param.Episode.Length > 0 && param.Season.Length>0) {
+ member = new XmlRpcStructMember("season",
+ new XmlRpcValueBasic(param.Season, XmlRpcBasicValueType.String));
+ strct.Members.Add(member);
+ member = new XmlRpcStructMember("episode",
+ new XmlRpcValueBasic(param.Episode, XmlRpcBasicValueType.String));
+ strct.Members.Add(member);
+ }
+
+ // imdbid member
+ if (param.IMDbID.Length > 0)
+ {
+ member = new XmlRpcStructMember("imdbid",
+ new XmlRpcValueBasic(param.IMDbID, XmlRpcBasicValueType.String));
+ strct.Members.Add(member);
+ }
+ // Add the struct to the array
+ array.Values.Add(strct);
+ }
+ // Add the array to the parameters
+ parms.Add(array);
+ // Call !
+ XmlRpcMethodCall call = new XmlRpcMethodCall("SearchSubtitles", parms);
+ OSHConsole.WriteLine("Sending SearchSubtitles request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ // We expect Struct of 3 members:
+ //* the first is status
+ //* the second is [array of structs, each one includes subtitle file].
+ //* the third is [double basic value] represent seconds token by server.
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseSubtitleSearch R = new MethodResponseSubtitleSearch();
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ if (MEMBER.Name == "status")
+ {
+ R.Status = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Status= " + R.Status);
+ }
+ else if (MEMBER.Name == "seconds")
+ {
+ R.Seconds = (double)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Seconds= " + R.Seconds);
+ }
+ else if (MEMBER.Name == "data")
+ {
+ if (MEMBER.Data is XmlRpcValueArray)
+ {
+ OSHConsole.WriteLine("Search results: ");
+
+ XmlRpcValueArray rarray = (XmlRpcValueArray)MEMBER.Data;
+ foreach (IXmlRpcValue subStruct in rarray.Values)
+ {
+ if (subStruct == null) continue;
+ if (!(subStruct is XmlRpcValueStruct)) continue;
+
+ SubtitleSearchResult result = new SubtitleSearchResult();
+ foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members)
+ {
+ // To avoid errors of arranged info or missing ones, let's do it with switch..
+ switch (submember.Name)
+ {
+ case "IDMovie": result.IDMovie = submember.Data.Data.ToString(); break;
+ case "IDMovieImdb": result.IDMovieImdb = submember.Data.Data.ToString(); break;
+ case "IDSubMovieFile": result.IDSubMovieFile = submember.Data.Data.ToString(); break;
+ case "IDSubtitle": result.IDSubtitle = submember.Data.Data.ToString(); break;
+ case "IDSubtitleFile": result.IDSubtitleFile = submember.Data.Data.ToString(); break;
+ case "ISO639": result.ISO639 = submember.Data.Data.ToString(); break;
+ case "LanguageName": result.LanguageName = submember.Data.Data.ToString(); break;
+ case "MovieByteSize": result.MovieByteSize = submember.Data.Data.ToString(); break;
+ case "MovieHash": result.MovieHash = submember.Data.Data.ToString(); break;
+ case "MovieImdbRating": result.MovieImdbRating = submember.Data.Data.ToString(); break;
+ case "MovieName": result.MovieName = submember.Data.Data.ToString(); break;
+ case "MovieNameEng": result.MovieNameEng = submember.Data.Data.ToString(); break;
+ case "MovieReleaseName": result.MovieReleaseName = submember.Data.Data.ToString(); break;
+ case "MovieTimeMS": result.MovieTimeMS = submember.Data.Data.ToString(); break;
+ case "MovieYear": result.MovieYear = submember.Data.Data.ToString(); break;
+ case "SubActualCD": result.SubActualCD = submember.Data.Data.ToString(); break;
+ case "SubAddDate": result.SubAddDate = submember.Data.Data.ToString(); break;
+ case "SubAuthorComment": result.SubAuthorComment = submember.Data.Data.ToString(); break;
+ case "SubBad": result.SubBad = submember.Data.Data.ToString(); break;
+ case "SubDownloadLink": result.SubDownloadLink = submember.Data.Data.ToString(); break;
+ case "SubDownloadsCnt": result.SubDownloadsCnt = submember.Data.Data.ToString(); break;
+ case "SeriesEpisode": result.SeriesEpisode = submember.Data.Data.ToString(); break;
+ case "SeriesSeason": result.SeriesSeason = submember.Data.Data.ToString(); break;
+ case "SubFileName": result.SubFileName = submember.Data.Data.ToString(); break;
+ case "SubFormat": result.SubFormat = submember.Data.Data.ToString(); break;
+ case "SubHash": result.SubHash = submember.Data.Data.ToString(); break;
+ case "SubLanguageID": result.SubLanguageID = submember.Data.Data.ToString(); break;
+ case "SubRating": result.SubRating = submember.Data.Data.ToString(); break;
+ case "SubSize": result.SubSize = submember.Data.Data.ToString(); break;
+ case "SubSumCD": result.SubSumCD = submember.Data.Data.ToString(); break;
+ case "UserID": result.UserID = submember.Data.Data.ToString(); break;
+ case "UserNickName": result.UserNickName = submember.Data.Data.ToString(); break;
+ case "ZipDownloadLink": result.ZipDownloadLink = submember.Data.Data.ToString(); break;
+ }
+ }
+ R.Results.Add(result);
+ OSHConsole.WriteLine(">" + result.ToString());
+ }
+ }
+ else// Unknown data ?
+ {
+ OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning);
+ }
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "Search Subtitles call failed !");
+ }
+
+ public static async Task<IMethodResponse> SearchSubtitlesAsync(SubtitleSearchParameters[] parameters, CancellationToken cancellationToken)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ if (parameters == null)
+ {
+ OSHConsole.UpdateLine("No subtitle search parameter passed !!", DebugCode.Error);
+ return new MethodResponseError("Fail", "No subtitle search parameter passed"); ;
+ }
+ if (parameters.Length == 0)
+ {
+ OSHConsole.UpdateLine("No subtitle search parameter passed !!", DebugCode.Error);
+ return new MethodResponseError("Fail", "No subtitle search parameter passed"); ;
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ // Add token param
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ // Add subtitle search parameters. Each one will be like 'array' of structs.
+ XmlRpcValueArray array = new XmlRpcValueArray();
+ foreach (SubtitleSearchParameters param in parameters)
+ {
+ XmlRpcValueStruct strct = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ // sublanguageid member
+ XmlRpcStructMember member = new XmlRpcStructMember("sublanguageid",
+ new XmlRpcValueBasic(param.SubLangaugeID, XmlRpcBasicValueType.String));
+ strct.Members.Add(member);
+ // moviehash member
+ if (param.MovieHash.Length > 0 && param.MovieByteSize > 0)
+ {
+ member = new XmlRpcStructMember("moviehash",
+ new XmlRpcValueBasic(param.MovieHash, XmlRpcBasicValueType.String));
+ strct.Members.Add(member);
+ // moviehash member
+ member = new XmlRpcStructMember("moviebytesize",
+ new XmlRpcValueBasic(param.MovieByteSize, XmlRpcBasicValueType.Int));
+ strct.Members.Add(member);
+ }
+ if (param.Query.Length > 0)
+ {
+ member = new XmlRpcStructMember("query",
+ new XmlRpcValueBasic(param.Query, XmlRpcBasicValueType.String));
+ strct.Members.Add(member);
+ }
+
+ if (param.Episode.Length > 0 && param.Season.Length > 0)
+ {
+ member = new XmlRpcStructMember("season",
+ new XmlRpcValueBasic(param.Season, XmlRpcBasicValueType.String));
+ strct.Members.Add(member);
+ member = new XmlRpcStructMember("episode",
+ new XmlRpcValueBasic(param.Episode, XmlRpcBasicValueType.String));
+ strct.Members.Add(member);
+ }
+
+ // imdbid member
+ if (param.IMDbID.Length > 0)
+ {
+ member = new XmlRpcStructMember("imdbid",
+ new XmlRpcValueBasic(param.IMDbID, XmlRpcBasicValueType.String));
+ strct.Members.Add(member);
+ }
+ // Add the struct to the array
+ array.Values.Add(strct);
+ }
+ // Add the array to the parameters
+ parms.Add(array);
+ // Call !
+ XmlRpcMethodCall call = new XmlRpcMethodCall("SearchSubtitles", parms);
+ OSHConsole.WriteLine("Sending SearchSubtitles request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(await Utilities.SendRequestAsync(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT, cancellationToken).ConfigureAwait(false));
+
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ // We expect Struct of 3 members:
+ //* the first is status
+ //* the second is [array of structs, each one includes subtitle file].
+ //* the third is [double basic value] represent seconds token by server.
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseSubtitleSearch R = new MethodResponseSubtitleSearch();
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ if (MEMBER.Name == "status")
+ {
+ R.Status = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Status= " + R.Status);
+ }
+ else if (MEMBER.Name == "seconds")
+ {
+ R.Seconds = (double)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Seconds= " + R.Seconds);
+ }
+ else if (MEMBER.Name == "data")
+ {
+ if (MEMBER.Data is XmlRpcValueArray)
+ {
+ OSHConsole.WriteLine("Search results: ");
+
+ XmlRpcValueArray rarray = (XmlRpcValueArray)MEMBER.Data;
+ foreach (IXmlRpcValue subStruct in rarray.Values)
+ {
+ if (subStruct == null) continue;
+ if (!(subStruct is XmlRpcValueStruct)) continue;
+
+ SubtitleSearchResult result = new SubtitleSearchResult();
+ foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members)
+ {
+ // To avoid errors of arranged info or missing ones, let's do it with switch..
+ switch (submember.Name)
+ {
+ case "IDMovie": result.IDMovie = submember.Data.Data.ToString(); break;
+ case "IDMovieImdb": result.IDMovieImdb = submember.Data.Data.ToString(); break;
+ case "IDSubMovieFile": result.IDSubMovieFile = submember.Data.Data.ToString(); break;
+ case "IDSubtitle": result.IDSubtitle = submember.Data.Data.ToString(); break;
+ case "IDSubtitleFile": result.IDSubtitleFile = submember.Data.Data.ToString(); break;
+ case "ISO639": result.ISO639 = submember.Data.Data.ToString(); break;
+ case "LanguageName": result.LanguageName = submember.Data.Data.ToString(); break;
+ case "MovieByteSize": result.MovieByteSize = submember.Data.Data.ToString(); break;
+ case "MovieHash": result.MovieHash = submember.Data.Data.ToString(); break;
+ case "MovieImdbRating": result.MovieImdbRating = submember.Data.Data.ToString(); break;
+ case "MovieName": result.MovieName = submember.Data.Data.ToString(); break;
+ case "MovieNameEng": result.MovieNameEng = submember.Data.Data.ToString(); break;
+ case "MovieReleaseName": result.MovieReleaseName = submember.Data.Data.ToString(); break;
+ case "MovieTimeMS": result.MovieTimeMS = submember.Data.Data.ToString(); break;
+ case "MovieYear": result.MovieYear = submember.Data.Data.ToString(); break;
+ case "SubActualCD": result.SubActualCD = submember.Data.Data.ToString(); break;
+ case "SubAddDate": result.SubAddDate = submember.Data.Data.ToString(); break;
+ case "SubAuthorComment": result.SubAuthorComment = submember.Data.Data.ToString(); break;
+ case "SubBad": result.SubBad = submember.Data.Data.ToString(); break;
+ case "SubDownloadLink": result.SubDownloadLink = submember.Data.Data.ToString(); break;
+ case "SubDownloadsCnt": result.SubDownloadsCnt = submember.Data.Data.ToString(); break;
+ case "SeriesEpisode": result.SeriesEpisode = submember.Data.Data.ToString(); break;
+ case "SeriesSeason": result.SeriesSeason = submember.Data.Data.ToString(); break;
+ case "SubFileName": result.SubFileName = submember.Data.Data.ToString(); break;
+ case "SubFormat": result.SubFormat = submember.Data.Data.ToString(); break;
+ case "SubHash": result.SubHash = submember.Data.Data.ToString(); break;
+ case "SubLanguageID": result.SubLanguageID = submember.Data.Data.ToString(); break;
+ case "SubRating": result.SubRating = submember.Data.Data.ToString(); break;
+ case "SubSize": result.SubSize = submember.Data.Data.ToString(); break;
+ case "SubSumCD": result.SubSumCD = submember.Data.Data.ToString(); break;
+ case "UserID": result.UserID = submember.Data.Data.ToString(); break;
+ case "UserNickName": result.UserNickName = submember.Data.Data.ToString(); break;
+ case "ZipDownloadLink": result.ZipDownloadLink = submember.Data.Data.ToString(); break;
+ }
+ }
+ R.Results.Add(result);
+ OSHConsole.WriteLine(">" + result.ToString());
+ }
+ }
+ else// Unknown data ?
+ {
+ OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning);
+ }
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "Search Subtitles call failed !");
+ }
+
+ /// <summary>
+ /// Download subtitle file(s)
+ /// </summary>
+ /// <param name="subIDS">The subtitle IDS (an array of IDSubtitleFile value that given by server as SearchSubtiles results)</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseSubtitleDownload' which will hold downloaded subtitles</returns>
+ public static IMethodResponse DownloadSubtitles(int[] subIDS)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ if (subIDS == null)
+ {
+ OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error);
+ return new MethodResponseError("Fail", "No subtitle id passed"); ;
+ }
+ if (subIDS.Length == 0)
+ {
+ OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error);
+ return new MethodResponseError("Fail", "No subtitle id passed"); ;
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ // Add token param
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ // Add subtitle search parameters. Each one will be like 'array' of structs.
+ XmlRpcValueArray array = new XmlRpcValueArray();
+ foreach (int id in subIDS)
+ {
+ array.Values.Add(new XmlRpcValueBasic(id, XmlRpcBasicValueType.Int));
+ }
+ // Add the array to the parameters
+ parms.Add(array);
+ // Call !
+ XmlRpcMethodCall call = new XmlRpcMethodCall("DownloadSubtitles", parms);
+ OSHConsole.WriteLine("Sending DownloadSubtitles request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ // We expect Struct of 3 members:
+ //* the first is status
+ //* the second is [array of structs, each one includes subtitle file].
+ //* the third is [double basic value] represent seconds token by server.
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseSubtitleDownload R = new MethodResponseSubtitleDownload();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ if (MEMBER.Name == "status")
+ {
+ R.Status = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Status= " + R.Status);
+ }
+ else if (MEMBER.Name == "seconds")
+ {
+ R.Seconds = (double)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Seconds= " + R.Seconds);
+ }
+ else if (MEMBER.Name == "data")
+ {
+ if (MEMBER.Data is XmlRpcValueArray)
+ {
+ OSHConsole.WriteLine("Download results:");
+ XmlRpcValueArray rarray = (XmlRpcValueArray)MEMBER.Data;
+ foreach (IXmlRpcValue subStruct in rarray.Values)
+ {
+ if (subStruct == null) continue;
+ if (!(subStruct is XmlRpcValueStruct)) continue;
+
+ SubtitleDownloadResult result = new SubtitleDownloadResult();
+ foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members)
+ {
+ // To avoid errors of arranged info or missing ones, let's do it with switch..
+ switch (submember.Name)
+ {
+ case "idsubtitlefile": result.IdSubtitleFile = (string)submember.Data.Data; break;
+ case "data": result.Data = (string)submember.Data.Data; break;
+ }
+ }
+ R.Results.Add(result);
+ OSHConsole.WriteLine("> IDSubtilteFile= " + result.ToString());
+ }
+ }
+ else// Unknown data ?
+ {
+ OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning);
+ }
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "DownloadSubtitles call failed !");
+ }
+
+ public static async Task<IMethodResponse> DownloadSubtitlesAsync(int[] subIDS, CancellationToken cancellationToken)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ if (subIDS == null)
+ {
+ OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error);
+ return new MethodResponseError("Fail", "No subtitle id passed"); ;
+ }
+ if (subIDS.Length == 0)
+ {
+ OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error);
+ return new MethodResponseError("Fail", "No subtitle id passed"); ;
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ // Add token param
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ // Add subtitle search parameters. Each one will be like 'array' of structs.
+ XmlRpcValueArray array = new XmlRpcValueArray();
+ foreach (int id in subIDS)
+ {
+ array.Values.Add(new XmlRpcValueBasic(id, XmlRpcBasicValueType.Int));
+ }
+ // Add the array to the parameters
+ parms.Add(array);
+ // Call !
+ XmlRpcMethodCall call = new XmlRpcMethodCall("DownloadSubtitles", parms);
+ OSHConsole.WriteLine("Sending DownloadSubtitles request to the server ...", DebugCode.Good);
+ // Send the request to the server
+
+ var httpResponse = await Utilities.SendRequestAsync(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT, cancellationToken).ConfigureAwait(false);
+
+ string response = Utilities.GetStreamString(httpResponse);
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ // We expect Struct of 3 members:
+ //* the first is status
+ //* the second is [array of structs, each one includes subtitle file].
+ //* the third is [double basic value] represent seconds token by server.
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseSubtitleDownload R = new MethodResponseSubtitleDownload();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ if (MEMBER.Name == "status")
+ {
+ R.Status = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Status= " + R.Status);
+ }
+ else if (MEMBER.Name == "seconds")
+ {
+ R.Seconds = (double)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Seconds= " + R.Seconds);
+ }
+ else if (MEMBER.Name == "data")
+ {
+ if (MEMBER.Data is XmlRpcValueArray)
+ {
+ OSHConsole.WriteLine("Download results:");
+ XmlRpcValueArray rarray = (XmlRpcValueArray)MEMBER.Data;
+ foreach (IXmlRpcValue subStruct in rarray.Values)
+ {
+ if (subStruct == null) continue;
+ if (!(subStruct is XmlRpcValueStruct)) continue;
+
+ SubtitleDownloadResult result = new SubtitleDownloadResult();
+ foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members)
+ {
+ // To avoid errors of arranged info or missing ones, let's do it with switch..
+ switch (submember.Name)
+ {
+ case "idsubtitlefile": result.IdSubtitleFile = (string)submember.Data.Data; break;
+ case "data": result.Data = (string)submember.Data.Data; break;
+ }
+ }
+ R.Results.Add(result);
+ OSHConsole.WriteLine("> IDSubtilteFile= " + result.ToString());
+ }
+ }
+ else// Unknown data ?
+ {
+ OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning);
+ }
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "DownloadSubtitles call failed !");
+ }
+
+ /// <summary>
+ /// Returns comments for subtitles
+ /// </summary>
+ /// <param name="subIDS">The subtitle IDS (an array of IDSubtitleFile value that given by server as SearchSubtiles results)</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseGetComments'</returns>
+ public static IMethodResponse GetComments(int[] subIDS)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ if (subIDS == null)
+ {
+ OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error);
+ return new MethodResponseError("Fail", "No subtitle id passed"); ;
+ }
+ if (subIDS.Length == 0)
+ {
+ OSHConsole.UpdateLine("No subtitle id passed !!", DebugCode.Error);
+ return new MethodResponseError("Fail", "No subtitle id passed"); ;
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ // Add token param
+ parms.Add(new XmlRpcValueBasic(TOKEN));
+ // Add subtitle search parameters. Each one will be like 'array' of structs.
+ XmlRpcValueArray array = new XmlRpcValueArray(subIDS);
+ // Add the array to the parameters
+ parms.Add(array);
+ // Call !
+ XmlRpcMethodCall call = new XmlRpcMethodCall("GetComments", parms);
+ OSHConsole.WriteLine("Sending GetComments request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseGetComments R = new MethodResponseGetComments();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ if (MEMBER.Name == "status")
+ {
+ R.Status = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Status= " + R.Status);
+ }
+ else if (MEMBER.Name == "seconds")
+ {
+ R.Seconds = (double)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Seconds= " + R.Seconds);
+ }
+ else if (MEMBER.Name == "data")
+ {
+ if (MEMBER.Data is XmlRpcValueArray)
+ {
+ OSHConsole.WriteLine("Comments results:");
+ XmlRpcValueArray rarray = (XmlRpcValueArray)MEMBER.Data;
+ foreach (IXmlRpcValue commentStruct in rarray.Values)
+ {
+ if (commentStruct == null) continue;
+ if (!(commentStruct is XmlRpcValueStruct)) continue;
+
+ GetCommentsResult result = new GetCommentsResult();
+ foreach (XmlRpcStructMember commentmember in ((XmlRpcValueStruct)commentStruct).Members)
+ {
+ // To avoid errors of arranged info or missing ones, let's do it with switch..
+ switch (commentmember.Name)
+ {
+ case "IDSubtitle": result.IDSubtitle = (string)commentmember.Data.Data; break;
+ case "UserID": result.UserID = (string)commentmember.Data.Data; break;
+ case "UserNickName": result.UserNickName = (string)commentmember.Data.Data; break;
+ case "Comment": result.Comment = (string)commentmember.Data.Data; break;
+ case "Created": result.Created = (string)commentmember.Data.Data; break;
+ }
+ }
+ R.Results.Add(result);
+ OSHConsole.WriteLine("> IDSubtitle= " + result.ToString());
+ }
+ }
+ else// Unknown data ?
+ {
+ OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning);
+ }
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "GetComments call failed !");
+ }
+
+ /// <summary>
+ /// Schedule a periodical search for subtitles matching given video files, send results to user's e-mail address.
+ /// </summary>
+ /// <param name="languageIDS">The language 3 lenght ids array</param>
+ /// <param name="movies">The movies parameters</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseSearchToMail'</returns>
+ public static IMethodResponse SearchToMail(string[] languageIDS, SearchToMailMovieParameter[] movies)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ // Array of sub langs
+ XmlRpcValueArray a = new XmlRpcValueArray(languageIDS);
+ parms.Add(a);
+ // Array of video parameters
+ a = new XmlRpcValueArray();
+ foreach (SearchToMailMovieParameter p in movies)
+ {
+ XmlRpcValueStruct str = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ str.Members.Add(new XmlRpcStructMember("moviehash", new XmlRpcValueBasic(p.moviehash)));
+ str.Members.Add(new XmlRpcStructMember("moviesize", new XmlRpcValueBasic(p.moviesize)));
+ a.Values.Add(str);
+ }
+ parms.Add(a);
+ XmlRpcMethodCall call = new XmlRpcMethodCall("SearchToMail", parms);
+
+ OSHConsole.WriteLine("Sending SearchToMail request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseSearchToMail R = new MethodResponseSearchToMail();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "SearchToMail call failed !");
+ }
+ /*Movies*/
+ /// <summary>
+ /// Search for a movie (using movie title)
+ /// </summary>
+ /// <param name="query">Movie title user is searching for, this is cleaned-up a bit (remove dvdrip, etc.) before searching </param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseSubtitleSearch'</returns>
+ public static IMethodResponse SearchMoviesOnIMDB(string query)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ // Add token param
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ // Add query param
+ parms.Add(new XmlRpcValueBasic(query, XmlRpcBasicValueType.String));
+ // Call !
+ XmlRpcMethodCall call = new XmlRpcMethodCall("SearchMoviesOnIMDB", parms);
+ OSHConsole.WriteLine("Sending SearchMoviesOnIMDB request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseMovieSearch R = new MethodResponseMovieSearch();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ if (MEMBER.Name == "status")
+ {
+ R.Status = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Status= " + R.Status);
+ }
+ else if (MEMBER.Name == "seconds")
+ {
+ R.Seconds = (double)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Seconds= " + R.Seconds);
+ }
+ else if (MEMBER.Name == "data")
+ {
+ if (MEMBER.Data is XmlRpcValueArray)
+ {
+ OSHConsole.WriteLine("Search results:");
+ XmlRpcValueArray rarray = (XmlRpcValueArray)MEMBER.Data;
+ foreach (IXmlRpcValue subStruct in rarray.Values)
+ {
+ if (subStruct == null) continue;
+ if (!(subStruct is XmlRpcValueStruct)) continue;
+
+ MovieSearchResult result = new MovieSearchResult();
+ foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members)
+ {
+ // To avoid errors of arranged info or missing ones, let's do it with switch..
+ switch (submember.Name)
+ {
+ case "id": result.ID = (string)submember.Data.Data; break;
+ case "title": result.Title = (string)submember.Data.Data; break;
+ }
+ }
+ R.Results.Add(result);
+ OSHConsole.WriteLine(">" + result.ToString());
+ }
+ }
+ else// Unknown data ?
+ {
+ OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning);
+ }
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "SearchMoviesOnIMDB call failed !");
+ }
+ /// <summary>
+ /// Get movie details for given IMDb ID
+ /// </summary>
+ /// <param name="imdbid">http://www.imdb.com/</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseMovieDetails'</returns>
+ public static IMethodResponse GetIMDBMovieDetails(string imdbid)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ // Add token param
+ parms.Add(new XmlRpcValueBasic(TOKEN));
+ // Add query param
+ parms.Add(new XmlRpcValueBasic(imdbid));
+ // Call !
+ XmlRpcMethodCall call = new XmlRpcMethodCall("GetIMDBMovieDetails", parms);
+ OSHConsole.WriteLine("Sending GetIMDBMovieDetails request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseMovieDetails R = new MethodResponseMovieDetails();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ if (MEMBER.Name == "status")
+ {
+ R.Status = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Status= " + R.Status);
+ }
+ else if (MEMBER.Name == "seconds")
+ {
+ R.Seconds = (double)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Seconds= " + R.Seconds);
+ }
+ else if (MEMBER.Name == "data")
+ {
+ // We expect struct with details...
+ if (MEMBER.Data is XmlRpcValueStruct)
+ {
+ OSHConsole.WriteLine("Details result:");
+ XmlRpcValueStruct detailsStruct = (XmlRpcValueStruct)MEMBER.Data;
+ foreach (XmlRpcStructMember dmem in detailsStruct.Members)
+ {
+ switch (dmem.Name)
+ {
+ case "id": R.ID = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break;
+ case "title": R.Title = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break;
+ case "year": R.Year = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break;
+ case "cover": R.CoverLink = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break;
+ case "duration": R.Duration = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break;
+ case "tagline": R.Tagline = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break;
+ case "plot": R.Plot = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break;
+ case "goofs": R.Goofs = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break;
+ case "trivia": R.Trivia = dmem.Data.Data.ToString(); OSHConsole.WriteLine(">" + dmem.Name + "= " + dmem.Data.Data.ToString()); break;
+ case "cast":
+ // this is another struct with cast members...
+ OSHConsole.WriteLine(">" + dmem.Name + "= ");
+ XmlRpcValueStruct castStruct = (XmlRpcValueStruct)dmem.Data;
+ foreach (XmlRpcStructMember castMemeber in castStruct.Members)
+ {
+ R.Cast.Add(castMemeber.Data.Data.ToString());
+ OSHConsole.WriteLine(" >" + castMemeber.Data.Data.ToString());
+ }
+ break;
+ case "directors":
+ OSHConsole.WriteLine(">" + dmem.Name + "= ");
+ // this is another struct with directors members...
+ XmlRpcValueStruct directorsStruct = (XmlRpcValueStruct)dmem.Data;
+ foreach (XmlRpcStructMember directorsMember in directorsStruct.Members)
+ {
+ R.Directors.Add(directorsMember.Data.Data.ToString());
+ OSHConsole.WriteLine(" >" + directorsMember.Data.Data.ToString());
+ }
+ break;
+ case "writers":
+ OSHConsole.WriteLine(">" + dmem.Name + "= ");
+ // this is another struct with writers members...
+ XmlRpcValueStruct writersStruct = (XmlRpcValueStruct)dmem.Data;
+ foreach (XmlRpcStructMember writersMember in writersStruct.Members)
+ {
+ R.Writers.Add(writersMember.Data.Data.ToString());
+ OSHConsole.WriteLine("+->" + writersMember.Data.Data.ToString());
+ }
+ break;
+ case "awards":
+ // this is an array of genres...
+ XmlRpcValueArray awardsArray = (XmlRpcValueArray)dmem.Data;
+ foreach (XmlRpcValueBasic award in awardsArray.Values)
+ {
+ R.Awards.Add(award.Data.ToString());
+ OSHConsole.WriteLine(" >" + award.Data.ToString());
+ }
+ break;
+ case "genres":
+ OSHConsole.WriteLine(">" + dmem.Name + "= ");
+ // this is an array of genres...
+ XmlRpcValueArray genresArray = (XmlRpcValueArray)dmem.Data;
+ foreach (XmlRpcValueBasic genre in genresArray.Values)
+ {
+ R.Genres.Add(genre.Data.ToString());
+ OSHConsole.WriteLine(" >" + genre.Data.ToString());
+ }
+ break;
+ case "country":
+ OSHConsole.WriteLine(">" + dmem.Name + "= ");
+ // this is an array of country...
+ XmlRpcValueArray countryArray = (XmlRpcValueArray)dmem.Data;
+ foreach (XmlRpcValueBasic country in countryArray.Values)
+ {
+ R.Country.Add(country.Data.ToString());
+ OSHConsole.WriteLine(" >" + country.Data.ToString());
+ }
+ break;
+ case "language":
+ OSHConsole.WriteLine(">" + dmem.Name + "= ");
+ // this is an array of language...
+ XmlRpcValueArray languageArray = (XmlRpcValueArray)dmem.Data;
+ foreach (XmlRpcValueBasic language in languageArray.Values)
+ {
+ R.Language.Add(language.Data.ToString());
+ OSHConsole.WriteLine(" >" + language.Data.ToString());
+ }
+ break;
+ case "certification":
+ OSHConsole.WriteLine(">" + dmem.Name + "= ");
+ // this is an array of certification...
+ XmlRpcValueArray certificationArray = (XmlRpcValueArray)dmem.Data;
+ foreach (XmlRpcValueBasic certification in certificationArray.Values)
+ {
+ R.Certification.Add(certification.Data.ToString());
+ OSHConsole.WriteLine(" >" + certification.Data.ToString());
+ }
+ break;
+ }
+ }
+ }
+ else// Unknown data ?
+ {
+ OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning);
+ }
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "GetIMDBMovieDetails call failed !");
+ }
+ /// <summary>
+ /// Allows registered users to insert new movies (not stored in IMDb) to the database.
+ /// </summary>
+ /// <param name="movieName">Movie title </param>
+ /// <param name="movieyear">Release year </param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseInsertMovie'</returns>
+ public static IMethodResponse InsertMovie(string movieName, string movieyear)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ // Add token param
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ // Add movieinfo struct
+ XmlRpcValueStruct movieinfo = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ movieinfo.Members.Add(new XmlRpcStructMember("moviename", new XmlRpcValueBasic(movieName)));
+ movieinfo.Members.Add(new XmlRpcStructMember("movieyear", new XmlRpcValueBasic(movieyear)));
+ parms.Add(movieinfo);
+ // Call !
+ XmlRpcMethodCall call = new XmlRpcMethodCall("InsertMovie", parms);
+ OSHConsole.WriteLine("Sending InsertMovie request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseInsertMovie R = new MethodResponseInsertMovie();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ if (MEMBER.Name == "status")
+ {
+ R.Status = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Status= " + R.Status);
+ }
+ else if (MEMBER.Name == "seconds")
+ {
+ R.Seconds = (double)MEMBER.Data.Data;
+ OSHConsole.WriteLine("Seconds= " + R.Seconds);
+ }
+ else if (MEMBER.Name == "id")
+ {
+ R.ID = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine("ID= " + R.Seconds);
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "InsertMovie call failed !");
+ }
+ /// <summary>
+ /// Inserts or updates data to tables, which are used for CheckMovieHash() and !CheckMovieHash2().
+ /// </summary>
+ /// <param name="parameters">The parameters</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseInsertMovieHash'</returns>
+ public static IMethodResponse InsertMovieHash(InsertMovieHashParameters[] parameters)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ foreach (InsertMovieHashParameters p in parameters)
+ {
+ XmlRpcValueStruct pstruct = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ pstruct.Members.Add(new XmlRpcStructMember("moviehash", new XmlRpcValueBasic(p.moviehash)));
+ pstruct.Members.Add(new XmlRpcStructMember("moviebytesize", new XmlRpcValueBasic(p.moviebytesize)));
+ pstruct.Members.Add(new XmlRpcStructMember("imdbid", new XmlRpcValueBasic(p.imdbid)));
+ pstruct.Members.Add(new XmlRpcStructMember("movietimems", new XmlRpcValueBasic(p.movietimems)));
+ pstruct.Members.Add(new XmlRpcStructMember("moviefps", new XmlRpcValueBasic(p.moviefps)));
+ pstruct.Members.Add(new XmlRpcStructMember("moviefilename", new XmlRpcValueBasic(p.moviefilename)));
+ parms.Add(pstruct);
+ }
+ XmlRpcMethodCall call = new XmlRpcMethodCall("InsertMovieHash", parms);
+
+ OSHConsole.WriteLine("Sending InsertMovieHash request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseInsertMovieHash R = new MethodResponseInsertMovieHash();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status":
+ R.Status = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "seconds":
+ R.Seconds = (double)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "data":
+ XmlRpcValueStruct dataStruct = (XmlRpcValueStruct)MEMBER.Data;
+ foreach (XmlRpcStructMember dataMember in dataStruct.Members)
+ {
+ switch (dataMember.Name)
+ {
+ case "accepted_moviehashes":
+ XmlRpcValueArray mh = (XmlRpcValueArray)dataMember.Data;
+ foreach (IXmlRpcValue val in mh.Values)
+ {
+ if (val is XmlRpcValueBasic)
+ {
+ R.accepted_moviehashes.Add(val.Data.ToString());
+ }
+ }
+ break;
+ case "new_imdbs":
+ XmlRpcValueArray mi = (XmlRpcValueArray)dataMember.Data;
+ foreach (IXmlRpcValue val in mi.Values)
+ {
+ if (val is XmlRpcValueBasic)
+ {
+ R.new_imdbs.Add(val.Data.ToString());
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "InsertMovieHash call failed !");
+ }
+ /*Reporting and rating*/
+ /// <summary>
+ /// Get basic server information and statistics
+ /// </summary>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseServerInfo'</returns>
+ public static IMethodResponse ServerInfo()
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ parms.Add(new XmlRpcValueBasic(XML_PRC_USERAGENT, XmlRpcBasicValueType.String));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("ServerInfo", parms);
+
+ OSHConsole.WriteLine("Sending ServerInfo request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseServerInfo R = new MethodResponseServerInfo();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status":
+ R.Status = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "seconds":
+ R.Seconds = (double)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "xmlrpc_version":
+ R.xmlrpc_version = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "xmlrpc_url":
+ R.xmlrpc_url = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "application":
+ R.application = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "contact":
+ R.contact = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "website_url":
+ R.website_url = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "users_online_total":
+ R.users_online_total = (int)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "users_online_program":
+ R.users_online_program = (int)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "users_loggedin":
+ R.users_loggedin = (int)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "users_max_alltime":
+ R.users_max_alltime = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "users_registered":
+ R.users_registered = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "subs_downloads":
+ R.subs_downloads = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "subs_subtitle_files":
+ R.subs_subtitle_files = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "movies_total":
+ R.movies_total = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "movies_aka":
+ R.movies_aka = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "total_subtitles_languages":
+ R.total_subtitles_languages = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "last_update_strings":
+ //R.total_subtitles_languages = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + ":");
+ XmlRpcValueStruct luStruct = (XmlRpcValueStruct)MEMBER.Data;
+ foreach (XmlRpcStructMember luMemeber in luStruct.Members)
+ {
+ R.last_update_strings.Add(luMemeber.Name + " [" + luMemeber.Data.Data.ToString() + "]");
+ OSHConsole.WriteLine(" >" + luMemeber.Name + "= " + luMemeber.Data.Data.ToString());
+ }
+ break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "ServerInfo call failed !");
+ }
+ /// <summary>
+ /// Report wrong subtitle file <--> video file combination
+ /// </summary>
+ /// <param name="IDSubMovieFile">Identifier of the subtitle file <--> video file combination </param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseReportWrongMovieHash'</returns>
+ public static IMethodResponse ReportWrongMovieHash(string IDSubMovieFile)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ parms.Add(new XmlRpcValueBasic(IDSubMovieFile, XmlRpcBasicValueType.String));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("ReportWrongMovieHash", parms);
+
+ OSHConsole.WriteLine("Sending ReportWrongMovieHash request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseReportWrongMovieHash R = new MethodResponseReportWrongMovieHash();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status":
+ R.Status = (string)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ case "seconds":
+ R.Seconds = (double)MEMBER.Data.Data;
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString());
+ break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "ReportWrongMovieHash call failed !");
+ }
+ /// <summary>
+ /// This method is needed to report bad movie hash for imdbid. This method should be used for correcting wrong entries,
+ /// when using CheckMovieHash2. Pass moviehash and moviebytesize for file, and imdbid as new, corrected one IMDBID
+ /// (id number without trailing zeroes). After some reports, moviehash will be linked to new imdbid.
+ /// </summary>
+ /// <param name="moviehash">The movie hash</param>
+ /// <param name="moviebytesize">The movie size in bytes</param>
+ /// <param name="imdbid">The movie imbid</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseReportWrongImdbMovie'</returns>
+ public static IMethodResponse ReportWrongImdbMovie(string moviehash, string moviebytesize, string imdbid)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ XmlRpcValueStruct s = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ s.Members.Add(new XmlRpcStructMember("moviehash", new XmlRpcValueBasic(moviehash)));
+ s.Members.Add(new XmlRpcStructMember("moviebytesize", new XmlRpcValueBasic(moviebytesize)));
+ s.Members.Add(new XmlRpcStructMember("imdbid", new XmlRpcValueBasic(imdbid)));
+ parms.Add(s);
+ XmlRpcMethodCall call = new XmlRpcMethodCall("ReportWrongImdbMovie", parms);
+
+ OSHConsole.WriteLine("Sending ReportWrongImdbMovie request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseAddComment R = new MethodResponseAddComment();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "ReportWrongImdbMovie call failed !");
+ }
+ /// <summary>
+ /// Rate subtitles
+ /// </summary>
+ /// <param name="idsubtitle">Id of subtitle (NOT subtitle file) user wants to rate </param>
+ /// <param name="score">Subtitle rating, must be in interval 1 (worst) to 10 (best). </param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseSubtitlesVote'</returns>
+ public static IMethodResponse SubtitlesVote(int idsubtitle, int score)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ XmlRpcValueStruct s = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ s.Members.Add(new XmlRpcStructMember("idsubtitle", new XmlRpcValueBasic(idsubtitle)));
+ s.Members.Add(new XmlRpcStructMember("score", new XmlRpcValueBasic(score)));
+ parms.Add(s);
+ XmlRpcMethodCall call = new XmlRpcMethodCall("SubtitlesVote", parms);
+
+ OSHConsole.WriteLine("Sending SubtitlesVote request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseSubtitlesVote R = new MethodResponseSubtitlesVote();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "data":
+ XmlRpcValueStruct dataStruct = (XmlRpcValueStruct)MEMBER.Data;
+ foreach (XmlRpcStructMember dataMemeber in dataStruct.Members)
+ {
+ OSHConsole.WriteLine(" >" + dataMemeber.Name + "= " + dataMemeber.Data.Data.ToString());
+ switch (dataMemeber.Name)
+ {
+ case "SubRating": R.SubRating = dataMemeber.Data.Data.ToString(); break;
+ case "SubSumVotes": R.SubSumVotes = dataMemeber.Data.Data.ToString(); break;
+ case "IDSubtitle": R.IDSubtitle = dataMemeber.Data.Data.ToString(); break;
+ }
+ }
+ break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "SubtitlesVote call failed !");
+ }
+ /// <summary>
+ /// Add comment to a subtitle
+ /// </summary>
+ /// <param name="idsubtitle">Subtitle identifier (BEWARE! this is not the ID of subtitle file but of the whole subtitle (a subtitle can contain multiple subtitle files))</param>
+ /// <param name="comment">User's comment</param>
+ /// <param name="badsubtitle">Optional parameter. If set to 1, subtitles are marked as bad.</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseAddComment'</returns>
+ public static IMethodResponse AddComment(int idsubtitle, string comment, int badsubtitle)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ XmlRpcValueStruct s = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ s.Members.Add(new XmlRpcStructMember("idsubtitle", new XmlRpcValueBasic(idsubtitle)));
+ s.Members.Add(new XmlRpcStructMember("comment", new XmlRpcValueBasic(comment)));
+ s.Members.Add(new XmlRpcStructMember("badsubtitle", new XmlRpcValueBasic(badsubtitle)));
+ parms.Add(s);
+ XmlRpcMethodCall call = new XmlRpcMethodCall("AddComment", parms);
+
+ OSHConsole.WriteLine("Sending AddComment request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseAddComment R = new MethodResponseAddComment();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "AddComment call failed !");
+ }
+ /// <summary>
+ /// Add new request for subtitles, user must be logged in
+ /// </summary>
+ /// <param name="sublanguageid">The subtitle language id 3 length</param>
+ /// <param name="idmovieimdb">http://www.imdb.com/</param>
+ /// <param name="comment">The comment</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseAddRequest'</returns>
+ public static IMethodResponse AddRequest(string sublanguageid, string idmovieimdb, string comment)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ XmlRpcValueStruct s = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ s.Members.Add(new XmlRpcStructMember("sublanguageid", new XmlRpcValueBasic(sublanguageid)));
+ s.Members.Add(new XmlRpcStructMember("idmovieimdb", new XmlRpcValueBasic(idmovieimdb)));
+ s.Members.Add(new XmlRpcStructMember("comment", new XmlRpcValueBasic(comment)));
+ parms.Add(s);
+ XmlRpcMethodCall call = new XmlRpcMethodCall("AddRequest", parms);
+
+ OSHConsole.WriteLine("Sending AddRequest request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseAddRequest R = new MethodResponseAddRequest();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "data":
+ XmlRpcValueStruct dataStruct = (XmlRpcValueStruct)MEMBER.Data;
+ foreach (XmlRpcStructMember dataMemeber in dataStruct.Members)
+ {
+ switch (dataMemeber.Name)
+ {
+ case "request_url": R.request_url = dataMemeber.Data.Data.ToString(); OSHConsole.WriteLine(">" + dataMemeber.Name + "= " + dataMemeber.Data.Data.ToString()); break;
+ }
+ }
+ break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "AddRequest call failed !");
+ }
+ /*User interface*/
+ /// <summary>
+ /// Get list of supported subtitle languages
+ /// </summary>
+ /// <param name="language">ISO639-1 2-letter language code of user's interface language. </param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseGetSubLanguages'</returns>
+ public static IMethodResponse GetSubLanguages(string language)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN));
+ parms.Add(new XmlRpcValueBasic(language));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("GetSubLanguages", parms);
+
+ OSHConsole.WriteLine("Sending GetSubLanguages request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseGetSubLanguages R = new MethodResponseGetSubLanguages();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "data":// array of structs
+ XmlRpcValueArray array = (XmlRpcValueArray)MEMBER.Data;
+ foreach (IXmlRpcValue value in array.Values)
+ {
+ if (value is XmlRpcValueStruct)
+ {
+ XmlRpcValueStruct valueStruct = (XmlRpcValueStruct)value;
+ SubtitleLanguage lang = new SubtitleLanguage();
+ OSHConsole.WriteLine(">SubLanguage:");
+ foreach (XmlRpcStructMember langMemeber in valueStruct.Members)
+ {
+ OSHConsole.WriteLine(" >" + langMemeber.Name + "= " + langMemeber.Data.Data.ToString());
+ switch (langMemeber.Name)
+ {
+ case "SubLanguageID": lang.SubLanguageID = langMemeber.Data.Data.ToString(); break;
+ case "LanguageName": lang.LanguageName = langMemeber.Data.Data.ToString(); break;
+ case "ISO639": lang.ISO639 = langMemeber.Data.Data.ToString(); break;
+ }
+ }
+ R.Languages.Add(lang);
+ }
+ else
+ {
+ OSHConsole.WriteLine(">" + MEMBER.Name + "= " +
+ MEMBER.Data.Data.ToString() + " [Struct expected !]", DebugCode.Warning);
+ }
+ }
+ break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "GetSubLanguages call failed !");
+ }
+ /// <summary>
+ /// Detect language for given strings
+ /// </summary>
+ /// <param name="texts">Array of strings you want language detected for</param>
+ /// <param name="encodingUsed">The encoding that will be used to get buffer of given strings. (this is not OS official parameter)</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseDetectLanguage'</returns>
+ public static IMethodResponse DetectLanguage(string[] texts, Encoding encodingUsed)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ // We need to gzip texts then code them with base 24
+ List<string> decodedTexts = new List<string>();
+ foreach (string text in texts)
+ {
+ // compress
+ Stream str = new MemoryStream();
+ byte[] stringData = encodingUsed.GetBytes(text);
+ str.Write(stringData, 0, stringData.Length);
+ str.Position = 0;
+ byte[] data = Utilities.Compress(str);
+ //base 64
+ decodedTexts.Add(Convert.ToBase64String(data));
+ }
+ parms.Add(new XmlRpcValueArray(decodedTexts.ToArray()));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("DetectLanguage", parms);
+
+ OSHConsole.WriteLine("Sending DetectLanguage request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseDetectLanguage R = new MethodResponseDetectLanguage();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "data":
+ if (MEMBER.Data is XmlRpcValueStruct)
+ {
+ OSHConsole.WriteLine(">Languages:");
+ XmlRpcValueStruct dataStruct = (XmlRpcValueStruct)MEMBER.Data;
+ foreach (XmlRpcStructMember dataMember in dataStruct.Members)
+ {
+ DetectLanguageResult lang = new DetectLanguageResult();
+ lang.InputSample = dataMember.Name;
+ lang.LanguageID = dataMember.Data.Data.ToString();
+ R.Results.Add(lang);
+ OSHConsole.WriteLine(" >" + dataMember.Name + " (" + dataMember.Data.Data.ToString() + ")");
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(">Languages ?? Struct expected but server return another type!!", DebugCode.Warning);
+ }
+ break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "DetectLanguage call failed !");
+ }
+ /// <summary>
+ /// Get available translations for given program
+ /// </summary>
+ /// <param name="program">Name of the program/client application you want translations for. Currently supported values: subdownloader, oscar</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseGetAvailableTranslations'</returns>
+ public static IMethodResponse GetAvailableTranslations(string program)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN));
+ parms.Add(new XmlRpcValueBasic(program));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("GetAvailableTranslations", parms);
+
+ OSHConsole.WriteLine("Sending GetAvailableTranslations request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseGetAvailableTranslations R = new MethodResponseGetAvailableTranslations();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "data":
+ XmlRpcValueStruct dataStruct = (XmlRpcValueStruct)MEMBER.Data;
+ OSHConsole.WriteLine(">data:");
+ foreach (XmlRpcStructMember dataMember in dataStruct.Members)
+ {
+ if (dataMember.Data is XmlRpcValueStruct)
+ {
+ XmlRpcValueStruct resStruct = (XmlRpcValueStruct)dataMember.Data;
+ GetAvailableTranslationsResult res = new GetAvailableTranslationsResult();
+ res.LanguageID = dataMember.Name;
+ OSHConsole.WriteLine(" >LanguageID: " + dataMember.Name);
+ foreach (XmlRpcStructMember resMember in resStruct.Members)
+ {
+ switch (resMember.Name)
+ {
+ case "LastCreated": res.LastCreated = resMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + resMember.Name + "= " + resMember.Data.Data.ToString()); break;
+ case "StringsNo": res.StringsNo = resMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + resMember.Name + "= " + resMember.Data.Data.ToString()); break;
+ }
+ R.Results.Add(res);
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(" >Struct expected !!", DebugCode.Warning);
+ }
+ }
+ break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "GetAvailableTranslations call failed !");
+ }
+ /// <summary>
+ /// Get a translation for given program and language
+ /// </summary>
+ /// <param name="iso639">language ​ISO639-1 2-letter code </param>
+ /// <param name="format">available formats: [gnugettext compatible: mo, po] and [additional: txt, xml]</param>
+ /// <param name="program">Name of the program/client application you want translations for. (currently supported values: subdownloader, oscar)</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseGetTranslation'</returns>
+ public static IMethodResponse GetTranslation(string iso639, string format, string program)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN));
+ parms.Add(new XmlRpcValueBasic(iso639));
+ parms.Add(new XmlRpcValueBasic(format));
+ parms.Add(new XmlRpcValueBasic(program));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("GetTranslation", parms);
+
+ OSHConsole.WriteLine("Sending GetTranslation request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ //File.WriteAllText(".\\REQUEST_GetTranslation.xml", Encoding.ASCII.GetString(XmlRpcGenerator.Generate(call)));
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseGetTranslation R = new MethodResponseGetTranslation();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "data": R.ContentData = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "GetTranslation call failed !");
+ }
+ /// <summary>
+ /// Check for the latest version of given application
+ /// </summary>
+ /// <param name="program">name of the program/client application you want to check. (Currently supported values: subdownloader, oscar)</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseAutoUpdate'</returns>
+ public static IMethodResponse AutoUpdate(string program)
+ {
+ /*if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }*/
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ // parms.Add(new XmlRpcValueBasic(TOKEN));
+ parms.Add(new XmlRpcValueBasic(program));
+ // parms.Add(new XmlRpcValueBasic(XML_PRC_USERAGENT));
+
+ XmlRpcMethodCall call = new XmlRpcMethodCall("AutoUpdate", parms);
+ OSHConsole.WriteLine("Sending AutoUpdate request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseAutoUpdate R = new MethodResponseAutoUpdate();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "version": R.version = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "url_windows": R.url_windows = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "url_linux": R.url_linux = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "comments": R.comments = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "AutoUpdate call failed !");
+ }
+ /*Checking*/
+ /// <summary>
+ /// Check if video file hashes are already stored in the database
+ /// </summary>
+ /// <param name="hashes">Array of video file hashes</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseCheckMovieHash'</returns>
+ public static IMethodResponse CheckMovieHash(string[] hashes)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN));
+ parms.Add(new XmlRpcValueArray(hashes));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("CheckMovieHash", parms);
+
+ OSHConsole.WriteLine("Sending CheckMovieHash request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseCheckMovieHash R = new MethodResponseCheckMovieHash();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "data":
+ XmlRpcValueStruct dataStruct = (XmlRpcValueStruct)MEMBER.Data;
+ OSHConsole.WriteLine(">Data:");
+ foreach (XmlRpcStructMember dataMember in dataStruct.Members)
+ {
+ CheckMovieHashResult res = new CheckMovieHashResult();
+ res.Name = dataMember.Name;
+ OSHConsole.WriteLine(" >" + res.Name + ":");
+ XmlRpcValueStruct movieStruct = (XmlRpcValueStruct)dataMember.Data;
+ foreach (XmlRpcStructMember movieMember in movieStruct.Members)
+ {
+ switch (movieMember.Name)
+ {
+ case "MovieHash": res.MovieHash = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break;
+ case "MovieImdbID": res.MovieImdbID = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break;
+ case "MovieName": res.MovieName = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break;
+ case "MovieYear": res.MovieYear = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break;
+ }
+ }
+ R.Results.Add(res);
+ }
+ break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "CheckMovieHash call failed !");
+ }
+ /// <summary>
+ /// Check if video file hashes are already stored in the database. This method returns matching !MovieImdbID, MovieName, MovieYear, SeriesSeason, SeriesEpisode,
+ /// MovieKind if available for each $moviehash, always sorted by SeenCount DESC.
+ /// </summary>
+ /// <param name="hashes">Array of video file hashes</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseCheckMovieHash2'</returns>
+ public static IMethodResponse CheckMovieHash2(string[] hashes)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN));
+ parms.Add(new XmlRpcValueArray(hashes));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("CheckMovieHash2", parms);
+
+ OSHConsole.WriteLine("Sending CheckMovieHash2 request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseCheckMovieHash2 R = new MethodResponseCheckMovieHash2();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "data":
+ XmlRpcValueStruct dataStruct = (XmlRpcValueStruct)MEMBER.Data;
+ OSHConsole.WriteLine(">Data:");
+ foreach (XmlRpcStructMember dataMember in dataStruct.Members)
+ {
+ CheckMovieHash2Result res = new CheckMovieHash2Result();
+ res.Name = dataMember.Name;
+ OSHConsole.WriteLine(" >" + res.Name + ":");
+
+ XmlRpcValueArray dataArray = (XmlRpcValueArray)dataMember.Data;
+ foreach (XmlRpcValueStruct movieStruct in dataArray.Values)
+ {
+ CheckMovieHash2Data d = new CheckMovieHash2Data();
+ foreach (XmlRpcStructMember movieMember in movieStruct.Members)
+ {
+ switch (movieMember.Name)
+ {
+ case "MovieHash": d.MovieHash = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break;
+ case "MovieImdbID": d.MovieImdbID = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break;
+ case "MovieName": d.MovieName = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break;
+ case "MovieYear": d.MovieYear = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break;
+ case "MovieKind": d.MovieKind = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break;
+ case "SeriesSeason": d.SeriesSeason = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break;
+ case "SeriesEpisode": d.SeriesEpisode = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break;
+ case "SeenCount": d.MovieYear = movieMember.Data.Data.ToString(); OSHConsole.WriteLine(" >" + movieMember.Name + "= " + movieMember.Data.Data.ToString()); break;
+ }
+ }
+ res.Items.Add(d);
+ }
+ R.Results.Add(res);
+ }
+ break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "CheckMovieHash2 call failed !");
+ }
+ /// <summary>
+ /// Check if given subtitle files are already stored in the database
+ /// </summary>
+ /// <param name="hashes">Array of subtitle file hashes (MD5 hashes of subtitle file contents) </param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseCheckSubHash'</returns>
+ public static IMethodResponse CheckSubHash(string[] hashes)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN));
+ parms.Add(new XmlRpcValueArray(hashes));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("CheckSubHash", parms);
+
+ OSHConsole.WriteLine("Sending CheckSubHash request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseCheckSubHash R = new MethodResponseCheckSubHash();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "data":
+ OSHConsole.WriteLine(">Data:");
+ XmlRpcValueStruct dataStruct = (XmlRpcValueStruct)MEMBER.Data;
+ foreach (XmlRpcStructMember dataMember in dataStruct.Members)
+ {
+ OSHConsole.WriteLine(" >" + dataMember.Name + "= " + dataMember.Data.Data.ToString());
+ CheckSubHashResult r = new CheckSubHashResult();
+ r.Hash = dataMember.Name;
+ r.SubID = dataMember.Data.Data.ToString();
+ R.Results.Add(r);
+ }
+ break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "CheckSubHash call failed !");
+ }
+ /*Upload*/
+ /// <summary>
+ /// Try to upload subtitles, perform pre-upload checking (i.e. check if subtitles already exist on server)
+ /// </summary>
+ /// <param name="subs">The subtitle parameters collection to try to upload</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseTryUploadSubtitles'</returns>
+ public static IMethodResponse TryUploadSubtitles(TryUploadSubtitlesParameters[] subs)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN, XmlRpcBasicValueType.String));
+ XmlRpcValueStruct s = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ int i = 1;
+ foreach (TryUploadSubtitlesParameters cd in subs)
+ {
+ XmlRpcStructMember member = new XmlRpcStructMember("cd" + i, null);
+ XmlRpcValueStruct memberStruct = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ memberStruct.Members.Add(new XmlRpcStructMember("subhash", new XmlRpcValueBasic(cd.subhash)));
+ memberStruct.Members.Add(new XmlRpcStructMember("subfilename", new XmlRpcValueBasic(cd.subfilename)));
+ memberStruct.Members.Add(new XmlRpcStructMember("moviehash", new XmlRpcValueBasic(cd.moviehash)));
+ memberStruct.Members.Add(new XmlRpcStructMember("moviebytesize", new XmlRpcValueBasic(cd.moviebytesize)));
+ memberStruct.Members.Add(new XmlRpcStructMember("moviefps", new XmlRpcValueBasic(cd.moviefps)));
+ memberStruct.Members.Add(new XmlRpcStructMember("movietimems", new XmlRpcValueBasic(cd.movietimems)));
+ memberStruct.Members.Add(new XmlRpcStructMember("movieframes", new XmlRpcValueBasic(cd.movieframes)));
+ memberStruct.Members.Add(new XmlRpcStructMember("moviefilename", new XmlRpcValueBasic(cd.moviefilename)));
+ member.Data = memberStruct;
+ s.Members.Add(member);
+ i++;
+ }
+ parms.Add(s);
+ XmlRpcMethodCall call = new XmlRpcMethodCall("TryUploadSubtitles", parms);
+
+ OSHConsole.WriteLine("Sending TryUploadSubtitles request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseTryUploadSubtitles R = new MethodResponseTryUploadSubtitles();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "alreadyindb": R.AlreadyInDB = (int)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "data":
+ if (MEMBER.Data is XmlRpcValueArray)
+ {
+ OSHConsole.WriteLine("Results: ");
+
+ XmlRpcValueArray rarray = (XmlRpcValueArray)MEMBER.Data;
+ foreach (IXmlRpcValue subStruct in rarray.Values)
+ {
+ if (subStruct == null) continue;
+ if (!(subStruct is XmlRpcValueStruct)) continue;
+
+ SubtitleSearchResult result = new SubtitleSearchResult();
+ foreach (XmlRpcStructMember submember in ((XmlRpcValueStruct)subStruct).Members)
+ {
+ // To avoid errors of arranged info or missing ones, let's do it with switch..
+ switch (submember.Name)
+ {
+ case "IDMovie": result.IDMovie = submember.Data.Data.ToString(); break;
+ case "IDMovieImdb": result.IDMovieImdb = submember.Data.Data.ToString(); break;
+ case "IDSubMovieFile": result.IDSubMovieFile = submember.Data.Data.ToString(); break;
+ case "IDSubtitle": result.IDSubtitle = submember.Data.Data.ToString(); break;
+ case "IDSubtitleFile": result.IDSubtitleFile = submember.Data.Data.ToString(); break;
+ case "ISO639": result.ISO639 = submember.Data.Data.ToString(); break;
+ case "LanguageName": result.LanguageName = submember.Data.Data.ToString(); break;
+ case "MovieByteSize": result.MovieByteSize = submember.Data.Data.ToString(); break;
+ case "MovieHash": result.MovieHash = submember.Data.Data.ToString(); break;
+ case "MovieImdbRating": result.MovieImdbRating = submember.Data.Data.ToString(); break;
+ case "MovieName": result.MovieName = submember.Data.Data.ToString(); break;
+ case "MovieNameEng": result.MovieNameEng = submember.Data.Data.ToString(); break;
+ case "MovieReleaseName": result.MovieReleaseName = submember.Data.Data.ToString(); break;
+ case "MovieTimeMS": result.MovieTimeMS = submember.Data.Data.ToString(); break;
+ case "MovieYear": result.MovieYear = submember.Data.Data.ToString(); break;
+ case "SubActualCD": result.SubActualCD = submember.Data.Data.ToString(); break;
+ case "SubAddDate": result.SubAddDate = submember.Data.Data.ToString(); break;
+ case "SubAuthorComment": result.SubAuthorComment = submember.Data.Data.ToString(); break;
+ case "SubBad": result.SubBad = submember.Data.Data.ToString(); break;
+ case "SubDownloadLink": result.SubDownloadLink = submember.Data.Data.ToString(); break;
+ case "SubDownloadsCnt": result.SubDownloadsCnt = submember.Data.Data.ToString(); break;
+ case "SubFileName": result.SubFileName = submember.Data.Data.ToString(); break;
+ case "SubFormat": result.SubFormat = submember.Data.Data.ToString(); break;
+ case "SubHash": result.SubHash = submember.Data.Data.ToString(); break;
+ case "SubLanguageID": result.SubLanguageID = submember.Data.Data.ToString(); break;
+ case "SubRating": result.SubRating = submember.Data.Data.ToString(); break;
+ case "SubSize": result.SubSize = submember.Data.Data.ToString(); break;
+ case "SubSumCD": result.SubSumCD = submember.Data.Data.ToString(); break;
+ case "UserID": result.UserID = submember.Data.Data.ToString(); break;
+ case "UserNickName": result.UserNickName = submember.Data.Data.ToString(); break;
+ case "ZipDownloadLink": result.ZipDownloadLink = submember.Data.Data.ToString(); break;
+ }
+ }
+ R.Results.Add(result);
+ OSHConsole.WriteLine(">" + result.ToString());
+ }
+ }
+ else// Unknown data ?
+ {
+ OSHConsole.WriteLine("Data= " + MEMBER.Data.Data.ToString(), DebugCode.Warning);
+ }
+ break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "TryUploadSubtitles call failed !");
+ }
+ /// <summary>
+ /// Upload given subtitles to OSDb server
+ /// </summary>
+ /// <param name="info">The pamaters of upload method</param>
+ /// <returns>Status of the call operation. If the call success the response will be 'MethodResponseUploadSubtitles'</returns>
+ public static IMethodResponse UploadSubtitles(UploadSubtitleInfoParameters info)
+ {
+ if (TOKEN == "")
+ {
+ OSHConsole.WriteLine("Can't do this call, 'token' value not set. Please use Log In method first.", DebugCode.Error);
+ return new MethodResponseError("Fail", "Can't do this call, 'token' value not set. Please use Log In method first.");
+ }
+ // Method call ..
+ List<IXmlRpcValue> parms = new List<IXmlRpcValue>();
+ parms.Add(new XmlRpcValueBasic(TOKEN));
+ // Main struct
+ XmlRpcValueStruct s = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+
+ // Base info member as struct
+ XmlRpcStructMember member = new XmlRpcStructMember("baseinfo", null);
+ XmlRpcValueStruct memberStruct = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ memberStruct.Members.Add(new XmlRpcStructMember("idmovieimdb", new XmlRpcValueBasic(info.idmovieimdb)));
+ memberStruct.Members.Add(new XmlRpcStructMember("sublanguageid", new XmlRpcValueBasic(info.sublanguageid)));
+ memberStruct.Members.Add(new XmlRpcStructMember("moviereleasename", new XmlRpcValueBasic(info.moviereleasename)));
+ memberStruct.Members.Add(new XmlRpcStructMember("movieaka", new XmlRpcValueBasic(info.movieaka)));
+ memberStruct.Members.Add(new XmlRpcStructMember("subauthorcomment", new XmlRpcValueBasic(info.subauthorcomment)));
+ // memberStruct.Members.Add(new XmlRpcStructMember("hearingimpaired", new XmlRpcValueBasic(info.hearingimpaired)));
+ // memberStruct.Members.Add(new XmlRpcStructMember("highdefinition", new XmlRpcValueBasic(info.highdefinition)));
+ // memberStruct.Members.Add(new XmlRpcStructMember("automatictranslation", new XmlRpcValueBasic(info.automatictranslation)));
+ member.Data = memberStruct;
+ s.Members.Add(member);
+
+ // CDS members
+ int i = 1;
+ foreach (UploadSubtitleParameters cd in info.CDS)
+ {
+ XmlRpcStructMember member2 = new XmlRpcStructMember("cd" + i, null);
+ XmlRpcValueStruct memberStruct2 = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ memberStruct2.Members.Add(new XmlRpcStructMember("subhash", new XmlRpcValueBasic(cd.subhash)));
+ memberStruct2.Members.Add(new XmlRpcStructMember("subfilename", new XmlRpcValueBasic(cd.subfilename)));
+ memberStruct2.Members.Add(new XmlRpcStructMember("moviehash", new XmlRpcValueBasic(cd.moviehash)));
+ memberStruct2.Members.Add(new XmlRpcStructMember("moviebytesize", new XmlRpcValueBasic(cd.moviebytesize)));
+ memberStruct2.Members.Add(new XmlRpcStructMember("moviefps", new XmlRpcValueBasic(cd.moviefps)));
+ memberStruct2.Members.Add(new XmlRpcStructMember("movietimems", new XmlRpcValueBasic(cd.movietimems)));
+ memberStruct2.Members.Add(new XmlRpcStructMember("movieframes", new XmlRpcValueBasic(cd.movieframes)));
+ memberStruct2.Members.Add(new XmlRpcStructMember("moviefilename", new XmlRpcValueBasic(cd.moviefilename)));
+ memberStruct2.Members.Add(new XmlRpcStructMember("subcontent", new XmlRpcValueBasic(cd.subcontent)));
+ member2.Data = memberStruct2;
+ s.Members.Add(member2);
+ i++;
+ }
+
+ // add main struct to parameters
+ parms.Add(s);
+ // add user agent
+ //parms.Add(new XmlRpcValueBasic(XML_PRC_USERAGENT));
+ XmlRpcMethodCall call = new XmlRpcMethodCall("UploadSubtitles", parms);
+ OSHConsole.WriteLine("Sending UploadSubtitles request to the server ...", DebugCode.Good);
+ // Send the request to the server
+ string response = Utilities.GetStreamString(Utilities.SendRequest(XmlRpcGenerator.Generate(call), XML_PRC_USERAGENT));
+ if (!response.Contains("ERROR:"))
+ {
+ // No error occur, get and decode the response.
+ XmlRpcMethodCall[] calls = XmlRpcGenerator.DecodeMethodResponse(response);
+ if (calls.Length > 0)
+ {
+ if (calls[0].Parameters.Count > 0)
+ {
+ XmlRpcValueStruct mainStruct = (XmlRpcValueStruct)calls[0].Parameters[0];
+ // Create the response, we'll need it later
+ MethodResponseUploadSubtitles R = new MethodResponseUploadSubtitles();
+
+ // To make sure response is not currepted by server, do it in loop
+ foreach (XmlRpcStructMember MEMBER in mainStruct.Members)
+ {
+ switch (MEMBER.Name)
+ {
+ case "status": R.Status = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "seconds": R.Seconds = (double)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "data": R.Data = (string)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ case "subtitles": R.SubTitles = (bool)MEMBER.Data.Data; OSHConsole.WriteLine(">" + MEMBER.Name + "= " + MEMBER.Data.Data.ToString()); break;
+ }
+ }
+ // Return the response to user !!
+ return R;
+ }
+ }
+ }
+ else
+ {
+ OSHConsole.WriteLine(response, DebugCode.Error);
+ return new MethodResponseError("Fail", response);
+ }
+ return new MethodResponseError("Fail", "UploadSubtitles call failed !");
+ }
+ }
+}
diff --git a/OpenSubtitlesHandler/OpenSubtitlesHandler.csproj b/OpenSubtitlesHandler/OpenSubtitlesHandler.csproj
new file mode 100644
index 000000000..d1257d058
--- /dev/null
+++ b/OpenSubtitlesHandler/OpenSubtitlesHandler.csproj
@@ -0,0 +1,129 @@
+<?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>{4A4402D4-E910-443B-B8FC-2C18286A2CA0}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>OpenSubtitlesHandler</RootNamespace>
+ <AssemblyName>OpenSubtitlesHandler</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>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release Mono|AnyCPU' ">
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Release Mono</OutputPath>
+ <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="Console\OSHConsole.cs" />
+ <Compile Include="Interfaces\IMethodResponse.cs" />
+ <Compile Include="Interfaces\MethodResponseAttr.cs" />
+ <Compile Include="Languages\DetectLanguageResult.cs" />
+ <Compile Include="MethodResponses\MethodResponseAddComment.cs" />
+ <Compile Include="MethodResponses\MethodResponseAddRequest.cs" />
+ <Compile Include="MethodResponses\MethodResponseAutoUpdate.cs" />
+ <Compile Include="MethodResponses\MethodResponseCheckMovieHash.cs" />
+ <Compile Include="MethodResponses\MethodResponseCheckMovieHash2.cs" />
+ <Compile Include="MethodResponses\MethodResponseCheckSubHash.cs" />
+ <Compile Include="MethodResponses\MethodResponseDetectLanguage.cs" />
+ <Compile Include="MethodResponses\MethodResponseError.cs" />
+ <Compile Include="MethodResponses\MethodResponseGetAvailableTranslations.cs" />
+ <Compile Include="MethodResponses\MethodResponseGetComments.cs" />
+ <Compile Include="MethodResponses\MethodResponseGetSubLanguages.cs" />
+ <Compile Include="MethodResponses\MethodResponseGetTranslation.cs" />
+ <Compile Include="MethodResponses\MethodResponseInsertMovie.cs" />
+ <Compile Include="MethodResponses\MethodResponseInsertMovieHash.cs" />
+ <Compile Include="MethodResponses\MethodResponseLogIn.cs" />
+ <Compile Include="MethodResponses\MethodResponseMovieDetails.cs" />
+ <Compile Include="MethodResponses\MethodResponseMovieSearch.cs" />
+ <Compile Include="MethodResponses\MethodResponseNoOperation.cs" />
+ <Compile Include="MethodResponses\MethodResponseReportWrongImdbMovie.cs" />
+ <Compile Include="MethodResponses\MethodResponseReportWrongMovieHash.cs" />
+ <Compile Include="MethodResponses\MethodResponseSearchToMail.cs" />
+ <Compile Include="MethodResponses\MethodResponseServerInfo.cs" />
+ <Compile Include="MethodResponses\MethodResponseSubtitleDownload.cs" />
+ <Compile Include="MethodResponses\MethodResponseSubtitleSearch.cs" />
+ <Compile Include="MethodResponses\MethodResponseSubtitlesVote.cs" />
+ <Compile Include="MethodResponses\MethodResponseTryUploadSubtitles.cs" />
+ <Compile Include="MethodResponses\MethodResponseUploadSubtitles.cs" />
+ <Compile Include="MovieHasher.cs" />
+ <Compile Include="Movies\CheckMovieHash2Data.cs" />
+ <Compile Include="Movies\CheckMovieHash2Result.cs" />
+ <Compile Include="Movies\CheckMovieHashResult.cs" />
+ <Compile Include="Movies\InsertMovieHashParameters.cs" />
+ <Compile Include="Movies\MovieSearchResult.cs" />
+ <Compile Include="Movies\SearchToMailMovieParameter.cs" />
+ <Compile Include="OpenSubtitles.cs" />
+ <Compile Include="OtherTypes\GetAvailableTranslationsResult.cs" />
+ <Compile Include="OtherTypes\GetCommentsResult.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="SubtitleTypes\CheckSubHashResult.cs" />
+ <Compile Include="SubtitleTypes\SubtitleDownloadResult.cs" />
+ <Compile Include="SubtitleTypes\SubtitleLanguage.cs" />
+ <Compile Include="SubtitleTypes\SubtitleSearchParameters.cs" />
+ <Compile Include="SubtitleTypes\SubtitleSearchResult.cs" />
+ <Compile Include="SubtitleTypes\TryUploadSubtitlesParameters.cs" />
+ <Compile Include="SubtitleTypes\UploadSubtitleInfoParameter.cs" />
+ <Compile Include="SubtitleTypes\UploadSubtitleParameters.cs" />
+ <Compile Include="Utilities.cs" />
+ <Compile Include="XML-RPC\Enums\XmlRpcValueType.cs" />
+ <Compile Include="XML-RPC\Types\XmlRpcMethodCall.cs" />
+ <Compile Include="XML-RPC\Values\IXmlRpcValue.cs" />
+ <Compile Include="XML-RPC\Values\XmlRpcStructMember.cs" />
+ <Compile Include="XML-RPC\Values\XmlRpcValueArray.cs" />
+ <Compile Include="XML-RPC\Values\XmlRpcValueBasic.cs" />
+ <Compile Include="XML-RPC\Values\XmlRpcValueStruct.cs" />
+ <Compile Include="XML-RPC\XmlRpcGenerator.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.Model\MediaBrowser.Model.csproj">
+ <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
+ <Name>MediaBrowser.Model</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="XML-RPC\Docs\XML-RPC.txt" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition=" '$(ConfigurationName)' != 'Release Mono' " />
+ <!-- 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/OpenSubtitlesHandler/OtherTypes/GetAvailableTranslationsResult.cs b/OpenSubtitlesHandler/OtherTypes/GetAvailableTranslationsResult.cs
new file mode 100644
index 000000000..ae6317b4d
--- /dev/null
+++ b/OpenSubtitlesHandler/OtherTypes/GetAvailableTranslationsResult.cs
@@ -0,0 +1,39 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+namespace OpenSubtitlesHandler
+{
+ public struct GetAvailableTranslationsResult
+ {
+ private string _language;
+ private string _LastCreated;
+ private string _StringsNo;
+
+ public string LanguageID { get { return _language; } set { _language = value; } }
+ public string LastCreated { get { return _LastCreated; } set { _LastCreated = value; } }
+ public string StringsNo { get { return _StringsNo; } set { _StringsNo = value; } }
+ /// <summary>
+ /// LanguageID (LastCreated)
+ /// </summary>
+ /// <returns></returns>
+ public override string ToString()
+ {
+ return _language + " (" + _LastCreated + ")";
+ }
+ }
+}
diff --git a/OpenSubtitlesHandler/OtherTypes/GetCommentsResult.cs b/OpenSubtitlesHandler/OtherTypes/GetCommentsResult.cs
new file mode 100644
index 000000000..2eedd2538
--- /dev/null
+++ b/OpenSubtitlesHandler/OtherTypes/GetCommentsResult.cs
@@ -0,0 +1,37 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ public struct GetCommentsResult
+ {
+ private string _IDSubtitle;
+ private string _UserID;
+ private string _UserNickName;
+ private string _Comment;
+ private string _Created;
+
+ public string IDSubtitle { get { return _IDSubtitle; } set { _IDSubtitle = value; } }
+ public string UserID { get { return _UserID; } set { _UserID = value; } }
+ public string UserNickName { get { return _UserNickName; } set { _UserNickName = value; } }
+ public string Comment { get { return _Comment; } set { _Comment = value; } }
+ public string Created { get { return _Created; } set { _Created = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/Properties/AssemblyInfo.cs b/OpenSubtitlesHandler/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..9fad43d74
--- /dev/null
+++ b/OpenSubtitlesHandler/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+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("OpenSubtitlesHandler")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("OpenSubtitlesHandler")]
+[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("7c43bda2-2037-449d-8aac-9c0ccee8191f")]
+
+// 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.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSubtitlesHandler/Readme.txt b/OpenSubtitlesHandler/Readme.txt
new file mode 100644
index 000000000..42b4fdab3
--- /dev/null
+++ b/OpenSubtitlesHandler/Readme.txt
@@ -0,0 +1,20 @@
+OpenSubtitlesHandler
+====================
+This project is for OpenSubtitles.org integration‏. The point is to allow user to access OpenSubtitles.org database directly
+within ASM without the need to open internet browser.
+The plan: Implement the "OSDb protocol" http://trac.opensubtitles.org/projects/opensubtitles/wiki/OSDb
+
+Copyright:
+=========
+This library ann all its content are written by Ala Ibrahim Hadid.
+Copyright © Ala Ibrahim Hadid 2013
+mailto:ahdsoftwares@hotmail.com
+
+Resources:
+==========
+* GetHash.dll: this dll is used to compute hash for movie.
+ For more information please visit http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes#C2
+
+XML_RPC:
+========
+This class is created to generate XML-RPC requests as XML String. All you need is to call XML_RPC.Generate() method. \ No newline at end of file
diff --git a/OpenSubtitlesHandler/SubtitleTypes/CheckSubHashResult.cs b/OpenSubtitlesHandler/SubtitleTypes/CheckSubHashResult.cs
new file mode 100644
index 000000000..0e77601ba
--- /dev/null
+++ b/OpenSubtitlesHandler/SubtitleTypes/CheckSubHashResult.cs
@@ -0,0 +1,31 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ public struct CheckSubHashResult
+ {
+ private string _hash;
+ private string _id;
+
+ public string Hash { get { return _hash; } set { _hash = value; } }
+ public string SubID { get { return _id; } set { _id = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/SubtitleTypes/SubtitleDownloadResult.cs b/OpenSubtitlesHandler/SubtitleTypes/SubtitleDownloadResult.cs
new file mode 100644
index 000000000..35bf796e6
--- /dev/null
+++ b/OpenSubtitlesHandler/SubtitleTypes/SubtitleDownloadResult.cs
@@ -0,0 +1,44 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ public struct SubtitleDownloadResult
+ {
+ private string idsubtitlefile;
+ private string data;
+
+ public string IdSubtitleFile
+ { get { return idsubtitlefile; } set { idsubtitlefile = value; } }
+ /// <summary>
+ /// Get or set the data of subtitle file. To decode, decode the string to base64 and then decompress with GZIP.
+ /// </summary>
+ public string Data
+ { get { return data; } set { data = value; } }
+ /// <summary>
+ /// IdSubtitleFile
+ /// </summary>
+ /// <returns></returns>
+ public override string ToString()
+ {
+ return idsubtitlefile.ToString();
+ }
+ }
+}
diff --git a/OpenSubtitlesHandler/SubtitleTypes/SubtitleLanguage.cs b/OpenSubtitlesHandler/SubtitleTypes/SubtitleLanguage.cs
new file mode 100644
index 000000000..511c98670
--- /dev/null
+++ b/OpenSubtitlesHandler/SubtitleTypes/SubtitleLanguage.cs
@@ -0,0 +1,39 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+namespace OpenSubtitlesHandler
+{
+ public struct SubtitleLanguage
+ {
+ private string _SubLanguageID;
+ private string _LanguageName;
+ private string _ISO639;
+
+ public string SubLanguageID { get { return _SubLanguageID; } set { _SubLanguageID = value; } }
+ public string LanguageName { get { return _LanguageName; } set { _LanguageName = value; } }
+ public string ISO639 { get { return _ISO639; } set { _ISO639 = value; } }
+ /// <summary>
+ /// LanguageName [SubLanguageID]
+ /// </summary>
+ /// <returns>LanguageName [SubLanguageID]</returns>
+ public override string ToString()
+ {
+ return _LanguageName + " [" + _SubLanguageID + "]";
+ }
+ }
+}
diff --git a/OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchParameters.cs b/OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchParameters.cs
new file mode 100644
index 000000000..46af6215b
--- /dev/null
+++ b/OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchParameters.cs
@@ -0,0 +1,80 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ /// <summary>
+ /// Paramaters for subtitle search call
+ /// </summary>
+ public struct SubtitleSearchParameters
+ {
+ public SubtitleSearchParameters(string subLanguageId, string query = "", string season = "", string episode = "", string movieHash = "", long movieByteSize = 0, string imdbid = "")
+ {
+ this.subLanguageId = subLanguageId;
+ this.movieHash = movieHash;
+ this.movieByteSize = movieByteSize;
+ this.imdbid = imdbid;
+ this._episode = episode;
+ this._season = season;
+ this._query = query;
+ }
+
+ private string subLanguageId;
+ private string movieHash;
+ private long movieByteSize;
+ private string imdbid;
+ private string _query;
+ private string _episode;
+
+ public string Episode {
+ get { return _episode; }
+ set { _episode = value; }
+ }
+
+ public string Season {
+ get { return _season; }
+ set { _season = value; }
+ }
+
+ private string _season;
+
+ public string Query {
+ get { return _query; }
+ set { _query = value; }
+ }
+
+ /// <summary>
+ /// List of language ISO639-3 language codes to search for, divided by ',' (e.g. 'cze,eng,slo')
+ /// </summary>
+ public string SubLangaugeID { get { return subLanguageId; } set { subLanguageId = value; } }
+ /// <summary>
+ /// Video file hash as calculated by one of the implementation functions as seen on http://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes
+ /// </summary>
+ public string MovieHash { get { return movieHash; } set { movieHash = value; } }
+ /// <summary>
+ /// Size of video file in bytes
+ /// </summary>
+ public long MovieByteSize { get { return movieByteSize; } set { movieByteSize = value; } }
+ /// <summary>
+ /// ​IMDb ID of movie this video is part of, belongs to.
+ /// </summary>
+ public string IMDbID { get { return imdbid; } set { imdbid = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchResult.cs b/OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchResult.cs
new file mode 100644
index 000000000..a56a6edab
--- /dev/null
+++ b/OpenSubtitlesHandler/SubtitleTypes/SubtitleSearchResult.cs
@@ -0,0 +1,137 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ /// <summary>
+ /// The subtitle search result that comes with server response on SearchSubtitles successed call
+ /// </summary>
+ public struct SubtitleSearchResult
+ {
+ private string _IDSubMovieFile;
+ private string _MovieHash;
+ private string _MovieByteSize;
+ private string _MovieTimeMS;
+ private string _IDSubtitleFile;
+ private string _SubFileName;
+ private string _SubActualCD;
+ private string _SubSize;
+ private string _SubHash;
+ private string _IDSubtitle;
+ private string _UserID;
+ private string _SubLanguageID;
+ private string _SubFormat;
+ private string _SeriesSeason;
+ private string _SeriesEpisode;
+ private string _SubSumCD;
+ private string _SubAuthorComment;
+ private string _SubAddDate;
+ private string _SubBad;
+ private string _SubRating;
+ private string _SubDownloadsCnt;
+ private string _MovieReleaseName;
+ private string _IDMovie;
+ private string _IDMovieImdb;
+ private string _MovieName;
+ private string _MovieNameEng;
+ private string _MovieYear;
+ private string _MovieImdbRating;
+ private string _UserNickName;
+ private string _ISO639;
+ private string _LanguageName;
+ private string _SubDownloadLink;
+ private string _ZipDownloadLink;
+
+ public string IDSubMovieFile
+ { get { return _IDSubMovieFile; } set { _IDSubMovieFile = value; } }
+ public string MovieHash
+ { get { return _MovieHash; } set { _MovieHash = value; } }
+ public string MovieByteSize
+ { get { return _MovieByteSize; } set { _MovieByteSize = value; } }
+ public string MovieTimeMS
+ { get { return _MovieTimeMS; } set { _MovieTimeMS = value; } }
+ public string IDSubtitleFile
+ { get { return _IDSubtitleFile; } set { _IDSubtitleFile = value; } }
+ public string SubFileName
+ { get { return _SubFileName; } set { _SubFileName = value; } }
+ public string SubActualCD
+ { get { return _SubActualCD; } set { _SubActualCD = value; } }
+ public string SubSize
+ { get { return _SubSize; } set { _SubSize = value; } }
+ public string SubHash
+ { get { return _SubHash; } set { _SubHash = value; } }
+ public string IDSubtitle
+ { get { return _IDSubtitle; } set { _IDSubtitle = value; } }
+ public string UserID
+ { get { return _UserID; } set { _UserID = value; } }
+ public string SubLanguageID
+ { get { return _SubLanguageID; } set { _SubLanguageID = value; } }
+ public string SubFormat
+ { get { return _SubFormat; } set { _SubFormat = value; } }
+ public string SubSumCD
+ { get { return _SubSumCD; } set { _SubSumCD = value; } }
+ public string SubAuthorComment
+ { get { return _SubAuthorComment; } set { _SubAuthorComment = value; } }
+ public string SubAddDate
+ { get { return _SubAddDate; } set { _SubAddDate = value; } }
+ public string SubBad
+ { get { return _SubBad; } set { _SubBad = value; } }
+ public string SubRating
+ { get { return _SubRating; } set { _SubRating = value; } }
+ public string SubDownloadsCnt
+ { get { return _SubDownloadsCnt; } set { _SubDownloadsCnt = value; } }
+ public string MovieReleaseName
+ { get { return _MovieReleaseName; } set { _MovieReleaseName = value; } }
+ public string IDMovie
+ { get { return _IDMovie; } set { _IDMovie = value; } }
+ public string IDMovieImdb
+ { get { return _IDMovieImdb; } set { _IDMovieImdb = value; } }
+ public string MovieName
+ { get { return _MovieName; } set { _MovieName = value; } }
+ public string MovieNameEng
+ { get { return _MovieNameEng; } set { _MovieNameEng = value; } }
+ public string MovieYear
+ { get { return _MovieYear; } set { _MovieYear = value; } }
+ public string MovieImdbRating
+ { get { return _MovieImdbRating; } set { _MovieImdbRating = value; } }
+ public string UserNickName
+ { get { return _UserNickName; } set { _UserNickName = value; } }
+ public string ISO639
+ { get { return _ISO639; } set { _ISO639 = value; } }
+ public string LanguageName
+ { get { return _LanguageName; } set { _LanguageName = value; } }
+ public string SubDownloadLink
+ { get { return _SubDownloadLink; } set { _SubDownloadLink = value; } }
+ public string ZipDownloadLink
+ { get { return _ZipDownloadLink; } set { _ZipDownloadLink = value; } }
+ public string SeriesSeason
+ { get { return _SeriesSeason; } set { _SeriesSeason = value; } }
+ public string SeriesEpisode
+ { get { return _SeriesEpisode; } set { _SeriesEpisode = value; } }
+ /// <summary>
+ /// SubFileName + " (" + SubFormat + ")"
+ /// </summary>
+ /// <returns></returns>
+ public override string ToString()
+ {
+ return _SubFileName + " (" + _SubFormat + ")";
+ }
+ }
+}
diff --git a/OpenSubtitlesHandler/SubtitleTypes/TryUploadSubtitlesParameters.cs b/OpenSubtitlesHandler/SubtitleTypes/TryUploadSubtitlesParameters.cs
new file mode 100644
index 000000000..a95d151eb
--- /dev/null
+++ b/OpenSubtitlesHandler/SubtitleTypes/TryUploadSubtitlesParameters.cs
@@ -0,0 +1,48 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ public class TryUploadSubtitlesParameters
+ {
+ private string _subhash = "";
+ private string _subfilename = "";
+ private string _moviehash = "";
+ private string _moviebytesize = "";
+ private int _movietimems = 0;
+ private int _movieframes = 0;
+ private double _moviefps = 0;
+ private string _moviefilename = "";
+
+ public string subhash { get { return _subhash; } set { _subhash = value; } }
+ public string subfilename { get { return _subfilename; } set { _subfilename = value; } }
+ public string moviehash { get { return _moviehash; } set { _moviehash = value; } }
+ public string moviebytesize { get { return _moviebytesize; } set { _moviebytesize = value; } }
+ public int movietimems { get { return _movietimems; } set { _movietimems = value; } }
+ public int movieframes { get { return _movieframes; } set { _movieframes = value; } }
+ public double moviefps { get { return _moviefps; } set { _moviefps = value; } }
+ public string moviefilename { get { return _moviefilename; } set { _moviefilename = value; } }
+
+ public override string ToString()
+ {
+ return _subfilename + " (" + _subhash + ")";
+ }
+ }
+}
diff --git a/OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleInfoParameter.cs b/OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleInfoParameter.cs
new file mode 100644
index 000000000..8e147878b
--- /dev/null
+++ b/OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleInfoParameter.cs
@@ -0,0 +1,46 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace OpenSubtitlesHandler
+{
+ public class UploadSubtitleInfoParameters
+ {
+ private string _idmovieimdb;
+ private string _moviereleasename;
+ private string _movieaka;
+ private string _sublanguageid;
+ private string _subauthorcomment;
+ private bool _hearingimpaired;
+ private bool _highdefinition;
+ private bool _automatictranslation;
+ private List<UploadSubtitleParameters> cds;
+
+ public string idmovieimdb { get { return _idmovieimdb; } set { _idmovieimdb = value; } }
+ public string moviereleasename { get { return _moviereleasename; } set { _moviereleasename = value; } }
+ public string movieaka { get { return _movieaka; } set { _movieaka = value; } }
+ public string sublanguageid { get { return _sublanguageid; } set { _sublanguageid = value; } }
+ public string subauthorcomment { get { return _subauthorcomment; } set { _subauthorcomment = value; } }
+ public bool hearingimpaired { get { return _hearingimpaired; } set { _hearingimpaired = value; } }
+ public bool highdefinition { get { return _highdefinition; } set { _highdefinition = value; } }
+ public bool automatictranslation { get { return _automatictranslation; } set { _automatictranslation = value; } }
+ public List<UploadSubtitleParameters> CDS { get { return cds; } set { cds = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleParameters.cs b/OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleParameters.cs
new file mode 100644
index 000000000..90a273959
--- /dev/null
+++ b/OpenSubtitlesHandler/SubtitleTypes/UploadSubtitleParameters.cs
@@ -0,0 +1,53 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace OpenSubtitlesHandler
+{
+ public struct UploadSubtitleParameters
+ {
+ private string _subhash;
+ private string _subfilename;
+ private string _moviehash;
+ private double _moviebytesize;
+ private int _movietimems;
+ private int _movieframes;
+ private double _moviefps;
+ private string _moviefilename;
+ private string _subcontent;
+
+ public string subhash { get { return _subhash; } set { _subhash = value; } }
+ public string subfilename { get { return _subfilename; } set { _subfilename = value; } }
+ public string moviehash { get { return _moviehash; } set { _moviehash = value; } }
+ public double moviebytesize { get { return _moviebytesize; } set { _moviebytesize = value; } }
+ public int movietimems { get { return _movietimems; } set { _movietimems = value; } }
+ public int movieframes { get { return _movieframes; } set { _movieframes = value; } }
+ public double moviefps { get { return _moviefps; } set { _moviefps = value; } }
+ public string moviefilename { get { return _moviefilename; } set { _moviefilename = value; } }
+ /// <summary>
+ /// Sub content. Note: this value must be the subtitle file gziped and then base64 decoded.
+ /// </summary>
+ public string subcontent { get { return _subcontent; } set { _subcontent = value; } }
+
+ public override string ToString()
+ {
+ return _subfilename + " (" + _subhash + ")";
+ }
+ }
+}
diff --git a/OpenSubtitlesHandler/Utilities.cs b/OpenSubtitlesHandler/Utilities.cs
new file mode 100644
index 000000000..7f0f93009
--- /dev/null
+++ b/OpenSubtitlesHandler/Utilities.cs
@@ -0,0 +1,247 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.IO.Compression;
+using System.Net;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Net;
+
+namespace OpenSubtitlesHandler
+{
+ /// <summary>
+ /// Include helper methods. All member are statics.
+ /// </summary>
+ public sealed class Utilities
+ {
+ private const string XML_RPC_SERVER = "http://api.opensubtitles.org/xml-rpc";
+
+ /// <summary>
+ /// Compute movie hash
+ /// </summary>
+ /// <param name="fileName">The complete media file path</param>
+ /// <returns>The hash as Hexadecimal string</returns>
+ public static string ComputeHash(string fileName)
+ {
+ byte[] hash = MovieHasher.ComputeMovieHash(fileName);
+ return MovieHasher.ToHexadecimal(hash);
+ }
+ /// <summary>
+ /// Compute md5 for a file
+ /// </summary>
+ /// <param name="filename">The complete file path</param>
+ /// <returns>MD5 of the file</returns>
+ public static string ComputeMd5(string filename)
+ {
+ var md5 = MD5.Create();
+ var sb = new StringBuilder();
+ Stream str = new FileStream(filename, FileMode.Open, FileAccess.Read);
+
+ foreach (var b in md5.ComputeHash(str))
+ sb.Append(b.ToString("x2").ToLower());
+ str.Close();
+ return sb.ToString();
+ }
+ /// <summary>
+ /// Decompress data using GZip
+ /// </summary>
+ /// <param name="dataToDecompress">The stream that hold the data</param>
+ /// <returns>Bytes array of decompressed data</returns>
+ public static byte[] Decompress(Stream dataToDecompress)
+ {
+ MemoryStream target = new MemoryStream();
+
+ using (System.IO.Compression.GZipStream decompressionStream = new System.IO.Compression.GZipStream(dataToDecompress,
+ System.IO.Compression.CompressionMode.Decompress))
+ {
+ decompressionStream.CopyTo(target);
+ }
+ return target.GetBuffer();
+
+ }
+
+ /// <summary>
+ /// Compress data using GZip (the retunred buffer will be WITHOUT HEADER)
+ /// </summary>
+ /// <param name="dataToCompress">The stream that hold the data</param>
+ /// <returns>Bytes array of compressed data WITHOUT HEADER bytes</returns>
+ public static byte[] Compress(Stream dataToCompress)
+ {
+ /*using (var compressed = new MemoryStream())
+ {
+ using (var compressor = new System.IO.Compression.GZipStream(compressed,
+ System.IO.Compression.CompressionMode.Compress))
+ {
+ dataToCompress.CopyTo(compressor);
+ }
+ // Get the compressed bytes only after closing the GZipStream
+ return compressed.ToArray();
+ }*/
+ //using (var compressedOutput = new MemoryStream())
+ //{
+ // using (var compressedStream = new ZlibStream(compressedOutput,
+ // Ionic.Zlib.CompressionMode.Compress,
+ // CompressionLevel.Default, false))
+ // {
+ // var buffer = new byte[4096];
+ // int byteCount;
+ // do
+ // {
+ // byteCount = dataToCompress.Read(buffer, 0, buffer.Length);
+
+ // if (byteCount > 0)
+ // {
+ // compressedStream.Write(buffer, 0, byteCount);
+ // }
+ // } while (byteCount > 0);
+ // }
+ // return compressedOutput.ToArray();
+ //}
+
+ throw new NotImplementedException();
+ }
+
+ /// <summary>
+ /// Handle server response stream and decode it as given encoding string.
+ /// </summary>
+ /// <param name="responseStream">The response stream. Expects a stream that doesn't support seek.</param>
+ /// <param name="encoding">The encoding that should be used to decode buffer</param>
+ /// <returns>The string of the stream after decode using given encoding</returns>
+ public static string GetStreamString(Stream responseStream, Encoding encoding)
+ {
+ // Handle response, should be XML text.
+ List<byte> data = new List<byte>();
+ while (true)
+ {
+ int r = responseStream.ReadByte();
+ if (r < 0)
+ break;
+ data.Add((byte)r);
+ }
+ responseStream.Close();
+ return encoding.GetString(data.ToArray());
+ }
+ /// <summary>
+ /// Handle server response stream and decode it as ASCII encoding string.
+ /// </summary>
+ /// <param name="responseStream">The response stream. Expects a stream that doesn't support seek.</param>
+ /// <returns>The string of the stream after decode using ASCII encoding</returns>
+ public static string GetStreamString(Stream responseStream)
+ {
+ return GetStreamString(responseStream, Encoding.ASCII);
+ }
+
+ public static IHttpClient HttpClient { get; set; }
+
+ /// <summary>
+ /// Send a request to the server
+ /// </summary>
+ /// <param name="request">The request buffer to send as bytes array.</param>
+ /// <param name="userAgent">The user agent value.</param>
+ /// <returns>Response of the server or stream of error message as string started with 'ERROR:' keyword.</returns>
+ public static Stream SendRequest(byte[] request, string userAgent)
+ {
+ return SendRequestAsync(request, userAgent, CancellationToken.None).Result;
+
+ //HttpWebRequest req = (HttpWebRequest)WebRequest.Create(XML_RPC_SERVER);
+ //req.ContentType = "text/xml";
+ //req.Host = "api.opensubtitles.org:80";
+ //req.Method = "POST";
+ //req.UserAgent = "xmlrpc-epi-php/0.2 (PHP)";
+ //req.ContentLength = request.Length;
+ //ServicePointManager.Expect100Continue = false;
+ //try
+ //{
+ // using (Stream stm = req.GetRequestStream())
+ // {
+ // stm.Write(request, 0, request.Length);
+ // }
+
+ // WebResponse response = req.GetResponse();
+ // return response.GetResponseStream();
+ //}
+ //catch (Exception ex)
+ //{
+ // Stream errorStream = new MemoryStream();
+ // byte[] dd = Encoding.ASCII.GetBytes("ERROR: " + ex.Message);
+ // errorStream.Write(dd, 0, dd.Length);
+ // errorStream.Position = 0;
+ // return errorStream;
+ //}
+ }
+
+ public static async Task<Stream> SendRequestAsync(byte[] request, string userAgent, CancellationToken cancellationToken)
+ {
+ var options = new HttpRequestOptions
+ {
+ RequestContentBytes = request,
+ RequestContentType = "text/xml",
+ UserAgent = userAgent,
+ Host = "api.opensubtitles.org:80",
+ Url = XML_RPC_SERVER,
+
+ // Response parsing will fail with this enabled
+ EnableHttpCompression = false,
+
+ CancellationToken = cancellationToken
+ };
+
+ if (string.IsNullOrEmpty(options.UserAgent))
+ {
+ options.UserAgent = "xmlrpc-epi-php/0.2 (PHP)";
+ }
+
+ var result = await HttpClient.Post(options).ConfigureAwait(false);
+
+ return result.Content;
+
+ //HttpWebRequest req = (HttpWebRequest)WebRequest.Create(XML_RPC_SERVER);
+ //req.ContentType = "text/xml";
+ //req.Host = "api.opensubtitles.org:80";
+ //req.Method = "POST";
+ //req.UserAgent = "xmlrpc-epi-php/0.2 (PHP)";
+ //req.ContentLength = request.Length;
+ //ServicePointManager.Expect100Continue = false;
+ //try
+ //{
+ // using (Stream stm = req.GetRequestStream())
+ // {
+ // stm.Write(request, 0, request.Length);
+ // }
+
+ // WebResponse response = req.GetResponse();
+ // return response.GetResponseStream();
+ //}
+ //catch (Exception ex)
+ //{
+ // Stream errorStream = new MemoryStream();
+ // byte[] dd = Encoding.ASCII.GetBytes("ERROR: " + ex.Message);
+ // errorStream.Write(dd, 0, dd.Length);
+ // errorStream.Position = 0;
+ // return errorStream;
+ //}
+ }
+
+ }
+}
diff --git a/OpenSubtitlesHandler/XML-RPC/Docs/XML-RPC.txt b/OpenSubtitlesHandler/XML-RPC/Docs/XML-RPC.txt
new file mode 100644
index 000000000..8c84444a9
--- /dev/null
+++ b/OpenSubtitlesHandler/XML-RPC/Docs/XML-RPC.txt
@@ -0,0 +1,225 @@
+XML-RPC Specification
+
+Tue, Jun 15, 1999; by Dave Winer.
+
+Updated 6/30/03 DW
+
+Updated 10/16/99 DW
+
+Updated 1/21/99 DW
+
+This specification documents the XML-RPC protocol implemented in UserLand Frontier 5.1.
+
+For a non-technical explanation, see XML-RPC for Newbies.
+
+This page provides all the information that an implementor needs.
+
+Overview
+
+XML-RPC is a Remote Procedure Calling protocol that works over the Internet.
+
+An XML-RPC message is an HTTP-POST request. The body of the request is in XML. A procedure executes on the server and the value it returns is also formatted in XML.
+
+Procedure parameters can be scalars, numbers, strings, dates, etc.; and can also be complex record and list structures.
+
+Request example
+
+Here's an example of an XML-RPC request:
+
+POST /RPC2 HTTP/1.0
+User-Agent: Frontier/5.1.2 (WinNT)
+Host: betty.userland.com
+Content-Type: text/xml
+Content-length: 181
+
+<?xml version="1.0"?>
+ <methodCall>
+ <methodName>examples.getStateName</methodName>
+ <params>
+ <param>
+ <value>
+ <i4>41</i4>
+ </value>
+ </param>
+ </params>
+ </methodCall>
+
+Header requirements
+
+The format of the URI in the first line of the header is not specified. For example, it could be empty, a single slash, if the server is only handling XML-RPC calls. However, if the server is handling a mix of incoming HTTP requests, we allow the URI to help route the request to the code that handles XML-RPC requests. (In the example, the URI is /RPC2, telling the server to route the request to the "RPC2" responder.)
+
+A User-Agent and Host must be specified.
+
+The Content-Type is text/xml.
+
+The Content-Length must be specified and must be correct.
+
+Payload format
+
+The payload is in XML, a single <methodCall> structure.
+
+The <methodCall> must contain a <methodName> sub-item, a string, containing the name of the method to be called. The string may only contain identifier characters, upper and lower-case A-Z, the numeric characters, 0-9, underscore, dot, colon and slash. It's entirely up to the server to decide how to interpret the characters in a methodName.
+
+For example, the methodName could be the name of a file containing a script that executes on an incoming request. It could be the name of a cell in a database table. Or it could be a path to a file contained within a hierarchy of folders and files.
+
+If the procedure call has parameters, the <methodCall> must contain a <params> sub-item. The <params> sub-item can contain any number of <param>s, each of which has a <value>.
+
+Scalar <value>s
+
+<value>s can be scalars, type is indicated by nesting the value inside one of the tags listed in this table:
+
+Tag Type Example
+<i4> or <int> four-byte signed integer -12
+<boolean> 0 (false) or 1 (true) 1
+<string> string hello world
+<double> double-precision signed floating point number -12.214
+<dateTime.iso8601> date/time 19980717T14:08:55
+<base64> base64-encoded binary eW91IGNhbid0IHJlYWQgdGhpcyE=
+
+If no type is indicated, the type is string.
+
+<struct>s
+
+A value can also be of type <struct>.
+
+A <struct> contains <member>s and each <member> contains a <name> and a <value>.
+
+Here's an example of a two-element <struct>:
+
+<struct>
+ <member>
+ <name>lowerBound</name>
+ <value><i4>18</i4></value>
+ </member>
+ <member>
+ <name>upperBound</name>
+ <value><i4>139</i4></value>
+ </member>
+ </struct>
+
+<struct>s can be recursive, any <value> may contain a <struct> or any other type, including an <array>, described below.
+
+<array>s
+
+A value can also be of type <array>.
+
+An <array> contains a single <data> element, which can contain any number of <value>s.
+
+Here's an example of a four-element array:
+
+<array>
+ <data>
+ <value><i4>12</i4></value>
+ <value><string>Egypt</string></value>
+ <value><boolean>0</boolean></value>
+ <value><i4>-31</i4></value>
+ </data>
+ </array>
+
+<array> elements do not have names.
+
+You can mix types as the example above illustrates.
+
+<arrays>s can be recursive, any value may contain an <array> or any other type, including a <struct>, described above.
+
+Response example
+
+Here's an example of a response to an XML-RPC request:
+
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: 158
+Content-Type: text/xml
+Date: Fri, 17 Jul 1998 19:55:08 GMT
+Server: UserLand Frontier/5.1.2-WinNT
+
+<?xml version="1.0"?> <methodResponse> <params> <param> <value><string>South Dakota</string></value> </param> </params> </methodResponse>
+
+Response format
+
+Unless there's a lower-level error, always return 200 OK.
+
+The Content-Type is text/xml. Content-Length must be present and correct.
+
+The body of the response is a single XML structure, a <methodResponse>, which can contain a single <params> which contains a single <param> which contains a single <value>.
+
+The <methodResponse> could also contain a <fault> which contains a <value> which is a <struct> containing two elements, one named <faultCode>, an <int> and one named <faultString>, a <string>.
+
+A <methodResponse> can not contain both a <fault> and a <params>.
+
+Fault example
+
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: 426
+Content-Type: text/xml
+Date: Fri, 17 Jul 1998 19:55:02 GMT
+Server: UserLand Frontier/5.1.2-WinNT
+
+<?xml version="1.0"?> <methodResponse> <fault> <value> <struct> <member> <name>faultCode</name> <value><int>4</int></value> </member> <member> <name>faultString</name> <value><string>Too many parameters.</string></value> </member> </struct> </value> </fault> </methodResponse>
+
+Strategies/Goals
+
+Firewalls. The goal of this protocol is to lay a compatible foundation across different environments, no new power is provided beyond the capabilities of the CGI interface. Firewall software can watch for POSTs whose Content-Type is text/xml.
+
+Discoverability. We wanted a clean, extensible format that's very simple. It should be possible for an HTML coder to be able to look at a file containing an XML-RPC procedure call, understand what it's doing, and be able to modify it and have it work on the first or second try.
+
+Easy to implement. We also wanted it to be an easy to implement protocol that could quickly be adapted to run in other environments or on other operating systems.
+
+Updated 1/21/99 DW
+
+The following questions came up on the UserLand discussion group as XML-RPC was being implemented in Python.
+
+ The Response Format section says "The body of the response is a single XML structure, a <methodResponse>, which can contain a single <params>..." This is confusing. Can we leave out the <params>?
+
+ No you cannot leave it out if the procedure executed successfully. There are only two options, either a response contains a <params> structure or it contains a <fault> structure. That's why we used the word "can" in that sentence.
+
+ Is "boolean" a distinct data type, or can boolean values be interchanged with integers (e.g. zero=false, non-zero=true)?
+
+ Yes, boolean is a distinct data type. Some languages/environments allow for an easy coercion from zero to false and one to true, but if you mean true, send a boolean type with the value true, so your intent can't possibly be misunderstood.
+
+ What is the legal syntax (and range) for integers? How to deal with leading zeros? Is a leading plus sign allowed? How to deal with whitespace?
+
+ An integer is a 32-bit signed number. You can include a plus or minus at the beginning of a string of numeric characters. Leading zeros are collapsed. Whitespace is not permitted. Just numeric characters preceeded by a plus or minus.
+
+ What is the legal syntax (and range) for floating point values (doubles)? How is the exponent represented? How to deal with whitespace? Can infinity and "not a number" be represented?
+
+ There is no representation for infinity or negative infinity or "not a number". At this time, only decimal point notation is allowed, a plus or a minus, followed by any number of numeric characters, followed by a period and any number of numeric characters. Whitespace is not allowed. The range of allowable values is implementation-dependent, is not specified.
+
+ What characters are allowed in strings? Non-printable characters? Null characters? Can a "string" be used to hold an arbitrary chunk of binary data?
+
+ Any characters are allowed in a string except < and &, which are encoded as &lt; and &amp;. A string can be used to encode binary data.
+
+ Does the "struct" element keep the order of keys. Or in other words, is the struct "foo=1, bar=2" equivalent to "bar=2, foo=1" or not?
+
+ The struct element does not preserve the order of the keys. The two structs are equivalent.
+
+ Can the <fault> struct contain other members than <faultCode> and <faultString>? Is there a global list of faultCodes? (so they can be mapped to distinct exceptions for languages like Python and Java)?
+
+ A <fault> struct may not contain members other than those specified. This is true for all other structures. We believe the specification is flexible enough so that all reasonable data-transfer needs can be accomodated within the specified structures. If you believe strongly that this is not true, please post a message on the discussion group.
+
+ There is no global list of fault codes. It is up to the server implementer, or higher-level standards to specify fault codes.
+
+ What timezone should be assumed for the dateTime.iso8601 type? UTC? localtime?
+
+ Don't assume a timezone. It should be specified by the server in its documentation what assumptions it makes about timezones.
+
+Additions
+
+ <base64> type. 1/21/99 DW.
+
+Updated 6/30/03 DW
+
+Removed "ASCII" from definition of string.
+
+Changed copyright dates, below, to 1999-2003 from 1998-99.
+
+Copyright and disclaimer
+
+© Copyright 1998-2003 UserLand Software. All Rights Reserved.
+
+This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and these paragraphs are included on all such copies and derivative works.
+
+This document may not be modified in any way, such as by removing the copyright notice or references to UserLand or other organizations. Further, while these copyright restrictions apply to the written XML-RPC specification, no claim of ownership is made by UserLand to the protocol it describes. Any party may, for commercial or non-commercial purposes, implement this protocol without royalty or license fee to UserLand. The limited permissions granted herein are perpetual and will not be revoked by UserLand or its successors or assigns.
+
+This document and the information contained herein is provided on an "AS IS" basis and USERLAND DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. \ No newline at end of file
diff --git a/OpenSubtitlesHandler/XML-RPC/Enums/XmlRpcValueType.cs b/OpenSubtitlesHandler/XML-RPC/Enums/XmlRpcValueType.cs
new file mode 100644
index 000000000..ef0c203ff
--- /dev/null
+++ b/OpenSubtitlesHandler/XML-RPC/Enums/XmlRpcValueType.cs
@@ -0,0 +1,25 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+namespace XmlRpcHandler
+{
+ public enum XmlRpcBasicValueType
+ {
+ String, Int, Boolean, Double, dateTime_iso8601, base64
+ }
+}
diff --git a/OpenSubtitlesHandler/XML-RPC/Types/XmlRpcMethodCall.cs b/OpenSubtitlesHandler/XML-RPC/Types/XmlRpcMethodCall.cs
new file mode 100644
index 000000000..1ec3622b2
--- /dev/null
+++ b/OpenSubtitlesHandler/XML-RPC/Types/XmlRpcMethodCall.cs
@@ -0,0 +1,63 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace XmlRpcHandler
+{
+ /// <summary>
+ /// A method call
+ /// </summary>
+ public struct XmlRpcMethodCall
+ {
+ /// <summary>
+ /// A method call
+ /// </summary>
+ /// <param name="name">The name of this method</param>
+ public XmlRpcMethodCall(string name)
+ {
+ this.name = name;
+ this.parameters = new List<IXmlRpcValue>();
+ }
+ /// <summary>
+ /// A method call
+ /// </summary>
+ /// <param name="name">The name of this method</param>
+ /// <param name="parameters">A list of parameters</param>
+ public XmlRpcMethodCall(string name, List<IXmlRpcValue> parameters)
+ {
+ this.name = name;
+ this.parameters = parameters;
+ }
+
+ private string name;
+ private List<IXmlRpcValue> parameters;
+
+ /// <summary>
+ /// Get or set the name of this method
+ /// </summary>
+ public string Name
+ { get { return name; } set { name = value; } }
+ /// <summary>
+ /// Get or set the parameters to be sent
+ /// </summary>
+ public List<IXmlRpcValue> Parameters
+ { get { return parameters; } set { parameters = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/XML-RPC/Values/IXmlRpcValue.cs b/OpenSubtitlesHandler/XML-RPC/Values/IXmlRpcValue.cs
new file mode 100644
index 000000000..19bc60347
--- /dev/null
+++ b/OpenSubtitlesHandler/XML-RPC/Values/IXmlRpcValue.cs
@@ -0,0 +1,37 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace XmlRpcHandler
+{
+ public abstract class IXmlRpcValue
+ {
+ public IXmlRpcValue()
+ { }
+ public IXmlRpcValue(object data)
+ {
+ this.data = data;
+ }
+ private object data;
+ /// <summary>
+ /// Get or set the data of this value
+ /// </summary>
+ public virtual object Data { get { return data; } set { data = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcStructMember.cs b/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcStructMember.cs
new file mode 100644
index 000000000..12c86fdbf
--- /dev/null
+++ b/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcStructMember.cs
@@ -0,0 +1,44 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+
+namespace XmlRpcHandler
+{
+ public class XmlRpcStructMember
+ {
+ public XmlRpcStructMember(string name, IXmlRpcValue data)
+ {
+ this.name = name;
+ this.data = data;
+ }
+ private string name;
+ private IXmlRpcValue data;
+
+ /// <summary>
+ /// Get or set the name of this member
+ /// </summary>
+ public string Name
+ { get { return name; } set { name = value; } }
+ /// <summary>
+ /// Get or set the data of this member
+ /// </summary>
+ public IXmlRpcValue Data
+ { get { return data; } set { data = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueArray.cs b/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueArray.cs
new file mode 100644
index 000000000..8fd8b5ca0
--- /dev/null
+++ b/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueArray.cs
@@ -0,0 +1,121 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace XmlRpcHandler
+{
+ public class XmlRpcValueArray : IXmlRpcValue
+ {
+ public XmlRpcValueArray() :
+ base()
+ {
+ values = new List<IXmlRpcValue>();
+ }
+ public XmlRpcValueArray(object data) :
+ base(data)
+ {
+ values = new List<IXmlRpcValue>();
+ }
+ public XmlRpcValueArray(string[] texts) :
+ base()
+ {
+ values = new List<IXmlRpcValue>();
+ foreach (string val in texts)
+ {
+ values.Add(new XmlRpcValueBasic(val));
+ }
+ }
+ public XmlRpcValueArray(int[] ints) :
+ base()
+ {
+ values = new List<IXmlRpcValue>();
+ foreach (int val in ints)
+ {
+ values.Add(new XmlRpcValueBasic(val));
+ }
+ }
+ public XmlRpcValueArray(double[] doubles) :
+ base()
+ {
+ values = new List<IXmlRpcValue>();
+ foreach (double val in doubles)
+ {
+ values.Add(new XmlRpcValueBasic(val));
+ }
+ }
+ public XmlRpcValueArray(bool[] bools) :
+ base()
+ {
+ values = new List<IXmlRpcValue>();
+ foreach (bool val in bools)
+ {
+ values.Add(new XmlRpcValueBasic(val));
+ }
+ }
+ public XmlRpcValueArray(long[] base24s) :
+ base()
+ {
+ values = new List<IXmlRpcValue>();
+ foreach (long val in base24s)
+ {
+ values.Add(new XmlRpcValueBasic(val));
+ }
+ }
+ public XmlRpcValueArray(DateTime[] dates) :
+ base()
+ {
+ values = new List<IXmlRpcValue>();
+ foreach (DateTime val in dates)
+ {
+ values.Add(new XmlRpcValueBasic(val));
+ }
+ }
+ public XmlRpcValueArray(XmlRpcValueBasic[] basicValues) :
+ base()
+ {
+ values = new List<IXmlRpcValue>();
+ foreach (XmlRpcValueBasic val in basicValues)
+ {
+ values.Add(val);
+ }
+ }
+ public XmlRpcValueArray(XmlRpcValueStruct[] structs) :
+ base()
+ {
+ values = new List<IXmlRpcValue>();
+ foreach (XmlRpcValueStruct val in structs)
+ {
+ values.Add(val);
+ }
+ }
+ public XmlRpcValueArray(XmlRpcValueArray[] arrays) :
+ base()
+ {
+ values = new List<IXmlRpcValue>();
+ foreach (XmlRpcValueArray val in arrays)
+ {
+ values.Add(val);
+ }
+ }
+ private List<IXmlRpcValue> values;
+
+ public List<IXmlRpcValue> Values { get { return values; } set { values = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueBasic.cs b/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueBasic.cs
new file mode 100644
index 000000000..2827283ff
--- /dev/null
+++ b/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueBasic.cs
@@ -0,0 +1,100 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace XmlRpcHandler
+{
+ public class XmlRpcValueBasic : IXmlRpcValue
+ {
+ public XmlRpcValueBasic()
+ : base()
+ { }
+ public XmlRpcValueBasic(string data)
+ : base(data)
+ { this.type = XmlRpcBasicValueType.String; }
+ public XmlRpcValueBasic(int data)
+ : base(data)
+ { this.type = XmlRpcBasicValueType.Int; }
+ public XmlRpcValueBasic(double data)
+ : base(data)
+ { this.type = XmlRpcBasicValueType.Double; }
+ public XmlRpcValueBasic(DateTime data)
+ : base(data)
+ { this.type = XmlRpcBasicValueType.dateTime_iso8601; }
+ public XmlRpcValueBasic(bool data)
+ : base(data)
+ { this.type = XmlRpcBasicValueType.Boolean; }
+ public XmlRpcValueBasic(long data)
+ : base(data)
+ { this.type = XmlRpcBasicValueType.base64; }
+ public XmlRpcValueBasic(object data, XmlRpcBasicValueType type)
+ : base(data)
+ { this.type = type; }
+
+ private XmlRpcBasicValueType type = XmlRpcBasicValueType.String;
+ /// <summary>
+ /// Get or set the type of this basic value
+ /// </summary>
+ public XmlRpcBasicValueType ValueType { get { return type; } set { type = value; } }
+ /*Oprators. help a lot.*/
+ public static implicit operator string(XmlRpcValueBasic f)
+ {
+ if (f.type == XmlRpcBasicValueType.String)
+ return f.Data.ToString();
+ else
+ throw new Exception("Unable to convert, this value is not string type.");
+ }
+ public static implicit operator int(XmlRpcValueBasic f)
+ {
+ if (f.type == XmlRpcBasicValueType.String)
+ return (int)f.Data;
+ else
+ throw new Exception("Unable to convert, this value is not int type.");
+ }
+ public static implicit operator double(XmlRpcValueBasic f)
+ {
+ if (f.type == XmlRpcBasicValueType.String)
+ return (double)f.Data;
+ else
+ throw new Exception("Unable to convert, this value is not double type.");
+ }
+ public static implicit operator bool(XmlRpcValueBasic f)
+ {
+ if (f.type == XmlRpcBasicValueType.String)
+ return (bool)f.Data;
+ else
+ throw new Exception("Unable to convert, this value is not bool type.");
+ }
+ public static implicit operator long(XmlRpcValueBasic f)
+ {
+ if (f.type == XmlRpcBasicValueType.String)
+ return (long)f.Data;
+ else
+ throw new Exception("Unable to convert, this value is not long type.");
+ }
+ public static implicit operator DateTime(XmlRpcValueBasic f)
+ {
+ if (f.type == XmlRpcBasicValueType.String)
+ return (DateTime)f.Data;
+ else
+ throw new Exception("Unable to convert, this value is not DateTime type.");
+ }
+ }
+}
diff --git a/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueStruct.cs b/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueStruct.cs
new file mode 100644
index 000000000..9e4cf6056
--- /dev/null
+++ b/OpenSubtitlesHandler/XML-RPC/Values/XmlRpcValueStruct.cs
@@ -0,0 +1,43 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Collections.Generic;
+
+namespace XmlRpcHandler
+{
+ /// <summary>
+ /// Represents XML-RPC struct
+ /// </summary>
+ public class XmlRpcValueStruct : IXmlRpcValue
+ {
+ /// <summary>
+ /// Represents XML-RPC struct
+ /// </summary>
+ /// <param name="members"></param>
+ public XmlRpcValueStruct(List<XmlRpcStructMember> members)
+ { this.members = members; }
+
+ private List<XmlRpcStructMember> members;
+ /// <summary>
+ /// Get or set the members collection
+ /// </summary>
+ public List<XmlRpcStructMember> Members
+ { get { return members; } set { members = value; } }
+ }
+}
diff --git a/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs b/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs
new file mode 100644
index 000000000..028b734dc
--- /dev/null
+++ b/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs
@@ -0,0 +1,323 @@
+/* This file is part of OpenSubtitles Handler
+ A library that handle OpenSubtitles.org XML-RPC methods.
+
+ Copyright © Ala Ibrahim Hadid 2013
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+using System;
+using System.Text;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+namespace XmlRpcHandler
+{
+ /// <summary>
+ /// A class for making XML-RPC requests. The requests then can be sent directly as http request.
+ /// </summary>
+ public class XmlRpcGenerator
+ {
+ /// <summary>
+ /// Generate XML-RPC request using method call.
+ /// </summary>
+ /// <param name="method">The method call</param>
+ /// <returns>The request in xml.</returns>
+ public static byte[] Generate(XmlRpcMethodCall method)
+ { return Generate(new XmlRpcMethodCall[] { method }); }
+ /// <summary>
+ /// Generate XML-RPC request using method calls array.
+ /// </summary>
+ /// <param name="methods">The method calls array</param>
+ /// <returns>The request in utf8 xml string as buffer</returns>
+ public static byte[] Generate(XmlRpcMethodCall[] methods)
+ {
+ if (methods == null)
+ throw new Exception("No method to write !");
+ if (methods.Length == 0)
+ throw new Exception("No method to write !");
+ // Create xml
+ XmlWriterSettings sett = new XmlWriterSettings();
+ sett.Indent = true;
+
+ sett.Encoding = Encoding.UTF8;
+ FileStream str = new FileStream(Path.GetTempPath() + "\\request.xml", FileMode.Create, FileAccess.Write);
+
+ XmlWriter XMLwrt = XmlWriter.Create(str, sett);
+ // Let's write the methods
+ foreach (XmlRpcMethodCall method in methods)
+ {
+ XMLwrt.WriteStartElement("methodCall");//methodCall
+ XMLwrt.WriteStartElement("methodName");//methodName
+ XMLwrt.WriteString(method.Name);
+ XMLwrt.WriteEndElement();//methodName
+ XMLwrt.WriteStartElement("params");//params
+ // Write values
+ foreach (IXmlRpcValue p in method.Parameters)
+ {
+ XMLwrt.WriteStartElement("param");//param
+ if (p is XmlRpcValueBasic)
+ {
+ WriteBasicValue(XMLwrt, (XmlRpcValueBasic)p);
+ }
+ else if (p is XmlRpcValueStruct)
+ {
+ WriteStructValue(XMLwrt, (XmlRpcValueStruct)p);
+ }
+ else if (p is XmlRpcValueArray)
+ {
+ WriteArrayValue(XMLwrt, (XmlRpcValueArray)p);
+ }
+ XMLwrt.WriteEndElement();//param
+ }
+
+ XMLwrt.WriteEndElement();//params
+ XMLwrt.WriteEndElement();//methodCall
+ }
+ XMLwrt.Flush();
+ XMLwrt.Close();
+ str.Close();
+ string requestContent = File.ReadAllText(Path.GetTempPath() + "\\request.xml");
+ return Encoding.UTF8.GetBytes(requestContent);
+ }
+ /// <summary>
+ /// Decode response then return the values
+ /// </summary>
+ /// <param name="xmlResponse">The response xml string as provided by server as methodResponse</param>
+ /// <returns></returns>
+ public static XmlRpcMethodCall[] DecodeMethodResponse(string xmlResponse)
+ {
+ List<XmlRpcMethodCall> methods = new List<XmlRpcMethodCall>();
+ XmlReaderSettings sett = new XmlReaderSettings();
+ sett.DtdProcessing = DtdProcessing.Ignore;
+ sett.IgnoreWhitespace = true;
+ MemoryStream str = new MemoryStream(Encoding.ASCII.GetBytes(xmlResponse));
+ if (xmlResponse.Contains(@"encoding=""utf-8"""))
+ {
+ str = new MemoryStream(Encoding.UTF8.GetBytes(xmlResponse));
+ }
+ XmlReader XMLread = XmlReader.Create(str, sett);
+
+ XmlRpcMethodCall call = new XmlRpcMethodCall("methodResponse");
+ // Read parameters
+ while (XMLread.Read())
+ {
+ if (XMLread.Name == "param" && XMLread.IsStartElement())
+ {
+ IXmlRpcValue val = ReadValue(XMLread);
+ if (val != null)
+ call.Parameters.Add(val);
+ }
+ }
+ methods.Add(call);
+ XMLread.Close();
+ return methods.ToArray();
+ }
+
+ private static void WriteBasicValue(XmlWriter XMLwrt, XmlRpcValueBasic val)
+ {
+ XMLwrt.WriteStartElement("value");//value
+ switch (val.ValueType)
+ {
+ case XmlRpcBasicValueType.String:
+ XMLwrt.WriteStartElement("string");
+ if (val.Data != null)
+ XMLwrt.WriteString(val.Data.ToString());
+ XMLwrt.WriteEndElement();
+ break;
+ case XmlRpcBasicValueType.Int:
+ XMLwrt.WriteStartElement("int");
+ if (val.Data != null)
+ XMLwrt.WriteString(val.Data.ToString());
+ XMLwrt.WriteEndElement();
+ break;
+ case XmlRpcBasicValueType.Boolean:
+ XMLwrt.WriteStartElement("boolean");
+ if (val.Data != null)
+ XMLwrt.WriteString(((bool)val.Data) ? "1" : "0");
+ XMLwrt.WriteEndElement();
+ break;
+ case XmlRpcBasicValueType.Double:
+ XMLwrt.WriteStartElement("double");
+ if (val.Data != null)
+ XMLwrt.WriteString(val.Data.ToString());
+ XMLwrt.WriteEndElement();
+ break;
+ case XmlRpcBasicValueType.dateTime_iso8601:
+ XMLwrt.WriteStartElement("dateTime.iso8601");
+ // Get date time format
+ if (val.Data != null)
+ {
+ DateTime time = (DateTime)val.Data;
+ string dt = time.Year + time.Month.ToString("D2") + time.Day.ToString("D2") +
+ "T" + time.Hour.ToString("D2") + ":" + time.Minute.ToString("D2") + ":" +
+ time.Second.ToString("D2");
+ XMLwrt.WriteString(dt);
+ }
+ XMLwrt.WriteEndElement();
+ break;
+ case XmlRpcBasicValueType.base64:
+ XMLwrt.WriteStartElement("base64");
+ if (val.Data != null)
+ XMLwrt.WriteString(Convert.ToBase64String(BitConverter.GetBytes((long)val.Data)));
+ XMLwrt.WriteEndElement();
+ break;
+ }
+ XMLwrt.WriteEndElement();//value
+ }
+ private static void WriteStructValue(XmlWriter XMLwrt, XmlRpcValueStruct val)
+ {
+ XMLwrt.WriteStartElement("value");//value
+ XMLwrt.WriteStartElement("struct");//struct
+ foreach (XmlRpcStructMember member in val.Members)
+ {
+ XMLwrt.WriteStartElement("member");//member
+
+ XMLwrt.WriteStartElement("name");//name
+ XMLwrt.WriteString(member.Name);
+ XMLwrt.WriteEndElement();//name
+
+ if (member.Data is XmlRpcValueBasic)
+ {
+ WriteBasicValue(XMLwrt, (XmlRpcValueBasic)member.Data);
+ }
+ else if (member.Data is XmlRpcValueStruct)
+ {
+ WriteStructValue(XMLwrt, (XmlRpcValueStruct)member.Data);
+ }
+ else if (member.Data is XmlRpcValueArray)
+ {
+ WriteArrayValue(XMLwrt, (XmlRpcValueArray)member.Data);
+ }
+
+ XMLwrt.WriteEndElement();//member
+ }
+ XMLwrt.WriteEndElement();//struct
+ XMLwrt.WriteEndElement();//value
+ }
+ private static void WriteArrayValue(XmlWriter XMLwrt, XmlRpcValueArray val)
+ {
+ XMLwrt.WriteStartElement("value");//value
+ XMLwrt.WriteStartElement("array");//array
+ XMLwrt.WriteStartElement("data");//data
+ foreach (IXmlRpcValue o in val.Values)
+ {
+ if (o is XmlRpcValueBasic)
+ {
+ WriteBasicValue(XMLwrt, (XmlRpcValueBasic)o);
+ }
+ else if (o is XmlRpcValueStruct)
+ {
+ WriteStructValue(XMLwrt, (XmlRpcValueStruct)o);
+ }
+ else if (o is XmlRpcValueArray)
+ {
+ WriteArrayValue(XMLwrt, (XmlRpcValueArray)o);
+ }
+ }
+ XMLwrt.WriteEndElement();//data
+ XMLwrt.WriteEndElement();//array
+ XMLwrt.WriteEndElement();//value
+ }
+ private static IXmlRpcValue ReadValue(XmlReader xmlReader)
+ {
+ while (xmlReader.Read())
+ {
+ if (xmlReader.Name == "value" && xmlReader.IsStartElement())
+ {
+ xmlReader.Read();
+ if (xmlReader.Name == "string" && xmlReader.IsStartElement())
+ {
+ return new XmlRpcValueBasic(xmlReader.ReadString(), XmlRpcBasicValueType.String);
+ }
+ else if (xmlReader.Name == "int" && xmlReader.IsStartElement())
+ {
+ return new XmlRpcValueBasic(int.Parse(xmlReader.ReadString()), XmlRpcBasicValueType.Int);
+ }
+ else if (xmlReader.Name == "boolean" && xmlReader.IsStartElement())
+ {
+ return new XmlRpcValueBasic(xmlReader.ReadString() == "1", XmlRpcBasicValueType.Boolean);
+ }
+ else if (xmlReader.Name == "double" && xmlReader.IsStartElement())
+ {
+ return new XmlRpcValueBasic(double.Parse(xmlReader.ReadString()), XmlRpcBasicValueType.Double);
+ }
+ else if (xmlReader.Name == "dateTime.iso8601" && xmlReader.IsStartElement())
+ {
+ string date = xmlReader.ReadString();
+ int year = int.Parse(date.Substring(0, 4));
+ int month = int.Parse(date.Substring(4, 2));
+ int day = int.Parse(date.Substring(6, 2));
+ int hour = int.Parse(date.Substring(9, 2));
+ int minute = int.Parse(date.Substring(12, 2));//19980717T14:08:55
+ int sec = int.Parse(date.Substring(15, 2));
+ DateTime time = new DateTime(year, month, day, hour, minute, sec);
+ return new XmlRpcValueBasic(time, XmlRpcBasicValueType.dateTime_iso8601);
+ }
+ else if (xmlReader.Name == "base64" && xmlReader.IsStartElement())
+ {
+ return new XmlRpcValueBasic(BitConverter.ToInt64(Convert.FromBase64String(xmlReader.ReadString()), 0)
+ , XmlRpcBasicValueType.Double);
+ }
+ else if (xmlReader.Name == "struct" && xmlReader.IsStartElement())
+ {
+ XmlRpcValueStruct strct = new XmlRpcValueStruct(new List<XmlRpcStructMember>());
+ // Read members...
+ while (xmlReader.Read())
+ {
+ if (xmlReader.Name == "member" && xmlReader.IsStartElement())
+ {
+ XmlRpcStructMember member = new XmlRpcStructMember("", null);
+ xmlReader.Read();// read name
+ member.Name = xmlReader.ReadString();
+
+ IXmlRpcValue val = ReadValue(xmlReader);
+ if (val != null)
+ {
+ member.Data = val;
+ strct.Members.Add(member);
+ }
+ }
+ else if (xmlReader.Name == "struct" && !xmlReader.IsStartElement())
+ {
+ return strct;
+ }
+ }
+ return strct;
+ }
+ else if (xmlReader.Name == "array" && xmlReader.IsStartElement())
+ {
+ XmlRpcValueArray array = new XmlRpcValueArray();
+ // Read members...
+ while (xmlReader.Read())
+ {
+ if (xmlReader.Name == "array" && !xmlReader.IsStartElement())
+ {
+ return array;
+ }
+ else
+ {
+ IXmlRpcValue val = ReadValue(xmlReader);
+ if (val != null)
+ array.Values.Add(val);
+ }
+ }
+ return array;
+ }
+ }
+ else break;
+ }
+ return null;
+ }
+ }
+}
diff --git a/README.md b/README.md
index 8f9902e85..cbee1282b 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ We have several client apps released and in production:
## New Users ##
-If you're a new user looking to install Media Browser Server, please head over to [mediabrowser3.com](http://www.mediabrowser3.com/ "mediabrowser3.com")
+If you're a new user looking to install Media Browser Server, please head over to [mediabrowser.tv](http://www.mediabrowser.tv/ "mediabrowser.tv")
## Developer Info ##