aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Api/ApiEntryPoint.cs23
-rw-r--r--MediaBrowser.Api/ConfigurationService.cs2
-rw-r--r--MediaBrowser.Api/IHasDtoOptions.cs12
-rw-r--r--MediaBrowser.Api/Images/ImageService.cs13
-rw-r--r--MediaBrowser.Api/ItemUpdateService.cs160
-rw-r--r--MediaBrowser.Api/Library/LibraryService.cs45
-rw-r--r--MediaBrowser.Api/LiveTv/LiveTvService.cs2
-rw-r--r--MediaBrowser.Api/Movies/CollectionService.cs5
-rw-r--r--MediaBrowser.Api/Movies/MoviesService.cs28
-rw-r--r--MediaBrowser.Api/NotificationsService.cs2
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs89
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs29
-rw-r--r--MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs22
-rw-r--r--MediaBrowser.Api/Playback/Hls/MpegDashService.cs18
-rw-r--r--MediaBrowser.Api/Playback/Hls/VideoHlsService.cs17
-rw-r--r--MediaBrowser.Api/Playback/Progressive/AudioService.cs2
-rw-r--r--MediaBrowser.Api/Playback/Progressive/VideoService.cs14
-rw-r--r--MediaBrowser.Api/Playback/StreamState.cs1
-rw-r--r--MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs1
-rw-r--r--MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs1
-rw-r--r--MediaBrowser.Api/Session/SessionsService.cs4
-rw-r--r--MediaBrowser.Api/Subtitles/SubtitleService.cs7
-rw-r--r--MediaBrowser.Api/Sync/SyncService.cs64
-rw-r--r--MediaBrowser.Api/System/ActivityLogWebSocketListener.cs4
-rw-r--r--MediaBrowser.Api/System/SystemInfoWebSocketListener.cs1
-rw-r--r--MediaBrowser.Api/UserLibrary/ArtistsService.cs9
-rw-r--r--MediaBrowser.Api/UserLibrary/GameGenresService.cs7
-rw-r--r--MediaBrowser.Api/UserLibrary/GenresService.cs7
-rw-r--r--MediaBrowser.Api/UserLibrary/MusicGenresService.cs7
-rw-r--r--MediaBrowser.Api/UserLibrary/PersonsService.cs7
-rw-r--r--MediaBrowser.Api/UserLibrary/StudiosService.cs7
-rw-r--r--MediaBrowser.Api/UserLibrary/UserLibraryService.cs45
-rw-r--r--MediaBrowser.Api/UserLibrary/YearsService.cs7
-rw-r--r--MediaBrowser.Api/UserService.cs115
-rw-r--r--MediaBrowser.Api/VideosService.cs16
-rw-r--r--MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs51
-rw-r--r--MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs (renamed from MediaBrowser.Common/Configuration/ConfigurationHelper.cs)17
-rw-r--r--MediaBrowser.Common.Implementations/Devices/DeviceId.cs5
-rw-r--r--MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj1
-rw-r--r--MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs4
-rw-r--r--MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs17
-rw-r--r--MediaBrowser.Common/Configuration/IConfigurationFactory.cs5
-rw-r--r--MediaBrowser.Common/Extensions/BaseExtensions.cs11
-rw-r--r--MediaBrowser.Common/MediaBrowser.Common.csproj8
-rw-r--r--MediaBrowser.Common/Plugins/BasePlugin.cs43
-rw-r--r--MediaBrowser.Controller/Channels/Channel.cs2
-rw-r--r--MediaBrowser.Controller/Channels/ChannelAudioItem.cs5
-rw-r--r--MediaBrowser.Controller/Channels/ChannelFolderItem.cs3
-rw-r--r--MediaBrowser.Controller/Channels/ChannelVideoItem.cs3
-rw-r--r--MediaBrowser.Controller/Entities/Audio/Audio.cs3
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs3
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs37
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs13
-rw-r--r--MediaBrowser.Controller/Entities/Book.cs3
-rw-r--r--MediaBrowser.Controller/Entities/CollectionFolder.cs16
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs8
-rw-r--r--MediaBrowser.Controller/Entities/Game.cs3
-rw-r--r--MediaBrowser.Controller/Entities/GameSystem.cs3
-rw-r--r--MediaBrowser.Controller/Entities/IHasMediaSources.cs4
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs14
-rw-r--r--MediaBrowser.Controller/Entities/Movies/Movie.cs12
-rw-r--r--MediaBrowser.Controller/Entities/MusicVideo.cs3
-rw-r--r--MediaBrowser.Controller/Entities/Photo.cs5
-rw-r--r--MediaBrowser.Controller/Entities/PhotoAlbum.cs5
-rw-r--r--MediaBrowser.Controller/Entities/TV/Episode.cs61
-rw-r--r--MediaBrowser.Controller/Entities/TV/Season.cs79
-rw-r--r--MediaBrowser.Controller/Entities/TV/Series.cs15
-rw-r--r--MediaBrowser.Controller/Entities/Trailer.cs3
-rw-r--r--MediaBrowser.Controller/Entities/User.cs72
-rw-r--r--MediaBrowser.Controller/Entities/UserView.cs3
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs37
-rw-r--r--MediaBrowser.Controller/Library/IUserDataManager.cs4
-rw-r--r--MediaBrowser.Controller/Library/IUserManager.cs29
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs3
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvChannel.cs3
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvProgram.cs3
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs3
-rw-r--r--MediaBrowser.Controller/LiveTv/RecordingGroup.cs3
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj9
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingOptions.cs80
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingResult.cs13
-rw-r--r--MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs12
-rw-r--r--MediaBrowser.Controller/MediaEncoding/VideoEncodingOptions.cs26
-rw-r--r--MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs (renamed from MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs)5
-rw-r--r--MediaBrowser.Controller/Net/IWebSocket.cs (renamed from MediaBrowser.Common/Net/IWebSocket.cs)2
-rw-r--r--MediaBrowser.Controller/Net/IWebSocketConnection.cs (renamed from MediaBrowser.Common/Net/IWebSocketConnection.cs)2
-rw-r--r--MediaBrowser.Controller/Net/IWebSocketListener.cs (renamed from MediaBrowser.Common/Net/IWebSocketListener.cs)5
-rw-r--r--MediaBrowser.Controller/Net/WebSocketConnectEventArgs.cs (renamed from MediaBrowser.Common/Net/WebSocketConnectEventArgs.cs)2
-rw-r--r--MediaBrowser.Controller/Net/WebSocketMessageInfo.cs (renamed from MediaBrowser.Common/Net/WebSocketMessageInfo.cs)2
-rw-r--r--MediaBrowser.Controller/Providers/DirectoryService.cs5
-rw-r--r--MediaBrowser.Controller/Sync/ISyncManager.cs15
-rw-r--r--MediaBrowser.Controller/Sync/ISyncProvider.cs5
-rw-r--r--MediaBrowser.Dlna/Didl/DidlBuilder.cs1
-rw-r--r--MediaBrowser.LocalMetadata/BaseXmlProvider.cs8
-rw-r--r--MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs19
-rw-r--r--MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs2
-rw-r--r--MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs45
-rw-r--r--MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj1
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs4
-rw-r--r--MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj46
-rw-r--r--MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj42
-rw-r--r--MediaBrowser.Model/ApiClient/IApiClient.cs66
-rw-r--r--MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs1
-rw-r--r--MediaBrowser.Model/Configuration/EncodingOptions.cs19
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs26
-rw-r--r--MediaBrowser.Model/Configuration/UserConfiguration.cs13
-rw-r--r--MediaBrowser.Model/Dlna/StreamInfo.cs14
-rw-r--r--MediaBrowser.Model/Dto/BaseItemDto.cs13
-rw-r--r--MediaBrowser.Model/Dto/DtoOptions.cs17
-rw-r--r--MediaBrowser.Model/Dto/MetadataEditorInfo.cs27
-rw-r--r--MediaBrowser.Model/Dto/NameValuePair.cs17
-rw-r--r--MediaBrowser.Model/Dto/StreamOptions.cs67
-rw-r--r--MediaBrowser.Model/Dto/VideoStreamOptions.cs58
-rw-r--r--MediaBrowser.Model/MediaBrowser.Model.csproj13
-rw-r--r--MediaBrowser.Model/Net/HttpResponse.cs64
-rw-r--r--MediaBrowser.Model/Net/MimeTypes.cs (renamed from MediaBrowser.Common/Net/MimeTypes.cs)149
-rw-r--r--MediaBrowser.Model/Querying/ItemFields.cs32
-rw-r--r--MediaBrowser.Model/Session/TranscodingInfo.cs2
-rw-r--r--MediaBrowser.Model/Sync/DeviceFileInfo.cs9
-rw-r--r--MediaBrowser.Model/Sync/ItemFIleInfo.cs28
-rw-r--r--MediaBrowser.Model/Sync/ItemFileType.cs19
-rw-r--r--MediaBrowser.Model/Sync/LocalItem.cs33
-rw-r--r--MediaBrowser.Model/Sync/SyncJobItem.cs6
-rw-r--r--MediaBrowser.Model/Sync/SyncedItem.cs38
-rw-r--r--MediaBrowser.Model/Users/UserAction.cs15
-rw-r--r--MediaBrowser.Model/Users/UserActionType.cs8
-rw-r--r--MediaBrowser.Model/Users/UserPolicy.cs63
-rw-r--r--MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/Manager/ImageSaver.cs1
-rw-r--r--MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs4
-rw-r--r--MediaBrowser.Providers/Music/AlbumMetadataService.cs20
-rw-r--r--MediaBrowser.Providers/Music/ArtistMetadataService.cs21
-rw-r--r--MediaBrowser.Providers/Music/FanArtAlbumProvider.cs4
-rw-r--r--MediaBrowser.Providers/Music/FanArtArtistProvider.cs4
-rw-r--r--MediaBrowser.Providers/People/TvdbPersonImageProvider.cs4
-rw-r--r--MediaBrowser.Providers/TV/FanArtSeasonProvider.cs4
-rw-r--r--MediaBrowser.Providers/TV/FanartSeriesProvider.cs4
-rw-r--r--MediaBrowser.Providers/TV/MissingEpisodeProvider.cs63
-rw-r--r--MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs8
-rw-r--r--MediaBrowser.Providers/TV/SeriesMetadataService.cs25
-rw-r--r--MediaBrowser.Providers/TV/SeriesPostScanTask.cs15
-rw-r--r--MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs15
-rw-r--r--MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs4
-rw-r--r--MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelManager.cs35
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs37
-rw-r--r--MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs49
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectManager.cs38
-rw-r--r--MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs5
-rw-r--r--MediaBrowser.Server.Implementations/Dto/DtoService.cs45
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs1
-rw-r--r--MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs31
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs16
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs2
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs4
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs6
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs2
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs8
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs6
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/LibraryManager.cs212
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs63
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs18
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs50
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs21
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs73
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs12
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs79
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs15
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs5
-rw-r--r--MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs479
-rw-r--r--MediaBrowser.Server.Implementations/Library/SearchEngine.cs17
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserDataManager.cs76
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserManager.cs249
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs9
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/da.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/de.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/el.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/es.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json28
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/he.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/it.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json16
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json26
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json22
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json18
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ar.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ca.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/cs.json21
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/da.json21
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/de.json21
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/el.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/en_GB.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/en_US.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/es.json21
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/es_MX.json27
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/fi.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/fr.json37
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/he.json21
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/hr.json21
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/it.json21
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/kk.json27
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ko.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ms.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/nb.json29
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/nl.json27
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/pl.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json21
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json35
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/ru.json57
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/server.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/sv.json21
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/tr.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/vi.json25
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json39
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json21
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj3
-rw-r--r--MediaBrowser.Server.Implementations/News/NewsService.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionManager.cs80
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs1
-rw-r--r--MediaBrowser.Server.Implementations/Session/WebSocketController.cs13
-rw-r--r--MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs78
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncManager.cs115
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncRepository.cs57
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs4
-rw-r--r--MediaBrowser.Server.Implementations/packages.config2
-rw-r--r--MediaBrowser.Server.Mac/Native/BaseMonoApp.cs2
-rw-r--r--MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj4
-rw-r--r--MediaBrowser.Server.Mono/Native/BaseMonoApp.cs2
-rw-r--r--MediaBrowser.Server.Startup.Common/ApplicationHost.cs81
-rw-r--r--MediaBrowser.Server.Startup.Common/INativeApp.cs5
-rw-r--r--MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj2
-rw-r--r--MediaBrowser.Server.Startup.Common/Migrations/MigrateTranscodingPath.cs30
-rw-r--r--MediaBrowser.Server.Startup.Common/Migrations/PlaylistImages.cs55
-rw-r--r--MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs4
-rw-r--r--MediaBrowser.ServerApplication/Native/RegisterServer.bat18
-rw-r--r--MediaBrowser.ServerApplication/Native/ServerAuthorization.cs9
-rw-r--r--MediaBrowser.ServerApplication/Native/WindowsApp.cs4
-rw-r--r--MediaBrowser.Tests/MediaBrowser.Tests.csproj1
-rw-r--r--MediaBrowser.Tests/Resolvers/TvUtilTests.cs246
-rw-r--r--MediaBrowser.WebDashboard/Api/DashboardService.cs1
-rw-r--r--MediaBrowser.WebDashboard/Api/PackageCreator.cs4
-rw-r--r--MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj746
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs4
-rw-r--r--MediaBrowser.sln5
-rw-r--r--Nuget/MediaBrowser.Common.Internal.nuspec4
-rw-r--r--Nuget/MediaBrowser.Common.nuspec2
-rw-r--r--Nuget/MediaBrowser.Model.Signed.nuspec2
-rw-r--r--Nuget/MediaBrowser.Server.Core.nuspec4
-rw-r--r--SharedVersion.cs4
275 files changed, 3957 insertions, 3442 deletions
diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs
index d386373d4..a05d7d1b2 100644
--- a/MediaBrowser.Api/ApiEntryPoint.cs
+++ b/MediaBrowser.Api/ApiEntryPoint.cs
@@ -1,7 +1,9 @@
using MediaBrowser.Api.Playback;
-using MediaBrowser.Controller;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Session;
using System;
@@ -33,7 +35,7 @@ namespace MediaBrowser.Api
/// <summary>
/// The application paths
/// </summary>
- private readonly IServerApplicationPaths _appPaths;
+ private readonly IServerConfigurationManager _config;
private readonly ISessionManager _sessionManager;
@@ -43,13 +45,13 @@ namespace MediaBrowser.Api
/// Initializes a new instance of the <see cref="ApiEntryPoint" /> class.
/// </summary>
/// <param name="logger">The logger.</param>
- /// <param name="appPaths">The application paths.</param>
/// <param name="sessionManager">The session manager.</param>
- public ApiEntryPoint(ILogger logger, IServerApplicationPaths appPaths, ISessionManager sessionManager)
+ /// <param name="config">The configuration.</param>
+ public ApiEntryPoint(ILogger logger, ISessionManager sessionManager, IServerConfigurationManager config)
{
Logger = logger;
- _appPaths = appPaths;
_sessionManager = sessionManager;
+ _config = config;
Instance = this;
}
@@ -73,12 +75,17 @@ namespace MediaBrowser.Api
}
}
+ public EncodingOptions GetEncodingOptions()
+ {
+ return _config.GetConfiguration<EncodingOptions>("encoding");
+ }
+
/// <summary>
/// Deletes the encoded media cache.
/// </summary>
private void DeleteEncodedMediaCache()
{
- foreach (var file in Directory.EnumerateFiles(_appPaths.TranscodingTempPath, "*", SearchOption.AllDirectories)
+ foreach (var file in Directory.EnumerateFiles(_config.ApplicationPaths.TranscodingTempPath, "*", SearchOption.AllDirectories)
.ToList())
{
File.Delete(file);
@@ -185,7 +192,9 @@ namespace MediaBrowser.Api
CompletionPercentage = percentComplete,
Width = state.OutputWidth,
Height = state.OutputHeight,
- AudioChannels = state.OutputAudioChannels
+ AudioChannels = state.OutputAudioChannels,
+ IsAudioDirect = string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase),
+ IsVideoDirect = string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)
});
}
}
diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs
index 5fe606e16..3eb0296fc 100644
--- a/MediaBrowser.Api/ConfigurationService.cs
+++ b/MediaBrowser.Api/ConfigurationService.cs
@@ -123,7 +123,7 @@ namespace MediaBrowser.Api
public void Post(AutoSetMetadataOptions request)
{
- _configurationManager.DisableMetadataService("Media Browser Legacy Xml");
+ _configurationManager.DisableMetadataService("Media Browser Xml");
_configurationManager.SaveConfiguration();
}
diff --git a/MediaBrowser.Api/IHasDtoOptions.cs b/MediaBrowser.Api/IHasDtoOptions.cs
index f7fb57f01..2e677e816 100644
--- a/MediaBrowser.Api/IHasDtoOptions.cs
+++ b/MediaBrowser.Api/IHasDtoOptions.cs
@@ -28,17 +28,7 @@ namespace MediaBrowser.Api
options.ImageTypeLimit = request.ImageTypeLimit.Value;
}
- if (string.IsNullOrWhiteSpace(request.EnableImageTypes))
- {
- if (options.EnableImages)
- {
- // Get everything
- options.ImageTypes = Enum.GetNames(typeof(ImageType))
- .Select(i => (ImageType)Enum.Parse(typeof(ImageType), i, true))
- .ToList();
- }
- }
- else
+ if (!string.IsNullOrWhiteSpace(request.EnableImageTypes))
{
options.ImageTypes = (request.EnableImageTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(v => (ImageType)Enum.Parse(typeof(ImageType), v, true)).ToList();
}
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs
index 0e4ccf0b1..f2586b043 100644
--- a/MediaBrowser.Api/Images/ImageService.cs
+++ b/MediaBrowser.Api/Images/ImageService.cs
@@ -18,6 +18,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
namespace MediaBrowser.Api.Images
{
@@ -668,26 +669,26 @@ namespace MediaBrowser.Api.Images
{
if (format == ImageFormat.Bmp)
{
- return Common.Net.MimeTypes.GetMimeType("i.bmp");
+ return MimeTypes.GetMimeType("i.bmp");
}
if (format == ImageFormat.Gif)
{
- return Common.Net.MimeTypes.GetMimeType("i.gif");
+ return MimeTypes.GetMimeType("i.gif");
}
if (format == ImageFormat.Jpg)
{
- return Common.Net.MimeTypes.GetMimeType("i.jpg");
+ return MimeTypes.GetMimeType("i.jpg");
}
if (format == ImageFormat.Png)
{
- return Common.Net.MimeTypes.GetMimeType("i.png");
+ return MimeTypes.GetMimeType("i.png");
}
if (format == ImageFormat.Webp)
{
- return Common.Net.MimeTypes.GetMimeType("i.webp");
+ return MimeTypes.GetMimeType("i.webp");
}
- return Common.Net.MimeTypes.GetMimeType(path);
+ return MimeTypes.GetMimeType(path);
}
/// <summary>
diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs
index 65c51beff..272dff3ec 100644
--- a/MediaBrowser.Api/ItemUpdateService.cs
+++ b/MediaBrowser.Api/ItemUpdateService.cs
@@ -1,9 +1,14 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
using ServiceStack;
using System;
using System.Collections.Generic;
@@ -20,14 +25,165 @@ namespace MediaBrowser.Api
public string ItemId { get; set; }
}
+ [Route("/Items/{ItemId}/MetadataEditor", "GET", Summary = "Gets metadata editor info for an item")]
+ public class GetMetadataEditorInfo : IReturn<MetadataEditorInfo>
+ {
+ [ApiMember(Name = "ItemId", Description = "The id of the item", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string ItemId { get; set; }
+ }
+
+ [Route("/Items/{ItemId}/ContentType", "POST", Summary = "Updates an item's content type")]
+ public class UpdateItemContentType : IReturnVoid
+ {
+ [ApiMember(Name = "ItemId", Description = "The id of the item", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public string ItemId { get; set; }
+
+ [ApiMember(Name = "ContentType", Description = "The content type of the item", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string ContentType { get; set; }
+ }
+
[Authenticated]
public class ItemUpdateService : BaseApiService
{
private readonly ILibraryManager _libraryManager;
+ private readonly IProviderManager _providerManager;
+ private readonly ILocalizationManager _localizationManager;
+ private readonly IServerConfigurationManager _config;
- public ItemUpdateService(ILibraryManager libraryManager)
+ public ItemUpdateService(ILibraryManager libraryManager, IProviderManager providerManager, ILocalizationManager localizationManager, IServerConfigurationManager config)
{
_libraryManager = libraryManager;
+ _providerManager = providerManager;
+ _localizationManager = localizationManager;
+ _config = config;
+ }
+
+ public object Get(GetMetadataEditorInfo request)
+ {
+ var item = _libraryManager.GetItemById(request.ItemId);
+
+ var info = new MetadataEditorInfo
+ {
+ ParentalRatingOptions = _localizationManager.GetParentalRatings().ToList(),
+ ExternalIdInfos = _providerManager.GetExternalIdInfos(item).ToList(),
+ Countries = _localizationManager.GetCountries().ToList(),
+ Cultures = _localizationManager.GetCultures().ToList()
+ };
+
+ var locationType = item.LocationType;
+ if (locationType == LocationType.FileSystem ||
+ locationType == LocationType.Offline)
+ {
+ if (!(item is ICollectionFolder) && !(item is UserView) && !(item is AggregateFolder) && !(item is LiveTvChannel) && !(item is IItemByName))
+ {
+ var collectionType = _libraryManager.GetInheritedContentType(item);
+ if (string.IsNullOrWhiteSpace(collectionType))
+ {
+ info.ContentTypeOptions = GetContentTypeOptions(true);
+ info.ContentType = _libraryManager.GetContentType(item);
+ }
+ }
+ }
+
+ return ToOptimizedResult(info);
+ }
+
+ public void Post(UpdateItemContentType request)
+ {
+ var item = _libraryManager.GetItemById(request.ItemId);
+ var path = item.ContainingFolderPath;
+
+ var types = _config.Configuration.ContentTypes
+ .Where(i => !string.Equals(i.Name, path, StringComparison.OrdinalIgnoreCase))
+ .ToList();
+
+ if (!string.IsNullOrWhiteSpace(request.ContentType))
+ {
+ types.Add(new NameValuePair
+ {
+ Name = path,
+ Value = request.ContentType
+ });
+ }
+
+ _config.Configuration.ContentTypes = types.ToArray();
+ _config.SaveConfiguration();
+ }
+
+ private List<NameValuePair> GetContentTypeOptions(bool isForItem)
+ {
+ var list = new List<NameValuePair>();
+
+ if (isForItem)
+ {
+ list.Add(new NameValuePair
+ {
+ Name = "FolderTypeInherit",
+ Value = ""
+ });
+ }
+
+ list.Add(new NameValuePair
+ {
+ Name = "FolderTypeMovies",
+ Value = "movies"
+ });
+ list.Add(new NameValuePair
+ {
+ Name = "FolderTypeMusic",
+ Value = "music"
+ });
+ list.Add(new NameValuePair
+ {
+ Name = "FolderTypeTvShows",
+ Value = "tvshows"
+ });
+
+ if (!isForItem)
+ {
+ list.Add(new NameValuePair
+ {
+ Name = "FolderTypeBooks",
+ Value = "books"
+ });
+ list.Add(new NameValuePair
+ {
+ Name = "FolderTypeGames",
+ Value = "games"
+ });
+ }
+
+ list.Add(new NameValuePair
+ {
+ Name = "FolderTypeHomeVideos",
+ Value = "homevideos"
+ });
+ list.Add(new NameValuePair
+ {
+ Name = "FolderTypeMusicVideos",
+ Value = "musicvideos"
+ });
+ list.Add(new NameValuePair
+ {
+ Name = "FolderTypePhotos",
+ Value = "photos"
+ });
+
+ if (!isForItem)
+ {
+ list.Add(new NameValuePair
+ {
+ Name = "FolderTypeMixed",
+ Value = ""
+ });
+ }
+
+ foreach (var val in list)
+ {
+ val.Name = _localizationManager.GetLocalizedString(val.Name);
+ }
+
+ return list;
}
public void Post(UpdateItem request)
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index 5cb007f8f..37d00b937 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -272,16 +272,13 @@ namespace MediaBrowser.Api.Library
items = items.Where(i => i.IsHidden == val).ToList();
}
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields))
- .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
- .ToList();
+ var dtoOptions = new DtoOptions();
var result = new ItemsResult
{
TotalRecordCount = items.Count,
- Items = items.Select(i => _dtoService.GetBaseItemDto(i, fields)).ToArray()
+ Items = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions)).ToArray()
};
return ToOptimizedResult(result);
@@ -347,10 +344,7 @@ namespace MediaBrowser.Api.Library
var user = request.UserId.HasValue ? _userManager.GetUserById(request.UserId.Value) : null;
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields))
- .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
- .ToList();
+ var dtoOptions = new DtoOptions();
BaseItem parent = item.Parent;
@@ -361,7 +355,7 @@ namespace MediaBrowser.Api.Library
parent = TranslateParentItem(parent, user);
}
- baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, fields, user));
+ baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user));
parent = parent.Parent;
}
@@ -479,14 +473,14 @@ namespace MediaBrowser.Api.Library
}
else if (item is ILiveTvRecording)
{
- if (!user.Configuration.EnableLiveTvManagement)
+ if (!user.Policy.EnableLiveTvManagement)
{
throw new UnauthorizedAccessException();
}
}
else
{
- if (!user.Configuration.EnableContentDeletion)
+ if (!user.Policy.EnableContentDeletion)
{
throw new UnauthorizedAccessException();
}
@@ -583,11 +577,6 @@ namespace MediaBrowser.Api.Library
item = item.Parent;
}
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields))
- .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
- .ToList();
-
var themeSongIds = GetThemeSongIds(item);
if (themeSongIds.Count == 0 && request.InheritFromParent)
@@ -607,10 +596,12 @@ namespace MediaBrowser.Api.Library
}
}
}
-
+
+ var dtoOptions = new DtoOptions();
+
var dtos = themeSongIds.Select(_libraryManager.GetItemById)
.OrderBy(i => i.SortName)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user, item));
+ .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
var items = dtos.ToArray();
@@ -651,11 +642,6 @@ namespace MediaBrowser.Api.Library
item = item.Parent;
}
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields))
- .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
- .ToList();
-
var themeVideoIds = GetThemeVideoIds(item);
if (themeVideoIds.Count == 0 && request.InheritFromParent)
@@ -681,9 +667,11 @@ namespace MediaBrowser.Api.Library
}
}
+ var dtoOptions = new DtoOptions();
+
var dtos = themeVideoIds.Select(_libraryManager.GetItemById)
.OrderBy(i => i.SortName)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user, item));
+ .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
var items = dtos.ToArray();
@@ -754,10 +742,7 @@ namespace MediaBrowser.Api.Library
: (Folder)_libraryManager.RootFolder)
: _libraryManager.GetItemById(id);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields))
- .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
- .ToList();
+ var dtoOptions = new DtoOptions();
var dtos = GetSoundtrackSongIds(item, inheritFromParent)
.Select(_libraryManager.GetItemById)
@@ -765,7 +750,7 @@ namespace MediaBrowser.Api.Library
.SelectMany(i => i.RecursiveChildren)
.OfType<Audio>()
.OrderBy(i => i.SortName)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user, item));
+ .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
var items = dtos.ToArray();
diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
index 3afe72866..f3dcf57e0 100644
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs
@@ -319,7 +319,7 @@ namespace MediaBrowser.Api.LiveTv
throw new UnauthorizedAccessException("Anonymous live tv management is not allowed.");
}
- if (!user.Configuration.EnableLiveTvManagement)
+ if (!user.Policy.EnableLiveTvManagement)
{
throw new UnauthorizedAccessException("The current user does not have permission to manage live tv.");
}
diff --git a/MediaBrowser.Api/Movies/CollectionService.cs b/MediaBrowser.Api/Movies/CollectionService.cs
index 346c085f8..97c6cd87d 100644
--- a/MediaBrowser.Api/Movies/CollectionService.cs
+++ b/MediaBrowser.Api/Movies/CollectionService.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Collections;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using ServiceStack;
using System;
@@ -70,7 +71,9 @@ namespace MediaBrowser.Api.Movies
}).ConfigureAwait(false);
- var dto = _dtoService.GetBaseItemDto(item, new List<ItemFields>());
+ var dtoOptions = new DtoOptions();
+
+ var dto = _dtoService.GetBaseItemDto(item, dtoOptions);
return ToOptimizedResult(new CollectionCreationResult
{
diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs
index fc03ab466..ba3c15a90 100644
--- a/MediaBrowser.Api/Movies/MoviesService.cs
+++ b/MediaBrowser.Api/Movies/MoviesService.cs
@@ -157,7 +157,11 @@ namespace MediaBrowser.Api.Movies
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
.ToList();
- var result = GetRecommendationCategories(user, listEligibleForCategories, listEligibleForSuggestion, request.CategoryLimit, request.ItemLimit, request.GetItemFields().ToList());
+ var dtoOptions = new DtoOptions();
+
+ dtoOptions.Fields = request.GetItemFields().ToList();
+
+ var result = GetRecommendationCategories(user, listEligibleForCategories, listEligibleForSuggestion, request.CategoryLimit, request.ItemLimit, dtoOptions);
return ToOptimizedResult(result);
}
@@ -232,7 +236,7 @@ namespace MediaBrowser.Api.Movies
return result;
}
- private IEnumerable<RecommendationDto> GetRecommendationCategories(User user, List<BaseItem> allMoviesForCategories, List<BaseItem> allMovies, int categoryLimit, int itemLimit, List<ItemFields> fields)
+ private IEnumerable<RecommendationDto> GetRecommendationCategories(User user, List<BaseItem> allMoviesForCategories, List<BaseItem> allMovies, int categoryLimit, int itemLimit, DtoOptions dtoOptions)
{
var categories = new List<RecommendationDto>();
@@ -282,11 +286,11 @@ namespace MediaBrowser.Api.Movies
.OrderBy(i => Guid.NewGuid())
.ToList();
- var similarToRecentlyPlayed = GetSimilarTo(user, allMovies, recentlyPlayedMovies.Take(7).OrderBy(i => Guid.NewGuid()), itemLimit, fields, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
- var similarToLiked = GetSimilarTo(user, allMovies, likedMovies, itemLimit, fields, RecommendationType.SimilarToLikedItem).GetEnumerator();
+ var similarToRecentlyPlayed = GetSimilarTo(user, allMovies, recentlyPlayedMovies.Take(7).OrderBy(i => Guid.NewGuid()), itemLimit, dtoOptions, RecommendationType.SimilarToRecentlyPlayed).GetEnumerator();
+ var similarToLiked = GetSimilarTo(user, allMovies, likedMovies, itemLimit, dtoOptions, RecommendationType.SimilarToLikedItem).GetEnumerator();
- var hasDirectorFromRecentlyPlayed = GetWithDirector(user, allMovies, recentDirectors, itemLimit, fields, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
- var hasActorFromRecentlyPlayed = GetWithActor(user, allMovies, recentActors, itemLimit, fields, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
+ var hasDirectorFromRecentlyPlayed = GetWithDirector(user, allMovies, recentDirectors, itemLimit, dtoOptions, RecommendationType.HasDirectorFromRecentlyPlayed).GetEnumerator();
+ var hasActorFromRecentlyPlayed = GetWithActor(user, allMovies, recentActors, itemLimit, dtoOptions, RecommendationType.HasActorFromRecentlyPlayed).GetEnumerator();
var categoryTypes = new List<IEnumerator<RecommendationDto>>
{
@@ -329,7 +333,7 @@ namespace MediaBrowser.Api.Movies
return categories.OrderBy(i => i.RecommendationType).ThenBy(i => Guid.NewGuid());
}
- private IEnumerable<RecommendationDto> GetWithDirector(User user, List<BaseItem> allMovies, IEnumerable<string> directors, int itemLimit, List<ItemFields> fields, RecommendationType type)
+ private IEnumerable<RecommendationDto> GetWithDirector(User user, List<BaseItem> allMovies, IEnumerable<string> directors, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
{
var userId = user.Id;
@@ -347,13 +351,13 @@ namespace MediaBrowser.Api.Movies
BaselineItemName = director,
CategoryId = director.GetMD5().ToString("N"),
RecommendationType = type,
- Items = items.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray()
+ Items = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray()
};
}
}
}
- private IEnumerable<RecommendationDto> GetWithActor(User user, List<BaseItem> allMovies, IEnumerable<string> names, int itemLimit, List<ItemFields> fields, RecommendationType type)
+ private IEnumerable<RecommendationDto> GetWithActor(User user, List<BaseItem> allMovies, IEnumerable<string> names, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
{
var userId = user.Id;
@@ -371,13 +375,13 @@ namespace MediaBrowser.Api.Movies
BaselineItemName = name,
CategoryId = name.GetMD5().ToString("N"),
RecommendationType = type,
- Items = items.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray()
+ Items = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray()
};
}
}
}
- private IEnumerable<RecommendationDto> GetSimilarTo(User user, List<BaseItem> allMovies, IEnumerable<BaseItem> baselineItems, int itemLimit, List<ItemFields> fields, RecommendationType type)
+ private IEnumerable<RecommendationDto> GetSimilarTo(User user, List<BaseItem> allMovies, IEnumerable<BaseItem> baselineItems, int itemLimit, DtoOptions dtoOptions, RecommendationType type)
{
var userId = user.Id;
@@ -395,7 +399,7 @@ namespace MediaBrowser.Api.Movies
BaselineItemName = item.Name,
CategoryId = item.Id.ToString("N"),
RecommendationType = type,
- Items = similar.Select(i => _dtoService.GetBaseItemDto(i, fields, user)).ToArray()
+ Items = similar.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray()
};
}
}
diff --git a/MediaBrowser.Api/NotificationsService.cs b/MediaBrowser.Api/NotificationsService.cs
index 69f1f3489..5103d1b5c 100644
--- a/MediaBrowser.Api/NotificationsService.cs
+++ b/MediaBrowser.Api/NotificationsService.cs
@@ -135,7 +135,7 @@ namespace MediaBrowser.Api
Level = request.Level,
Name = request.Name,
Url = request.Url,
- UserIds = _userManager.Users.Where(i => i.Configuration.IsAdministrator).Select(i => i.Id.ToString("N")).ToList()
+ UserIds = _userManager.Users.Where(i => i.Policy.IsAdministrator).Select(i => i.Id.ToString("N")).ToList()
};
await _notificationManager.SendNotification(notification, CancellationToken.None).ConfigureAwait(false);
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 12ccfb6b1..03106b6e7 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
@@ -202,6 +203,10 @@ namespace MediaBrowser.Api.Playback
{
args += " -map -0:s";
}
+ else if (state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)
+ {
+ args += " -map 1:0 -sn";
+ }
return args;
}
@@ -245,7 +250,7 @@ namespace MediaBrowser.Api.Playback
protected EncodingQuality GetQualitySetting()
{
- var quality = ServerConfigurationManager.Configuration.MediaEncodingQuality;
+ var quality = ApiEntryPoint.Instance.GetEncodingOptions().EncodingQuality;
if (quality == EncodingQuality.Auto)
{
@@ -273,7 +278,7 @@ namespace MediaBrowser.Api.Playback
// Recommended per docs
return Math.Max(Environment.ProcessorCount - 1, 2);
}
-
+
// Use more when this is true. -re will keep cpu usage under control
if (state.ReadInputAtNativeFramerate)
{
@@ -302,6 +307,21 @@ namespace MediaBrowser.Api.Playback
}
}
+ protected string H264Encoder
+ {
+ get
+ {
+ var lib = ApiEntryPoint.Instance.GetEncodingOptions().H264Encoder;
+
+ if (!string.IsNullOrWhiteSpace(lib))
+ {
+ return lib;
+ }
+
+ return "libx264";
+ }
+ }
+
/// <summary>
/// Gets the video bitrate to specify on the command line
/// </summary>
@@ -318,7 +338,7 @@ namespace MediaBrowser.Api.Playback
var qualitySetting = GetQualitySetting();
- if (string.Equals(videoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(videoCodec, H264Encoder, StringComparison.OrdinalIgnoreCase))
{
switch (qualitySetting)
{
@@ -442,7 +462,7 @@ namespace MediaBrowser.Api.Playback
{
if (state.AudioStream != null && state.AudioStream.Channels.HasValue && state.AudioStream.Channels.Value > 5)
{
- volParam = ",volume=" + ServerConfigurationManager.Configuration.DownMixAudioBoost.ToString(UsCulture);
+ volParam = ",volume=" + ApiEntryPoint.Instance.GetEncodingOptions().DownMixAudioBoost.ToString(UsCulture);
}
}
@@ -651,9 +671,18 @@ namespace MediaBrowser.Api.Playback
videoSizeParam = string.Format(",scale={0}:{1}", state.VideoStream.Width.Value.ToString(UsCulture), state.VideoStream.Height.Value.ToString(UsCulture));
}
- return string.Format(" -filter_complex \"[0:{0}]format=yuva444p{3},lut=u=128:v=128:y=gammaval(.3)[sub] ; [0:{1}] [sub] overlay{2}\"",
- state.SubtitleStream.Index,
- state.VideoStream.Index,
+ var mapPrefix = state.SubtitleStream.IsExternal ?
+ 1 :
+ 0;
+
+ var subtitleStreamIndex = state.SubtitleStream.IsExternal
+ ? 0
+ : state.SubtitleStream.Index;
+
+ return string.Format(" -filter_complex \"[{0}:{1}]format=yuva444p{4},lut=u=128:v=128:y=gammaval(.3)[sub] ; [0:{2}] [sub] overlay{3}\"",
+ mapPrefix.ToString(UsCulture),
+ subtitleStreamIndex.ToString(UsCulture),
+ state.VideoStream.Index.ToString(UsCulture),
outputSizeParam,
videoSizeParam);
}
@@ -700,7 +729,8 @@ namespace MediaBrowser.Api.Playback
return Math.Min(request.MaxAudioChannels.Value, audioStream.Channels.Value);
}
- return request.MaxAudioChannels.Value;
+ // If we don't have any media info then limit it to 5 to prevent encoding errors due to asking for too many channels
+ return Math.Min(request.MaxAudioChannels.Value, 5);
}
return request.AudioChannels;
@@ -761,7 +791,7 @@ namespace MediaBrowser.Api.Playback
{
if (string.Equals(codec, "h264", StringComparison.OrdinalIgnoreCase))
{
- return "libx264";
+ return H264Encoder;
}
if (string.Equals(codec, "vpx", StringComparison.OrdinalIgnoreCase))
{
@@ -798,6 +828,21 @@ namespace MediaBrowser.Api.Playback
/// <returns>System.String.</returns>
protected string GetInputArgument(string transcodingJobId, StreamState state)
{
+ var arg = "-i " + GetInputPathArgument(transcodingJobId, state);
+
+ if (state.SubtitleStream != null)
+ {
+ if (state.SubtitleStream.IsExternal && !state.SubtitleStream.IsTextSubtitleStream)
+ {
+ arg += " -i " + state.SubtitleStream.Path;
+ }
+ }
+
+ return arg;
+ }
+
+ private string GetInputPathArgument(string transcodingJobId, StreamState state)
+ {
if (state.InputProtocol == MediaProtocol.File &&
state.RunTimeTicks.HasValue &&
state.VideoType == VideoType.VideoFile &&
@@ -868,7 +913,7 @@ namespace MediaBrowser.Api.Playback
state.InputProtocol = streamInfo.Protocol;
await Task.Delay(1500, cancellationTokenSource.Token).ConfigureAwait(false);
-
+
AttachMediaStreamInfo(state, streamInfo, state.VideoRequest, state.RequestedUrl);
checkCodecs = true;
}
@@ -898,8 +943,8 @@ namespace MediaBrowser.Api.Playback
/// <param name="cancellationTokenSource">The cancellation token source.</param>
/// <param name="workingDirectory">The working directory.</param>
/// <returns>Task.</returns>
- protected async Task<TranscodingJob> StartFfMpeg(StreamState state,
- string outputPath,
+ protected async Task<TranscodingJob> StartFfMpeg(StreamState state,
+ string outputPath,
CancellationTokenSource cancellationTokenSource,
string workingDirectory = null)
{
@@ -910,7 +955,7 @@ namespace MediaBrowser.Api.Playback
var transcodingId = Guid.NewGuid().ToString("N");
var commandLineArgs = GetCommandLineArguments(outputPath, transcodingId, state, true);
- if (ServerConfigurationManager.Configuration.EnableDebugEncodingLogging)
+ if (ApiEntryPoint.Instance.GetEncodingOptions().EnableDebugLogging)
{
commandLineArgs = "-loglevel debug " + commandLineArgs;
}
@@ -1088,7 +1133,7 @@ namespace MediaBrowser.Api.Playback
if (scale.HasValue)
{
long val;
-
+
if (long.TryParse(size, NumberStyles.Any, UsCulture, out val))
{
bytesTranscoded = val * scale.Value;
@@ -1562,9 +1607,6 @@ namespace MediaBrowser.Api.Playback
mediaStreams = new List<MediaStream>();
state.DeInterlace = true;
- state.OutputAudioSync = "1000";
- state.InputVideoSync = "-1";
- state.InputAudioSync = "1";
// Just to prevent this from being null and causing other methods to fail
state.MediaPath = string.Empty;
@@ -1630,7 +1672,7 @@ namespace MediaBrowser.Api.Playback
if (string.IsNullOrEmpty(container))
{
- container = request.Static ?
+ container = request.Static ?
state.InputContainer :
(Path.GetExtension(GetOutputFilePath(state)) ?? string.Empty).TrimStart('.');
}
@@ -1696,9 +1738,16 @@ namespace MediaBrowser.Api.Playback
state.InputFileSize = mediaSource.Size;
state.ReadInputAtNativeFramerate = mediaSource.ReadAtNativeFramerate;
+ if (state.ReadInputAtNativeFramerate)
+ {
+ state.OutputAudioSync = "1000";
+ state.InputVideoSync = "-1";
+ state.InputAudioSync = "1";
+ }
+
AttachMediaStreamInfo(state, mediaSource.MediaStreams, videoRequest, requestedUrl);
}
-
+
private void AttachMediaStreamInfo(StreamState state,
List<MediaStream> mediaStreams,
VideoStreamRequest videoRequest,
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index c963636fd..8a33a88f2 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
@@ -6,7 +7,6 @@ using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
-using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.IO;
using System;
using System.Collections.Generic;
@@ -14,6 +14,7 @@ using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Net;
namespace MediaBrowser.Api.Playback.Hls
{
@@ -119,11 +120,7 @@ namespace MediaBrowser.Api.Playback.Hls
if (isLive)
{
- //var file = request.PlaylistId + Path.GetExtension(Request.PathInfo);
-
- //file = Path.Combine(ServerConfigurationManager.ApplicationPaths.TranscodingTempPath, file);
-
- return ResultFactory.GetStaticFileResult(Request, playlist, FileShare.ReadWrite);
+ return ResultFactory.GetResult(GetLivePlaylistText(playlist, state.SegmentLength), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
var audioBitrate = state.OutputAudioBitrate ?? 0;
@@ -144,6 +141,22 @@ namespace MediaBrowser.Api.Playback.Hls
return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
+ private string GetLivePlaylistText(string path, int segmentLength)
+ {
+ using (var stream = FileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ {
+ using (var reader = new StreamReader(stream))
+ {
+ var text = reader.ReadToEnd();
+
+ var newDuration = "#EXT-X-TARGETDURATION:" + segmentLength.ToString(UsCulture) + Environment.NewLine + "#EXT-X-ALLOW-CACHE:NO";
+
+ // ffmpeg pads the reported length by a full second
+ return text.Replace("#EXT-X-TARGETDURATION:" + (segmentLength + 1).ToString(UsCulture), newDuration, StringComparison.OrdinalIgnoreCase);
+ }
+ }
+ }
+
private string GetMasterPlaylistFileText(string firstPlaylist, int bitrate, bool includeBaselineStream, int baselineStreamBitrate)
{
var builder = new StringBuilder();
@@ -227,7 +240,7 @@ namespace MediaBrowser.Api.Playback.Hls
"hls/" + Path.GetFileNameWithoutExtension(outputPath));
}
- var args = string.Format("{0} {1} -i {2} -map_metadata -1 -threads {3} {4} {5} -sc_threshold 0 {6} -hls_time {7} -start_number {8} -hls_list_size {9}{10} -y \"{11}\"",
+ var args = string.Format("{0} {1} {2} -map_metadata -1 -threads {3} {4} {5} -sc_threshold 0 {6} -hls_time {7} -start_number {8} -hls_list_size {9}{10} -y \"{11}\"",
itsOffset,
inputModifier,
GetInputArgument(transcodingJobId, state),
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index fe3bd12fb..86866bdf5 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -20,6 +20,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
namespace MediaBrowser.Api.Playback.Hls
{
@@ -387,7 +388,7 @@ namespace MediaBrowser.Api.Playback.Hls
playlistText = GetMasterPlaylistFileText(state, videoBitrate + audioBitrate);
}
- return ResultFactory.GetResult(playlistText, Common.Net.MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
+ return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
private string GetMasterPlaylistFileText(StreamState state, int totalBitrate)
@@ -603,7 +604,7 @@ namespace MediaBrowser.Api.Playback.Hls
var playlistText = builder.ToString();
- return ResultFactory.GetResult(playlistText, Common.Net.MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
+ return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
protected override string GetAudioArguments(StreamState state)
@@ -640,10 +641,19 @@ namespace MediaBrowser.Api.Playback.Hls
{
var codec = state.OutputVideoCodec;
+ var args = "-codec:v:0 " + codec;
+
+ if (state.EnableMpegtsM2TsMode)
+ {
+ args += " -mpegts_m2ts_mode 1";
+ }
+
// See if we can save come cpu cycles by avoiding encoding
- if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
+ if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
{
- return state.VideoStream != null && IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf:v h264_mp4toannexb" : "-codec:v:0 copy";
+ return state.VideoStream != null && IsH264(state.VideoStream) ?
+ args + " -bsf:v h264_mp4toannexb" :
+ args;
}
var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
@@ -651,7 +661,7 @@ namespace MediaBrowser.Api.Playback.Hls
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
- var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264", true) + keyFrameArg;
+ args += " " + GetVideoQualityParam(state, H264Encoder, true) + keyFrameArg;
// Add resolution params, if specified
if (!hasGraphicalSubs)
@@ -677,7 +687,7 @@ namespace MediaBrowser.Api.Playback.Hls
// If isEncoding is true we're actually starting ffmpeg
var startNumberParam = isEncoding ? GetStartNumber(state).ToString(UsCulture) : "0";
- var args = string.Format("{0} -i {1} -map_metadata -1 -threads {2} {3} {4} -copyts -flags -global_header {5} -hls_time {6} -start_number {7} -hls_list_size {8} -y \"{9}\"",
+ var args = string.Format("{0} {1} -map_metadata -1 -threads {2} {3} {4} -copyts -flags -global_header {5} -hls_time {6} -start_number {7} -hls_list_size {8} -y \"{9}\"",
inputModifier,
GetInputArgument(transcodingJobId, state),
threads,
diff --git a/MediaBrowser.Api/Playback/Hls/MpegDashService.cs b/MediaBrowser.Api/Playback/Hls/MpegDashService.cs
index 260a4c467..87e2eedcf 100644
--- a/MediaBrowser.Api/Playback/Hls/MpegDashService.cs
+++ b/MediaBrowser.Api/Playback/Hls/MpegDashService.cs
@@ -18,6 +18,7 @@ using System.Security;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
namespace MediaBrowser.Api.Playback.Hls
{
@@ -97,7 +98,7 @@ namespace MediaBrowser.Api.Playback.Hls
playlistText = GetManifestText(state);
}
- return ResultFactory.GetResult(playlistText, Common.Net.MimeTypes.GetMimeType("playlist.mpd"), new Dictionary<string, string>());
+ return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.mpd"), new Dictionary<string, string>());
}
private string GetManifestText(StreamState state)
@@ -583,10 +584,19 @@ namespace MediaBrowser.Api.Playback.Hls
{
var codec = state.OutputVideoCodec;
+ var args = "-codec:v:0 " + codec;
+
+ if (state.EnableMpegtsM2TsMode)
+ {
+ args += " -mpegts_m2ts_mode 1";
+ }
+
// See if we can save come cpu cycles by avoiding encoding
if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
{
- return IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf:v h264_mp4toannexb" : "-codec:v:0 copy";
+ return state.VideoStream != null && IsH264(state.VideoStream) ?
+ args + " -bsf:v h264_mp4toannexb" :
+ args;
}
var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
@@ -594,7 +604,7 @@ namespace MediaBrowser.Api.Playback.Hls
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
- var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264", true) + keyFrameArg;
+ args+= " " + GetVideoQualityParam(state, H264Encoder, true) + keyFrameArg;
args += " -r 24 -g 24";
@@ -627,7 +637,7 @@ namespace MediaBrowser.Api.Playback.Hls
var segmentFilename = Path.GetFileNameWithoutExtension(outputPath) + "%03d" + GetSegmentFileExtension(state);
- var args = string.Format("{0} -i {1} -map_metadata -1 -threads {2} {3} {4} -copyts {5} -f ssegment -segment_time {6} -segment_list_size {8} -segment_list \"{9}\" {10}",
+ var args = string.Format("{0} {1} -map_metadata -1 -threads {2} {3} {4} -copyts {5} -f ssegment -segment_time {6} -segment_list_size {8} -segment_list \"{9}\" {10}",
inputModifier,
GetInputArgument(transcodingJobId, state),
threads,
diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
index 06fa4065c..de845c88d 100644
--- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
@@ -9,8 +9,6 @@ using MediaBrowser.Model.IO;
using ServiceStack;
using System;
using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
namespace MediaBrowser.Api.Playback.Hls
{
@@ -136,18 +134,27 @@ namespace MediaBrowser.Api.Playback.Hls
{
var codec = state.OutputVideoCodec;
+ var args = "-codec:v:0 " + codec;
+
+ if (state.EnableMpegtsM2TsMode)
+ {
+ args += " -mpegts_m2ts_mode 1";
+ }
+
// See if we can save come cpu cycles by avoiding encoding
if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
{
- return state.VideoStream != null && IsH264(state.VideoStream) ? "-codec:v:0 copy -bsf:v h264_mp4toannexb" : "-codec:v:0 copy";
+ return state.VideoStream != null && IsH264(state.VideoStream) ?
+ args + " -bsf:v h264_mp4toannexb" :
+ args;
}
-
+
var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
state.SegmentLength.ToString(UsCulture));
var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream;
- var args = "-codec:v:0 " + codec + " " + GetVideoQualityParam(state, "libx264", true) + keyFrameArg;
+ args += " " + GetVideoQualityParam(state, H264Encoder, true) + keyFrameArg;
// Add resolution params, if specified
if (!hasGraphicalSubs)
diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
index ae592c428..725526ecd 100644
--- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs
@@ -82,7 +82,7 @@ namespace MediaBrowser.Api.Playback.Progressive
var inputModifier = GetInputModifier(state);
- return string.Format("{0} -i {1} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1 -y \"{5}\"",
+ return string.Format("{0} {1} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1 -y \"{5}\"",
inputModifier,
GetInputArgument(transcodingJobId, state),
threads,
diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
index a64866d68..5ef72a495 100644
--- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs
+++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs
@@ -103,7 +103,7 @@ namespace MediaBrowser.Api.Playback.Progressive
var inputModifier = GetInputModifier(state);
- return string.Format("{0} -i {1}{2} {3} {4} -map_metadata -1 -threads {5} {6}{7} -y \"{8}\"",
+ return string.Format("{0} {1}{2} {3} {4} -map_metadata -1 -threads {5} {6}{7} -y \"{8}\"",
inputModifier,
GetInputArgument(transcodingJobId, state),
keyFrame,
@@ -124,7 +124,7 @@ namespace MediaBrowser.Api.Playback.Progressive
/// <returns>System.String.</returns>
private string GetVideoArguments(StreamState state, string codec)
{
- var args = "-vcodec " + codec;
+ var args = "-codec:v:0 " + codec;
if (state.EnableMpegtsM2TsMode)
{
@@ -134,7 +134,9 @@ namespace MediaBrowser.Api.Playback.Progressive
// See if we can save come cpu cycles by avoiding encoding
if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
{
- return state.VideoStream != null && IsH264(state.VideoStream) ? args + " -bsf:v h264_mp4toannexb" : args;
+ return state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) ?
+ args + " -bsf:v h264_mp4toannexb" :
+ args;
}
var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})",
@@ -182,13 +184,13 @@ namespace MediaBrowser.Api.Playback.Progressive
// Get the output codec name
var codec = state.OutputAudioCodec;
+ var args = "-codec:a:0 " + codec;
+
if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase))
{
- return "-acodec copy";
+ return args;
}
- var args = "-acodec " + codec;
-
// Add the number of audio channels
var channels = state.OutputAudioChannels;
diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs
index d26259a3a..40e765f1a 100644
--- a/MediaBrowser.Api/Playback/StreamState.cs
+++ b/MediaBrowser.Api/Playback/StreamState.cs
@@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading;
+using MediaBrowser.Model.Net;
namespace MediaBrowser.Api.Playback
{
diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTasksWebSocketListener.cs
index f34c53b16..cb8f91ab6 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.Controller.Net;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Tasks;
diff --git a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
index e6b525e53..25130776e 100644
--- a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
+++ b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Session;
diff --git a/MediaBrowser.Api/Session/SessionsService.cs b/MediaBrowser.Api/Session/SessionsService.cs
index d2881893b..4f47b9f54 100644
--- a/MediaBrowser.Api/Session/SessionsService.cs
+++ b/MediaBrowser.Api/Session/SessionsService.cs
@@ -373,12 +373,12 @@ namespace MediaBrowser.Api.Session
var user = _userManager.GetUserById(request.ControllableByUserId.Value);
- if (!user.Configuration.EnableRemoteControlOfOtherUsers)
+ if (!user.Policy.EnableRemoteControlOfOtherUsers)
{
result = result.Where(i => i.ContainsUser(request.ControllableByUserId.Value));
}
- if (!user.Configuration.EnableSharedDeviceControl)
+ if (!user.Policy.EnableSharedDeviceControl)
{
result = result.Where(i => !i.UserId.HasValue);
}
diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs
index a2a93d50e..32e6ba076 100644
--- a/MediaBrowser.Api/Subtitles/SubtitleService.cs
+++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs
@@ -15,6 +15,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
namespace MediaBrowser.Api.Subtitles
{
@@ -175,7 +176,7 @@ namespace MediaBrowser.Api.Subtitles
builder.AppendLine("#EXT-X-ENDLIST");
- return ResultFactory.GetResult(builder.ToString(), Common.Net.MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
+ return ResultFactory.GetResult(builder.ToString(), MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
}
public object Get(GetSubtitle request)
@@ -199,7 +200,7 @@ namespace MediaBrowser.Api.Subtitles
var stream = GetSubtitles(request).Result;
- return ResultFactory.GetResult(stream, Common.Net.MimeTypes.GetMimeType("file." + request.Format));
+ return ResultFactory.GetResult(stream, MimeTypes.GetMimeType("file." + request.Format));
}
private async Task<Stream> GetSubtitles(GetSubtitle request)
@@ -240,7 +241,7 @@ namespace MediaBrowser.Api.Subtitles
{
var result = _subtitleManager.GetRemoteSubtitles(request.Id, CancellationToken.None).Result;
- return ResultFactory.GetResult(result.Stream, Common.Net.MimeTypes.GetMimeType("file." + result.Format));
+ return ResultFactory.GetResult(result.Stream, MimeTypes.GetMimeType("file." + result.Format));
}
public void Post(DownloadRemoteSubtitles request)
diff --git a/MediaBrowser.Api/Sync/SyncService.cs b/MediaBrowser.Api/Sync/SyncService.cs
index cefb0e46e..0036b316f 100644
--- a/MediaBrowser.Api/Sync/SyncService.cs
+++ b/MediaBrowser.Api/Sync/SyncService.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Controller.Sync;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Sync;
+using MediaBrowser.Model.Users;
using ServiceStack;
using System;
using System.Collections.Generic;
@@ -55,8 +56,14 @@ namespace MediaBrowser.Api.Sync
[ApiMember(Name = "UserId", Description = "UserId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
public string UserId { get; set; }
- [ApiMember(Name = "ItemIds", Description = "ItemIds", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+ [ApiMember(Name = "ItemIds", Description = "ItemIds", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string ItemIds { get; set; }
+
+ [ApiMember(Name = "ParentId", Description = "ParentId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string ParentId { get; set; }
+
+ [ApiMember(Name = "Category", Description = "Category", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public SyncCategory? Category { get; set; }
}
[Route("/Sync/JobItems/{Id}/Transferred", "POST", Summary = "Reports that a sync job item has successfully been transferred.")]
@@ -73,6 +80,18 @@ namespace MediaBrowser.Api.Sync
public string Id { get; set; }
}
+ [Route("/Sync/OfflineActions", "POST", Summary = "Reports an action that occurred while offline.")]
+ public class ReportOfflineActions : List<UserAction>, IReturnVoid
+ {
+ }
+
+ [Route("/Sync/Items/Ready", "GET", Summary = "Gets ready to download sync items.")]
+ public class GetReadySyncItems : IReturn<List<SyncedItem>>
+ {
+ [ApiMember(Name = "TargetId", Description = "TargetId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
+ public string TargetId { get; set; }
+ }
+
[Authenticated]
public class SyncService : BaseApiService
{
@@ -155,21 +174,50 @@ namespace MediaBrowser.Api.Sync
result.Targets = _syncManager.GetSyncTargets(request.UserId)
.ToList();
- var dtos = request.ItemIds.Split(',')
- .Select(_libraryManager.GetItemById)
- .Where(i => i != null)
- .Select(i => _dtoService.GetBaseItemDto(i, new DtoOptions
+ if (request.Category.HasValue)
+ {
+ result.Options = SyncHelper.GetSyncOptions(request.Category.Value);
+ }
+ else
+ {
+ var dtoOptions = new DtoOptions
{
Fields = new List<ItemFields>
{
ItemFields.SyncInfo
}
- }))
- .ToList();
+ };
+
+ var dtos = request.ItemIds.Split(',')
+ .Select(_libraryManager.GetItemById)
+ .Where(i => i != null)
+ .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions))
+ .ToList();
- result.Options = SyncHelper.GetSyncOptions(dtos);
+ result.Options = SyncHelper.GetSyncOptions(dtos);
+ }
return ToOptimizedResult(result);
}
+
+ public void Post(ReportOfflineActions request)
+ {
+ var task = PostAsync(request);
+
+ Task.WaitAll(task);
+ }
+
+ public async Task PostAsync(ReportOfflineActions request)
+ {
+ foreach (var action in request)
+ {
+ await _syncManager.ReportOfflineAction(action).ConfigureAwait(false);
+ }
+ }
+
+ public object Get(GetReadySyncItems request)
+ {
+ return ToOptimizedResult(_syncManager.GetReadySyncItems(request.TargetId));
+ }
}
}
diff --git a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs
index 4629b2a8c..a951cd3d6 100644
--- a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs
+++ b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs
@@ -1,5 +1,5 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Activity;
+using MediaBrowser.Controller.Activity;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
diff --git a/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs b/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs
index c20cef3b3..49a3e3291 100644
--- a/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs
+++ b/MediaBrowser.Api/System/SystemInfoWebSocketListener.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.System;
using System.Threading.Tasks;
diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs
index 2299b2b1a..128423238 100644
--- a/MediaBrowser.Api/UserLibrary/ArtistsService.cs
+++ b/MediaBrowser.Api/UserLibrary/ArtistsService.cs
@@ -83,17 +83,16 @@ namespace MediaBrowser.Api.UserLibrary
{
var item = GetArtist(request.Name, LibraryManager);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
+ var dtoOptions = new DtoOptions();
if (request.UserId.HasValue)
{
var user = UserManager.GetUserById(request.UserId.Value);
-
- return DtoService.GetBaseItemDto(item, fields.ToList(), user);
+
+ return DtoService.GetBaseItemDto(item, dtoOptions, user);
}
- return DtoService.GetBaseItemDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, dtoOptions);
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/GameGenresService.cs b/MediaBrowser.Api/UserLibrary/GameGenresService.cs
index adc21c362..2f1c73ace 100644
--- a/MediaBrowser.Api/UserLibrary/GameGenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/GameGenresService.cs
@@ -69,17 +69,16 @@ namespace MediaBrowser.Api.UserLibrary
{
var item = GetGameGenre(request.Name, LibraryManager);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
+ var dtoOptions = new DtoOptions();
if (request.UserId.HasValue)
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetBaseItemDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, dtoOptions, user);
}
- return DtoService.GetBaseItemDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, dtoOptions);
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs
index 7b6b18c9c..db0b0fe61 100644
--- a/MediaBrowser.Api/UserLibrary/GenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/GenresService.cs
@@ -74,17 +74,16 @@ namespace MediaBrowser.Api.UserLibrary
{
var item = GetGenre(request.Name, LibraryManager);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
+ var dtoOptions = new DtoOptions();
if (request.UserId.HasValue)
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetBaseItemDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, dtoOptions, user);
}
- return DtoService.GetBaseItemDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, dtoOptions);
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
index 1088ada02..f8575aa7c 100644
--- a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
@@ -69,17 +69,16 @@ namespace MediaBrowser.Api.UserLibrary
{
var item = GetMusicGenre(request.Name, LibraryManager);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
+ var dtoOptions = new DtoOptions();
if (request.UserId.HasValue)
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetBaseItemDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, dtoOptions, user);
}
- return DtoService.GetBaseItemDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, dtoOptions);
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs
index dd80801ee..33ce6cd80 100644
--- a/MediaBrowser.Api/UserLibrary/PersonsService.cs
+++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs
@@ -86,17 +86,16 @@ namespace MediaBrowser.Api.UserLibrary
{
var item = GetPerson(request.Name, LibraryManager);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
+ var dtoOptions = new DtoOptions();
if (request.UserId.HasValue)
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetBaseItemDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, dtoOptions, user);
}
- return DtoService.GetBaseItemDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, dtoOptions);
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs
index 2024d779b..272134b70 100644
--- a/MediaBrowser.Api/UserLibrary/StudiosService.cs
+++ b/MediaBrowser.Api/UserLibrary/StudiosService.cs
@@ -73,17 +73,16 @@ namespace MediaBrowser.Api.UserLibrary
{
var item = GetStudio(request.Name, LibraryManager);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
+ var dtoOptions = new DtoOptions();
if (request.UserId.HasValue)
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetBaseItemDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, dtoOptions, user);
}
- return DtoService.GetBaseItemDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, dtoOptions);
}
/// <summary>
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
index 040cad436..45a330a50 100644
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
@@ -407,9 +407,6 @@ namespace MediaBrowser.Api.UserLibrary
{
var user = _userManager.GetUserById(request.UserId);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
-
var query = new UserViewQuery
{
UserId = request.UserId
@@ -423,7 +420,9 @@ namespace MediaBrowser.Api.UserLibrary
var folders = await _userViewManager.GetUserViews(query, CancellationToken.None).ConfigureAwait(false);
- var dtos = folders.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
+ var dtoOptions = new DtoOptions();
+
+ var dtos = folders.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user))
.ToArray();
var result = new QueryResult<BaseItemDto>
@@ -443,14 +442,16 @@ namespace MediaBrowser.Api.UserLibrary
user.RootFolder :
_libraryManager.GetItemById(request.Id);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
-
var series = item as Series;
// Get them from the child tree
if (series != null)
{
+ var dtoOptions = new DtoOptions();
+
+ // Avoid implicitly captured closure
+ var currentUser = user;
+
var dtos = series
.GetRecursiveChildren()
.Where(i => i is Episode && i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == 0)
@@ -468,7 +469,7 @@ namespace MediaBrowser.Api.UserLibrary
return DateTime.MinValue;
})
.ThenBy(i => i.SortName)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user));
+ .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, currentUser));
return dtos.ToList();
}
@@ -478,10 +479,12 @@ namespace MediaBrowser.Api.UserLibrary
// Get them from the db
if (movie != null)
{
+ var dtoOptions = new DtoOptions();
+
var dtos = movie.SpecialFeatureIds
.Select(_libraryManager.GetItemById)
.OrderBy(i => i.SortName)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user, item));
+ .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
return dtos.ToList();
}
@@ -507,9 +510,6 @@ namespace MediaBrowser.Api.UserLibrary
var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : _libraryManager.GetItemById(request.Id);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
-
var trailerIds = new List<Guid>();
var hasTrailers = item as IHasTrailers;
@@ -518,10 +518,12 @@ namespace MediaBrowser.Api.UserLibrary
trailerIds = hasTrailers.GetTrailerIds();
}
+ var dtoOptions = new DtoOptions();
+
var dtos = trailerIds
.Select(_libraryManager.GetItemById)
.OrderBy(i => i.SortName)
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user, item));
+ .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item));
return dtos.ToList();
}
@@ -537,10 +539,9 @@ namespace MediaBrowser.Api.UserLibrary
var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : _libraryManager.GetItemById(request.Id);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
+ var dtoOptions = new DtoOptions();
- var result = _dtoService.GetBaseItemDto(item, fields, user);
+ var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
return ToOptimizedSerializedResultUsingCache(result);
}
@@ -556,10 +557,9 @@ namespace MediaBrowser.Api.UserLibrary
var item = user.RootFolder;
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
+ var dtoOptions = new DtoOptions();
- var result = _dtoService.GetBaseItemDto(item, fields, user);
+ var result = _dtoService.GetBaseItemDto(item, dtoOptions, user);
return ToOptimizedSerializedResultUsingCache(result);
}
@@ -577,12 +577,9 @@ namespace MediaBrowser.Api.UserLibrary
var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields))
- .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
- .ToList();
+ var dtoOptions = new DtoOptions();
- var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
+ var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user))
.ToArray();
var result = new ItemsResult
diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs
index 2b300f900..b1b0aeb63 100644
--- a/MediaBrowser.Api/UserLibrary/YearsService.cs
+++ b/MediaBrowser.Api/UserLibrary/YearsService.cs
@@ -73,17 +73,16 @@ namespace MediaBrowser.Api.UserLibrary
{
var item = LibraryManager.GetYear(request.Year);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
+ var dtoOptions = new DtoOptions();
if (request.UserId.HasValue)
{
var user = UserManager.GetUserById(request.UserId.Value);
- return DtoService.GetBaseItemDto(item, fields.ToList(), user);
+ return DtoService.GetBaseItemDto(item, dtoOptions, user);
}
- return DtoService.GetBaseItemDto(item, fields.ToList());
+ return DtoService.GetBaseItemDto(item, dtoOptions);
}
/// <summary>
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
index 4b720c775..760cb07fd 100644
--- a/MediaBrowser.Api/UserService.cs
+++ b/MediaBrowser.Api/UserService.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Connect;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Users;
@@ -51,7 +52,7 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid Id { get; set; }
+ public string Id { get; set; }
}
/// <summary>
@@ -66,7 +67,7 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid Id { get; set; }
+ public string Id { get; set; }
}
/// <summary>
@@ -80,7 +81,7 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
+ public string Id { get; set; }
/// <summary>
/// Gets or sets the password.
@@ -125,7 +126,7 @@ namespace MediaBrowser.Api
/// 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 password.
@@ -156,6 +157,28 @@ namespace MediaBrowser.Api
}
/// <summary>
+ /// Class UpdateUser
+ /// </summary>
+ [Route("/Users/{Id}/Policy", "POST", Summary = "Updates a user policy")]
+ [Authenticated(Roles = "admin")]
+ public class UpdateUserPolicy : UserPolicy, IReturnVoid
+ {
+ [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public string Id { get; set; }
+ }
+
+ /// <summary>
+ /// Class UpdateUser
+ /// </summary>
+ [Route("/Users/{Id}/Configuration", "POST", Summary = "Updates a user configuration")]
+ [Authenticated]
+ public class UpdateUserConfiguration : UserConfiguration, IReturnVoid
+ {
+ [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public string Id { get; set; }
+ }
+
+ /// <summary>
/// Class CreateUser
/// </summary>
[Route("/Users/New", "POST", Summary = "Creates a user")]
@@ -196,12 +219,6 @@ namespace MediaBrowser.Api
public IAuthorizationContext AuthorizationContext { get; set; }
- /// <summary>
- /// Initializes a new instance of the <see cref="UserService" /> class.
- /// </summary>
- /// <param name="userManager">The user manager.</param>
- /// <param name="dtoService">The dto service.</param>
- /// <param name="sessionMananger">The session mananger.</param>
public UserService(IUserManager userManager, IDtoService dtoService, ISessionManager sessionMananger, IServerConfigurationManager config, INetworkManager networkManager)
{
_userManager = userManager;
@@ -247,12 +264,12 @@ namespace MediaBrowser.Api
if (request.IsDisabled.HasValue)
{
- users = users.Where(i => i.Configuration.IsDisabled == request.IsDisabled.Value);
+ users = users.Where(i => i.Policy.IsDisabled == request.IsDisabled.Value);
}
if (request.IsHidden.HasValue)
{
- users = users.Where(i => i.Configuration.IsHidden == request.IsHidden.Value);
+ users = users.Where(i => i.Policy.IsHidden == request.IsHidden.Value);
}
if (request.IsGuest.HasValue)
@@ -428,39 +445,13 @@ namespace MediaBrowser.Api
var user = _userManager.GetUserById(id);
- // If removing admin access
- if (!dtoUser.Configuration.IsAdministrator && user.Configuration.IsAdministrator)
- {
- if (_userManager.Users.Count(i => i.Configuration.IsAdministrator) == 1)
- {
- throw new ArgumentException("There must be at least one user in the system with administrative access.");
- }
- }
-
- // If disabling
- if (dtoUser.Configuration.IsDisabled && user.Configuration.IsAdministrator)
- {
- throw new ArgumentException("Administrators cannot be disabled.");
- }
-
- // If disabling
- if (dtoUser.Configuration.IsDisabled && !user.Configuration.IsDisabled)
- {
- if (_userManager.Users.Count(i => !i.Configuration.IsDisabled) == 1)
- {
- throw new ArgumentException("There must be at least one enabled user in the system.");
- }
-
- await _sessionMananger.RevokeUserTokens(user.Id.ToString("N")).ConfigureAwait(false);
- }
-
var task = user.Name.Equals(dtoUser.Name, StringComparison.Ordinal) ?
_userManager.UpdateUser(user) :
_userManager.RenameUser(user, dtoUser.Name);
await task.ConfigureAwait(false);
- user.UpdateConfiguration(dtoUser.Configuration);
+ await _userManager.UpdateConfiguration(dtoUser.Id, dtoUser.Configuration);
}
/// <summary>
@@ -495,5 +486,51 @@ namespace MediaBrowser.Api
{
return _userManager.RedeemPasswordResetPin(request.Pin);
}
+
+ public void Post(UpdateUserConfiguration request)
+ {
+ var task = _userManager.UpdateConfiguration(request.Id, request);
+
+ Task.WaitAll(task);
+ }
+
+ public void Post(UpdateUserPolicy request)
+ {
+ var task = UpdateUserPolicy(request);
+ Task.WaitAll(task);
+ }
+
+ private async Task UpdateUserPolicy(UpdateUserPolicy request)
+ {
+ var user = _userManager.GetUserById(request.Id);
+
+ // If removing admin access
+ if (!request.IsAdministrator && user.Policy.IsAdministrator)
+ {
+ if (_userManager.Users.Count(i => i.Policy.IsAdministrator) == 1)
+ {
+ throw new ArgumentException("There must be at least one user in the system with administrative access.");
+ }
+ }
+
+ // If disabling
+ if (request.IsDisabled && user.Policy.IsAdministrator)
+ {
+ throw new ArgumentException("Administrators cannot be disabled.");
+ }
+
+ // If disabling
+ if (request.IsDisabled && !user.Policy.IsDisabled)
+ {
+ if (_userManager.Users.Count(i => !i.Policy.IsDisabled) == 1)
+ {
+ throw new ArgumentException("There must be at least one enabled user in the system.");
+ }
+
+ await _sessionMananger.RevokeUserTokens(user.Id.ToString("N")).ConfigureAwait(false);
+ }
+
+ await _userManager.UpdateUserPolicy(request.Id, request).ConfigureAwait(false);
+ }
}
}
diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs
index fbf9cec2e..28db46b98 100644
--- a/MediaBrowser.Api/VideosService.cs
+++ b/MediaBrowser.Api/VideosService.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using ServiceStack;
using System;
@@ -79,15 +80,12 @@ namespace MediaBrowser.Api
: _libraryManager.RootFolder)
: _libraryManager.GetItemById(request.Id);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields))
- .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
- .ToList();
+ var dtoOptions = new DtoOptions();
var video = (Video)item;
var items = video.GetAdditionalParts()
- .Select(i => _dtoService.GetBaseItemDto(i, fields, user, video))
+ .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, video))
.ToArray();
var result = new ItemsResult
@@ -114,11 +112,11 @@ namespace MediaBrowser.Api
{
link.PrimaryVersionId = null;
- await link.UpdateToRepository(ItemUpdateType.MetadataDownload, CancellationToken.None).ConfigureAwait(false);
+ await link.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
}
video.LinkedAlternateVersions.Clear();
- await video.UpdateToRepository(ItemUpdateType.MetadataDownload, CancellationToken.None).ConfigureAwait(false);
+ await video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
}
public void Post(MergeVersions request)
@@ -186,7 +184,7 @@ namespace MediaBrowser.Api
{
item.PrimaryVersionId = primaryVersion.Id;
- await item.UpdateToRepository(ItemUpdateType.MetadataDownload, CancellationToken.None).ConfigureAwait(false);
+ await item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
primaryVersion.LinkedAlternateVersions.Add(new LinkedChild
{
@@ -195,7 +193,7 @@ namespace MediaBrowser.Api
});
}
- await primaryVersion.UpdateToRepository(ItemUpdateType.MetadataDownload, CancellationToken.None).ConfigureAwait(false);
+ await primaryVersion.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
}
}
}
diff --git a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs
index 4a70697fa..c53947e44 100644
--- a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs
+++ b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs
@@ -105,7 +105,7 @@ namespace MediaBrowser.Common.Implementations.Configuration
UpdateCachePath();
}
- public void AddParts(IEnumerable<IConfigurationFactory> factories)
+ public virtual void AddParts(IEnumerable<IConfigurationFactory> factories)
{
_configurationFactories = factories.ToArray();
@@ -208,20 +208,51 @@ namespace MediaBrowser.Common.Implementations.Configuration
lock (_configurationSyncLock)
{
- return ConfigurationHelper.GetXmlConfiguration(configurationType, file, XmlSerializer);
+ return LoadConfiguration(file, configurationType);
}
});
}
+ private object LoadConfiguration(string path, Type configurationType)
+ {
+ try
+ {
+ return XmlSerializer.DeserializeFromFile(configurationType, path);
+ }
+ catch (FileNotFoundException)
+ {
+ return Activator.CreateInstance(configurationType);
+ }
+ catch (DirectoryNotFoundException)
+ {
+ return Activator.CreateInstance(configurationType);
+ }
+ catch (Exception ex)
+ {
+ Logger.ErrorException("Error loading configuration file: {0}", ex, path);
+
+ return Activator.CreateInstance(configurationType);
+ }
+ }
+
public void SaveConfiguration(string key, object configuration)
{
- var configurationType = GetConfigurationType(key);
+ var configurationStore = GetConfigurationStore(key);
+ var configurationType = configurationStore.ConfigurationType;
if (configuration.GetType() != configurationType)
{
throw new ArgumentException("Expected configuration type is " + configurationType.Name);
}
+ var validatingStore = configurationStore as IValidatingConfiguration;
+ if (validatingStore != null)
+ {
+ var currentConfiguration = GetConfiguration(key);
+
+ validatingStore.Validate(currentConfiguration, configuration);
+ }
+
EventHelper.FireEventIfNotNull(NamedConfigurationUpdating, this, new ConfigurationUpdateEventArgs
{
Key = key,
@@ -239,6 +270,11 @@ namespace MediaBrowser.Common.Implementations.Configuration
XmlSerializer.SerializeToFile(configuration, path);
}
+ OnNamedConfigurationUpdated(key, configuration);
+ }
+
+ protected virtual void OnNamedConfigurationUpdated(string key, object configuration)
+ {
EventHelper.FireEventIfNotNull(NamedConfigurationUpdated, this, new ConfigurationUpdateEventArgs
{
Key = key,
@@ -249,9 +285,14 @@ namespace MediaBrowser.Common.Implementations.Configuration
public Type GetConfigurationType(string key)
{
- return _configurationStores
- .First(i => string.Equals(i.Key, key, StringComparison.OrdinalIgnoreCase))
+ return GetConfigurationStore(key)
.ConfigurationType;
}
+
+ private ConfigurationStore GetConfigurationStore(string key)
+ {
+ return _configurationStores
+ .First(i => string.Equals(i.Key, key, StringComparison.OrdinalIgnoreCase));
+ }
}
}
diff --git a/MediaBrowser.Common/Configuration/ConfigurationHelper.cs b/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs
index 8c904b0db..ff5b8bd59 100644
--- a/MediaBrowser.Common/Configuration/ConfigurationHelper.cs
+++ b/MediaBrowser.Common.Implementations/Configuration/ConfigurationHelper.cs
@@ -3,7 +3,7 @@ using System;
using System.IO;
using System.Linq;
-namespace MediaBrowser.Common.Configuration
+namespace MediaBrowser.Common.Implementations.Configuration
{
/// <summary>
/// Class ConfigurationHelper
@@ -55,20 +55,5 @@ namespace MediaBrowser.Common.Configuration
return configuration;
}
}
-
- /// <summary>
- /// Reads an xml configuration file from the file system
- /// It will immediately save the configuration after loading it, just
- /// in case there are new serializable properties
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="path">The path.</param>
- /// <param name="xmlSerializer">The XML serializer.</param>
- /// <returns>``0.</returns>
- public static T GetXmlConfiguration<T>(string path, IXmlSerializer xmlSerializer)
- where T : class
- {
- return GetXmlConfiguration(typeof(T), path, xmlSerializer) as T;
- }
}
}
diff --git a/MediaBrowser.Common.Implementations/Devices/DeviceId.cs b/MediaBrowser.Common.Implementations/Devices/DeviceId.cs
index 5af236026..7c0dc1e1f 100644
--- a/MediaBrowser.Common.Implementations/Devices/DeviceId.cs
+++ b/MediaBrowser.Common.Implementations/Devices/DeviceId.cs
@@ -38,7 +38,10 @@ namespace MediaBrowser.Common.Implementations.Devices
_logger.Error("Invalid value found in device id file");
}
}
- catch (FileNotFoundException ex)
+ catch (DirectoryNotFoundException)
+ {
+ }
+ catch (FileNotFoundException)
{
}
catch (Exception ex)
diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
index 42a402940..0aaf0b4e0 100644
--- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
+++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
@@ -80,6 +80,7 @@
<Compile Include="BaseApplicationHost.cs" />
<Compile Include="BaseApplicationPaths.cs" />
<Compile Include="Configuration\BaseConfigurationManager.cs" />
+ <Compile Include="Configuration\ConfigurationHelper.cs" />
<Compile Include="Devices\DeviceId.cs" />
<Compile Include="HttpClientManager\HttpClientInfo.cs" />
<Compile Include="HttpClientManager\HttpClientManager.cs" />
diff --git a/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs b/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs
index 8f3225f4e..63381efcd 100644
--- a/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs
+++ b/MediaBrowser.Common.Implementations/Security/MBLicenseFile.cs
@@ -101,6 +101,10 @@ namespace MediaBrowser.Common.Implementations.Security
{
contents = File.ReadAllLines(licenseFile);
}
+ catch (DirectoryNotFoundException)
+ {
+ (File.Create(licenseFile)).Close();
+ }
catch (FileNotFoundException)
{
(File.Create(licenseFile)).Close();
diff --git a/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs b/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs
index cef744753..04030522f 100644
--- a/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs
+++ b/MediaBrowser.Common.Implementations/Serialization/XmlSerializer.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Model.Serialization;
using System;
+using System.Collections.Concurrent;
using System.IO;
using System.Xml;
@@ -10,6 +11,17 @@ namespace MediaBrowser.Common.Implementations.Serialization
/// </summary>
public class XmlSerializer : IXmlSerializer
{
+ // Need to cache these
+ // http://dotnetcodebox.blogspot.com/2013/01/xmlserializer-class-may-result-in.html
+ private readonly ConcurrentDictionary<string, System.Xml.Serialization.XmlSerializer> _serializers =
+ new ConcurrentDictionary<string, System.Xml.Serialization.XmlSerializer>();
+
+ private System.Xml.Serialization.XmlSerializer GetSerializer(Type type)
+ {
+ var key = type.FullName;
+ return _serializers.GetOrAdd(key, k => new System.Xml.Serialization.XmlSerializer(type));
+ }
+
/// <summary>
/// Serializes to writer.
/// </summary>
@@ -18,7 +30,7 @@ namespace MediaBrowser.Common.Implementations.Serialization
private void SerializeToWriter(object obj, XmlTextWriter writer)
{
writer.Formatting = Formatting.Indented;
- var netSerializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
+ var netSerializer = GetSerializer(obj.GetType());
netSerializer.Serialize(writer, obj);
}
@@ -32,8 +44,7 @@ namespace MediaBrowser.Common.Implementations.Serialization
{
using (var reader = new XmlTextReader(stream))
{
- var netSerializer = new System.Xml.Serialization.XmlSerializer(type);
-
+ var netSerializer = GetSerializer(type);
return netSerializer.Deserialize(reader);
}
}
diff --git a/MediaBrowser.Common/Configuration/IConfigurationFactory.cs b/MediaBrowser.Common/Configuration/IConfigurationFactory.cs
index d418d0a42..6ed638536 100644
--- a/MediaBrowser.Common/Configuration/IConfigurationFactory.cs
+++ b/MediaBrowser.Common/Configuration/IConfigurationFactory.cs
@@ -14,4 +14,9 @@ namespace MediaBrowser.Common.Configuration
public Type ConfigurationType { get; set; }
}
+
+ public interface IValidatingConfiguration
+ {
+ void Validate(object oldConfig, object newConfig);
+ }
}
diff --git a/MediaBrowser.Common/Extensions/BaseExtensions.cs b/MediaBrowser.Common/Extensions/BaseExtensions.cs
index 8e96373f4..4c94f3aa2 100644
--- a/MediaBrowser.Common/Extensions/BaseExtensions.cs
+++ b/MediaBrowser.Common/Extensions/BaseExtensions.cs
@@ -1,4 +1,6 @@
using System;
+using System.Globalization;
+using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
@@ -54,6 +56,15 @@ namespace MediaBrowser.Common.Extensions
return sb.ToString();
}
+ public static string RemoveDiacritics(this string text)
+ {
+ return String.Concat(
+ text.Normalize(NormalizationForm.FormD)
+ .Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) !=
+ UnicodeCategory.NonSpacingMark)
+ ).Normalize(NormalizationForm.FormC);
+ }
+
/// <summary>
/// Gets the M d5.
/// </summary>
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj
index 9fdfccaaf..c46dd4a4f 100644
--- a/MediaBrowser.Common/MediaBrowser.Common.csproj
+++ b/MediaBrowser.Common/MediaBrowser.Common.csproj
@@ -53,7 +53,6 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
- <Compile Include="Configuration\ConfigurationHelper.cs" />
<Compile Include="Configuration\ConfigurationUpdateEventArgs.cs" />
<Compile Include="Configuration\IConfigurationManager.cs" />
<Compile Include="Configuration\IConfigurationFactory.cs" />
@@ -64,19 +63,12 @@
<Compile Include="IO\IFileSystem.cs" />
<Compile Include="IO\ProgressStream.cs" />
<Compile Include="IO\StreamDefaults.cs" />
- <Compile Include="Net\BasePeriodicWebSocketListener.cs" />
<Compile Include="Configuration\IApplicationPaths.cs" />
<Compile Include="Net\HttpRequestOptions.cs" />
<Compile Include="Net\HttpResponseInfo.cs" />
- <Compile Include="Net\IWebSocketListener.cs" />
<Compile Include="IApplicationHost.cs" />
<Compile Include="Net\IHttpClient.cs" />
<Compile Include="Net\INetworkManager.cs" />
- <Compile Include="Net\IWebSocket.cs" />
- <Compile Include="Net\IWebSocketConnection.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" />
diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs
index 6bbd69f04..9d0133c67 100644
--- a/MediaBrowser.Common/Plugins/BasePlugin.cs
+++ b/MediaBrowser.Common/Plugins/BasePlugin.cs
@@ -5,7 +5,6 @@ using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
-using System.Threading;
namespace MediaBrowser.Common.Plugins
{
@@ -164,11 +163,7 @@ namespace MediaBrowser.Common.Plugins
/// <summary>
/// The _configuration sync lock
/// </summary>
- private object _configurationSyncLock = new object();
- /// <summary>
- /// The _configuration initialized
- /// </summary>
- private bool _configurationInitialized;
+ private readonly object _configurationSyncLock = new object();
/// <summary>
/// The _configuration
/// </summary>
@@ -182,17 +177,43 @@ namespace MediaBrowser.Common.Plugins
get
{
// Lazy load
- LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationInitialized, ref _configurationSyncLock, () => ConfigurationHelper.GetXmlConfiguration(ConfigurationType, ConfigurationFilePath, XmlSerializer) as TConfigurationType);
+ if (_configuration == null)
+ {
+ lock (_configurationSyncLock)
+ {
+ if (_configuration == null)
+ {
+ _configuration = LoadConfiguration();
+ }
+ }
+ }
return _configuration;
}
protected set
{
_configuration = value;
+ }
+ }
- if (value == null)
- {
- _configurationInitialized = false;
- }
+ private TConfigurationType LoadConfiguration()
+ {
+ var path = ConfigurationFilePath;
+
+ try
+ {
+ return (TConfigurationType)XmlSerializer.DeserializeFromFile(typeof(TConfigurationType), path);
+ }
+ catch (DirectoryNotFoundException)
+ {
+ return (TConfigurationType)Activator.CreateInstance(typeof(TConfigurationType));
+ }
+ catch (FileNotFoundException)
+ {
+ return (TConfigurationType)Activator.CreateInstance(typeof(TConfigurationType));
+ }
+ catch (Exception ex)
+ {
+ return (TConfigurationType)Activator.CreateInstance(typeof(TConfigurationType));
}
}
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index f618c8a25..5a9fc3322 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Channels
public override bool IsVisible(User user)
{
- if (user.Configuration.BlockedChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
+ if (user.Policy.BlockedChannels.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase))
{
return false;
}
diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
index ede366dab..896d598bb 100644
--- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
@@ -6,6 +6,7 @@ using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Channels
{
@@ -25,8 +26,8 @@ namespace MediaBrowser.Controller.Channels
public string OriginalImageUrl { get; set; }
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
-
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent);
}
diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
index 5362cc195..8482e38df 100644
--- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
@@ -5,6 +5,7 @@ using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Querying;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Channels
{
@@ -20,7 +21,7 @@ namespace MediaBrowser.Controller.Channels
public string OriginalImageUrl { get; set; }
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
// Don't block.
return false;
diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
index 72e2b110a..f0eafcbdf 100644
--- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
+++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Channels
{
@@ -51,7 +52,7 @@ namespace MediaBrowser.Controller.Channels
return ExternalId;
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.ChannelContent);
}
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 447328ea1..623ae8968 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -8,6 +8,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities.Audio
{
@@ -173,7 +174,7 @@ namespace MediaBrowser.Controller.Entities.Audio
return base.GetUserDataKey();
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Music);
}
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index 1f7c62de0..90edfcce7 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities.Audio
{
@@ -154,7 +155,7 @@ namespace MediaBrowser.Controller.Entities.Audio
return base.GetUserDataKey();
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Music);
}
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index 2d9e052b1..a60258d1a 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities.Audio
{
@@ -114,7 +115,7 @@ namespace MediaBrowser.Controller.Entities.Audio
return "Artist-" + item.Name;
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Music);
}
@@ -135,7 +136,7 @@ namespace MediaBrowser.Controller.Entities.Audio
// Refresh songs
foreach (var item in songs)
{
- if (tasks.Count >= 3)
+ if (tasks.Count >= 2)
{
await Task.WhenAll(tasks).ConfigureAwait(false);
tasks.Clear();
@@ -172,37 +173,23 @@ namespace MediaBrowser.Controller.Entities.Audio
// Refresh all non-songs
foreach (var item in others)
{
- if (tasks.Count >= 3)
- {
- await Task.WhenAll(tasks).ConfigureAwait(false);
- tasks.Clear();
- }
-
cancellationToken.ThrowIfCancellationRequested();
- var innerProgress = new ActionableProgress<double>();
// Avoid implicitly captured closure
var currentChild = item;
- innerProgress.RegisterAction(p =>
- {
- lock (percentages)
- {
- percentages[currentChild.Id] = p / 100;
- var percent = percentages.Values.Sum();
- percent /= totalItems;
- percent *= 100;
- progress.Report(percent);
- }
- });
+ await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
+ lock (percentages)
+ {
+ percentages[currentChild.Id] = 1;
- // Avoid implicitly captured closure
- var taskChild = item;
- tasks.Add(Task.Run(async () => await RefreshItem(taskChild, refreshOptions, innerProgress, cancellationToken).ConfigureAwait(false), cancellationToken));
+ var percent = percentages.Values.Sum();
+ percent /= totalItems;
+ percent *= 100;
+ progress.Report(percent);
+ }
}
- await Task.WhenAll(tasks).ConfigureAwait(false);
-
progress.Report(100);
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index ed950b1c5..90427de75 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -14,6 +14,7 @@ using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Users;
using System;
using System.Collections.Generic;
using System.IO;
@@ -45,6 +46,8 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg", ".tbn" };
+ public static readonly List<string> SupportedImageExtensionsList = SupportedImageExtensions.ToList();
+
/// <summary>
/// The trailer folder name
/// </summary>
@@ -593,7 +596,7 @@ namespace MediaBrowser.Controller.Entities
/// <returns>PlayAccess.</returns>
public PlayAccess GetPlayAccess(User user)
{
- if (!user.Configuration.EnableMediaPlayback)
+ if (!user.Policy.EnableMediaPlayback)
{
return PlayAccess.None;
}
@@ -985,7 +988,7 @@ namespace MediaBrowser.Controller.Entities
return false;
}
- var maxAllowedRating = user.Configuration.MaxParentalRating;
+ var maxAllowedRating = user.Policy.MaxParentalRating;
if (maxAllowedRating == null)
{
@@ -1001,7 +1004,7 @@ namespace MediaBrowser.Controller.Entities
if (string.IsNullOrWhiteSpace(rating))
{
- return !GetBlockUnratedValue(user.Configuration);
+ return !GetBlockUnratedValue(user.Policy);
}
var value = LocalizationManager.GetRatingLevel(rating);
@@ -1021,7 +1024,7 @@ namespace MediaBrowser.Controller.Entities
if (hasTags != null)
{
- if (user.Configuration.BlockedTags.Any(i => hasTags.Tags.Contains(i, StringComparer.OrdinalIgnoreCase)))
+ if (user.Policy.BlockedTags.Any(i => hasTags.Tags.Contains(i, StringComparer.OrdinalIgnoreCase)))
{
return false;
}
@@ -1035,7 +1038,7 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <param name="config">The configuration.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
- protected virtual bool GetBlockUnratedValue(UserConfiguration config)
+ protected virtual bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Other);
}
diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs
index ea7ecfb4a..381b2101d 100644
--- a/MediaBrowser.Controller/Entities/Book.cs
+++ b/MediaBrowser.Controller/Entities/Book.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Model.Configuration;
using System.Collections.Generic;
using System.Linq;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities
{
@@ -36,7 +37,7 @@ namespace MediaBrowser.Controller.Entities
Tags = new List<string>();
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Book);
}
diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index a10742f01..f47a439a7 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -66,6 +66,22 @@ namespace MediaBrowser.Controller.Entities
return CreateResolveArgs(directoryService).FileSystemChildren;
}
+ internal override bool IsValidFromResolver(BaseItem newItem)
+ {
+ var newCollectionFolder = newItem as CollectionFolder;
+
+ if (newCollectionFolder != null)
+ {
+ if (!string.Equals(CollectionType, newCollectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+ }
+
+
+ return base.IsValidFromResolver(newItem);
+ }
+
private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService)
{
var path = ContainingFolderPath;
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 87ad9c380..2761aa5d7 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -303,10 +303,10 @@ namespace MediaBrowser.Controller.Entities
{
if (this is ICollectionFolder)
{
- if (user.Configuration.BlockedMediaFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase) ||
+ if (user.Policy.BlockedMediaFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase) ||
// Backwards compatibility
- user.Configuration.BlockedMediaFolders.Contains(Name, StringComparer.OrdinalIgnoreCase))
+ user.Policy.BlockedMediaFolders.Contains(Name, StringComparer.OrdinalIgnoreCase))
{
return false;
}
@@ -545,7 +545,7 @@ namespace MediaBrowser.Controller.Entities
foreach (var child in children)
{
- if (tasks.Count >= 3)
+ if (tasks.Count >= 2)
{
await Task.WhenAll(tasks).ConfigureAwait(false);
tasks.Clear();
@@ -708,7 +708,7 @@ namespace MediaBrowser.Controller.Entities
/// <returns>IEnumerable{BaseItem}.</returns>
protected virtual IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
{
- var collectionType = LibraryManager.FindCollectionType(this);
+ var collectionType = LibraryManager.GetContentType(this);
return LibraryManager.ResolvePaths(GetFileSystemChildren(directoryService), directoryService, this, collectionType);
}
diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs
index e4d032359..bf32d3e63 100644
--- a/MediaBrowser.Controller/Entities/Game.cs
+++ b/MediaBrowser.Controller/Entities/Game.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities
{
@@ -108,7 +109,7 @@ namespace MediaBrowser.Controller.Entities
return base.GetDeletePaths();
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Game);
}
diff --git a/MediaBrowser.Controller/Entities/GameSystem.cs b/MediaBrowser.Controller/Entities/GameSystem.cs
index f2fec4397..758498977 100644
--- a/MediaBrowser.Controller/Entities/GameSystem.cs
+++ b/MediaBrowser.Controller/Entities/GameSystem.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using System;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities
{
@@ -43,7 +44,7 @@ namespace MediaBrowser.Controller.Entities
return base.GetUserDataKey();
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
// Don't block. Determine by game
return false;
diff --git a/MediaBrowser.Controller/Entities/IHasMediaSources.cs b/MediaBrowser.Controller/Entities/IHasMediaSources.cs
index d487362f5..98d268298 100644
--- a/MediaBrowser.Controller/Entities/IHasMediaSources.cs
+++ b/MediaBrowser.Controller/Entities/IHasMediaSources.cs
@@ -49,8 +49,8 @@ namespace MediaBrowser.Controller.Entities
: new[] { user.Configuration.AudioLanguagePreference };
var preferredSubs = string.IsNullOrEmpty(user.Configuration.SubtitleLanguagePreference)
- ? new string[] { }
- : new[] { user.Configuration.SubtitleLanguagePreference };
+ ? new List<string> { }
+ : new List<string> { user.Configuration.SubtitleLanguagePreference };
foreach (var source in sources)
{
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index 9dc600675..4483c7b0f 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -9,6 +9,7 @@ using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities.Movies
{
@@ -18,7 +19,7 @@ namespace MediaBrowser.Controller.Entities.Movies
public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasPreferredMetadataLanguage, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IMetadataContainer, IHasShares
{
public List<Share> Shares { get; set; }
-
+
public BoxSet()
{
RemoteTrailers = new List<MediaUrl>();
@@ -67,7 +68,7 @@ namespace MediaBrowser.Controller.Entities.Movies
/// <value>The display order.</value>
public string DisplayOrder { get; set; }
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
}
@@ -170,10 +171,13 @@ namespace MediaBrowser.Controller.Entities.Movies
{
var userId = user.Id.ToString("N");
- return Shares.Any(i => string.Equals(userId, i.UserId, StringComparison.OrdinalIgnoreCase)) ||
+ // Need to check Count > 0 for boxsets created prior to the introduction of Shares
+ if (Shares.Count > 0 && !Shares.Any(i => string.Equals(userId, i.UserId, StringComparison.OrdinalIgnoreCase)))
+ {
+ //return false;
+ }
- // Need to support this for boxsets created prior to the creation of Shares
- Shares.Count == 0;
+ return true;
}
return false;
diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs
index e749d89e4..4c1aac700 100644
--- a/MediaBrowser.Controller/Entities/Movies/Movie.cs
+++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs
@@ -8,6 +8,7 @@ using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities.Movies
{
@@ -146,14 +147,21 @@ namespace MediaBrowser.Controller.Entities.Movies
return itemsChanged;
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
}
public MovieInfo GetLookupInfo()
{
- return GetItemLookupInfo<MovieInfo>();
+ var info = GetItemLookupInfo<MovieInfo>();
+
+ if (!IsInMixedFolder)
+ {
+ info.Name = System.IO.Path.GetFileName(ContainingFolderPath);
+ }
+
+ return info;
}
public override bool BeforeMetadataRefresh()
diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs
index d7cd62aa6..4ca8cf1c5 100644
--- a/MediaBrowser.Controller/Entities/MusicVideo.cs
+++ b/MediaBrowser.Controller/Entities/MusicVideo.cs
@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities
{
@@ -80,7 +81,7 @@ namespace MediaBrowser.Controller.Entities
return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.GetUserDataKey();
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Music);
}
diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs
index 367db5dcb..a3d892181 100644
--- a/MediaBrowser.Controller/Entities/Photo.cs
+++ b/MediaBrowser.Controller/Entities/Photo.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Model.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities
{
@@ -69,8 +70,8 @@ namespace MediaBrowser.Controller.Entities
public double? Longitude { get; set; }
public double? Altitude { get; set; }
public int? IsoSpeedRating { get; set; }
-
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Other);
}
diff --git a/MediaBrowser.Controller/Entities/PhotoAlbum.cs b/MediaBrowser.Controller/Entities/PhotoAlbum.cs
index 982b1ef17..24ebf8815 100644
--- a/MediaBrowser.Controller/Entities/PhotoAlbum.cs
+++ b/MediaBrowser.Controller/Entities/PhotoAlbum.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Model.Configuration;
using System.Linq;
using System.Runtime.Serialization;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities
{
@@ -22,8 +23,8 @@ namespace MediaBrowser.Controller.Entities
return true;
}
}
-
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Other);
}
diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs
index cc0fc6812..6b67cebc8 100644
--- a/MediaBrowser.Controller/Entities/TV/Episode.cs
+++ b/MediaBrowser.Controller/Entities/TV/Episode.cs
@@ -1,7 +1,7 @@
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Providers;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Users;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -179,6 +179,15 @@ namespace MediaBrowser.Controller.Entities.TV
}
[IgnoreDataMember]
+ public bool IsInSeasonFolder
+ {
+ get
+ {
+ return FindParent<Season>() != null;
+ }
+ }
+
+ [IgnoreDataMember]
public string SeriesName
{
get
@@ -275,7 +284,7 @@ namespace MediaBrowser.Controller.Entities.TV
return new[] { Path };
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Series);
}
@@ -301,51 +310,9 @@ namespace MediaBrowser.Controller.Entities.TV
{
var hasChanges = base.BeforeMetadataRefresh();
- var locationType = LocationType;
- if (locationType == LocationType.FileSystem || locationType == LocationType.Offline)
- {
- if (!IndexNumber.HasValue && !string.IsNullOrEmpty(Path))
- {
- IndexNumber = LibraryManager.GetEpisodeNumberFromFile(Path, true);
-
- // If a change was made record it
- if (IndexNumber.HasValue)
- {
- hasChanges = true;
- }
- }
-
- if (!IndexNumberEnd.HasValue && !string.IsNullOrEmpty(Path))
- {
- IndexNumberEnd = LibraryManager.GetEndingEpisodeNumberFromFile(Path);
-
- // If a change was made record it
- if (IndexNumberEnd.HasValue)
- {
- hasChanges = true;
- }
- }
- }
-
- if (!ParentIndexNumber.HasValue)
+ if (LibraryManager.FillMissingEpisodeNumbersFromPath(this))
{
- var season = Season;
-
- if (season != null)
- {
- ParentIndexNumber = season.IndexNumber;
- }
-
- if (!ParentIndexNumber.HasValue && !string.IsNullOrEmpty(Path))
- {
- ParentIndexNumber = LibraryManager.GetSeasonNumberFromEpisodeFile(Path);
- }
-
- // If a change was made record it
- if (ParentIndexNumber.HasValue)
- {
- hasChanges = true;
- }
+ hasChanges = true;
}
return hasChanges;
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs
index 2df90244c..54db12b6f 100644
--- a/MediaBrowser.Controller/Entities/TV/Season.cs
+++ b/MediaBrowser.Controller/Entities/TV/Season.cs
@@ -1,9 +1,9 @@
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Localization;
+using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
+using MediaBrowser.Model.Users;
+using MoreLinq;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
@@ -155,24 +155,6 @@ namespace MediaBrowser.Controller.Entities.TV
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
}
- private IEnumerable<Episode> GetEpisodes()
- {
- var series = Series;
-
- if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
- {
- var seasonNumber = IndexNumber;
-
- if (seasonNumber.HasValue)
- {
- return series.RecursiveChildren.OfType<Episode>()
- .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value);
- }
- }
-
- return Children.OfType<Episode>();
- }
-
[IgnoreDataMember]
public bool IsMissingSeason
{
@@ -220,16 +202,32 @@ namespace MediaBrowser.Controller.Entities.TV
var episodes = GetRecursiveChildren(user)
.OfType<Episode>();
- if (IndexNumber.HasValue)
+ var series = Series;
+
+ if (IndexNumber.HasValue && series != null)
{
- var series = Series;
+ return series.GetEpisodes(user, IndexNumber.Value, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
+ }
- if (series != null)
+ if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
+ {
+ var seasonNumber = IndexNumber;
+ var list = episodes.ToList();
+
+ if (seasonNumber.HasValue)
{
- return series.GetEpisodes(user, IndexNumber.Value, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
+ list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>()
+ .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value));
+ }
+ else
+ {
+ list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>()
+ .Where(i => !i.ParentIndexNumber.HasValue));
}
- }
+ episodes = list.DistinctBy(i => i.Id);
+ }
+
if (!includeMissingEpisodes)
{
episodes = episodes.Where(i => !i.IsMissingEpisode);
@@ -244,12 +242,39 @@ namespace MediaBrowser.Controller.Entities.TV
.Cast<Episode>();
}
+ private IEnumerable<Episode> GetEpisodes()
+ {
+ var episodes = RecursiveChildren.OfType<Episode>();
+ var series = Series;
+
+ if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
+ {
+ var seasonNumber = IndexNumber;
+ var list = episodes.ToList();
+
+ if (seasonNumber.HasValue)
+ {
+ list.AddRange(series.RecursiveChildren.OfType<Episode>()
+ .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value));
+ }
+ else
+ {
+ list.AddRange(series.RecursiveChildren.OfType<Episode>()
+ .Where(i => !i.ParentIndexNumber.HasValue));
+ }
+
+ episodes = list.DistinctBy(i => i.Id);
+ }
+
+ return episodes;
+ }
+
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
{
return GetEpisodes(user);
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
// Don't block. Let either the entire series rating or episode rating determine it
return false;
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs
index 4c0d1fdfb..55cfffeb2 100644
--- a/MediaBrowser.Controller/Entities/TV/Series.cs
+++ b/MediaBrowser.Controller/Entities/TV/Series.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
+using MediaBrowser.Model.Users;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -87,7 +88,17 @@ namespace MediaBrowser.Controller.Entities.TV
/// Gets or sets the date last episode added.
/// </summary>
/// <value>The date last episode added.</value>
- public DateTime DateLastEpisodeAdded { get; set; }
+ [IgnoreDataMember]
+ public DateTime DateLastEpisodeAdded
+ {
+ get
+ {
+ return RecursiveChildren.OfType<Episode>()
+ .Select(i => i.DateCreated)
+ .OrderByDescending(i => i)
+ .FirstOrDefault();
+ }
+ }
/// <summary>
/// Series aren't included directly in indices - Their Episodes will roll up to them
@@ -246,7 +257,7 @@ namespace MediaBrowser.Controller.Entities.TV
});
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Series);
}
diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs
index bb165d790..7a1eef8db 100644
--- a/MediaBrowser.Controller/Entities/Trailer.cs
+++ b/MediaBrowser.Controller/Entities/Trailer.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.Serialization;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities
{
@@ -98,7 +99,7 @@ namespace MediaBrowser.Controller.Entities
return base.GetUserDataKey();
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Trailer);
}
diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs
index 3dfc8cc7d..626afcfdf 100644
--- a/MediaBrowser.Controller/Entities/User.cs
+++ b/MediaBrowser.Controller/Entities/User.cs
@@ -1,5 +1,4 @@
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Connect;
@@ -107,37 +106,27 @@ namespace MediaBrowser.Controller.Entities
/// <value>The last activity date.</value>
public DateTime? LastActivityDate { get; set; }
- /// <summary>
- /// The _configuration
- /// </summary>
- private UserConfiguration _configuration;
- /// <summary>
- /// The _configuration initialized
- /// </summary>
- private bool _configurationInitialized;
- /// <summary>
- /// The _configuration sync lock
- /// </summary>
- private object _configurationSyncLock = new object();
- /// <summary>
- /// Gets the user's configuration
- /// </summary>
- /// <value>The configuration.</value>
+ private UserConfiguration _config;
+ private readonly object _configSyncLock = new object();
[IgnoreDataMember]
public UserConfiguration Configuration
{
get
{
- // Lazy load
- LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationInitialized, ref _configurationSyncLock, () => (UserConfiguration)ConfigurationHelper.GetXmlConfiguration(typeof(UserConfiguration), ConfigurationFilePath, XmlSerializer));
- return _configuration;
- }
- private set
- {
- _configuration = value;
+ if (_config == null)
+ {
+ lock (_configSyncLock)
+ {
+ if (_config == null)
+ {
+ _config = UserManager.GetUserConfiguration(this);
+ }
+ }
+ }
- _configurationInitialized = value != null;
+ return _config;
}
+ set { _config = value; }
}
private UserPolicy _policy;
@@ -256,35 +245,6 @@ namespace MediaBrowser.Controller.Entities
return System.IO.Path.Combine(parentPath, Id.ToString("N"));
}
- /// <summary>
- /// Gets the path to the user's configuration file
- /// </summary>
- /// <value>The configuration file path.</value>
- [IgnoreDataMember]
- public string ConfigurationFilePath
- {
- get
- {
- return System.IO.Path.Combine(ConfigurationDirectoryPath, "config.xml");
- }
- }
-
- /// <summary>
- /// Updates the configuration.
- /// </summary>
- /// <param name="config">The config.</param>
- /// <exception cref="System.ArgumentNullException">config</exception>
- public void UpdateConfiguration(UserConfiguration config)
- {
- if (config == null)
- {
- throw new ArgumentNullException("config");
- }
-
- Configuration = config;
- UserManager.UpdateConfiguration(this, Configuration);
- }
-
public bool IsParentalScheduleAllowed()
{
return IsParentalScheduleAllowed(DateTime.UtcNow);
@@ -292,7 +252,7 @@ namespace MediaBrowser.Controller.Entities
public bool IsParentalScheduleAllowed(DateTime date)
{
- var schedules = Configuration.AccessSchedules;
+ var schedules = Policy.AccessSchedules;
if (schedules.Length == 0)
{
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index 926ffa19c..0364ff678 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -63,7 +63,8 @@ namespace MediaBrowser.Controller.Entities
{
CollectionType.Books,
CollectionType.HomeVideos,
- CollectionType.Photos
+ CollectionType.Photos,
+ string.Empty
};
var collectionFolder = folder as ICollectionFolder;
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index 33dea4dca..8573f32e0 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Controller.Sorting;
@@ -22,11 +23,9 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="fileInfo">The file information.</param>
/// <param name="parent">The parent.</param>
- /// <param name="collectionType">Type of the collection.</param>
/// <returns>BaseItem.</returns>
BaseItem ResolvePath(FileSystemInfo fileInfo,
- Folder parent = null,
- string collectionType = null);
+ Folder parent = null);
/// <summary>
/// Resolves a set of files into a list of BaseItem
@@ -258,9 +257,16 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
- string FindCollectionType(BaseItem item);
+ string GetContentType(BaseItem item);
/// <summary>
+ /// Gets the type of the inherited content.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>System.String.</returns>
+ string GetInheritedContentType(BaseItem item);
+
+ /// <summary>
/// Normalizes the root path list.
/// </summary>
/// <param name="paths">The paths.</param>
@@ -340,26 +346,11 @@ namespace MediaBrowser.Controller.Library
int? GetSeasonNumberFromPath(string path);
/// <summary>
- /// Gets the season number from episode file.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <returns>System.Nullable&lt;System.Int32&gt;.</returns>
- int? GetSeasonNumberFromEpisodeFile(string path);
-
- /// <summary>
- /// Gets the ending episode number from file.
+ /// Fills the missing episode numbers from path.
/// </summary>
- /// <param name="path">The path.</param>
- /// <returns>System.Nullable&lt;System.Int32&gt;.</returns>
- int? GetEndingEpisodeNumberFromFile(string path);
-
- /// <summary>
- /// Gets the episode number from file.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="considerSeasonless">if set to <c>true</c> [consider seasonless].</param>
- /// <returns>System.Nullable&lt;System.Int32&gt;.</returns>
- int? GetEpisodeNumberFromFile(string path, bool considerSeasonless);
+ /// <param name="episode">The episode.</param>
+ /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
+ bool FillMissingEpisodeNumbersFromPath(Episode episode);
/// <summary>
/// Parses the name.
diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs
index 226f77525..06e7d1763 100644
--- a/MediaBrowser.Controller/Library/IUserDataManager.cs
+++ b/MediaBrowser.Controller/Library/IUserDataManager.cs
@@ -61,5 +61,9 @@ namespace MediaBrowser.Controller.Library
/// <returns></returns>
Task SaveAllUserData(Guid userId, IEnumerable<UserItemData> userData, CancellationToken cancellationToken);
+ /// <summary>
+ /// Updates playstate for an item and returns true or false indicating if it was played to completion
+ /// </summary>
+ bool UpdatePlayState(BaseItem item, UserItemData data, long positionTicks);
}
}
diff --git a/MediaBrowser.Controller/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs
index 9dc16ba4d..f5846973e 100644
--- a/MediaBrowser.Controller/Library/IUserManager.cs
+++ b/MediaBrowser.Controller/Library/IUserManager.cs
@@ -36,13 +36,6 @@ namespace MediaBrowser.Controller.Library
event EventHandler<GenericEventArgs<User>> UserPasswordChanged;
/// <summary>
- /// Updates the configuration.
- /// </summary>
- /// <param name="user">The user.</param>
- /// <param name="newConfiguration">The new configuration.</param>
- void UpdateConfiguration(User user, UserConfiguration newConfiguration);
-
- /// <summary>
/// Gets a User by Id
/// </summary>
/// <param name="id">The id.</param>
@@ -173,10 +166,32 @@ namespace MediaBrowser.Controller.Library
UserPolicy GetUserPolicy(User user);
/// <summary>
+ /// Gets the user configuration.
+ /// </summary>
+ /// <param name="user">The user.</param>
+ /// <returns>UserConfiguration.</returns>
+ UserConfiguration GetUserConfiguration(User user);
+
+ /// <summary>
+ /// Updates the configuration.
+ /// </summary>
+ /// <param name="userId">The user identifier.</param>
+ /// <param name="newConfiguration">The new configuration.</param>
+ /// <returns>Task.</returns>
+ Task UpdateConfiguration(string userId, UserConfiguration newConfiguration);
+
+ /// <summary>
/// Updates the user policy.
/// </summary>
/// <param name="userId">The user identifier.</param>
/// <param name="userPolicy">The user policy.</param>
Task UpdateUserPolicy(string userId, UserPolicy userPolicy);
+
+ /// <summary>
+ /// Makes the valid username.
+ /// </summary>
+ /// <param name="username">The username.</param>
+ /// <returns>System.String.</returns>
+ string MakeValidUsername(string username);
}
}
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
index 9f8d67a48..b95d67ad8 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using System.Linq;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.LiveTv
{
@@ -78,7 +79,7 @@ namespace MediaBrowser.Controller.LiveTv
}
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram);
}
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
index df118b25f..de72accff 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
@@ -6,6 +6,7 @@ using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.MediaInfo;
using System.Collections.Generic;
using System.Linq;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.LiveTv
{
@@ -33,7 +34,7 @@ namespace MediaBrowser.Controller.LiveTv
}
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvChannel);
}
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
index 266eaabee..29b23a551 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
@@ -6,6 +6,7 @@ using System;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.LiveTv
{
@@ -199,7 +200,7 @@ namespace MediaBrowser.Controller.LiveTv
return ItemRepository.SaveItem(this, cancellationToken);
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram);
}
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
index 66de81213..6fc985643 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using System.Linq;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.LiveTv
{
@@ -78,7 +79,7 @@ namespace MediaBrowser.Controller.LiveTv
}
}
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.LiveTvProgram);
}
diff --git a/MediaBrowser.Controller/LiveTv/RecordingGroup.cs b/MediaBrowser.Controller/LiveTv/RecordingGroup.cs
index 7bd810b8d..d7250d9d2 100644
--- a/MediaBrowser.Controller/LiveTv/RecordingGroup.cs
+++ b/MediaBrowser.Controller/LiveTv/RecordingGroup.cs
@@ -1,11 +1,12 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.LiveTv
{
public class RecordingGroup : Folder
{
- protected override bool GetBlockUnratedValue(UserConfiguration config)
+ protected override bool GetBlockUnratedValue(UserPolicy config)
{
// Don't block.
return false;
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index c198a58d4..3ed87ced8 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -198,18 +198,16 @@
<Compile Include="LiveTv\SeriesTimerInfo.cs" />
<Compile Include="LiveTv\TimerInfo.cs" />
<Compile Include="Localization\ILocalizationManager.cs" />
- <Compile Include="MediaEncoding\EncodingOptions.cs" />
<Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" />
- <Compile Include="MediaEncoding\EncodingResult.cs" />
<Compile Include="MediaEncoding\IEncodingManager.cs" />
<Compile Include="MediaEncoding\ImageEncodingOptions.cs" />
<Compile Include="MediaEncoding\IMediaEncoder.cs" />
<Compile Include="MediaEncoding\InternalMediaInfoResult.cs" />
<Compile Include="MediaEncoding\ISubtitleEncoder.cs" />
<Compile Include="MediaEncoding\MediaStreamSelector.cs" />
- <Compile Include="MediaEncoding\VideoEncodingOptions.cs" />
<Compile Include="Net\AuthenticatedAttribute.cs" />
<Compile Include="Net\AuthorizationInfo.cs" />
+ <Compile Include="Net\BasePeriodicWebSocketListener.cs" />
<Compile Include="Net\IAuthorizationContext.cs" />
<Compile Include="Net\IAuthService.cs" />
<Compile Include="Net\IHasAuthorization.cs" />
@@ -221,10 +219,15 @@
<Compile Include="Net\IServerManager.cs" />
<Compile Include="Net\IServiceRequest.cs" />
<Compile Include="Net\ISessionContext.cs" />
+ <Compile Include="Net\IWebSocket.cs" />
+ <Compile Include="Net\IWebSocketConnection.cs" />
+ <Compile Include="Net\IWebSocketListener.cs" />
<Compile Include="Net\LoggedAttribute.cs" />
<Compile Include="Net\SecurityException.cs" />
<Compile Include="Net\ServiceStackServiceRequest.cs" />
<Compile Include="Net\StaticResultOptions.cs" />
+ <Compile Include="Net\WebSocketConnectEventArgs.cs" />
+ <Compile Include="Net\WebSocketMessageInfo.cs" />
<Compile Include="News\INewsService.cs" />
<Compile Include="Notifications\INotificationManager.cs" />
<Compile Include="Notifications\INotificationService.cs" />
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingOptions.cs
deleted file mode 100644
index 26182ebc4..000000000
--- a/MediaBrowser.Controller/MediaEncoding/EncodingOptions.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using MediaBrowser.Controller.Dlna;
-using MediaBrowser.Model.Dlna;
-
-namespace MediaBrowser.Controller.MediaEncoding
-{
- public class EncodingOptions
- {
- /// <summary>
- /// Gets or sets the item identifier.
- /// </summary>
- /// <value>The item identifier.</value>
- public string ItemId { get; set; }
-
- /// <summary>
- /// Gets or sets the media source identifier.
- /// </summary>
- /// <value>The media source identifier.</value>
- public string MediaSourceId { get; set; }
-
- /// <summary>
- /// Gets or sets the device profile.
- /// </summary>
- /// <value>The device profile.</value>
- public DeviceProfile DeviceProfile { get; set; }
-
- /// <summary>
- /// Gets or sets the output path.
- /// </summary>
- /// <value>The output path.</value>
- public string OutputPath { get; set; }
-
- /// <summary>
- /// Gets or sets the container.
- /// </summary>
- /// <value>The container.</value>
- public string Container { get; set; }
-
- /// <summary>
- /// Gets or sets the audio codec.
- /// </summary>
- /// <value>The audio codec.</value>
- public string AudioCodec { get; set; }
-
- /// <summary>
- /// Gets or sets the start time ticks.
- /// </summary>
- /// <value>The start time ticks.</value>
- public long? StartTimeTicks { get; set; }
-
- /// <summary>
- /// Gets or sets the maximum channels.
- /// </summary>
- /// <value>The maximum channels.</value>
- public int? MaxAudioChannels { get; set; }
-
- /// <summary>
- /// Gets or sets the channels.
- /// </summary>
- /// <value>The channels.</value>
- public int? AudioChannels { get; set; }
-
- /// <summary>
- /// Gets or sets the sample rate.
- /// </summary>
- /// <value>The sample rate.</value>
- public int? AudioSampleRate { get; set; }
-
- /// <summary>
- /// Gets or sets the bit rate.
- /// </summary>
- /// <value>The bit rate.</value>
- public int? AudioBitRate { get; set; }
-
- /// <summary>
- /// Gets or sets the maximum audio bit rate.
- /// </summary>
- /// <value>The maximum audio bit rate.</value>
- public int? MaxAudioBitRate { get; set; }
- }
-}
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingResult.cs b/MediaBrowser.Controller/MediaEncoding/EncodingResult.cs
deleted file mode 100644
index 75ee90e42..000000000
--- a/MediaBrowser.Controller/MediaEncoding/EncodingResult.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Controller.MediaEncoding
-{
- public class EncodingResult
- {
- public string OutputPath { get; set; }
- }
-}
diff --git a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs
index 58a68c257..4a807df7a 100644
--- a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs
+++ b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs
@@ -34,15 +34,13 @@ namespace MediaBrowser.Controller.MediaEncoding
}
public static int? GetDefaultSubtitleStreamIndex(List<MediaStream> streams,
- IEnumerable<string> preferredLanguages,
+ List<string> preferredLanguages,
SubtitlePlaybackMode mode,
string audioTrackLanguage)
{
- var languages = preferredLanguages.ToList();
- streams = GetSortedStreams(streams, MediaStreamType.Subtitle, languages).ToList();
+ streams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages).ToList();
var full = streams.Where(s => !s.IsForced);
- var forced = streams.Where(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase));
MediaStream stream = null;
@@ -54,9 +52,9 @@ namespace MediaBrowser.Controller.MediaEncoding
if (mode == SubtitlePlaybackMode.Default)
{
// if the audio language is not understood by the user, load their preferred subs, if there are any
- if (!ContainsOrdinal(languages, audioTrackLanguage))
+ if (!ContainsOrdinal(preferredLanguages, audioTrackLanguage))
{
- stream = full.FirstOrDefault(s => ContainsOrdinal(languages, s.Language));
+ stream = full.FirstOrDefault(s => ContainsOrdinal(preferredLanguages, s.Language));
}
}
else if (mode == SubtitlePlaybackMode.Always)
@@ -66,7 +64,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// load forced subs if we have found no suitable full subtitles
- stream = stream ?? forced.FirstOrDefault();
+ stream = stream ?? streams.FirstOrDefault(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase));
if (stream != null)
{
diff --git a/MediaBrowser.Controller/MediaEncoding/VideoEncodingOptions.cs b/MediaBrowser.Controller/MediaEncoding/VideoEncodingOptions.cs
deleted file mode 100644
index 773f0ea46..000000000
--- a/MediaBrowser.Controller/MediaEncoding/VideoEncodingOptions.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-
-namespace MediaBrowser.Controller.MediaEncoding
-{
- public class VideoEncodingOptions : EncodingOptions
- {
- public string VideoCodec { get; set; }
-
- public string VideoProfile { get; set; }
-
- public double? VideoLevel { get; set; }
-
- public int? VideoStreamIndex { get; set; }
-
- public int? AudioStreamIndex { get; set; }
-
- public int? SubtitleStreamIndex { get; set; }
-
- public int? MaxWidth { get; set; }
-
- public int? MaxHeight { get; set; }
-
- public int? Height { get; set; }
-
- public int? Width { get; set; }
- }
-}
diff --git a/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs
index a2af3707b..f1e371c1a 100644
--- a/MediaBrowser.Common/Net/BasePeriodicWebSocketListener.cs
+++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Logging;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using System;
using System.Collections.Generic;
@@ -7,7 +8,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-namespace MediaBrowser.Common.Net
+namespace MediaBrowser.Controller.Net
{
/// <summary>
/// Starts sending data over a web socket periodically when a message is received, and then stops when a corresponding stop message is received
diff --git a/MediaBrowser.Common/Net/IWebSocket.cs b/MediaBrowser.Controller/Net/IWebSocket.cs
index b31a95319..b88f2c389 100644
--- a/MediaBrowser.Common/Net/IWebSocket.cs
+++ b/MediaBrowser.Controller/Net/IWebSocket.cs
@@ -3,7 +3,7 @@ using System;
using System.Threading;
using System.Threading.Tasks;
-namespace MediaBrowser.Common.Net
+namespace MediaBrowser.Controller.Net
{
/// <summary>
/// Interface IWebSocket
diff --git a/MediaBrowser.Common/Net/IWebSocketConnection.cs b/MediaBrowser.Controller/Net/IWebSocketConnection.cs
index b7715e20b..37fd6708d 100644
--- a/MediaBrowser.Common/Net/IWebSocketConnection.cs
+++ b/MediaBrowser.Controller/Net/IWebSocketConnection.cs
@@ -3,7 +3,7 @@ using System;
using System.Threading;
using System.Threading.Tasks;
-namespace MediaBrowser.Common.Net
+namespace MediaBrowser.Controller.Net
{
public interface IWebSocketConnection : IDisposable
{
diff --git a/MediaBrowser.Common/Net/IWebSocketListener.cs b/MediaBrowser.Controller/Net/IWebSocketListener.cs
index 4b6c4111d..2b4fc7676 100644
--- a/MediaBrowser.Common/Net/IWebSocketListener.cs
+++ b/MediaBrowser.Controller/Net/IWebSocketListener.cs
@@ -1,6 +1,7 @@
-using System.Threading.Tasks;
+using MediaBrowser.Common.Net;
+using System.Threading.Tasks;
-namespace MediaBrowser.Common.Net
+namespace MediaBrowser.Controller.Net
{
/// <summary>
///This is an interface for listening to messages coming through a web socket connection
diff --git a/MediaBrowser.Common/Net/WebSocketConnectEventArgs.cs b/MediaBrowser.Controller/Net/WebSocketConnectEventArgs.cs
index ce22c9520..394fcd92f 100644
--- a/MediaBrowser.Common/Net/WebSocketConnectEventArgs.cs
+++ b/MediaBrowser.Controller/Net/WebSocketConnectEventArgs.cs
@@ -1,6 +1,6 @@
using System;
-namespace MediaBrowser.Common.Net
+namespace MediaBrowser.Controller.Net
{
/// <summary>
/// Class WebSocketConnectEventArgs
diff --git a/MediaBrowser.Common/Net/WebSocketMessageInfo.cs b/MediaBrowser.Controller/Net/WebSocketMessageInfo.cs
index c1f935a7b..332f16420 100644
--- a/MediaBrowser.Common/Net/WebSocketMessageInfo.cs
+++ b/MediaBrowser.Controller/Net/WebSocketMessageInfo.cs
@@ -1,6 +1,6 @@
using MediaBrowser.Model.Net;
-namespace MediaBrowser.Common.Net
+namespace MediaBrowser.Controller.Net
{
/// <summary>
/// Class WebSocketMessageInfo
diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs
index 74a9c6606..06ea7be02 100644
--- a/MediaBrowser.Controller/Providers/DirectoryService.cs
+++ b/MediaBrowser.Controller/Providers/DirectoryService.cs
@@ -46,6 +46,11 @@ namespace MediaBrowser.Controller.Providers
private Dictionary<string, FileSystemInfo> GetFileSystemDictionary(string path, bool clearCache)
{
+ if (string.IsNullOrWhiteSpace(path))
+ {
+ throw new ArgumentNullException("path");
+ }
+
Dictionary<string, FileSystemInfo> entries;
if (clearCache)
diff --git a/MediaBrowser.Controller/Sync/ISyncManager.cs b/MediaBrowser.Controller/Sync/ISyncManager.cs
index 47339f677..39cec4f00 100644
--- a/MediaBrowser.Controller/Sync/ISyncManager.cs
+++ b/MediaBrowser.Controller/Sync/ISyncManager.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Sync;
using System.Collections.Generic;
using System.Threading.Tasks;
+using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Sync
{
@@ -80,5 +81,19 @@ namespace MediaBrowser.Controller.Sync
/// <param name="id">The identifier.</param>
/// <returns>SyncJobItem.</returns>
SyncJobItem GetJobItem(string id);
+
+ /// <summary>
+ /// Reports the offline action.
+ /// </summary>
+ /// <param name="action">The action.</param>
+ /// <returns>Task.</returns>
+ Task ReportOfflineAction(UserAction action);
+
+ /// <summary>
+ /// Gets the ready synchronize items.
+ /// </summary>
+ /// <param name="targetId">The target identifier.</param>
+ /// <returns>List&lt;SyncedItem&gt;.</returns>
+ List<SyncedItem> GetReadySyncItems(string targetId);
}
}
diff --git a/MediaBrowser.Controller/Sync/ISyncProvider.cs b/MediaBrowser.Controller/Sync/ISyncProvider.cs
index 89f61b80e..5ebdee207 100644
--- a/MediaBrowser.Controller/Sync/ISyncProvider.cs
+++ b/MediaBrowser.Controller/Sync/ISyncProvider.cs
@@ -25,4 +25,9 @@ namespace MediaBrowser.Controller.Sync
/// <returns>DeviceProfile.</returns>
DeviceProfile GetDeviceProfile(SyncTarget target);
}
+
+ public interface IHasUniqueTargetIds
+ {
+
+ }
}
diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
index bdb1c4cbf..d1941c856 100644
--- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs
+++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
@@ -18,6 +18,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Xml;
+using MediaBrowser.Model.Net;
namespace MediaBrowser.Dlna.Didl
{
diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs
index 6f8047e4c..74e3b61ca 100644
--- a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs
+++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs
@@ -28,8 +28,6 @@ namespace MediaBrowser.LocalMetadata
var path = file.FullName;
- //await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
-
try
{
result.Item = new T();
@@ -45,10 +43,6 @@ namespace MediaBrowser.LocalMetadata
{
result.HasMetadata = false;
}
- finally
- {
- //XmlProviderUtils.XmlParsingResourcePool.Release();
- }
return result;
}
@@ -90,7 +84,7 @@ namespace MediaBrowser.LocalMetadata
{
get
{
- return "Media Browser Legacy Xml";
+ return "Media Browser Xml";
}
}
diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
index 044d29a1b..7f83aa61d 100644
--- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
@@ -1,7 +1,6 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
@@ -76,11 +75,14 @@ namespace MediaBrowser.LocalMetadata.Images
{
return directoryService.GetFileSystemEntries(path)
.Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase) ||
- (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory);
+ (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
+
+ .OrderBy(i => BaseItem.SupportedImageExtensionsList.IndexOf(i.Extension ?? string.Empty));
}
return directoryService.GetFiles(path)
- .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase));
+ .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase))
+ .OrderBy(i => BaseItem.SupportedImageExtensionsList.IndexOf(i.Extension ?? string.Empty));
}
public List<LocalImageInfo> GetImages(IHasImages item, IDirectoryService directoryService)
@@ -109,6 +111,7 @@ namespace MediaBrowser.LocalMetadata.Images
return !string.IsNullOrEmpty(ext) &&
BaseItem.SupportedImageExtensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
})
+ .OrderBy(i => BaseItem.SupportedImageExtensionsList.IndexOf(i.Extension ?? string.Empty))
.ToList();
var list = new List<LocalImageInfo>();
@@ -166,8 +169,8 @@ namespace MediaBrowser.LocalMetadata.Images
var names = new List<string>
{
"folder",
- "cover",
"poster",
+ "cover",
"default"
};
@@ -402,13 +405,7 @@ namespace MediaBrowser.LocalMetadata.Images
private FileSystemInfo GetImage(IEnumerable<FileSystemInfo> files, string name)
{
- var candidates = files
- .Where(i => string.Equals(name, _fileSystem.GetFileNameWithoutExtension(i), StringComparison.OrdinalIgnoreCase))
- .ToList();
-
- return BaseItem.SupportedImageExtensions
- .Select(i => candidates.FirstOrDefault(c => string.Equals(c.Extension, i, StringComparison.OrdinalIgnoreCase)))
- .FirstOrDefault(i => i != null);
+ return files.FirstOrDefault(i => ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory) && string.Equals(name, _fileSystem.GetFileNameWithoutExtension(i), StringComparison.OrdinalIgnoreCase));
}
}
}
diff --git a/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs
index fa3d7d87d..67fa12b55 100644
--- a/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/FolderXmlSaver.cs
@@ -49,7 +49,7 @@ namespace MediaBrowser.LocalMetadata.Savers
!(item is GameSystem) &&
!(item is Playlist))
{
- return updateType >= ItemUpdateType.MetadataDownload;
+ return updateType >= ItemUpdateType.MetadataEdit;
}
}
diff --git a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
index 3e11c994b..4388ec964 100644
--- a/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
+++ b/MediaBrowser.LocalMetadata/Savers/XmlSaverHelpers.cs
@@ -649,7 +649,7 @@ namespace MediaBrowser.LocalMetadata.Savers
var hasShares = item as IHasShares;
if (hasShares != null)
{
-
+ AddShares(hasShares, builder);
}
}
diff --git a/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs
new file mode 100644
index 000000000..17470d206
--- /dev/null
+++ b/MediaBrowser.MediaEncoding/Configuration/EncodingConfigurationFactory.cs
@@ -0,0 +1,45 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Configuration;
+using System.Collections.Generic;
+using System.IO;
+
+namespace MediaBrowser.MediaEncoding.Configuration
+{
+ public class EncodingConfigurationFactory : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new[]
+ {
+ new EncodingConfigurationStore()
+ };
+ }
+ }
+
+ public class EncodingConfigurationStore : ConfigurationStore, IValidatingConfiguration
+ {
+ public EncodingConfigurationStore()
+ {
+ ConfigurationType = typeof(EncodingOptions);
+ Key = "encoding";
+ }
+
+ public void Validate(object oldConfig, object newConfig)
+ {
+ var oldEncodingConfig = (EncodingOptions)oldConfig;
+ var newEncodingConfig = (EncodingOptions)newConfig;
+
+ var newPath = newEncodingConfig.TranscodingTempPath;
+
+ if (!string.IsNullOrWhiteSpace(newPath)
+ && !string.Equals(oldEncodingConfig.TranscodingTempPath ?? string.Empty, newPath))
+ {
+ // Validate
+ if (!Directory.Exists(newPath))
+ {
+ throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath));
+ }
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
index 6f59b7bec..5c472ebc8 100644
--- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
+++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
@@ -56,6 +56,7 @@
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="BdInfo\BdInfoExaminer.cs" />
+ <Compile Include="Configuration\EncodingConfigurationFactory.cs" />
<Compile Include="Encoder\EncodingUtils.cs" />
<Compile Include="Encoder\MediaEncoder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index 7c512840b..67c9123f5 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -613,6 +613,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
}
+ catch (DirectoryNotFoundException)
+ {
+
+ }
catch (IOException ex)
{
_logger.ErrorException("Error deleting extracted subtitle {0}", ex, outputPath);
diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
index 2629dac8b..f4d92b6f3 100644
--- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
+++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
@@ -10,8 +10,8 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MediaBrowser.Model</RootNamespace>
<AssemblyName>MediaBrowser.Model</AssemblyName>
- <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
- <TargetFrameworkProfile>Profile344</TargetFrameworkProfile>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
@@ -188,6 +188,9 @@
<Compile Include="..\MediaBrowser.Model\Configuration\DynamicDayOfWeek.cs">
<Link>Configuration\DynamicDayOfWeek.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\EncodingOptions.cs">
+ <Link>Configuration\EncodingOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\EncodingQuality.cs">
<Link>Configuration\EncodingQuality.cs</Link>
</Compile>
@@ -461,6 +464,12 @@
<Compile Include="..\MediaBrowser.Model\Dto\MediaSourceType.cs">
<Link>Dto\MediaSourceType.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dto\MetadataEditorInfo.cs">
+ <Link>Dto\MetadataEditorInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Dto\NameValuePair.cs">
+ <Link>Dto\NameValuePair.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\RatingType.cs">
<Link>Dto\RatingType.cs</Link>
</Compile>
@@ -470,9 +479,6 @@
<Compile Include="..\MediaBrowser.Model\Dto\RecommendationType.cs">
<Link>Dto\RecommendationType.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Dto\StreamOptions.cs">
- <Link>Dto\StreamOptions.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\StudioDto.cs">
<Link>Dto\StudioDto.cs</Link>
</Compile>
@@ -788,6 +794,12 @@
<Compile Include="..\MediaBrowser.Model\Net\HttpException.cs">
<Link>Net\HttpException.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Net\HttpResponse.cs">
+ <Link>Net\HttpResponse.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Net\MimeTypes.cs">
+ <Link>Net\MimeTypes.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Net\NetworkShare.cs">
<Link>Net\NetworkShare.cs</Link>
</Compile>
@@ -1028,12 +1040,30 @@
<Compile Include="..\MediaBrowser.Model\Session\UserDataChangeInfo.cs">
<Link>Session\UserDataChangeInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\DeviceFileInfo.cs">
+ <Link>Sync\DeviceFileInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\ItemFIleInfo.cs">
+ <Link>Sync\ItemFIleInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\ItemFileType.cs">
+ <Link>Sync\ItemFileType.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\LocalItem.cs">
+ <Link>Sync\LocalItem.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Sync\SyncCategory.cs">
<Link>Sync\SyncCategory.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Sync\SyncDialogOptions.cs">
<Link>Sync\SyncDialogOptions.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncedItem.cs">
+ <Link>Sync\SyncedItem.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncHelper.cs">
+ <Link>Sync\SyncHelper.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Sync\SyncJob.cs">
<Link>Sync\SyncJob.cs</Link>
</Compile>
@@ -1136,6 +1166,12 @@
<Compile Include="..\MediaBrowser.Model\Users\PinRedeemResult.cs">
<Link>Users\PinRedeemResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Users\UserAction.cs">
+ <Link>Users\UserAction.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Users\UserActionType.cs">
+ <Link>Users\UserActionType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Users\UserPolicy.cs">
<Link>Users\UserPolicy.cs</Link>
</Compile>
diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
index 4840777a5..b07e8557f 100644
--- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
+++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
@@ -153,6 +153,9 @@
<Compile Include="..\MediaBrowser.Model\Configuration\DynamicDayOfWeek.cs">
<Link>Configuration\DynamicDayOfWeek.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Configuration\EncodingOptions.cs">
+ <Link>Configuration\EncodingOptions.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Configuration\EncodingQuality.cs">
<Link>Configuration\EncodingQuality.cs</Link>
</Compile>
@@ -426,6 +429,12 @@
<Compile Include="..\MediaBrowser.Model\Dto\MediaSourceType.cs">
<Link>Dto\MediaSourceType.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Dto\MetadataEditorInfo.cs">
+ <Link>Dto\MetadataEditorInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Dto\NameValuePair.cs">
+ <Link>Dto\NameValuePair.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\RatingType.cs">
<Link>Dto\RatingType.cs</Link>
</Compile>
@@ -435,9 +444,6 @@
<Compile Include="..\MediaBrowser.Model\Dto\RecommendationType.cs">
<Link>Dto\RecommendationType.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Dto\StreamOptions.cs">
- <Link>Dto\StreamOptions.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Dto\StudioDto.cs">
<Link>Dto\StudioDto.cs</Link>
</Compile>
@@ -747,6 +753,12 @@
<Compile Include="..\MediaBrowser.Model\Net\HttpException.cs">
<Link>Net\HttpException.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Net\HttpResponse.cs">
+ <Link>Net\HttpResponse.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Net\MimeTypes.cs">
+ <Link>Net\MimeTypes.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Net\NetworkShare.cs">
<Link>Net\NetworkShare.cs</Link>
</Compile>
@@ -987,12 +999,30 @@
<Compile Include="..\MediaBrowser.Model\Session\UserDataChangeInfo.cs">
<Link>Session\UserDataChangeInfo.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\DeviceFileInfo.cs">
+ <Link>Sync\DeviceFileInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\ItemFIleInfo.cs">
+ <Link>Sync\ItemFIleInfo.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\ItemFileType.cs">
+ <Link>Sync\ItemFileType.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\LocalItem.cs">
+ <Link>Sync\LocalItem.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Sync\SyncCategory.cs">
<Link>Sync\SyncCategory.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Sync\SyncDialogOptions.cs">
<Link>Sync\SyncDialogOptions.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncedItem.cs">
+ <Link>Sync\SyncedItem.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Sync\SyncHelper.cs">
+ <Link>Sync\SyncHelper.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Sync\SyncJob.cs">
<Link>Sync\SyncJob.cs</Link>
</Compile>
@@ -1095,6 +1125,12 @@
<Compile Include="..\MediaBrowser.Model\Users\PinRedeemResult.cs">
<Link>Users\PinRedeemResult.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\Users\UserAction.cs">
+ <Link>Users\UserAction.cs</Link>
+ </Compile>
+ <Compile Include="..\MediaBrowser.Model\Users\UserActionType.cs">
+ <Link>Users\UserActionType.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Users\UserPolicy.cs">
<Link>Users\UserPolicy.cs</Link>
</Compile>
diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs
index 9521f8538..883e54308 100644
--- a/MediaBrowser.Model/ApiClient/IApiClient.cs
+++ b/MediaBrowser.Model/ApiClient/IApiClient.cs
@@ -7,6 +7,7 @@ using MediaBrowser.Model.Events;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.MediaInfo;
+using MediaBrowser.Model.Net;
using MediaBrowser.Model.Notifications;
using MediaBrowser.Model.Playlists;
using MediaBrowser.Model.Plugins;
@@ -186,6 +187,30 @@ namespace MediaBrowser.Model.ApiClient
Task<Stream> GetImageStreamAsync(string url, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
+ /// Gets the stream.
+ /// </summary>
+ /// <param name="url">The URL.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task&lt;Stream&gt;.</returns>
+ Task<Stream> GetStream(string url, CancellationToken cancellationToken = default(CancellationToken));
+
+ /// <summary>
+ /// Gets the response.
+ /// </summary>
+ /// <param name="url">The URL.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task&lt;HttpResponse&gt;.</returns>
+ Task<HttpResponse> GetResponse(string url, CancellationToken cancellationToken = default(CancellationToken));
+
+ /// <summary>
+ /// Updates the user configuration.
+ /// </summary>
+ /// <param name="userId">The user identifier.</param>
+ /// <param name="configuration">The configuration.</param>
+ /// <returns>Task.</returns>
+ Task UpdateUserConfiguration(string userId, UserConfiguration configuration);
+
+ /// <summary>
/// Gets a BaseItem
/// </summary>
/// <param name="id">The id.</param>
@@ -497,15 +522,6 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;PublicSystemInfo&gt;.</returns>
Task<PublicSystemInfo> GetPublicSystemInfoAsync(CancellationToken cancellationToken = default(CancellationToken));
-
- /// <summary>
- /// Gets a person
- /// </summary>
- /// <param name="name">The name.</param>
- /// <param name="userId">The user id.</param>
- /// <returns>Task{BaseItemDto}.</returns>
- /// <exception cref="ArgumentNullException">userId</exception>
- Task<BaseItemDto> GetPersonAsync(string name, string userId);
/// <summary>
/// Gets a list of plugins installed on the server
@@ -962,15 +978,6 @@ namespace MediaBrowser.Model.ApiClient
/// <summary>
/// Gets an image url that can be used to download an image from the api
/// </summary>
- /// <param name="name">The name of the person</param>
- /// <param name="options">The options.</param>
- /// <returns>System.String.</returns>
- /// <exception cref="ArgumentNullException">name</exception>
- string GetPersonImageUrl(string name, ImageOptions options);
-
- /// <summary>
- /// Gets an image url that can be used to download an image from the api
- /// </summary>
/// <param name="year">The year.</param>
/// <param name="options">The options.</param>
/// <returns>System.String.</returns>
@@ -1310,15 +1317,6 @@ namespace MediaBrowser.Model.ApiClient
Task<QueryResult<BaseItemDto>> GetPlaylistItems(PlaylistItemQuery query);
/// <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>
- [Obsolete]
- string GetAudioStreamUrl(StreamOptions options);
-
- /// <summary>
/// Gets the url needed to stream a video file
/// </summary>
/// <param name="options">The options.</param>
@@ -1421,5 +1419,19 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="webSocketFactory">The web socket factory.</param>
/// <param name="keepAliveTimerMs">The keep alive timer ms.</param>
void OpenWebSocket(Func<IClientWebSocket> webSocketFactory, int keepAliveTimerMs = 60000);
+
+ /// <summary>
+ /// Reports the offline actions.
+ /// </summary>
+ /// <param name="actions">The actions.</param>
+ /// <returns>Task.</returns>
+ Task ReportOfflineActions(List<UserAction> actions);
+
+ /// <summary>
+ /// Gets the ready synchronize items.
+ /// </summary>
+ /// <param name="targetId">The target identifier.</param>
+ /// <returns>List&lt;SyncedItem&gt;.</returns>
+ Task<List<SyncedItem>> GetReadySyncItems(string targetId);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs b/MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs
index bd20713de..764a7222f 100644
--- a/MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/CinemaModeConfiguration.cs
@@ -19,6 +19,7 @@ namespace MediaBrowser.Model.Configuration
public CinemaModeConfiguration()
{
EnableIntrosParentalControl = true;
+ EnableIntrosFromSimilarMovies = true;
TrailerLimit = 2;
}
}
diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs
new file mode 100644
index 000000000..f24367298
--- /dev/null
+++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs
@@ -0,0 +1,19 @@
+
+namespace MediaBrowser.Model.Configuration
+{
+ public class EncodingOptions
+ {
+ public EncodingQuality EncodingQuality { get; set; }
+ public string TranscodingTempPath { get; set; }
+ public double DownMixAudioBoost { get; set; }
+ public string H264Encoder { get; set; }
+ public bool EnableDebugLogging { get; set; }
+
+ public EncodingOptions()
+ {
+ H264Encoder = "libx264";
+ DownMixAudioBoost = 2;
+ EncodingQuality = EncodingQuality.Auto;
+ }
+ }
+}
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index b9eaf7001..ba5b6a122 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
namespace MediaBrowser.Model.Configuration
{
@@ -144,21 +145,8 @@ namespace MediaBrowser.Model.Configuration
/// <value>The image saving convention.</value>
public ImageSavingConvention ImageSavingConvention { get; set; }
- /// <summary>
- /// Gets or sets a value indicating whether [enable people prefix sub folders].
- /// </summary>
- /// <value><c>true</c> if [enable people prefix sub folders]; otherwise, <c>false</c>.</value>
- public bool EnablePeoplePrefixSubFolders { get; set; }
-
- /// <summary>
- /// Gets or sets the encoding quality.
- /// </summary>
- /// <value>The encoding quality.</value>
- public EncodingQuality MediaEncodingQuality { get; set; }
-
public MetadataOptions[] MetadataOptions { get; set; }
- public bool EnableDebugEncodingLogging { get; set; }
public string TranscodingTempPath { get; set; }
public bool EnableAutomaticRestart { get; set; }
@@ -171,16 +159,15 @@ namespace MediaBrowser.Model.Configuration
public string UICulture { get; set; }
- public double DownMixAudioBoost { get; set; }
-
public PeopleMetadataOptions PeopleMetadataOptions { get; set; }
public bool FindInternetTrailers { get; set; }
public string[] InsecureApps7 { get; set; }
public bool SaveMetadataHidden { get; set; }
+ public bool EnableWin8HttpListener { get; set; }
- public bool PlaylistImagesDeleted { get; set; }
+ public NameValuePair[] ContentTypes { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
@@ -188,17 +175,15 @@ namespace MediaBrowser.Model.Configuration
public ServerConfiguration()
: base()
{
- MediaEncodingQuality = EncodingQuality.Auto;
ImageSavingConvention = ImageSavingConvention.Compatible;
PublicPort = 8096;
HttpServerPortNumber = 8096;
EnableDashboardResponseCaching = true;
EnableAutomaticRestart = true;
- EnablePeoplePrefixSubFolders = true;
+ EnableWin8HttpListener = true;
EnableUPnP = true;
- DownMixAudioBoost = 2;
MinResumePct = 5;
MaxResumePct = 90;
@@ -212,6 +197,7 @@ namespace MediaBrowser.Model.Configuration
FindInternetTrailers = true;
PathSubstitutions = new PathSubstitution[] { };
+ ContentTypes = new NameValuePair[] { };
PreferredMetadataLanguage = "en";
MetadataCountryCode = "US";
diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs
index f0a27a2b9..9e33c1c36 100644
--- a/MediaBrowser.Model/Configuration/UserConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs
@@ -42,6 +42,10 @@ namespace MediaBrowser.Model.Configuration
/// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
public bool IsHidden { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is disabled.
+ /// </summary>
+ /// <value><c>true</c> if this instance is disabled; otherwise, <c>false</c>.</value>
public bool IsDisabled { get; set; }
public bool DisplayMissingEpisodes { get; set; }
@@ -74,9 +78,6 @@ namespace MediaBrowser.Model.Configuration
public string[] OrderedViews { get; set; }
- public bool SyncConnectName { get; set; }
- public bool SyncConnectImage { get; set; }
-
public bool IncludeTrailersInSuggestions { get; set; }
public bool EnableCinemaMode { get; set; }
@@ -87,7 +88,9 @@ namespace MediaBrowser.Model.Configuration
public string[] LatestItemsExcludes { get; set; }
public string[] BlockedTags { get; set; }
-
+
+ public bool HasMigratedToPolicy { get; set; }
+
/// <summary>
/// Initializes a new instance of the <see cref="UserConfiguration" /> class.
/// </summary>
@@ -110,8 +113,6 @@ namespace MediaBrowser.Model.Configuration
ExcludeFoldersFromGrouping = new string[] { };
DisplayCollectionsView = true;
- SyncConnectName = true;
- SyncConnectImage = true;
IncludeTrailersInSuggestions = true;
EnableCinemaMode = true;
EnableUserPreferenceAccess = true;
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index 7ca8ab6b0..703c73566 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -374,9 +374,17 @@ namespace MediaBrowser.Model.Dlna
MediaStream stream = TargetAudioStream;
int? streamChannels = stream == null ? null : stream.Channels;
- return MaxAudioChannels.HasValue && !IsDirectStream
- ? (streamChannels.HasValue ? Math.Min(MaxAudioChannels.Value, streamChannels.Value) : MaxAudioChannels.Value)
- : streamChannels;
+ if (MaxAudioChannels.HasValue && !IsDirectStream)
+ {
+ if (streamChannels.HasValue)
+ {
+ return Math.Min(MaxAudioChannels.Value, streamChannels.Value);
+ }
+
+ return MaxAudioChannels.Value;
+ }
+
+ return streamChannels;
}
}
diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs
index 71cefa076..2383d4809 100644
--- a/MediaBrowser.Model/Dto/BaseItemDto.cs
+++ b/MediaBrowser.Model/Dto/BaseItemDto.cs
@@ -366,6 +366,11 @@ namespace MediaBrowser.Model.Dto
/// </summary>
/// <value>The user data.</value>
public UserItemDataDto UserData { get; set; }
+ /// <summary>
+ /// Gets or sets the season user data.
+ /// </summary>
+ /// <value>The season user data.</value>
+ public UserItemDataDto SeasonUserData { get; set; }
/// <summary>
/// Gets or sets the recursive item count.
@@ -549,7 +554,13 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets a value indicating whether [supports playlists].
/// </summary>
/// <value><c>true</c> if [supports playlists]; otherwise, <c>false</c>.</value>
- public bool SupportsPlaylists { get; set; }
+ public bool SupportsPlaylists
+ {
+ get
+ {
+ return RunTimeTicks.HasValue || IsFolder || IsGenre || IsMusicGenre || IsArtist;
+ }
+ }
/// <summary>
/// Determines whether the specified type is type.
diff --git a/MediaBrowser.Model/Dto/DtoOptions.cs b/MediaBrowser.Model/Dto/DtoOptions.cs
index 069d71fce..60eb6b1fe 100644
--- a/MediaBrowser.Model/Dto/DtoOptions.cs
+++ b/MediaBrowser.Model/Dto/DtoOptions.cs
@@ -1,11 +1,18 @@
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
+using System;
using System.Collections.Generic;
+using System.Linq;
namespace MediaBrowser.Model.Dto
{
public class DtoOptions
{
+ private static readonly List<ItemFields> DefaultExcludedFields = new List<ItemFields>
+ {
+ ItemFields.SeasonUserData
+ };
+
public List<ItemFields> Fields { get; set; }
public List<ImageType> ImageTypes { get; set; }
public int ImageTypeLimit { get; set; }
@@ -14,9 +21,17 @@ namespace MediaBrowser.Model.Dto
public DtoOptions()
{
Fields = new List<ItemFields>();
- ImageTypes = new List<ImageType>();
ImageTypeLimit = int.MaxValue;
EnableImages = true;
+
+ Fields = Enum.GetNames(typeof (ItemFields))
+ .Select(i => (ItemFields) Enum.Parse(typeof (ItemFields), i, true))
+ .Except(DefaultExcludedFields)
+ .ToList();
+
+ ImageTypes = Enum.GetNames(typeof(ImageType))
+ .Select(i => (ImageType)Enum.Parse(typeof(ImageType), i, true))
+ .ToList();
}
public int GetImageLimit(ImageType type)
diff --git a/MediaBrowser.Model/Dto/MetadataEditorInfo.cs b/MediaBrowser.Model/Dto/MetadataEditorInfo.cs
new file mode 100644
index 000000000..9bd15fc8f
--- /dev/null
+++ b/MediaBrowser.Model/Dto/MetadataEditorInfo.cs
@@ -0,0 +1,27 @@
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Globalization;
+using MediaBrowser.Model.Providers;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.Dto
+{
+ public class MetadataEditorInfo
+ {
+ public List<ParentalRating> ParentalRatingOptions { get; set; }
+ public List<CountryInfo> Countries { get; set; }
+ public List<CultureDto> Cultures { get; set; }
+ public List<ExternalIdInfo> ExternalIdInfos { get; set; }
+
+ public string ContentType { get; set; }
+ public List<NameValuePair> ContentTypeOptions { get; set; }
+
+ public MetadataEditorInfo()
+ {
+ ParentalRatingOptions = new List<ParentalRating>();
+ Countries = new List<CountryInfo>();
+ Cultures = new List<CultureDto>();
+ ExternalIdInfos = new List<ExternalIdInfo>();
+ ContentTypeOptions = new List<NameValuePair>();
+ }
+ }
+}
diff --git a/MediaBrowser.Model/Dto/NameValuePair.cs b/MediaBrowser.Model/Dto/NameValuePair.cs
new file mode 100644
index 000000000..2d55e8f2a
--- /dev/null
+++ b/MediaBrowser.Model/Dto/NameValuePair.cs
@@ -0,0 +1,17 @@
+
+namespace MediaBrowser.Model.Dto
+{
+ public class NameValuePair
+ {
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+ /// <summary>
+ /// Gets or sets the value.
+ /// </summary>
+ /// <value>The value.</value>
+ public string Value { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Dto/StreamOptions.cs b/MediaBrowser.Model/Dto/StreamOptions.cs
deleted file mode 100644
index 5b7cdc6fb..000000000
--- a/MediaBrowser.Model/Dto/StreamOptions.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System;
-
-namespace MediaBrowser.Model.Dto
-{
- /// <summary>
- /// Class StreamOptions
- /// </summary>
- [Obsolete]
- public class StreamOptions
- {
- /// <summary>
- /// Gets or sets the audio bit rate.
- /// </summary>
- /// <value>The audio bit rate.</value>
- public int? AudioBitRate { get; set; }
-
- /// <summary>
- /// Gets or sets the audio codec.
- /// Omit to copy the original stream
- /// </summary>
- /// <value>The audio encoding format.</value>
- public string AudioCodec { get; set; }
-
- /// <summary>
- /// Gets or sets the item id.
- /// </summary>
- /// <value>The item id.</value>
- public string ItemId { get; set; }
-
- /// <summary>
- /// Gets or sets the max audio channels.
- /// </summary>
- /// <value>The max audio channels.</value>
- public int? MaxAudioChannels { get; set; }
-
- /// <summary>
- /// Gets or sets the max audio sample rate.
- /// </summary>
- /// <value>The max audio sample rate.</value>
- public int? MaxAudioSampleRate { get; set; }
-
- /// <summary>
- /// Gets or sets the start time ticks.
- /// </summary>
- /// <value>The start time ticks.</value>
- public long? StartTimeTicks { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether the original media should be served statically
- /// Only used with progressive streaming
- /// </summary>
- /// <value><c>true</c> if static; otherwise, <c>false</c>.</value>
- public bool? Static { get; set; }
-
- /// <summary>
- /// Gets or sets the output file extension.
- /// </summary>
- /// <value>The output file extension.</value>
- public string OutputFileExtension { get; set; }
-
- /// <summary>
- /// Gets or sets the device id.
- /// </summary>
- /// <value>The device id.</value>
- public string DeviceId { get; set; }
- }
-}
diff --git a/MediaBrowser.Model/Dto/VideoStreamOptions.cs b/MediaBrowser.Model/Dto/VideoStreamOptions.cs
index 606e928f2..e9a83bd12 100644
--- a/MediaBrowser.Model/Dto/VideoStreamOptions.cs
+++ b/MediaBrowser.Model/Dto/VideoStreamOptions.cs
@@ -6,9 +6,65 @@ namespace MediaBrowser.Model.Dto
/// Class VideoStreamOptions
/// </summary>
[Obsolete]
- public class VideoStreamOptions : StreamOptions
+ public class VideoStreamOptions
{
/// <summary>
+ /// Gets or sets the audio bit rate.
+ /// </summary>
+ /// <value>The audio bit rate.</value>
+ public int? AudioBitRate { get; set; }
+
+ /// <summary>
+ /// Gets or sets the audio codec.
+ /// Omit to copy the original stream
+ /// </summary>
+ /// <value>The audio encoding format.</value>
+ public string AudioCodec { get; set; }
+
+ /// <summary>
+ /// Gets or sets the item id.
+ /// </summary>
+ /// <value>The item id.</value>
+ public string ItemId { get; set; }
+
+ /// <summary>
+ /// Gets or sets the max audio channels.
+ /// </summary>
+ /// <value>The max audio channels.</value>
+ public int? MaxAudioChannels { get; set; }
+
+ /// <summary>
+ /// Gets or sets the max audio sample rate.
+ /// </summary>
+ /// <value>The max audio sample rate.</value>
+ public int? MaxAudioSampleRate { get; set; }
+
+ /// <summary>
+ /// Gets or sets the start time ticks.
+ /// </summary>
+ /// <value>The start time ticks.</value>
+ public long? StartTimeTicks { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the original media should be served statically
+ /// Only used with progressive streaming
+ /// </summary>
+ /// <value><c>true</c> if static; otherwise, <c>false</c>.</value>
+ public bool? Static { get; set; }
+
+ /// <summary>
+ /// Gets or sets the output file extension.
+ /// </summary>
+ /// <value>The output file extension.</value>
+ public string OutputFileExtension { get; set; }
+
+ /// <summary>
+ /// Gets or sets the device id.
+ /// </summary>
+ /// <value>The device id.</value>
+ public string DeviceId { get; set; }
+
+ /// <summary>
/// Gets or sets the video codec.
/// Omit to copy
/// </summary>
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index b81b4c1fd..8ec271626 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -96,6 +96,7 @@
<Compile Include="Configuration\ChannelOptions.cs" />
<Compile Include="Configuration\ChapterOptions.cs" />
<Compile Include="Configuration\CinemaModeConfiguration.cs" />
+ <Compile Include="Configuration\EncodingOptions.cs" />
<Compile Include="Configuration\MetadataConfiguration.cs" />
<Compile Include="Configuration\PeopleMetadataOptions.cs" />
<Compile Include="Configuration\XbmcMetadataOptions.cs" />
@@ -128,9 +129,10 @@
<Compile Include="Drawing\ImageOrientation.cs" />
<Compile Include="Dto\DtoOptions.cs" />
<Compile Include="Dto\IHasServerId.cs" />
+ <Compile Include="Dto\MetadataEditorInfo.cs" />
+ <Compile Include="Dto\NameValuePair.cs" />
<Compile Include="MediaInfo\LiveMediaInfoResult.cs" />
<Compile Include="Dto\MediaSourceType.cs" />
- <Compile Include="Dto\StreamOptions.cs" />
<Compile Include="Dto\VideoStreamOptions.cs" />
<Compile Include="Configuration\DynamicDayOfWeek.cs" />
<Compile Include="Entities\ExtraType.cs" />
@@ -152,6 +154,8 @@
<Compile Include="Configuration\MetadataPluginType.cs" />
<Compile Include="Dlna\SubtitleProfile.cs" />
<Compile Include="MediaInfo\MediaProtocol.cs" />
+ <Compile Include="Net\HttpResponse.cs" />
+ <Compile Include="Net\MimeTypes.cs" />
<Compile Include="Notifications\NotificationOption.cs" />
<Compile Include="Notifications\NotificationOptions.cs" />
<Compile Include="Notifications\NotificationType.cs" />
@@ -363,8 +367,13 @@
<Compile Include="Session\TranscodingInfo.cs" />
<Compile Include="Session\UserDataChangeInfo.cs" />
<Compile Include="Devices\ContentUploadHistory.cs" />
+ <Compile Include="Sync\DeviceFileInfo.cs" />
+ <Compile Include="Sync\ItemFIleInfo.cs" />
+ <Compile Include="Sync\ItemFileType.cs" />
+ <Compile Include="Sync\LocalItem.cs" />
<Compile Include="Sync\SyncCategory.cs" />
<Compile Include="Sync\SyncDialogOptions.cs" />
+ <Compile Include="Sync\SyncedItem.cs" />
<Compile Include="Sync\SyncHelper.cs" />
<Compile Include="Sync\SyncJob.cs" />
<Compile Include="Sync\SyncJobCreationResult.cs" />
@@ -419,6 +428,8 @@
<Compile Include="Users\ForgotPasswordAction.cs" />
<Compile Include="Users\ForgotPasswordResult.cs" />
<Compile Include="Users\PinRedeemResult.cs" />
+ <Compile Include="Users\UserAction.cs" />
+ <Compile Include="Users\UserActionType.cs" />
<Compile Include="Users\UserPolicy.cs" />
<None Include="Fody.targets" />
<None Include="FodyWeavers.xml" />
diff --git a/MediaBrowser.Model/Net/HttpResponse.cs b/MediaBrowser.Model/Net/HttpResponse.cs
new file mode 100644
index 000000000..f4bd8e681
--- /dev/null
+++ b/MediaBrowser.Model/Net/HttpResponse.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+
+namespace MediaBrowser.Model.Net
+{
+ public class HttpResponse : IDisposable
+ {
+ /// <summary>
+ /// Gets or sets the type of the content.
+ /// </summary>
+ /// <value>The type of the content.</value>
+ public string ContentType { get; set; }
+
+ /// <summary>
+ /// Gets or sets the response URL.
+ /// </summary>
+ /// <value>The response URL.</value>
+ public string ResponseUrl { get; set; }
+
+ /// <summary>
+ /// Gets or sets the content.
+ /// </summary>
+ /// <value>The content.</value>
+ public Stream Content { get; set; }
+
+ /// <summary>
+ /// Gets or sets the status code.
+ /// </summary>
+ /// <value>The status code.</value>
+ public HttpStatusCode StatusCode { get; set; }
+
+ /// <summary>
+ /// Gets or sets the length of the content.
+ /// </summary>
+ /// <value>The length of the content.</value>
+ public long? ContentLength { get; set; }
+
+ /// <summary>
+ /// Gets or sets the headers.
+ /// </summary>
+ /// <value>The headers.</value>
+ public Dictionary<string, string> Headers { get; set; }
+
+ private readonly IDisposable _disposable;
+
+ public HttpResponse(IDisposable disposable)
+ {
+ _disposable = disposable;
+ }
+ public HttpResponse()
+ {
+ }
+
+ public void Dispose()
+ {
+ if (_disposable != null)
+ {
+ _disposable.Dispose();
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Common/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs
index 14052e759..19dda0603 100644
--- a/MediaBrowser.Common/Net/MimeTypes.cs
+++ b/MediaBrowser.Model/Net/MimeTypes.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
-namespace MediaBrowser.Common.Net
+namespace MediaBrowser.Model.Net
{
/// <summary>
/// Class MimeTypes
@@ -11,11 +11,6 @@ namespace MediaBrowser.Common.Net
public static class MimeTypes
{
/// <summary>
- /// The json MIME type
- /// </summary>
- public static string JsonMimeType = "application/json";
-
- /// <summary>
/// Any extension in this list is considered a video file - can be added to at runtime for extensibility
/// </summary>
private static readonly List<string> VideoFileExtensions = new List<string>
@@ -52,35 +47,44 @@ namespace MediaBrowser.Common.Net
private static readonly Dictionary<string, string> VideoFileExtensionsDictionary = VideoFileExtensions.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
- /// <summary>
- /// Determines whether [is video file] [the specified path].
- /// </summary>
- /// <param name="path">The path.</param>
- /// <returns><c>true</c> if [is video file] [the specified path]; otherwise, <c>false</c>.</returns>
- public static bool IsVideoFile(string path)
- {
- if (string.IsNullOrEmpty(path))
- {
- throw new ArgumentNullException("path");
- }
-
- var extension = Path.GetExtension(path);
+ // http://en.wikipedia.org/wiki/Internet_media_type
+ // Add more as needed
- if (string.IsNullOrEmpty(extension))
+ private static readonly Dictionary<string, string> MimeTypeLookup =
+ new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
- return false;
- }
+ {".jpg", "image/jpeg"},
+ {".jpeg", "image/jpeg"},
+ {".tbn", "image/jpeg"},
+ {".png", "image/png"},
+ {".gif", "image/gif"},
+ {".webp", "image/webp"},
+ {".ico", "image/vnd.microsoft.icon"},
+ {".mpg", "video/mpeg"},
+ {".mpeg", "video/mpeg"},
+ {".ogv", "video/ogg"},
+ {".mov", "video/quicktime"},
+ {".webm", "video/webm"},
+ {".mkv", "video/x-matroska"},
+ {".wmv", "video/x-ms-wmv"},
+ {".flv", "video/x-flv"},
+ {".avi", "video/x-msvideo"},
+ {".asf", "video/x-ms-asf"},
+ {".m4v", "video/x-m4v"}
+ };
- return VideoFileExtensionsDictionary.ContainsKey(extension);
- }
+ private static readonly Dictionary<string, string> ExtensionLookup =
+ MimeTypeLookup
+ .GroupBy(i => i.Value)
+ .ToDictionary(x => x.Key, x => x.First().Key, StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Gets the type of the MIME.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>System.String.</returns>
- /// <exception cref="System.ArgumentNullException">path</exception>
- /// <exception cref="System.InvalidOperationException">Argument not supported: + path</exception>
+ /// <exception cref="ArgumentNullException">path</exception>
+ /// <exception cref="InvalidOperationException">Argument not supported: + path</exception>
public static string GetMimeType(string path)
{
if (string.IsNullOrEmpty(path))
@@ -90,50 +94,13 @@ namespace MediaBrowser.Common.Net
var ext = Path.GetExtension(path) ?? string.Empty;
- // http://en.wikipedia.org/wiki/Internet_media_type
- // Add more as needed
-
- // Type video
- if (ext.Equals(".mpg", StringComparison.OrdinalIgnoreCase) || ext.EndsWith("mpeg", StringComparison.OrdinalIgnoreCase))
- {
- return "video/mpeg";
- }
- if (ext.Equals(".ogv", StringComparison.OrdinalIgnoreCase))
- {
- return "video/ogg";
- }
- if (ext.Equals(".mov", StringComparison.OrdinalIgnoreCase))
- {
- return "video/quicktime";
- }
- if (ext.Equals(".webm", StringComparison.OrdinalIgnoreCase))
- {
- return "video/webm";
- }
- if (ext.Equals(".mkv", StringComparison.OrdinalIgnoreCase))
- {
- return "video/x-matroska";
- }
- if (ext.Equals(".wmv", StringComparison.OrdinalIgnoreCase))
- {
- return "video/x-ms-wmv";
- }
- if (ext.Equals(".flv", StringComparison.OrdinalIgnoreCase))
- {
- return "video/x-flv";
- }
- if (ext.Equals(".avi", StringComparison.OrdinalIgnoreCase))
- {
- return "video/x-msvideo";
- }
- if (ext.Equals(".m4v", StringComparison.OrdinalIgnoreCase))
- {
- return "video/x-m4v";
- }
- if (ext.EndsWith("asf", StringComparison.OrdinalIgnoreCase))
+ string result;
+ if (MimeTypeLookup.TryGetValue(ext, out result))
{
- return "video/x-ms-asf";
+ return result;
}
+
+ // Type video
if (ext.Equals(".3gp", StringComparison.OrdinalIgnoreCase))
{
return "video/3gpp";
@@ -197,28 +164,6 @@ namespace MediaBrowser.Common.Net
return "application/x-cdisplay";
}
- // Type image
- if (ext.Equals(".gif", StringComparison.OrdinalIgnoreCase))
- {
- return "image/gif";
- }
- if (ext.Equals(".jpg", StringComparison.OrdinalIgnoreCase) || ext.Equals(".jpeg", StringComparison.OrdinalIgnoreCase) || ext.Equals(".tbn", StringComparison.OrdinalIgnoreCase))
- {
- return "image/jpeg";
- }
- if (ext.Equals(".png", StringComparison.OrdinalIgnoreCase))
- {
- return "image/png";
- }
- if (ext.Equals(".webp", StringComparison.OrdinalIgnoreCase))
- {
- return "image/webp";
- }
- if (ext.Equals(".ico", StringComparison.OrdinalIgnoreCase))
- {
- return "image/vnd.microsoft.icon";
- }
-
// Type audio
if (ext.Equals(".mp3", StringComparison.OrdinalIgnoreCase))
{
@@ -272,7 +217,7 @@ namespace MediaBrowser.Common.Net
}
if (ext.Equals(".json", StringComparison.OrdinalIgnoreCase))
{
- return JsonMimeType;
+ return "application/json";
}
if (ext.Equals(".map", StringComparison.OrdinalIgnoreCase))
{
@@ -320,19 +265,19 @@ namespace MediaBrowser.Common.Net
throw new ArgumentException("Argument not supported: " + path);
}
- private static readonly Dictionary<string, string> MimeExtensions =
- new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
- {
- {"image/jpeg", "jpg"},
- {"image/jpg", "jpg"},
- {"image/png", "png"},
- {"image/gif", "gif"},
- {"image/webp", "webp"}
- };
-
public static string ToExtension(string mimeType)
{
- return "." + MimeExtensions[mimeType];
+ if (string.IsNullOrEmpty(mimeType))
+ {
+ throw new ArgumentNullException("mimeType");
+ }
+
+ string result;
+ if (ExtensionLookup.TryGetValue(mimeType, out result))
+ {
+ return result;
+ }
+ throw new ArgumentNullException("Unable to determine extension for mimeType: " + mimeType);
}
}
}
diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs
index 19e30cd8a..5018f8e51 100644
--- a/MediaBrowser.Model/Querying/ItemFields.cs
+++ b/MediaBrowser.Model/Querying/ItemFields.cs
@@ -7,6 +7,11 @@ namespace MediaBrowser.Model.Querying
public enum ItemFields
{
/// <summary>
+ /// The air time
+ /// </summary>
+ AirTime,
+
+ /// <summary>
/// The alternate episode numbers
/// </summary>
AlternateEpisodeNumbers,
@@ -102,11 +107,6 @@ namespace MediaBrowser.Model.Querying
Metascore,
/// <summary>
- /// The metadata settings
- /// </summary>
- Settings,
-
- /// <summary>
/// The item overview
/// </summary>
Overview,
@@ -152,6 +152,16 @@ namespace MediaBrowser.Model.Querying
Revenue,
/// <summary>
+ /// The season name
+ /// </summary>
+ SeasonName,
+
+ /// <summary>
+ /// The settings
+ /// </summary>
+ Settings,
+
+ /// <summary>
/// The short overview
/// </summary>
ShortOverview,
@@ -182,6 +192,11 @@ namespace MediaBrowser.Model.Querying
SortName,
/// <summary>
+ /// The special episode numbers
+ /// </summary>
+ SpecialEpisodeNumbers,
+
+ /// <summary>
/// The studios of the item
/// </summary>
Studios,
@@ -219,6 +234,11 @@ namespace MediaBrowser.Model.Querying
/// <summary>
/// The media streams
/// </summary>
- MediaStreams
+ MediaStreams,
+
+ /// <summary>
+ /// The season user data
+ /// </summary>
+ SeasonUserData
}
}
diff --git a/MediaBrowser.Model/Session/TranscodingInfo.cs b/MediaBrowser.Model/Session/TranscodingInfo.cs
index b3ab32a44..e646d80d3 100644
--- a/MediaBrowser.Model/Session/TranscodingInfo.cs
+++ b/MediaBrowser.Model/Session/TranscodingInfo.cs
@@ -5,6 +5,8 @@ namespace MediaBrowser.Model.Session
public string AudioCodec { get; set; }
public string VideoCodec { get; set; }
public string Container { get; set; }
+ public bool IsVideoDirect { get; set; }
+ public bool IsAudioDirect { get; set; }
public int? Bitrate { get; set; }
public float? Framerate { get; set; }
diff --git a/MediaBrowser.Model/Sync/DeviceFileInfo.cs b/MediaBrowser.Model/Sync/DeviceFileInfo.cs
new file mode 100644
index 000000000..bb9a0c6ef
--- /dev/null
+++ b/MediaBrowser.Model/Sync/DeviceFileInfo.cs
@@ -0,0 +1,9 @@
+
+namespace MediaBrowser.Model.Sync
+{
+ public class DeviceFileInfo
+ {
+ public string[] Path { get; set; }
+ public string Name { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Sync/ItemFIleInfo.cs b/MediaBrowser.Model/Sync/ItemFIleInfo.cs
new file mode 100644
index 000000000..f0829bc2b
--- /dev/null
+++ b/MediaBrowser.Model/Sync/ItemFIleInfo.cs
@@ -0,0 +1,28 @@
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Model.Sync
+{
+ public class ItemFileInfo
+ {
+ /// <summary>
+ /// Gets or sets the type.
+ /// </summary>
+ /// <value>The type.</value>
+ public ItemFileType Type { get; set; }
+ /// <summary>
+ /// Gets or sets the name.
+ /// </summary>
+ /// <value>The name.</value>
+ public string Name { get; set; }
+ /// <summary>
+ /// Gets or sets the path.
+ /// </summary>
+ /// <value>The path.</value>
+ public string[] Path { get; set; }
+ /// <summary>
+ /// Gets or sets the type of the image.
+ /// </summary>
+ /// <value>The type of the image.</value>
+ public ImageType ImageType { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Sync/ItemFileType.cs b/MediaBrowser.Model/Sync/ItemFileType.cs
new file mode 100644
index 000000000..305f4c502
--- /dev/null
+++ b/MediaBrowser.Model/Sync/ItemFileType.cs
@@ -0,0 +1,19 @@
+
+namespace MediaBrowser.Model.Sync
+{
+ public enum ItemFileType
+ {
+ /// <summary>
+ /// The media
+ /// </summary>
+ Media = 0,
+ /// <summary>
+ /// The image
+ /// </summary>
+ Image = 1,
+ /// <summary>
+ /// The subtitles
+ /// </summary>
+ Subtitles = 2
+ }
+}
diff --git a/MediaBrowser.Model/Sync/LocalItem.cs b/MediaBrowser.Model/Sync/LocalItem.cs
new file mode 100644
index 000000000..9e660c590
--- /dev/null
+++ b/MediaBrowser.Model/Sync/LocalItem.cs
@@ -0,0 +1,33 @@
+using MediaBrowser.Model.Dto;
+
+namespace MediaBrowser.Model.Sync
+{
+ public class LocalItem
+ {
+ /// <summary>
+ /// Gets or sets the item.
+ /// </summary>
+ /// <value>The item.</value>
+ public BaseItemDto Item { get; set; }
+ /// <summary>
+ /// Gets or sets the local path.
+ /// </summary>
+ /// <value>The local path.</value>
+ public string[] LocalPath { get; set; }
+ /// <summary>
+ /// Gets or sets the server identifier.
+ /// </summary>
+ /// <value>The server identifier.</value>
+ public string ServerId { get; set; }
+ /// <summary>
+ /// Gets or sets the unique identifier.
+ /// </summary>
+ /// <value>The unique identifier.</value>
+ public string UniqueId { get; set; }
+ /// <summary>
+ /// Gets or sets the item identifier.
+ /// </summary>
+ /// <value>The item identifier.</value>
+ public string ItemId { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Sync/SyncJobItem.cs b/MediaBrowser.Model/Sync/SyncJobItem.cs
index 063f7feb2..d9fb1ed09 100644
--- a/MediaBrowser.Model/Sync/SyncJobItem.cs
+++ b/MediaBrowser.Model/Sync/SyncJobItem.cs
@@ -23,6 +23,12 @@ namespace MediaBrowser.Model.Sync
public string ItemId { get; set; }
/// <summary>
+ /// Gets or sets the media source identifier.
+ /// </summary>
+ /// <value>The media source identifier.</value>
+ public string MediaSourceId { get; set; }
+
+ /// <summary>
/// Gets or sets the target identifier.
/// </summary>
/// <value>The target identifier.</value>
diff --git a/MediaBrowser.Model/Sync/SyncedItem.cs b/MediaBrowser.Model/Sync/SyncedItem.cs
new file mode 100644
index 000000000..784a12bc9
--- /dev/null
+++ b/MediaBrowser.Model/Sync/SyncedItem.cs
@@ -0,0 +1,38 @@
+using MediaBrowser.Model.Dto;
+
+namespace MediaBrowser.Model.Sync
+{
+ public class SyncedItem
+ {
+ /// <summary>
+ /// Gets or sets the server identifier.
+ /// </summary>
+ /// <value>The server identifier.</value>
+ public string ServerId { get; set; }
+ /// <summary>
+ /// Gets or sets the synchronize job identifier.
+ /// </summary>
+ /// <value>The synchronize job identifier.</value>
+ public string SyncJobId { get; set; }
+ /// <summary>
+ /// Gets or sets the synchronize job item identifier.
+ /// </summary>
+ /// <value>The synchronize job item identifier.</value>
+ public string SyncJobItemId { get; set; }
+ /// <summary>
+ /// Gets or sets the name of the original file.
+ /// </summary>
+ /// <value>The name of the original file.</value>
+ public string OriginalFileName { get; set; }
+ /// <summary>
+ /// Gets or sets the item.
+ /// </summary>
+ /// <value>The item.</value>
+ public BaseItemDto Item { get; set; }
+ /// <summary>
+ /// Gets or sets the user identifier.
+ /// </summary>
+ /// <value>The user identifier.</value>
+ public string UserId { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Users/UserAction.cs b/MediaBrowser.Model/Users/UserAction.cs
new file mode 100644
index 000000000..680835364
--- /dev/null
+++ b/MediaBrowser.Model/Users/UserAction.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace MediaBrowser.Model.Users
+{
+ public class UserAction
+ {
+ public string Id { get; set; }
+ public string ServerId { get; set; }
+ public string UserId { get; set; }
+ public string ItemId { get; set; }
+ public UserActionType Type { get; set; }
+ public DateTime Date { get; set; }
+ public long? PositionTicks { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Users/UserActionType.cs b/MediaBrowser.Model/Users/UserActionType.cs
new file mode 100644
index 000000000..493de6272
--- /dev/null
+++ b/MediaBrowser.Model/Users/UserActionType.cs
@@ -0,0 +1,8 @@
+
+namespace MediaBrowser.Model.Users
+{
+ public enum UserActionType
+ {
+ PlayedItem = 0
+ }
+}
diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs
index b458e2854..4d09ae8e8 100644
--- a/MediaBrowser.Model/Users/UserPolicy.cs
+++ b/MediaBrowser.Model/Users/UserPolicy.cs
@@ -1,8 +1,69 @@
-
+using MediaBrowser.Model.Configuration;
+
namespace MediaBrowser.Model.Users
{
public class UserPolicy
{
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is administrator.
+ /// </summary>
+ /// <value><c>true</c> if this instance is administrator; otherwise, <c>false</c>.</value>
+ public bool IsAdministrator { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is hidden.
+ /// </summary>
+ /// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
+ public bool IsHidden { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether this instance is disabled.
+ /// </summary>
+ /// <value><c>true</c> if this instance is disabled; otherwise, <c>false</c>.</value>
+ public bool IsDisabled { get; set; }
+
+ /// <summary>
+ /// Gets or sets the max parental rating.
+ /// </summary>
+ /// <value>The max parental rating.</value>
+ public int? MaxParentalRating { get; set; }
+
+ public string[] BlockedTags { get; set; }
+ public bool EnableUserPreferenceAccess { get; set; }
+ public AccessSchedule[] AccessSchedules { get; set; }
+ public UnratedItem[] BlockUnratedItems { get; set; }
+ public string[] BlockedMediaFolders { get; set; }
+ public string[] BlockedChannels { get; set; }
+ public bool EnableRemoteControlOfOtherUsers { get; set; }
+ public bool EnableSharedDeviceControl { get; set; }
+
+ public bool EnableLiveTvManagement { get; set; }
+ public bool EnableLiveTvAccess { get; set; }
+
+ public bool EnableMediaPlayback { get; set; }
+ public bool EnableContentDeletion { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether [enable synchronize].
+ /// </summary>
+ /// <value><c>true</c> if [enable synchronize]; otherwise, <c>false</c>.</value>
public bool EnableSync { get; set; }
+
+ public UserPolicy()
+ {
+ EnableLiveTvManagement = true;
+ EnableMediaPlayback = true;
+ EnableLiveTvAccess = true;
+ EnableSharedDeviceControl = true;
+
+ BlockedMediaFolders = new string[] { };
+ BlockedTags = new string[] { };
+ BlockedChannels = new string[] { };
+ BlockUnratedItems = new UnratedItem[] { };
+
+ EnableUserPreferenceAccess = true;
+
+ AccessSchedules = new AccessSchedule[] { };
+ }
}
}
diff --git a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
index 062519f9d..5afaaa875 100644
--- a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
+++ b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
@@ -75,7 +75,7 @@ namespace MediaBrowser.Providers.BoxSets
if (!string.Equals(currentOfficialRating ?? string.Empty, item.OfficialRating ?? string.Empty,
StringComparison.OrdinalIgnoreCase))
{
- updateType = updateType | ItemUpdateType.MetadataDownload;
+ updateType = updateType | ItemUpdateType.MetadataEdit;
}
}
diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs
index 2c97f2c16..700bca0fa 100644
--- a/MediaBrowser.Providers/Manager/ImageSaver.cs
+++ b/MediaBrowser.Providers/Manager/ImageSaver.cs
@@ -16,6 +16,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Net;
namespace MediaBrowser.Providers.Manager
{
diff --git a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
index a7ccf3f6e..6813f2ff5 100644
--- a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
+++ b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs
@@ -106,6 +106,10 @@ namespace MediaBrowser.Providers.Movies
{
// No biggie. Don't blow up
}
+ catch (DirectoryNotFoundException)
+ {
+ // No biggie. Don't blow up
+ }
}
var language = item.GetPreferredMetadataLanguage();
diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs
index 79fab2f70..6e3a5bf06 100644
--- a/MediaBrowser.Providers/Music/AlbumMetadataService.cs
+++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs
@@ -54,7 +54,7 @@ namespace MediaBrowser.Providers.Music
if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
{
- updateType = updateType | ItemUpdateType.MetadataDownload;
+ updateType = updateType | ItemUpdateType.MetadataEdit;
}
}
@@ -68,7 +68,7 @@ namespace MediaBrowser.Providers.Music
if (currentList.Count != item.Studios.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Studios.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
{
- updateType = updateType | ItemUpdateType.MetadataDownload;
+ updateType = updateType | ItemUpdateType.MetadataEdit;
}
}
@@ -81,15 +81,15 @@ namespace MediaBrowser.Providers.Music
if (!string.Equals(item.Name, name, StringComparison.Ordinal))
{
item.Name = name;
- updateType = updateType | ItemUpdateType.MetadataDownload;
+ updateType = updateType | ItemUpdateType.MetadataEdit;
}
}
}
- }
- updateType = updateType | SetAlbumArtistFromSongs(item, songs);
- updateType = updateType | SetArtistsFromSongs(item, songs);
- updateType = updateType | SetDateFromSongs(item, songs);
+ updateType = updateType | SetAlbumArtistFromSongs(item, songs);
+ updateType = updateType | SetArtistsFromSongs(item, songs);
+ updateType = updateType | SetDateFromSongs(item, songs);
+ }
return updateType;
}
@@ -106,7 +106,7 @@ namespace MediaBrowser.Providers.Music
if (!item.AlbumArtists.SequenceEqual(albumArtists, StringComparer.OrdinalIgnoreCase))
{
item.AlbumArtists = albumArtists;
- updateType = updateType | ItemUpdateType.MetadataDownload;
+ updateType = updateType | ItemUpdateType.MetadataEdit;
}
return updateType;
@@ -124,7 +124,7 @@ namespace MediaBrowser.Providers.Music
if (currentList.Count != item.Artists.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Artists.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
{
- updateType = updateType | ItemUpdateType.MetadataDownload;
+ updateType = updateType | ItemUpdateType.MetadataEdit;
}
return updateType;
@@ -158,7 +158,7 @@ namespace MediaBrowser.Providers.Music
if ((originalPremiereDate ?? DateTime.MinValue) != (item.PremiereDate ?? DateTime.MinValue) ||
(originalProductionYear ?? -1) != (item.ProductionYear ?? -1))
{
- updateType = updateType | ItemUpdateType.MetadataDownload;
+ updateType = updateType | ItemUpdateType.MetadataEdit;
}
return updateType;
diff --git a/MediaBrowser.Providers/Music/ArtistMetadataService.cs b/MediaBrowser.Providers/Music/ArtistMetadataService.cs
index 939bd2b3b..a73d82992 100644
--- a/MediaBrowser.Providers/Music/ArtistMetadataService.cs
+++ b/MediaBrowser.Providers/Music/ArtistMetadataService.cs
@@ -35,19 +35,22 @@ namespace MediaBrowser.Providers.Music
{
var updateType = base.BeforeSave(item);
- if (!item.IsAccessedByName && !item.LockedFields.Contains(MetadataFields.Genres))
+ if (!item.IsAccessedByName && !item.IsLocked)
{
- var songs = item.RecursiveChildren.OfType<Audio>().ToList();
+ if (!item.LockedFields.Contains(MetadataFields.Genres))
+ {
+ var songs = item.RecursiveChildren.OfType<Audio>().ToList();
- var currentList = item.Genres.ToList();
+ var currentList = item.Genres.ToList();
- item.Genres = songs.SelectMany(i => i.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToList();
+ item.Genres = songs.SelectMany(i => i.Genres)
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToList();
- if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
- {
- updateType = updateType | ItemUpdateType.MetadataDownload;
+ if (currentList.Count != item.Genres.Count || !currentList.OrderBy(i => i).SequenceEqual(item.Genres.OrderBy(i => i), StringComparer.OrdinalIgnoreCase))
+ {
+ updateType = updateType | ItemUpdateType.MetadataEdit;
+ }
}
}
diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
index 94d682f44..123ff9e29 100644
--- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs
@@ -83,6 +83,10 @@ namespace MediaBrowser.Providers.Music
{
}
+ catch (DirectoryNotFoundException)
+ {
+
+ }
}
var language = item.GetPreferredMetadataLanguage();
diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
index a8df95fd1..6f633cfc8 100644
--- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
+++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs
@@ -91,6 +91,10 @@ namespace MediaBrowser.Providers.Music
{
}
+ catch (DirectoryNotFoundException)
+ {
+
+ }
}
var language = item.GetPreferredMetadataLanguage();
diff --git a/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs b/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs
index 63d054664..253acc13f 100644
--- a/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs
+++ b/MediaBrowser.Providers/People/TvdbPersonImageProvider.cs
@@ -83,6 +83,10 @@ namespace MediaBrowser.Providers.People
{
return null;
}
+ catch (DirectoryNotFoundException)
+ {
+ return null;
+ }
}
private RemoteImageInfo GetImageInfo(string xmlFile, string personName, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs
index 05244af74..9f0cd4ff1 100644
--- a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs
@@ -98,6 +98,10 @@ namespace MediaBrowser.Providers.TV
{
// No biggie. Don't blow up
}
+ catch (DirectoryNotFoundException)
+ {
+ // No biggie. Don't blow up
+ }
}
}
diff --git a/MediaBrowser.Providers/TV/FanartSeriesProvider.cs b/MediaBrowser.Providers/TV/FanartSeriesProvider.cs
index afc71698b..8ba25e9f1 100644
--- a/MediaBrowser.Providers/TV/FanartSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/FanartSeriesProvider.cs
@@ -106,6 +106,10 @@ namespace MediaBrowser.Providers.TV
{
// No biggie. Don't blow up
}
+ catch (DirectoryNotFoundException)
+ {
+ // No biggie. Don't blow up
+ }
}
var language = item.GetPreferredMetadataLanguage();
diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
index 21d41ca00..0b52956de 100644
--- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -22,14 +23,16 @@ namespace MediaBrowser.Providers.TV
private readonly IServerConfigurationManager _config;
private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager;
+ private readonly ILocalizationManager _localization;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
- public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager)
+ public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization)
{
_logger = logger;
_config = config;
_libraryManager = libraryManager;
+ _localization = localization;
}
public async Task Run(IEnumerable<IGrouping<string, Series>> series, CancellationToken cancellationToken)
@@ -93,16 +96,16 @@ namespace MediaBrowser.Providers.TV
var hasBadData = HasInvalidContent(group);
- var anySeasonsRemoved = await RemoveObsoleteOrMissingSeasons(group, episodeLookup, false)
+ var anySeasonsRemoved = await RemoveObsoleteOrMissingSeasons(group, episodeLookup)
.ConfigureAwait(false);
- var anyEpisodesRemoved = await RemoveObsoleteOrMissingEpisodes(group, episodeLookup, false)
+ var anyEpisodesRemoved = await RemoveObsoleteOrMissingEpisodes(group, episodeLookup)
.ConfigureAwait(false);
var hasNewEpisodes = false;
var hasNewSeasons = false;
- foreach (var series in group.Where(s => s.ContainsEpisodesWithoutSeasonFolders))
+ foreach (var series in group)
{
hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false);
}
@@ -165,14 +168,15 @@ namespace MediaBrowser.Providers.TV
/// <returns></returns>
private async Task<bool> AddDummySeasonFolders(Series series, CancellationToken cancellationToken)
{
- var existingEpisodes = series.RecursiveChildren
+ var episodesInSeriesFolder = series.RecursiveChildren
.OfType<Episode>()
+ .Where(i => !i.IsInSeasonFolder)
.ToList();
var hasChanges = false;
// Loop through the unique season numbers
- foreach (var seasonNumber in existingEpisodes.Select(i => i.ParentIndexNumber ?? -1)
+ foreach (var seasonNumber in episodesInSeriesFolder.Select(i => i.ParentIndexNumber ?? -1)
.Where(i => i >= 0)
.Distinct()
.ToList())
@@ -188,6 +192,20 @@ namespace MediaBrowser.Providers.TV
}
}
+ // Unknown season - create a dummy season to put these under
+ if (episodesInSeriesFolder.Any(i => !i.ParentIndexNumber.HasValue))
+ {
+ var hasSeason = series.Children.OfType<Season>()
+ .Any(i => !i.IndexNumber.HasValue);
+
+ if (!hasSeason)
+ {
+ await AddSeason(series, null, cancellationToken).ConfigureAwait(false);
+
+ hasChanges = true;
+ }
+ }
+
return hasChanges;
}
@@ -292,8 +310,7 @@ namespace MediaBrowser.Providers.TV
/// Removes the virtual entry after a corresponding physical version has been added
/// </summary>
private async Task<bool> RemoveObsoleteOrMissingEpisodes(IEnumerable<Series> series,
- IEnumerable<Tuple<int, int>> episodeLookup,
- bool forceRemoveAll)
+ IEnumerable<Tuple<int, int>> episodeLookup)
{
var existingEpisodes = (from s in series
let seasonOffset = TvdbSeriesProvider.GetSeriesOffset(s.ProviderIds) ?? ((s.AnimeSeriesIndex ?? 1) - 1)
@@ -312,11 +329,6 @@ namespace MediaBrowser.Providers.TV
var episodesToRemove = virtualEpisodes
.Where(i =>
{
- if (forceRemoveAll)
- {
- return true;
- }
-
if (i.Episode.IndexNumber.HasValue && i.Episode.ParentIndexNumber.HasValue)
{
var seasonNumber = i.Episode.ParentIndexNumber.Value + i.SeasonOffset;
@@ -362,11 +374,9 @@ namespace MediaBrowser.Providers.TV
/// </summary>
/// <param name="series">The series.</param>
/// <param name="episodeLookup">The episode lookup.</param>
- /// <param name="forceRemoveAll">if set to <c>true</c> [force remove all].</param>
/// <returns>Task{System.Boolean}.</returns>
private async Task<bool> RemoveObsoleteOrMissingSeasons(IEnumerable<Series> series,
- IEnumerable<Tuple<int, int>> episodeLookup,
- bool forceRemoveAll)
+ IEnumerable<Tuple<int, int>> episodeLookup)
{
var existingSeasons = (from s in series
let seasonOffset = TvdbSeriesProvider.GetSeriesOffset(s.ProviderIds) ?? ((s.AnimeSeriesIndex ?? 1) - 1)
@@ -385,11 +395,6 @@ namespace MediaBrowser.Providers.TV
var seasonsToRemove = virtualSeasons
.Where(i =>
{
- if (forceRemoveAll)
- {
- return true;
- }
-
if (i.Season.IndexNumber.HasValue)
{
var seasonNumber = i.Season.IndexNumber.Value + i.SeasonOffset;
@@ -409,7 +414,9 @@ namespace MediaBrowser.Providers.TV
return false;
}
- return true;
+ // Season does not have a number
+ // Remove if there are no episodes directly in series without a season number
+ return i.Season.Series.RecursiveChildren.OfType<Episode>().All(s => s.ParentIndexNumber.HasValue || s.IsInSeasonFolder);
})
.ToList();
@@ -472,20 +479,22 @@ namespace MediaBrowser.Providers.TV
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Season}.</returns>
private async Task<Season> AddSeason(Series series,
- int seasonNumber,
+ int? seasonNumber,
CancellationToken cancellationToken)
{
- _logger.Info("Creating Season {0} entry for {1}", seasonNumber, series.Name);
+ var seasonName = seasonNumber == 0 ?
+ _config.Configuration.SeasonZeroDisplayName :
+ (seasonNumber.HasValue ? string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.Value.ToString(UsCulture)) : _localization.GetLocalizedString("NameSeasonUnknown"));
- var name = seasonNumber == 0 ? _config.Configuration.SeasonZeroDisplayName : string.Format("Season {0}", seasonNumber.ToString(UsCulture));
+ _logger.Info("Creating Season {0} entry for {1}", seasonName, series.Name);
var season = new Season
{
- Name = name,
+ Name = seasonName,
IndexNumber = seasonNumber,
Parent = series,
DisplayMediaType = typeof(Season).Name,
- Id = (series.Id + seasonNumber.ToString(UsCulture) + name).GetMBId(typeof(Season))
+ Id = (series.Id + (seasonNumber ?? -1).ToString(UsCulture) + seasonName).GetMBId(typeof(Season))
};
await series.AddChild(season, cancellationToken).ConfigureAwait(false);
diff --git a/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs b/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs
index 26b2711de..80f4c9485 100644
--- a/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/MovieDbSeasonProvider.cs
@@ -52,18 +52,18 @@ namespace MediaBrowser.Providers.TV
if (!string.IsNullOrWhiteSpace(seriesTmdbId) && seasonNumber.HasValue)
{
- result.HasMetadata = true;
- result.Item = new Season();
-
try
{
var seasonInfo = await GetSeasonInfo(seriesTmdbId, seasonNumber.Value, info.MetadataLanguage, cancellationToken)
.ConfigureAwait(false);
+ result.HasMetadata = true;
+ result.Item = new Season();
result.Item.Name = info.Name;
- result.Item.Overview = seasonInfo.overview;
result.Item.IndexNumber = seasonNumber;
+ result.Item.Overview = seasonInfo.overview;
+
if (seasonInfo.external_ids.tvdb_id > 0)
{
result.Item.SetProviderId(MetadataProviders.Tvdb, seasonInfo.external_ids.tvdb_id.ToString(CultureInfo.InvariantCulture));
diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
index a7571f7ad..713d46347 100644
--- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
@@ -7,7 +7,6 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using System.Linq;
namespace MediaBrowser.Providers.TV
{
@@ -54,29 +53,5 @@ namespace MediaBrowser.Providers.TV
target.DisplaySpecialsWithSeasons = source.DisplaySpecialsWithSeasons;
}
}
-
- protected override ItemUpdateType BeforeSave(Series item)
- {
- var updateType = base.BeforeSave(item);
-
- var episodes = item.RecursiveChildren
- .OfType<Episode>()
- .ToList();
-
- var dateLastEpisodeAdded = item.DateLastEpisodeAdded;
-
- item.DateLastEpisodeAdded = episodes
- .Where(i => i.LocationType != LocationType.Virtual)
- .Select(i => i.DateCreated)
- .OrderByDescending(i => i)
- .FirstOrDefault();
-
- if (dateLastEpisodeAdded != item.DateLastEpisodeAdded)
- {
- updateType = updateType | ItemUpdateType.MetadataImport;
- }
-
- return updateType;
- }
}
}
diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
index d350d2fe4..17a219f52 100644
--- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
+++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
@@ -1,11 +1,12 @@
-using System.Collections.Generic;
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -25,12 +26,14 @@ namespace MediaBrowser.Providers.TV
private readonly ILibraryManager _libraryManager;
private readonly IServerConfigurationManager _config;
private readonly ILogger _logger;
+ private readonly ILocalizationManager _localization;
- public SeriesPostScanTask(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config)
+ public SeriesPostScanTask(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, ILocalizationManager localization)
{
_libraryManager = libraryManager;
_logger = logger;
_config = config;
+ _localization = localization;
}
public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
@@ -47,7 +50,7 @@ namespace MediaBrowser.Providers.TV
var seriesGroups = FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList();
- await new MissingEpisodeProvider(_logger, _config, _libraryManager).Run(seriesGroups, cancellationToken).ConfigureAwait(false);
+ await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization).Run(seriesGroups, cancellationToken).ConfigureAwait(false);
var numComplete = 0;
@@ -73,10 +76,6 @@ namespace MediaBrowser.Providers.TV
.Select(i => i.Id)
.ToList();
- series.DateLastEpisodeAdded = physicalEpisodes.Select(i => i.DateCreated)
- .OrderByDescending(i => i)
- .FirstOrDefault();
-
numComplete++;
double percent = numComplete;
percent /= seriesList.Count;
diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
index ef9f5427c..52c1ab7dd 100644
--- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
@@ -72,6 +72,10 @@ namespace MediaBrowser.Providers.TV
{
// Don't fail the provider because this will just keep on going and going.
}
+ catch (DirectoryNotFoundException)
+ {
+ // Don't fail the provider because this will just keep on going and going.
+ }
}
return list;
@@ -101,6 +105,10 @@ namespace MediaBrowser.Providers.TV
{
// Don't fail the provider because this will just keep on going and going.
}
+ catch (DirectoryNotFoundException)
+ {
+ // Don't fail the provider because this will just keep on going and going.
+ }
}
return result;
@@ -208,8 +216,9 @@ namespace MediaBrowser.Providers.TV
/// Fetches the episode data.
/// </summary>
/// <param name="id">The identifier.</param>
+ /// <param name="identity">The identity.</param>
/// <param name="seriesDataPath">The series data path.</param>
- /// <param name="seriesProviderIds"></param>
+ /// <param name="seriesProviderIds">The series provider ids.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.Boolean}.</returns>
private Episode FetchEpisodeData(EpisodeInfo id, EpisodeIdentity identity, string seriesDataPath, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken)
@@ -279,6 +288,10 @@ namespace MediaBrowser.Providers.TV
{
break;
}
+ catch (DirectoryNotFoundException)
+ {
+ break;
+ }
episodeNumber++;
}
diff --git a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs
index efafeae96..1ebd7bed5 100644
--- a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs
@@ -94,6 +94,10 @@ namespace MediaBrowser.Providers.TV
{
// No tvdb data yet. Don't blow up
}
+ catch (DirectoryNotFoundException)
+ {
+ // No tvdb data yet. Don't blow up
+ }
}
return new RemoteImageInfo[] { };
diff --git a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs
index 9cc09c40c..08913d3b4 100644
--- a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs
@@ -87,6 +87,10 @@ namespace MediaBrowser.Providers.TV
{
// No tvdb data yet. Don't blow up
}
+ catch (DirectoryNotFoundException)
+ {
+ // No tvdb data yet. Don't blow up
+ }
}
return new RemoteImageInfo[] { };
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
index bfdbb8ccf..ce939aeb4 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs
@@ -95,7 +95,7 @@ namespace MediaBrowser.Server.Implementations.Channels
public static string GetUserDistinctValue(User user)
{
- var channels = user.Configuration.BlockedChannels
+ var channels = user.Policy.BlockedChannels
.OrderBy(i => i)
.ToList();
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index 9e7679f93..d88625396 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -179,12 +179,9 @@ namespace MediaBrowser.Server.Implementations.Channels
var internalResult = await GetChannelsInternal(query, cancellationToken).ConfigureAwait(false);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields))
- .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
- .ToList();
+ var dtoOptions = new DtoOptions();
- var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
+ var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user))
.ToArray();
var result = new QueryResult<BaseItemDto>
@@ -544,11 +541,6 @@ namespace MediaBrowser.Server.Implementations.Channels
var internalResult = await GetLatestChannelItemsInternal(query, cancellationToken).ConfigureAwait(false);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields))
- .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
- .ToList();
-
var items = internalResult.Items;
var totalRecordCount = internalResult.TotalRecordCount;
@@ -563,7 +555,9 @@ namespace MediaBrowser.Server.Implementations.Channels
totalRecordCount = items.Length;
}
- var returnItems = items.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
+ var dtoOptions = new DtoOptions();
+
+ var returnItems = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user))
.ToArray();
var result = new QueryResult<BaseItemDto>
@@ -828,12 +822,9 @@ namespace MediaBrowser.Server.Implementations.Channels
await RefreshIfNeeded(internalResult.Items, new Progress<double>(), cancellationToken).ConfigureAwait(false);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields))
- .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
- .ToList();
+ var dtoOptions = new DtoOptions();
- var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
+ var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user))
.ToArray();
var result = new QueryResult<BaseItemDto>
@@ -980,12 +971,9 @@ namespace MediaBrowser.Server.Implementations.Channels
var internalResult = await GetChannelItemsInternal(query, new Progress<double>(), cancellationToken).ConfigureAwait(false);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields))
- .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
- .ToList();
+ var dtoOptions = new DtoOptions();
- var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
+ var returnItems = internalResult.Items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user))
.ToArray();
var result = new QueryResult<BaseItemDto>
@@ -1407,12 +1395,9 @@ namespace MediaBrowser.Server.Implementations.Channels
{
var user = string.IsNullOrEmpty(userId) ? null : _userManager.GetUserById(userId);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
-
var folder = await GetInternalChannelFolder(userId, cancellationToken).ConfigureAwait(false);
- return _dtoService.GetBaseItemDto(folder, fields, user);
+ return _dtoService.GetBaseItemDto(folder, new DtoOptions(), user);
}
public async Task<Folder> GetInternalChannelFolder(string userId, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs
index 72c524ec5..d266cca6c 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelPostScanTask.cs
@@ -72,26 +72,29 @@ namespace MediaBrowser.Server.Implementations.Channels
var features = _channelManager.GetChannelFeatures(channelId);
const int currentRefreshLevel = 1;
- var maxRefreshLevel = features.AutoRefreshLevels ?? 1;
+ var maxRefreshLevel = features.AutoRefreshLevels ?? 0;
- var innerProgress = new ActionableProgress<double>();
-
- var startingNumberComplete = numComplete;
- innerProgress.RegisterAction(p =>
+ if (maxRefreshLevel > 0)
{
- double innerPercent = startingNumberComplete;
- innerPercent += (p / 100);
- innerPercent /= numItems;
- progress.Report(innerPercent * 100);
- });
+ var innerProgress = new ActionableProgress<double>();
- try
- {
- await GetAllItems(user, channelId, null, currentRefreshLevel, maxRefreshLevel, innerProgress, cancellationToken).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error getting channel content", ex);
+ var startingNumberComplete = numComplete;
+ innerProgress.RegisterAction(p =>
+ {
+ double innerPercent = startingNumberComplete;
+ innerPercent += (p / 100);
+ innerPercent /= numItems;
+ progress.Report(innerPercent * 100);
+ });
+
+ try
+ {
+ await GetAllItems(user, channelId, null, currentRefreshLevel, maxRefreshLevel, innerProgress, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error getting channel content", ex);
+ }
}
numComplete++;
diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
index b9896e9ce..b3b8ccbd8 100644
--- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
+++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Configuration;
+using System.Collections.Generic;
+using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Implementations.Configuration;
using MediaBrowser.Controller;
@@ -32,7 +33,6 @@ namespace MediaBrowser.Server.Implementations.Configuration
: base(applicationPaths, logManager, xmlSerializer)
{
UpdateItemsByNamePath();
- UpdateTranscodingTempPath();
UpdateMetadataPath();
}
@@ -71,12 +71,18 @@ namespace MediaBrowser.Server.Implementations.Configuration
protected override void OnConfigurationUpdated()
{
UpdateItemsByNamePath();
- UpdateTranscodingTempPath();
UpdateMetadataPath();
base.OnConfigurationUpdated();
}
+ public override void AddParts(IEnumerable<IConfigurationFactory> factories)
+ {
+ base.AddParts(factories);
+
+ UpdateTranscodingTempPath();
+ }
+
/// <summary>
/// Updates the items by name path.
/// </summary>
@@ -102,9 +108,21 @@ namespace MediaBrowser.Server.Implementations.Configuration
/// </summary>
private void UpdateTranscodingTempPath()
{
- ((ServerApplicationPaths)ApplicationPaths).TranscodingTempPath = string.IsNullOrEmpty(Configuration.TranscodingTempPath) ?
+ var encodingConfig = this.GetConfiguration<EncodingOptions>("encoding");
+
+ ((ServerApplicationPaths)ApplicationPaths).TranscodingTempPath = string.IsNullOrEmpty(encodingConfig.TranscodingTempPath) ?
null :
- Configuration.TranscodingTempPath;
+ encodingConfig.TranscodingTempPath;
+ }
+
+ protected override void OnNamedConfigurationUpdated(string key, object configuration)
+ {
+ base.OnNamedConfigurationUpdated(key, configuration);
+
+ if (string.Equals(key, "encoding", StringComparison.OrdinalIgnoreCase))
+ {
+ UpdateTranscodingTempPath();
+ }
}
/// <summary>
@@ -117,7 +135,6 @@ namespace MediaBrowser.Server.Implementations.Configuration
var newConfig = (ServerConfiguration)newConfiguration;
ValidateItemByNamePath(newConfig);
- ValidateTranscodingTempPath(newConfig);
ValidatePathSubstitutions(newConfig);
ValidateMetadataPath(newConfig);
@@ -158,26 +175,6 @@ namespace MediaBrowser.Server.Implementations.Configuration
}
/// <summary>
- /// Validates the transcoding temporary path.
- /// </summary>
- /// <param name="newConfig">The new configuration.</param>
- /// <exception cref="DirectoryNotFoundException"></exception>
- private void ValidateTranscodingTempPath(ServerConfiguration newConfig)
- {
- var newPath = newConfig.TranscodingTempPath;
-
- if (!string.IsNullOrWhiteSpace(newPath)
- && !string.Equals(Configuration.TranscodingTempPath ?? string.Empty, newPath))
- {
- // Validate
- if (!Directory.Exists(newPath))
- {
- throw new DirectoryNotFoundException(string.Format("{0} does not exist.", newPath));
- }
- }
- }
-
- /// <summary>
/// Validates the metadata path.
/// </summary>
/// <param name="newConfig">The new configuration.</param>
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
index 52c252d24..52ec5c9b1 100644
--- a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
@@ -34,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.Connect
{
LoadCachedAddress();
- _timer = new Timer(TimerCallback, null, TimeSpan.FromSeconds(10), TimeSpan.FromHours(6));
+ _timer = new Timer(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(3));
}
private async void TimerCallback(object state)
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
index cbd75cdeb..67d844543 100644
--- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
@@ -432,9 +433,7 @@ namespace MediaBrowser.Server.Implementations.Connect
await user.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
- user.Configuration.SyncConnectImage = false;
- user.Configuration.SyncConnectName = false;
- _userManager.UpdateConfiguration(user, user.Configuration);
+ await _userManager.UpdateConfiguration(user.Id.ToString("N"), user.Configuration);
await RefreshAuthorizationsInternal(false, CancellationToken.None).ConfigureAwait(false);
@@ -791,7 +790,7 @@ namespace MediaBrowser.Server.Implementations.Connect
if (user == null)
{
// Add user
- user = await _userManager.CreateUser(connectEntry.UserName).ConfigureAwait(false);
+ user = await _userManager.CreateUser(_userManager.MakeValidUsername(connectEntry.UserName)).ConfigureAwait(false);
user.ConnectUserName = connectEntry.UserName;
user.ConnectUserId = connectEntry.UserId;
@@ -800,23 +799,21 @@ namespace MediaBrowser.Server.Implementations.Connect
await _userManager.UpdateUser(user).ConfigureAwait(false);
- user.Configuration.SyncConnectImage = true;
- user.Configuration.SyncConnectName = true;
- user.Configuration.IsHidden = true;
- user.Configuration.EnableLiveTvManagement = false;
- user.Configuration.EnableContentDeletion = false;
- user.Configuration.EnableRemoteControlOfOtherUsers = false;
- user.Configuration.EnableSharedDeviceControl = false;
- user.Configuration.IsAdministrator = false;
+ user.Policy.IsHidden = true;
+ user.Policy.EnableLiveTvManagement = false;
+ user.Policy.EnableContentDeletion = false;
+ user.Policy.EnableRemoteControlOfOtherUsers = false;
+ user.Policy.EnableSharedDeviceControl = false;
+ user.Policy.IsAdministrator = false;
if (currentPendingEntry != null)
{
- user.Configuration.EnableLiveTvAccess = currentPendingEntry.EnableLiveTv;
- user.Configuration.BlockedMediaFolders = currentPendingEntry.ExcludedLibraries;
- user.Configuration.BlockedChannels = currentPendingEntry.ExcludedChannels;
+ user.Policy.EnableLiveTvAccess = currentPendingEntry.EnableLiveTv;
+ user.Policy.BlockedMediaFolders = currentPendingEntry.ExcludedLibraries;
+ user.Policy.BlockedChannels = currentPendingEntry.ExcludedChannels;
}
- _userManager.UpdateConfiguration(user, user.Configuration);
+ await _userManager.UpdateConfiguration(user.Id.ToString("N"), user.Configuration);
}
}
else if (string.Equals(connectEntry.AcceptStatus, "waiting", StringComparison.OrdinalIgnoreCase))
@@ -844,7 +841,7 @@ namespace MediaBrowser.Server.Implementations.Connect
{
var users = _userManager.Users
.Where(i => !string.IsNullOrEmpty(i.ConnectUserId) &&
- (i.Configuration.SyncConnectImage || i.Configuration.SyncConnectName))
+ (i.ConnectLinkType.HasValue && i.ConnectLinkType.Value == UserLinkType.Guest))
.ToList();
foreach (var user in users)
@@ -857,7 +854,10 @@ namespace MediaBrowser.Server.Implementations.Connect
continue;
}
- if (user.Configuration.SyncConnectName)
+ var syncConnectName = true;
+ var syncConnectImage = true;
+
+ if (syncConnectName)
{
var changed = !string.Equals(authorization.UserName, user.Name, StringComparison.OrdinalIgnoreCase);
@@ -867,7 +867,7 @@ namespace MediaBrowser.Server.Implementations.Connect
}
}
- if (user.Configuration.SyncConnectImage)
+ if (syncConnectImage)
{
var imageUrl = authorization.UserImageUrl;
diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
index b141fea1e..967c78c50 100644
--- a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
+++ b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs
@@ -78,6 +78,11 @@ namespace MediaBrowser.Server.Implementations.Drawing
// No biggie
sizeDictionary = new Dictionary<Guid, ImageSize>();
}
+ catch (DirectoryNotFoundException)
+ {
+ // No biggie
+ sizeDictionary = new Dictionary<Guid, ImageSize>();
+ }
catch (Exception ex)
{
logger.ErrorException("Error parsing image size cache file", ex);
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index 1020a4373..362ee80b0 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -73,11 +73,6 @@ namespace MediaBrowser.Server.Implementations.Dto
{
Fields = fields
};
-
- // Get everything
- options.ImageTypes = Enum.GetNames(typeof(ImageType))
- .Select(i => (ImageType)Enum.Parse(typeof(ImageType), i, true))
- .ToList();
return GetBaseItemDto(item, options, user, owner);
}
@@ -121,8 +116,6 @@ namespace MediaBrowser.Server.Implementations.Dto
ServerId = _appHost.SystemId
};
- dto.SupportsPlaylists = item.SupportsAddingToPlaylist;
-
if (fields.Contains(ItemFields.People))
{
AttachPeople(dto, item);
@@ -275,6 +268,21 @@ namespace MediaBrowser.Server.Implementations.Dto
}
dto.PlayAccess = item.GetPlayAccess(user);
+
+ if (fields.Contains(ItemFields.SeasonUserData))
+ {
+ var episode = item as Episode;
+
+ if (episode != null)
+ {
+ var season = episode.Season;
+
+ if (season != null)
+ {
+ dto.SeasonUserData = _userDataRepository.GetUserDataDto(season, user);
+ }
+ }
+ }
}
private int GetChildCount(Folder folder, User user)
@@ -750,7 +758,7 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.AspectRatio = hasAspectRatio.AspectRatio;
}
- if (fields.Contains(ItemFields.ProductionLocations))
+ if (fields.Contains(ItemFields.Metascore))
{
var hasMetascore = item as IHasMetascore;
if (hasMetascore != null)
@@ -1132,15 +1140,22 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.AbsoluteEpisodeNumber = episode.AbsoluteEpisodeNumber;
}
- dto.AirsAfterSeasonNumber = episode.AirsAfterSeasonNumber;
- dto.AirsBeforeEpisodeNumber = episode.AirsBeforeEpisodeNumber;
- dto.AirsBeforeSeasonNumber = episode.AirsBeforeSeasonNumber;
+ //if (fields.Contains(ItemFields.SpecialEpisodeNumbers))
+ {
+ dto.AirsAfterSeasonNumber = episode.AirsAfterSeasonNumber;
+ dto.AirsBeforeEpisodeNumber = episode.AirsBeforeEpisodeNumber;
+ dto.AirsBeforeSeasonNumber = episode.AirsBeforeSeasonNumber;
+ }
var episodeSeason = episode.Season;
if (episodeSeason != null)
{
dto.SeasonId = episodeSeason.Id.ToString("N");
- dto.SeasonName = episodeSeason.Name;
+
+ if (fields.Contains(ItemFields.SeasonName))
+ {
+ dto.SeasonName = episodeSeason.Name;
+ }
}
if (fields.Contains(ItemFields.SeriesGenres))
@@ -1180,7 +1195,11 @@ namespace MediaBrowser.Server.Implementations.Dto
{
dto.SeriesId = GetDtoId(series);
dto.SeriesName = series.Name;
- dto.AirTime = series.AirTime;
+
+ if (fields.Contains(ItemFields.AirTime))
+ {
+ dto.AirTime = series.AirTime;
+ }
if (options.GetImageLimit(ImageType.Thumb) > 0)
{
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs
index de53201c9..fcc664011 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs
@@ -1,6 +1,5 @@
using MediaBrowser.Common;
using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Implementations.Security;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
index d4625d402..432ea1f69 100644
--- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
+++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs
@@ -4,11 +4,11 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Controller.Resolvers;
-using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.FileOrganization;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Naming.Common;
+using MediaBrowser.Naming.IO;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -16,8 +16,6 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Server.Implementations.Library;
-using MediaBrowser.Server.Implementations.Library.Resolvers.TV;
namespace MediaBrowser.Server.Implementations.FileOrganization
{
@@ -57,18 +55,23 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
FileSize = new FileInfo(path).Length
};
- var seriesName = SeriesResolver.GetSeriesNameFromEpisodeFile(path);
+ var resolver = new Naming.TV.EpisodeResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
+
+ var episodeInfo = resolver.Resolve(path, FileInfoType.File) ??
+ new Naming.TV.EpisodeInfo();
+
+ var seriesName = episodeInfo.SeriesName;
if (!string.IsNullOrEmpty(seriesName))
{
- var season = SeriesResolver.GetSeasonNumberFromEpisodeFile(path);
+ var season = episodeInfo.SeasonNumber;
result.ExtractedSeasonNumber = season;
if (season.HasValue)
{
// Passing in true will include a few extra regex's
- var episode = SeriesResolver.GetEpisodeNumberFromFile(path, true);
+ var episode = episodeInfo.EpisodeNumber;
result.ExtractedEpisodeNumber = episode;
@@ -76,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
_logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, season, episode);
- var endingEpisodeNumber = SeriesResolver.GetEndingEpisodeNumberFromFile(path);
+ var endingEpisodeNumber = episodeInfo.EndingEpsiodeNumber;
result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;
@@ -251,7 +254,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
var folder = Path.GetDirectoryName(targetPath);
var targetFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(targetPath);
-
+
try
{
var filesOfOtherExtensions = Directory.EnumerateFiles(folder, "*", SearchOption.TopDirectoryOnly)
@@ -456,11 +459,11 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
private bool IsSameEpisode(string sourcePath, string newPath)
{
- var sourceFileInfo = new FileInfo(sourcePath);
- var destinationFileInfo = new FileInfo(newPath);
-
try
{
+ var sourceFileInfo = new FileInfo(sourcePath);
+ var destinationFileInfo = new FileInfo(newPath);
+
if (sourceFileInfo.Length == destinationFileInfo.Length)
{
return true;
@@ -470,6 +473,10 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
return false;
}
+ catch (DirectoryNotFoundException)
+ {
+ return false;
+ }
return false;
}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
index 56e2e5247..c3228db92 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -1,7 +1,6 @@
using Funq;
using MediaBrowser.Common;
using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Implementations.HttpServer.NetListener;
@@ -205,10 +204,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
{
HostContext.Config.HandlerFactoryPath = ListenerRequest.GetHandlerPathIfAny(UrlPrefixes.First());
- _listener = _supportsNativeWebSocket && NativeWebSocket.IsSupported
- ? _listener = new HttpListenerServer(_logger, OnRequestReceived)
- //? _listener = new WebSocketSharpListener(_logger, OnRequestReceived)
- : _listener = new WebSocketSharpListener(_logger, OnRequestReceived);
+ _listener = GetListener();
_listener.WebSocketHandler = WebSocketHandler;
_listener.ErrorHandler = ErrorHandler;
@@ -217,6 +213,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer
_listener.Start(UrlPrefixes);
}
+ private IHttpListener GetListener()
+ {
+ if (_supportsNativeWebSocket && NativeWebSocket.IsSupported)
+ {
+ return new HttpListenerServer(_logger, OnRequestReceived);
+ }
+
+ return new WebSocketSharpListener(_logger, OnRequestReceived);
+ }
+
private void WebSocketHandler(WebSocketConnectEventArgs args)
{
if (WebSocketConnected != null)
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs
index e13e27d5a..681d3ac5e 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs
@@ -12,7 +12,7 @@ using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
-using MimeTypes = MediaBrowser.Common.Net.MimeTypes;
+using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
namespace MediaBrowser.Server.Implementations.HttpServer
{
diff --git a/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs
index 86e8856cf..e77600e93 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/IHttpListener.cs
@@ -1,8 +1,8 @@
-using System.Threading.Tasks;
-using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Net;
using ServiceStack.Web;
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.HttpServer
{
diff --git a/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs b/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs
index 8cc614fe5..cac2f8e09 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/NativeWebSocket.cs
@@ -1,9 +1,9 @@
-using System.Text;
-using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using System;
using System.Net.WebSockets;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WebSocketMessageType = MediaBrowser.Model.Net.WebSocketMessageType;
diff --git a/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs b/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs
index 2d41cc26f..31c0e87b3 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/NetListener/HttpListenerServer.cs
@@ -1,4 +1,4 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using ServiceStack;
using ServiceStack.Host.HttpListener;
diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
index 57d87749c..13563ce19 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
@@ -68,7 +68,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
if (user != null)
{
- if (user.Configuration.IsDisabled)
+ if (user.Policy.IsDisabled)
{
throw new SecurityException("User account has been disabled.")
{
@@ -76,7 +76,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
};
}
- if (!user.Configuration.IsAdministrator &&
+ if (!user.Policy.IsAdministrator &&
!authAttribtues.EscapeParentalControl &&
!user.IsParentalScheduleAllowed())
{
@@ -135,7 +135,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
{
if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase))
{
- if (user == null || !user.Configuration.IsAdministrator)
+ if (user == null || !user.Policy.IsAdministrator)
{
throw new SecurityException("User does not have admin access.")
{
@@ -145,7 +145,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
}
if (roles.Contains("delete", StringComparer.OrdinalIgnoreCase))
{
- if (user == null || !user.Configuration.EnableContentDeletion)
+ if (user == null || !user.Policy.EnableContentDeletion)
{
throw new SecurityException("User does not have delete access.")
{
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs
index 7ff3a1247..401d49325 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/SharpWebSocket.cs
@@ -1,11 +1,9 @@
-using System.Text;
-using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
-using WebSocketMessageType = MediaBrowser.Model.Net.WebSocketMessageType;
using WebSocketState = MediaBrowser.Model.Net.WebSocketState;
namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
index 9deb34e91..4d2d57b6e 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs
@@ -1,4 +1,4 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using ServiceStack;
using ServiceStack.Web;
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index 4cb39778c..b4a4c7e9a 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -18,8 +18,8 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Naming.Audio;
using MediaBrowser.Naming.Common;
using MediaBrowser.Naming.IO;
+using MediaBrowser.Naming.TV;
using MediaBrowser.Naming.Video;
-using MediaBrowser.Server.Implementations.Library.Resolvers.TV;
using MediaBrowser.Server.Implementations.Library.Validators;
using MediaBrowser.Server.Implementations.ScheduledTasks;
using System;
@@ -68,6 +68,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// </summary>
/// <value>The entity resolvers enumerable.</value>
private IItemResolver[] EntityResolvers { get; set; }
+ private IMultiItemResolver[] MultiItemResolvers { get; set; }
/// <summary>
/// Gets or sets the comparers.
@@ -196,9 +197,10 @@ namespace MediaBrowser.Server.Implementations.Library
EntityResolutionIgnoreRules = rules.ToArray();
PluginFolderCreators = pluginFolders.ToArray();
EntityResolvers = resolvers.OrderBy(i => i.Priority).ToArray();
+ MultiItemResolvers = EntityResolvers.OfType<IMultiItemResolver>().ToArray();
IntroProviders = introProviders.ToArray();
Comparers = itemComparers.ToArray();
-
+
PostscanTasks = postscanTasks.OrderBy(i =>
{
var hasOrder = i as IHasOrder;
@@ -344,7 +346,7 @@ namespace MediaBrowser.Server.Implementations.Library
try
{
- await UpdateItem(season, ItemUpdateType.MetadataDownload, cancellationToken).ConfigureAwait(false);
+ await UpdateItem(season, ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -560,10 +562,9 @@ namespace MediaBrowser.Server.Implementations.Library
}
public BaseItem ResolvePath(FileSystemInfo fileInfo,
- Folder parent = null,
- string collectionType = null)
+ Folder parent = null)
{
- return ResolvePath(fileInfo, new DirectoryService(_logger), parent, collectionType);
+ return ResolvePath(fileInfo, new DirectoryService(_logger), parent);
}
private BaseItem ResolvePath(FileSystemInfo fileInfo, IDirectoryService directoryService, Folder parent = null, string collectionType = null)
@@ -573,10 +574,17 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentNullException("fileInfo");
}
+ var fullPath = fileInfo.FullName;
+
+ if (string.IsNullOrWhiteSpace(collectionType))
+ {
+ collectionType = GetConfiguredContentType(fullPath);
+ }
+
var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, this, directoryService)
{
Parent = parent,
- Path = fileInfo.FullName,
+ Path = fullPath,
FileInfo = fileInfo,
CollectionType = collectionType
};
@@ -652,9 +660,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (parent != null)
{
- var multiItemResolvers = EntityResolvers.OfType<IMultiItemResolver>();
-
- foreach (var resolver in multiItemResolvers)
+ foreach (var resolver in MultiItemResolvers)
{
var result = resolver.ResolveMultiple(parent, fileList, collectionType, directoryService);
@@ -862,7 +868,7 @@ namespace MediaBrowser.Server.Implementations.Library
var type = typeof(T);
- if (type == typeof(Person) && ConfigurationManager.Configuration.EnablePeoplePrefixSubFolders)
+ if (type == typeof(Person))
{
subFolderPrefix = validFilename.Substring(0, 1);
}
@@ -1546,12 +1552,48 @@ namespace MediaBrowser.Server.Implementations.Library
return ItemRepository.RetrieveItem(id);
}
- /// <summary>
- /// Finds the type of the collection.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <returns>System.String.</returns>
- public string FindCollectionType(BaseItem item)
+ public string GetContentType(BaseItem item)
+ {
+ // Types cannot be overridden, so go from the top down until we find a configured content type
+
+ var type = GetTopFolderContentType(item);
+
+ if (!string.IsNullOrWhiteSpace(type))
+ {
+ return type;
+ }
+
+ type = GetInheritedContentType(item);
+
+ if (!string.IsNullOrWhiteSpace(type))
+ {
+ return type;
+ }
+
+ return GetConfiguredContentType(item);
+ }
+
+ public string GetInheritedContentType(BaseItem item)
+ {
+ return item.Parents
+ .Select(GetConfiguredContentType)
+ .LastOrDefault(i => !string.IsNullOrWhiteSpace(i));
+ }
+
+ private string GetConfiguredContentType(BaseItem item)
+ {
+ return GetConfiguredContentType(item.ContainingFolderPath);
+ }
+
+ private string GetConfiguredContentType(string path)
+ {
+ var type = ConfigurationManager.Configuration.ContentTypes
+ .FirstOrDefault(i => string.Equals(i.Name, path, StringComparison.OrdinalIgnoreCase) || _fileSystem.ContainsSubPath(i.Name, path));
+
+ return type == null ? null : type.Value;
+ }
+
+ private string GetTopFolderContentType(BaseItem item)
{
while (!(item.Parent is AggregateFolder) && item.Parent != null)
{
@@ -1563,14 +1605,11 @@ namespace MediaBrowser.Server.Implementations.Library
return null;
}
- var collectionTypes = GetUserRootFolder().Children
+ return GetUserRootFolder().Children
.OfType<ICollectionFolder>()
- .Where(i => !string.IsNullOrEmpty(i.CollectionType) && (string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path)))
+ .Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path))
.Select(i => i.CollectionType)
- .Distinct()
- .ToList();
-
- return collectionTypes.Count == 1 ? collectionTypes[0] : null;
+ .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
}
public async Task<UserView> GetNamedView(string name,
@@ -1708,22 +1747,127 @@ namespace MediaBrowser.Server.Implementations.Library
public int? GetSeasonNumberFromPath(string path)
{
- return SeriesResolver.GetSeasonNumberFromPath(path, CollectionType.TvShows);
+ return new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(path, true).SeasonNumber;
}
- public int? GetSeasonNumberFromEpisodeFile(string path)
+ public bool FillMissingEpisodeNumbersFromPath(Episode episode)
{
- return SeriesResolver.GetSeasonNumberFromEpisodeFile(path);
- }
+ var resolver = new EpisodeResolver(new ExtendedNamingOptions(),
+ new Naming.Logging.NullLogger());
- public int? GetEndingEpisodeNumberFromFile(string path)
- {
- return SeriesResolver.GetEndingEpisodeNumberFromFile(path);
- }
+ var fileType = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd || episode.VideoType == VideoType.HdDvd ?
+ FileInfoType.Directory :
+ FileInfoType.File;
- public int? GetEpisodeNumberFromFile(string path, bool considerSeasonless)
- {
- return SeriesResolver.GetEpisodeNumberFromFile(path, considerSeasonless);
+ var locationType = episode.LocationType;
+
+ var episodeInfo = locationType == LocationType.FileSystem || locationType == LocationType.Offline ?
+ resolver.Resolve(episode.Path, fileType) :
+ new Naming.TV.EpisodeInfo();
+
+ if (episodeInfo == null)
+ {
+ episodeInfo = new Naming.TV.EpisodeInfo();
+ }
+
+ var changed = false;
+
+ if (episodeInfo.IsByDate)
+ {
+ if (episode.IndexNumber.HasValue)
+ {
+ episode.IndexNumber = null;
+ changed = true;
+ }
+
+ if (episode.IndexNumberEnd.HasValue)
+ {
+ episode.IndexNumberEnd = null;
+ changed = true;
+ }
+
+ if (!episode.PremiereDate.HasValue)
+ {
+ if (episodeInfo.Year.HasValue && episodeInfo.Month.HasValue && episodeInfo.Day.HasValue)
+ {
+ episode.PremiereDate = new DateTime(episodeInfo.Year.Value, episodeInfo.Month.Value, episodeInfo.Day.Value).ToUniversalTime();
+ }
+
+ if (episode.PremiereDate.HasValue)
+ {
+ changed = true;
+ }
+ }
+
+ if (!episode.ProductionYear.HasValue)
+ {
+ episode.ProductionYear = episodeInfo.Year;
+
+ if (episode.ProductionYear.HasValue)
+ {
+ changed = true;
+ }
+ }
+
+ if (!episode.ParentIndexNumber.HasValue)
+ {
+ var season = episode.Season;
+
+ if (season != null)
+ {
+ episode.ParentIndexNumber = season.IndexNumber;
+ }
+
+ if (episode.ParentIndexNumber.HasValue)
+ {
+ changed = true;
+ }
+ }
+ }
+ else
+ {
+ if (!episode.IndexNumber.HasValue)
+ {
+ episode.IndexNumber = episodeInfo.EpisodeNumber;
+
+ if (episode.IndexNumber.HasValue)
+ {
+ changed = true;
+ }
+ }
+
+ if (!episode.IndexNumberEnd.HasValue)
+ {
+ episode.IndexNumberEnd = episodeInfo.EndingEpsiodeNumber;
+
+ if (episode.IndexNumberEnd.HasValue)
+ {
+ changed = true;
+ }
+ }
+
+ if (!episode.ParentIndexNumber.HasValue)
+ {
+ episode.ParentIndexNumber = episodeInfo.SeasonNumber;
+
+ if (!episode.ParentIndexNumber.HasValue)
+ {
+ var season = episode.Season;
+
+ if (season != null)
+ {
+ episode.ParentIndexNumber = season.IndexNumber;
+ }
+ }
+
+ if (episode.ParentIndexNumber.HasValue)
+ {
+ changed = true;
+ }
+ }
+ }
+
+ return changed;
}
public ItemLookupInfo ParseName(string name)
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
index f32ed2b20..0f703cb22 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
@@ -37,7 +37,11 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
/// <value>The priority.</value>
public override ResolverPriority Priority
{
- get { return ResolverPriority.Third; } // we need to be ahead of the generic folder resolver but behind the movie one
+ get
+ {
+ // Behind special folder resolver
+ return ResolverPriority.Second;
+ }
}
/// <summary>
@@ -49,21 +53,13 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
{
if (!args.IsDirectory) return null;
- //Avoid mis-identifying top folders
- if (args.Parent == null) return null;
+ // Avoid mis-identifying top folders
if (args.Parent.IsRoot) return null;
if (args.HasParent<MusicAlbum>()) return null;
- // Optimization
- if (args.HasParent<BoxSet>() || args.HasParent<Series>() || args.HasParent<Season>())
- {
- return null;
- }
-
var collectionType = args.GetCollectionType();
- var isMusicMediaFolder = string.Equals(collectionType, CollectionType.Music,
- StringComparison.OrdinalIgnoreCase);
+ var isMusicMediaFolder = string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase);
// If there's a collection type and it's not music, don't allow it.
if (!isMusicMediaFolder)
@@ -125,14 +121,28 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
ILibraryManager libraryManager)
{
var discSubfolderCount = 0;
+ var notMultiDisc = false;
foreach (var fileSystemInfo in list)
{
if ((fileSystemInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
{
- if (allowSubfolders && IsAlbumSubfolder(fileSystemInfo, directoryService, logger, fileSystem, libraryManager))
+ if (allowSubfolders)
{
- discSubfolderCount++;
+ var path = fileSystemInfo.FullName;
+ var isMultiDisc = IsMultiDiscFolder(path);
+ var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager);
+
+ if (isMultiDisc && hasMusic)
+ {
+ logger.Debug("Found multi-disc folder: " + path);
+ discSubfolderCount++;
+ }
+ else if (hasMusic)
+ {
+ // If there are folders underneath with music that are not multidisc, then this can't be a multi-disc album
+ notMultiDisc = true;
+ }
}
}
@@ -144,34 +154,15 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
}
}
- return discSubfolderCount > 0;
- }
-
- private static bool IsAlbumSubfolder(FileSystemInfo directory, IDirectoryService directoryService, ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager)
- {
- var path = directory.FullName;
-
- if (IsMultiDiscFolder(path))
+ if (notMultiDisc)
{
- logger.Debug("Found multi-disc folder: " + path);
-
- return ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager);
+ return false;
}
- return false;
- }
-
- public static bool IsMultiDiscFolder(string path)
- {
- return IsMultiDiscAlbumFolder(path);
+ return discSubfolderCount > 0 && discSubfolderCount > 10;
}
- /// <summary>
- /// Determines whether [is multi disc album folder] [the specified path].
- /// </summary>
- /// <param name="path">The path.</param>
- /// <returns><c>true</c> if [is multi disc album folder] [the specified path]; otherwise, <c>false</c>.</returns>
- private static bool IsMultiDiscAlbumFolder(string path)
+ private static bool IsMultiDiscFolder(string path)
{
var parser = new AlbumParser(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
var result = parser.ParseMultiPart(path);
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
index 71b6c0843..edbc87415 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
@@ -34,7 +34,11 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
/// <value>The priority.</value>
public override ResolverPriority Priority
{
- get { return ResolverPriority.Third; } // we need to be ahead of the generic folder resolver but behind the movie one
+ get
+ {
+ // Behind special folder resolver
+ return ResolverPriority.Second;
+ }
}
/// <summary>
@@ -46,8 +50,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
{
if (!args.IsDirectory) return null;
- //Avoid mis-identifying top folders
- if (args.Parent == null) return null;
+ // Avoid mis-identifying top folders
if (args.Parent.IsRoot) return null;
// Don't allow nested artists
@@ -56,16 +59,9 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
return null;
}
- // Optimization
- if (args.HasParent<BoxSet>() || args.HasParent<Series>() || args.HasParent<Season>())
- {
- return null;
- }
-
var collectionType = args.GetCollectionType();
- var isMusicMediaFolder = string.Equals(collectionType, CollectionType.Music,
- StringComparison.OrdinalIgnoreCase);
+ var isMusicMediaFolder = string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase);
// If there's a collection type and it's not music, it can't be a series
if (!isMusicMediaFolder)
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs
index 166465f72..34237622d 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/FolderResolver.cs
@@ -1,10 +1,6 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Resolvers;
-using System;
-using System.IO;
-using System.Linq;
namespace MediaBrowser.Server.Implementations.Library.Resolvers
{
@@ -13,13 +9,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
/// </summary>
public class FolderResolver : FolderResolver<Folder>
{
- private readonly IFileSystem _fileSystem;
-
- public FolderResolver(IFileSystem fileSystem)
- {
- _fileSystem = fileSystem;
- }
-
/// <summary>
/// Gets the priority.
/// </summary>
@@ -38,48 +27,11 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
{
if (args.IsDirectory)
{
- if (args.IsPhysicalRoot)
- {
- return new AggregateFolder();
- }
- if (args.IsRoot)
- {
- return new UserRootFolder(); //if we got here and still a root - must be user root
- }
- if (args.IsVf)
- {
- return new CollectionFolder
- {
- CollectionType = GetCollectionType(args)
- };
- }
-
return new Folder();
}
return null;
}
-
- private string GetCollectionType(ItemResolveArgs args)
- {
- return args.FileSystemChildren
- .Where(i =>
- {
-
- try
- {
- return (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory &&
- string.Equals(".collection", i.Extension, StringComparison.OrdinalIgnoreCase);
- }
- catch (IOException)
- {
- return false;
- }
-
- })
- .Select(i => _fileSystem.GetFileNameWithoutExtension(i))
- .FirstOrDefault();
- }
}
/// <summary>
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs
index cc261c3e7..390113cc8 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using System;
using System.IO;
+using System.Linq;
namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
{
@@ -24,15 +25,14 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
// Contains [boxset] in the path
if (args.IsDirectory)
{
- var filename = Path.GetFileName(args.Path);
-
- if (string.IsNullOrEmpty(filename))
+ if (IsInvalid(args.GetCollectionType()))
{
return null;
}
+
+ var filename = Path.GetFileName(args.Path);
- // This is a bit of a one-off but it's here to combat MCM's over-aggressive placement of collection.xml files where they don't belong, including in series folders.
- if (args.ContainsMetaFileByName("series.xml"))
+ if (string.IsNullOrEmpty(filename))
{
return null;
}
@@ -51,6 +51,17 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
return null;
}
+ private bool IsInvalid(string collectionType)
+ {
+ var validCollectionTypes = new[]
+ {
+ CollectionType.Movies,
+ CollectionType.BoxSets
+ };
+
+ return !validCollectionTypes.Contains(collectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
+ }
+
/// <summary>
/// Sets the initial item values.
/// </summary>
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
index 276b99d3a..f7a82c5b8 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
@@ -2,7 +2,6 @@
using MediaBrowser.Controller;
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.Resolvers;
@@ -79,11 +78,10 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
return ResolveVideos<Video>(parent, files, directoryService, collectionType);
}
- return ResolveVideos<Movie>(parent, files, directoryService, collectionType);
+ return ResolveVideos<Video>(parent, files, directoryService, collectionType);
}
- if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) ||
- string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
{
return ResolveVideos<Movie>(parent, files, directoryService, collectionType);
}
@@ -117,7 +115,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
FullName = i.FullName,
Type = FileInfoType.File
- }).ToList()).ToList();
+ }).ToList(), false).ToList();
var result = new MultiItemResolverResult
{
@@ -168,12 +166,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
{
if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
{
- return FindMovie<MusicVideo>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType, false);
+ return FindMovie<MusicVideo>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
}
if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase))
{
- return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType, false);
+ return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
}
if (string.IsNullOrEmpty(collectionType))
@@ -184,17 +182,10 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
}
- // Since the looping is expensive, this is an optimization to help us avoid it
- if (args.ContainsMetaFileByName("series.xml"))
- {
- return null;
- }
-
- return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
+ return FindMovie<Video>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
}
- if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) ||
- string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
{
return FindMovie<Movie>(args.Path, args.Parent, args.FileSystemChildren.ToList(), args.DirectoryService, collectionType);
}
@@ -216,8 +207,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
}
// To find a movie file, the collection type must be movies or boxsets
- else if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) ||
- string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
+ else if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase))
{
item = ResolveVideo<Movie>(args, true);
}
@@ -228,7 +218,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
}
else if (string.IsNullOrEmpty(collectionType))
{
- item = ResolveVideo<Movie>(args, false);
+ item = ResolveVideo<Video>(args, false);
}
if (item != null)
@@ -277,9 +267,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
/// <param name="fileSystemEntries">The file system entries.</param>
/// <param name="directoryService">The directory service.</param>
/// <param name="collectionType">Type of the collection.</param>
- /// <param name="supportMultiVersion">if set to <c>true</c> [support multi version].</param>
/// <returns>Movie.</returns>
- private T FindMovie<T>(string path, Folder parent, List<FileSystemInfo> fileSystemEntries, IDirectoryService directoryService, string collectionType, bool supportMultiVersion = true)
+ private T FindMovie<T>(string path, Folder parent, List<FileSystemInfo> fileSystemEntries, IDirectoryService directoryService, string collectionType)
where T : Video, new()
{
var multiDiscFolders = new List<FileSystemInfo>();
@@ -328,8 +317,11 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, collectionType);
+ var supportsMultiVersion = !string.Equals(collectionType, CollectionType.HomeVideos) &&
+ !string.Equals(collectionType, CollectionType.MusicVideos);
+
// Test for multi-editions
- if (result.Items.Count > 1 && supportMultiVersion)
+ if (result.Items.Count > 1 && supportsMultiVersion)
{
var filenamePrefix = Path.GetFileName(path);
@@ -353,6 +345,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
{
var movie = (T)result.Items[0];
movie.IsInMixedFolder = false;
+ movie.Name = Path.GetFileName(movie.ContainingFolderPath);
return movie;
}
@@ -453,52 +446,16 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
}
}
- // Don't do any resolving within a series structure
- if (string.IsNullOrEmpty(collectionType))
- {
- if (HasParent<Series>(parent) || HasParent<Season>(parent))
- {
- return true;
- }
-
- // Since the looping is expensive, this is an optimization to help us avoid it
- if (files.Select(i => i.Name).Contains("series.xml", StringComparer.OrdinalIgnoreCase))
- {
- return true;
- }
- }
-
var validCollectionTypes = new[]
{
string.Empty,
CollectionType.Movies,
CollectionType.HomeVideos,
CollectionType.MusicVideos,
- CollectionType.BoxSets,
CollectionType.Movies
};
return !validCollectionTypes.Contains(collectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}
-
- private bool HasParent<T>(Folder parent)
- where T : Folder
- {
- if (parent != null)
- {
- var item = parent as T;
-
- // Just in case the user decided to nest episodes.
- // Not officially supported but in some cases we can handle it.
- if (item == null)
- {
- item = parent.Parents.OfType<T>().FirstOrDefault();
- }
-
- return item != null;
-
- }
- return false;
- }
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
index 2fcfd7086..acae5b801 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
using System;
using System.IO;
@@ -17,7 +18,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
protected override PhotoAlbum Resolve(ItemResolveArgs args)
{
// Must be an image file within a photo collection
- if (!args.IsRoot && args.IsDirectory && string.Equals(args.GetCollectionType(), CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
+ if (args.IsDirectory && string.Equals(args.GetCollectionType(), CollectionType.Photos, StringComparison.OrdinalIgnoreCase))
{
if (HasPhotos(args))
{
@@ -35,5 +36,14 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
{
return args.FileSystemChildren.Any(i => ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory) && PhotoResolver.IsImageFile(i.FullName));
}
+
+ public override ResolverPriority Priority
+ {
+ get
+ {
+ // Behind special folder resolver
+ return ResolverPriority.Second;
+ }
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
index 5580b442c..02960ea7e 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
@@ -17,8 +17,8 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
protected override Photo Resolve(ItemResolveArgs args)
{
// Must be an image file within a photo collection
- if (!args.IsDirectory &&
- string.Equals(args.GetCollectionType(), CollectionType.Photos, StringComparison.OrdinalIgnoreCase) &&
+ if (string.Equals(args.GetCollectionType(), CollectionType.Photos, StringComparison.OrdinalIgnoreCase) &&
+ !args.IsDirectory &&
IsImageFile(args.Path))
{
return new Photo
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs
new file mode 100644
index 000000000..0a41a6c04
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs
@@ -0,0 +1,79 @@
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Resolvers;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace MediaBrowser.Server.Implementations.Library.Resolvers
+{
+ class SpecialFolderResolver : FolderResolver<Folder>
+ {
+ private readonly IFileSystem _fileSystem;
+
+ public SpecialFolderResolver(IFileSystem fileSystem)
+ {
+ _fileSystem = fileSystem;
+ }
+
+ /// <summary>
+ /// Gets the priority.
+ /// </summary>
+ /// <value>The priority.</value>
+ public override ResolverPriority Priority
+ {
+ get { return ResolverPriority.First; }
+ }
+
+ /// <summary>
+ /// Resolves the specified args.
+ /// </summary>
+ /// <param name="args">The args.</param>
+ /// <returns>Folder.</returns>
+ protected override Folder Resolve(ItemResolveArgs args)
+ {
+ if (args.IsDirectory)
+ {
+ if (args.IsPhysicalRoot)
+ {
+ return new AggregateFolder();
+ }
+ if (args.IsRoot)
+ {
+ return new UserRootFolder(); //if we got here and still a root - must be user root
+ }
+ if (args.IsVf)
+ {
+ return new CollectionFolder
+ {
+ CollectionType = GetCollectionType(args)
+ };
+ }
+ }
+
+ return null;
+ }
+
+ private string GetCollectionType(ItemResolveArgs args)
+ {
+ return args.FileSystemChildren
+ .Where(i =>
+ {
+
+ try
+ {
+ return (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory &&
+ string.Equals(".collection", i.Extension, StringComparison.OrdinalIgnoreCase);
+ }
+ catch (IOException)
+ {
+ return false;
+ }
+
+ })
+ .Select(i => _fileSystem.GetFileNameWithoutExtension(i))
+ .FirstOrDefault();
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
index 057425ca9..1a873f01e 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
@@ -37,23 +37,10 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
}
// If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something
- if (season != null || parent is Series || parent.Parents.OfType<Series>().Any())
+ if (season != null || args.HasParent<Series>())
{
var episode = ResolveVideo<Episode>(args, false);
- if (episode != null)
- {
- if (season != null)
- {
- episode.ParentIndexNumber = season.IndexNumber;
- }
-
- if (episode.ParentIndexNumber == null)
- {
- episode.ParentIndexNumber = SeriesResolver.GetSeasonNumberFromEpisodeFile(args.Path);
- }
- }
-
return episode;
}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
index 058fb1489..80477e567 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
@@ -1,7 +1,8 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Naming.Common;
+using MediaBrowser.Naming.TV;
namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
{
@@ -35,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
{
var season = new Season
{
- IndexNumber = SeriesResolver.GetSeasonNumberFromPath(args.Path, CollectionType.TvShows)
+ IndexNumber = new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(args.Path, true).SeasonNumber
};
if (season.IndexNumber.HasValue && season.IndexNumber.Value == 0)
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
index 72c0bae53..7f1416ad6 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
@@ -1,18 +1,9 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
using System;
-using System.Collections.Generic;
-using System.Globalization;
using System.IO;
-using System.Linq;
-using System.Text.RegularExpressions;
namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
{
@@ -21,17 +12,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
/// </summary>
public class SeriesResolver : FolderResolver<Series>
{
- private readonly IFileSystem _fileSystem;
- private readonly ILogger _logger;
- private readonly ILibraryManager _libraryManager;
-
- public SeriesResolver(IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager)
- {
- _fileSystem = fileSystem;
- _logger = logger;
- _libraryManager = libraryManager;
- }
-
/// <summary>
/// Gets the priority.
/// </summary>
@@ -53,33 +33,16 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
{
if (args.IsDirectory)
{
- // Avoid expensive tests against VF's and all their children by not allowing this
- if (args.Parent == null || args.Parent.IsRoot)
- {
- return null;
- }
-
- // Optimization to avoid running these tests against Seasons
- if (args.HasParent<Series>() || args.HasParent<Season>() || args.HasParent<MusicArtist>() || args.HasParent<MusicAlbum>())
- {
- return null;
- }
-
var collectionType = args.GetCollectionType();
- var isTvShowsFolder = string.Equals(collectionType, CollectionType.TvShows,
- StringComparison.OrdinalIgnoreCase);
-
// If there's a collection type and it's not tv, it can't be a series
- if (!string.IsNullOrEmpty(collectionType) &&
- !isTvShowsFolder &&
- !string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase))
- {
- return null;
- }
-
- if (IsSeriesFolder(args.Path, collectionType, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager))
+ if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
{
+ if (args.HasParent<Series>())
+ {
+ return null;
+ }
+
return new Series
{
Path = args.Path,
@@ -92,434 +55,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
}
/// <summary>
- /// Determines whether [is series folder] [the specified path].
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="collectionType">Type of the collection.</param>
- /// <param name="fileSystemChildren">The file system children.</param>
- /// <param name="directoryService">The directory service.</param>
- /// <param name="fileSystem">The file system.</param>
- /// <param name="logger">The logger.</param>
- /// <param name="libraryManager">The library manager.</param>
- /// <returns><c>true</c> if [is series folder] [the specified path]; otherwise, <c>false</c>.</returns>
- public static bool IsSeriesFolder(string path, string collectionType, IEnumerable<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService, IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager)
- {
- foreach (var child in fileSystemChildren)
- {
- var attributes = child.Attributes;
-
- if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
- {
- //logger.Debug("Igoring series file or folder marked hidden: {0}", child.FullName);
- continue;
- }
-
- // Can't enforce this because files saved by Bitcasa are always marked System
- //if ((attributes & FileAttributes.System) == FileAttributes.System)
- //{
- // logger.Debug("Igoring series subfolder marked system: {0}", child.FullName);
- // continue;
- //}
-
- if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
- {
- if (IsSeasonFolder(child.FullName, collectionType, directoryService, fileSystem))
- {
- //logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName);
- return true;
- }
- }
- else
- {
- var fullName = child.FullName;
-
- if (libraryManager.IsVideoFile(fullName) || IsVideoPlaceHolder(fullName))
- {
- var isTvShowsFolder = string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase);
-
- if (GetEpisodeNumberFromFile(fullName, isTvShowsFolder).HasValue)
- {
- return true;
- }
- }
- }
- }
-
- logger.Debug("{0} is not a series folder.", path);
- return false;
- }
-
- /// <summary>
- /// Determines whether [is place holder] [the specified path].
- /// </summary>
- /// <param name="path">The path.</param>
- /// <returns><c>true</c> if [is place holder] [the specified path]; otherwise, <c>false</c>.</returns>
- /// <exception cref="System.ArgumentNullException">path</exception>
- private static bool IsVideoPlaceHolder(string path)
- {
- if (string.IsNullOrEmpty(path))
- {
- throw new ArgumentNullException("path");
- }
-
- var extension = Path.GetExtension(path);
-
- return string.Equals(extension, ".disc", StringComparison.OrdinalIgnoreCase);
- }
-
- /// <summary>
- /// Determines whether [is season folder] [the specified path].
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="collectionType">Type of the collection.</param>
- /// <param name="directoryService">The directory service.</param>
- /// <param name="fileSystem">The file system.</param>
- /// <returns><c>true</c> if [is season folder] [the specified path]; otherwise, <c>false</c>.</returns>
- private static bool IsSeasonFolder(string path, string collectionType, IDirectoryService directoryService, IFileSystem fileSystem)
- {
- var seasonNumber = GetSeasonNumberFromPath(path, collectionType);
- var hasSeasonNumber = seasonNumber != null;
-
- if (!hasSeasonNumber)
- {
- return false;
- }
-
- //// It's a season folder if it's named as such and does not contain any audio files, apart from theme.mp3
- //foreach (var fileSystemInfo in directoryService.GetFileSystemEntries(path))
- //{
- // var attributes = fileSystemInfo.Attributes;
-
- // if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
- // {
- // continue;
- // }
-
- // // Can't enforce this because files saved by Bitcasa are always marked System
- // //if ((attributes & FileAttributes.System) == FileAttributes.System)
- // //{
- // // continue;
- // //}
-
- // if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
- // {
- // //if (IsBadFolder(fileSystemInfo.Name))
- // //{
- // // return false;
- // //}
- // }
- // else
- // {
- // if (EntityResolutionHelper.IsAudioFile(fileSystemInfo.FullName) &&
- // !string.Equals(fileSystem.GetFileNameWithoutExtension(fileSystemInfo), BaseItem.ThemeSongFilename))
- // {
- // return false;
- // }
- // }
- //}
-
- return true;
- }
-
- /// <summary>
- /// A season folder must contain one of these somewhere in the name
- /// </summary>
- private static readonly string[] SeasonFolderNames =
- {
- "season",
- "sæson",
- "temporada",
- "saison",
- "staffel",
- "series",
- "сезон"
- };
-
- /// <summary>
- /// Used to detect paths that represent episodes, need to make sure they don't also
- /// match movie titles like "2001 A Space..."
- /// Currently we limit the numbers here to 2 digits to try and avoid this
- /// </summary>
- private static readonly Regex[] EpisodeExpressions =
- {
- new Regex(
- @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})[^\\\/]*$",
- RegexOptions.Compiled),
- new Regex(
- @".*(\\|\/)[sS](?<seasonnumber>\d{1,4})[x,X]?[eE](?<epnumber>\d{1,3})[^\\\/]*$",
- RegexOptions.Compiled),
- new Regex(
- @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))[^\\\/]*$",
- RegexOptions.Compiled),
- new Regex(
- @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})[^\\\/]*$",
- RegexOptions.Compiled)
- };
- private static readonly Regex[] MultipleEpisodeExpressions =
- {
- new Regex(
- @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )\d{1,4}[eExX](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
- RegexOptions.Compiled),
- new Regex(
- @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )\d{1,4}[xX][eE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
- RegexOptions.Compiled),
- new Regex(
- @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
- RegexOptions.Compiled),
- new Regex(
- @".*(\\|\/)[sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3})(-[xE]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
- RegexOptions.Compiled),
- new Regex(
- @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )\d{1,4}[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
- RegexOptions.Compiled),
- new Regex(
- @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )\d{1,4}[xX][eE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
- RegexOptions.Compiled),
- new Regex(
- @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
- RegexOptions.Compiled),
- new Regex(
- @".*(\\|\/)(?<seriesname>((?![sS]?\d{1,4}[xX]\d{1,3})[^\\\/])*)?([sS]?(?<seasonnumber>\d{1,4})[xX](?<epnumber>\d{1,3}))(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
- RegexOptions.Compiled),
- new Regex(
- @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})((-| - )?[xXeE](?<endingepnumber>\d{1,3}))+[^\\\/]*$",
- RegexOptions.Compiled),
- new Regex(
- @".*(\\|\/)(?<seriesname>[^\\\/]*)[sS](?<seasonnumber>\d{1,4})[xX\.]?[eE](?<epnumber>\d{1,3})(-[xX]?[eE]?(?<endingepnumber>\d{1,3}))+[^\\\/]*$",
- RegexOptions.Compiled)
- };
-
- /// <summary>
- /// To avoid the following matching movies they are only valid when contained in a folder which has been matched as a being season, or the media type is TV series
- /// </summary>
- private static readonly Regex[] EpisodeExpressionsWithoutSeason =
- {
- new Regex(
- @".*[\\\/](?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\.\w+$",
- RegexOptions.Compiled),
- // "01.avi"
- new Regex(
- @".*(\\|\/)(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\s?-\s?[^\\\/]*$",
- RegexOptions.Compiled),
- // "01 - blah.avi", "01-blah.avi"
- new Regex(
- @".*(\\|\/)(?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*\.[^\\\/]+$",
- RegexOptions.Compiled),
- // "01.blah.avi"
- new Regex(
- @".*[\\\/][^\\\/]* - (?<epnumber>\d{1,3})(-(?<endingepnumber>\d{2,3}))*[^\\\/]*$",
- RegexOptions.Compiled),
- // "blah - 01.avi", "blah 2 - 01.avi", "blah - 01 blah.avi", "blah 2 - 01 blah", "blah - 01 - blah.avi", "blah 2 - 01 - blah"
- };
-
- public static int? GetSeasonNumberFromPath(string path)
- {
- return GetSeasonNumberFromPath(path, CollectionType.TvShows);
- }
-
- /// <summary>
- /// Gets the season number from path.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <param name="collectionType">Type of the collection.</param>
- /// <returns>System.Nullable{System.Int32}.</returns>
- public static int? GetSeasonNumberFromPath(string path, string collectionType)
- {
- var filename = Path.GetFileName(path);
-
- if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
- {
- if (string.Equals(filename, "specials", StringComparison.OrdinalIgnoreCase))
- {
- return 0;
- }
- }
-
- int val;
- if (int.TryParse(filename, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
- {
- return val;
- }
-
- if (filename.StartsWith("s", StringComparison.OrdinalIgnoreCase))
- {
- var testFilename = filename.Substring(1);
-
- if (int.TryParse(testFilename, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
- {
- return val;
- }
- }
-
- // Look for one of the season folder names
- foreach (var name in SeasonFolderNames)
- {
- var index = filename.IndexOf(name, StringComparison.OrdinalIgnoreCase);
-
- if (index != -1)
- {
- return GetSeasonNumberFromPathSubstring(filename.Substring(index + name.Length));
- }
- }
-
- return null;
- }
-
- /// <summary>
- /// Extracts the season number from the second half of the Season folder name (everything after "Season", or "Staffel")
- /// </summary>
- /// <param name="path">The path.</param>
- /// <returns>System.Nullable{System.Int32}.</returns>
- private static int? GetSeasonNumberFromPathSubstring(string path)
- {
- var numericStart = -1;
- var length = 0;
-
- // Find out where the numbers start, and then keep going until they end
- for (var i = 0; i < path.Length; i++)
- {
- if (char.IsNumber(path, i))
- {
- if (numericStart == -1)
- {
- numericStart = i;
- }
- length++;
- }
- else if (numericStart != -1)
- {
- break;
- }
- }
-
- if (numericStart == -1)
- {
- return null;
- }
-
- return int.Parse(path.Substring(numericStart, length), CultureInfo.InvariantCulture);
- }
-
- /// <summary>
- /// Episodes the number from file.
- /// </summary>
- /// <param name="fullPath">The full path.</param>
- /// <param name="considerSeasonlessNames">if set to <c>true</c> [is in season].</param>
- /// <returns>System.String.</returns>
- public static int? GetEpisodeNumberFromFile(string fullPath, bool considerSeasonlessNames)
- {
- string fl = fullPath.ToLower();
- foreach (var r in EpisodeExpressions)
- {
- Match m = r.Match(fl);
- if (m.Success)
- return ParseEpisodeNumber(m.Groups["epnumber"].Value);
- }
- if (considerSeasonlessNames)
- {
- var match = EpisodeExpressionsWithoutSeason.Select(r => r.Match(fl))
- .FirstOrDefault(m => m.Success);
-
- if (match != null)
- {
- return ParseEpisodeNumber(match.Groups["epnumber"].Value);
- }
- }
-
- return null;
- }
-
- public static int? GetEndingEpisodeNumberFromFile(string fullPath)
- {
- var fl = fullPath.ToLower();
- foreach (var r in MultipleEpisodeExpressions)
- {
- var m = r.Match(fl);
- if (m.Success && !string.IsNullOrEmpty(m.Groups["endingepnumber"].Value))
- return ParseEpisodeNumber(m.Groups["endingepnumber"].Value);
- }
- foreach (var r in EpisodeExpressionsWithoutSeason)
- {
- var m = r.Match(fl);
- if (m.Success && !string.IsNullOrEmpty(m.Groups["endingepnumber"].Value))
- return ParseEpisodeNumber(m.Groups["endingepnumber"].Value);
- }
- return null;
- }
-
- /// <summary>
- /// Seasons the number from episode file.
- /// </summary>
- /// <param name="fullPath">The full path.</param>
- /// <returns>System.String.</returns>
- public static int? GetSeasonNumberFromEpisodeFile(string fullPath)
- {
- string fl = fullPath.ToLower();
- foreach (var r in EpisodeExpressions)
- {
- Match m = r.Match(fl);
- if (m.Success)
- {
- Group g = m.Groups["seasonnumber"];
- if (g != null)
- {
- var val = g.Value;
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- int num;
-
- if (int.TryParse(val, NumberStyles.Integer, UsCulture, out num))
- {
- return num;
- }
- }
- }
- return null;
- }
- }
- return null;
- }
-
- public static string GetSeriesNameFromEpisodeFile(string fullPath)
- {
- var fl = fullPath.ToLower();
- foreach (var r in EpisodeExpressions)
- {
- var m = r.Match(fl);
- if (m.Success)
- {
- var g = m.Groups["seriesname"];
- if (g != null)
- {
- var val = g.Value;
-
- if (!string.IsNullOrWhiteSpace(val))
- {
- return val;
- }
- }
- return null;
- }
- }
- return null;
- }
-
- private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
- private static int? ParseEpisodeNumber(string val)
- {
- int num;
-
- if (!string.IsNullOrEmpty(val) && int.TryParse(val, NumberStyles.Integer, UsCulture, out num))
- {
- return num;
- }
-
- return null;
- }
-
- /// <summary>
/// Sets the initial item values.
/// </summary>
/// <param name="item">The item.</param>
diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs
index bd845ef4a..071031b25 100644
--- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs
+++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs
@@ -1,5 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
@@ -105,7 +106,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (query.IncludeMedia)
{
// Add search hints based on item name
- hints.AddRange(items.Where(i => !string.IsNullOrWhiteSpace(i.Name)).Select(item =>
+ hints.AddRange(items.Where(i => !string.IsNullOrWhiteSpace(i.Name) && IncludeInSearch(i)).Select(item =>
{
var index = GetIndex(item.Name, searchTerm, terms);
@@ -289,6 +290,20 @@ namespace MediaBrowser.Server.Implementations.Library
return Task.FromResult(returnValue);
}
+ private bool IncludeInSearch(BaseItem item)
+ {
+ var episode = item as Episode;
+
+ if (episode != null)
+ {
+ if (episode.IsVirtualUnaired || episode.IsMissingEpisode)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
/// <summary>
/// Gets the index.
/// </summary>
diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
index 3f132ab7f..ed3503c1b 100644
--- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs
@@ -1,6 +1,8 @@
using System.Collections.Generic;
using MediaBrowser.Common.Events;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
@@ -23,9 +25,11 @@ namespace MediaBrowser.Server.Implementations.Library
private readonly ConcurrentDictionary<string, UserItemData> _userData = new ConcurrentDictionary<string, UserItemData>();
private readonly ILogger _logger;
+ private readonly IServerConfigurationManager _config;
- public UserDataManager(ILogManager logManager)
+ public UserDataManager(ILogManager logManager, IServerConfigurationManager config)
{
+ _config = config;
_logger = logManager.GetLogger(GetType().Name);
}
@@ -35,22 +39,6 @@ namespace MediaBrowser.Server.Implementations.Library
/// <value>The repository.</value>
public IUserDataRepository Repository { get; set; }
- /// <summary>
- /// Saves the user data.
- /// </summary>
- /// <param name="userId">The user id.</param>
- /// <param name="item">The item.</param>
- /// <param name="userData">The user data.</param>
- /// <param name="reason">The reason.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException">userData
- /// or
- /// cancellationToken
- /// or
- /// userId
- /// or
- /// key</exception>
public async Task SaveUserData(Guid userId, IHasUserData item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken)
{
if (userData == null)
@@ -219,5 +207,59 @@ namespace MediaBrowser.Server.Implementations.Library
Key = data.Key
};
}
+
+ public bool UpdatePlayState(BaseItem item, UserItemData data, long positionTicks)
+ {
+ var playedToCompletion = false;
+
+ var hasRuntime = item.RunTimeTicks.HasValue && item.RunTimeTicks > 0;
+
+ // If a position has been reported, and if we know the duration
+ if (positionTicks > 0 && hasRuntime)
+ {
+ var pctIn = Decimal.Divide(positionTicks, item.RunTimeTicks.Value) * 100;
+
+ // Don't track in very beginning
+ if (pctIn < _config.Configuration.MinResumePct)
+ {
+ positionTicks = 0;
+ }
+
+ // If we're at the end, assume completed
+ else if (pctIn > _config.Configuration.MaxResumePct || positionTicks >= item.RunTimeTicks.Value)
+ {
+ positionTicks = 0;
+ data.Played = playedToCompletion = true;
+ }
+
+ else
+ {
+ // Enforce MinResumeDuration
+ var durationSeconds = TimeSpan.FromTicks(item.RunTimeTicks.Value).TotalSeconds;
+
+ if (durationSeconds < _config.Configuration.MinResumeDurationSeconds)
+ {
+ positionTicks = 0;
+ data.Played = playedToCompletion = true;
+ }
+ }
+ }
+ else if (!hasRuntime)
+ {
+ // If we don't know the runtime we'll just have to assume it was fully played
+ data.Played = playedToCompletion = true;
+ positionTicks = 0;
+ }
+
+ if (item is Audio)
+ {
+ positionTicks = 0;
+ }
+
+ data.PlaybackPositionTicks = positionTicks;
+
+ return playedToCompletion;
+ }
+
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs
index 791cae553..503af4970 100644
--- a/MediaBrowser.Server.Implementations/Library/UserManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs
@@ -1,5 +1,4 @@
-using System.Collections.Concurrent;
-using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
@@ -63,6 +62,7 @@ namespace MediaBrowser.Server.Implementations.Library
public event EventHandler<GenericEventArgs<User>> UserPasswordChanged;
private readonly IXmlSerializer _xmlSerializer;
+ private readonly IJsonSerializer _jsonSerializer;
private readonly INetworkManager _networkManager;
@@ -71,13 +71,7 @@ namespace MediaBrowser.Server.Implementations.Library
private readonly Func<IConnectManager> _connectFactory;
private readonly IServerApplicationHost _appHost;
- /// <summary>
- /// Initializes a new instance of the <see cref="UserManager" /> class.
- /// </summary>
- /// <param name="logger">The logger.</param>
- /// <param name="configurationManager">The configuration manager.</param>
- /// <param name="userRepository">The user repository.</param>
- public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory, Func<IConnectManager> connectFactory, IServerApplicationHost appHost)
+ public UserManager(ILogger logger, IServerConfigurationManager configurationManager, IUserRepository userRepository, IXmlSerializer xmlSerializer, INetworkManager networkManager, Func<IImageProcessor> imageProcessorFactory, Func<IDtoService> dtoServiceFactory, Func<IConnectManager> connectFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer)
{
_logger = logger;
UserRepository = userRepository;
@@ -87,6 +81,7 @@ namespace MediaBrowser.Server.Implementations.Library
_dtoServiceFactory = dtoServiceFactory;
_connectFactory = connectFactory;
_appHost = appHost;
+ _jsonSerializer = jsonSerializer;
ConfigurationManager = configurationManager;
Users = new List<User>();
@@ -164,6 +159,11 @@ namespace MediaBrowser.Server.Implementations.Library
public async Task Initialize()
{
Users = await LoadUsers().ConfigureAwait(false);
+
+ foreach (var user in Users.ToList())
+ {
+ await DoPolicyMigration(user).ConfigureAwait(false);
+ }
}
public Task<bool> AuthenticateUser(string username, string passwordSha1, string remoteEndPoint)
@@ -171,6 +171,38 @@ namespace MediaBrowser.Server.Implementations.Library
return AuthenticateUser(username, passwordSha1, null, remoteEndPoint);
}
+ public bool IsValidUsername(string username)
+ {
+ // Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)
+ return username.All(IsValidCharacter);
+ }
+
+ private bool IsValidCharacter(char i)
+ {
+ return char.IsLetterOrDigit(i) || char.Equals(i, '-') || char.Equals(i, '_') || char.Equals(i, '\'') ||
+ char.Equals(i, '.');
+ }
+
+ public string MakeValidUsername(string username)
+ {
+ if (IsValidUsername(username))
+ {
+ return username;
+ }
+
+ // Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)
+ var builder = new StringBuilder();
+
+ foreach (var c in username)
+ {
+ if (IsValidCharacter(c))
+ {
+ builder.Append(c);
+ }
+ }
+ return builder.ToString();
+ }
+
public async Task<bool> AuthenticateUser(string username, string passwordSha1, string passwordMd5, string remoteEndPoint)
{
if (string.IsNullOrWhiteSpace(username))
@@ -178,14 +210,15 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentNullException("username");
}
- var user = Users.FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
+ var user = Users
+ .FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
if (user == null)
{
throw new SecurityException("Invalid username or password entered.");
}
- if (user.Configuration.IsDisabled)
+ if (user.Policy.IsDisabled)
{
throw new SecurityException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
}
@@ -203,20 +236,6 @@ namespace MediaBrowser.Server.Implementations.Library
}
}
- // Maybe user accidently entered connect credentials. let's be flexible
- if (!success && user.ConnectLinkType.HasValue && !string.IsNullOrWhiteSpace(passwordMd5))
- {
- try
- {
- await _connectFactory().Authenticate(user.ConnectUserName, passwordMd5).ConfigureAwait(false);
- success = true;
- }
- catch
- {
-
- }
- }
-
// Update LastActivityDate and LastLoginDate, then save
if (success)
{
@@ -273,7 +292,7 @@ namespace MediaBrowser.Server.Implementations.Library
// There always has to be at least one user.
if (users.Count == 0)
{
- var name = Environment.UserName;
+ var name = MakeValidUsername(Environment.UserName);
var user = InstantiateNewUser(name, false);
@@ -283,14 +302,42 @@ namespace MediaBrowser.Server.Implementations.Library
users.Add(user);
- user.Configuration.IsAdministrator = true;
- user.Configuration.EnableRemoteControlOfOtherUsers = true;
- UpdateConfiguration(user, user.Configuration);
+ user.Policy.IsAdministrator = true;
+ user.Policy.EnableRemoteControlOfOtherUsers = true;
+ await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false);
}
return users;
}
+ private async Task DoPolicyMigration(User user)
+ {
+ if (!user.Configuration.HasMigratedToPolicy)
+ {
+ user.Policy.AccessSchedules = user.Configuration.AccessSchedules;
+ user.Policy.BlockedChannels = user.Configuration.BlockedChannels;
+ user.Policy.BlockedMediaFolders = user.Configuration.BlockedMediaFolders;
+ user.Policy.BlockedTags = user.Configuration.BlockedTags;
+ user.Policy.BlockUnratedItems = user.Configuration.BlockUnratedItems;
+ user.Policy.EnableContentDeletion = user.Configuration.EnableContentDeletion;
+ user.Policy.EnableLiveTvAccess = user.Configuration.EnableLiveTvAccess;
+ user.Policy.EnableLiveTvManagement = user.Configuration.EnableLiveTvManagement;
+ user.Policy.EnableMediaPlayback = user.Configuration.EnableMediaPlayback;
+ user.Policy.EnableRemoteControlOfOtherUsers = user.Configuration.EnableRemoteControlOfOtherUsers;
+ user.Policy.EnableSharedDeviceControl = user.Configuration.EnableSharedDeviceControl;
+ user.Policy.EnableUserPreferenceAccess = user.Configuration.EnableUserPreferenceAccess;
+ user.Policy.IsAdministrator = user.Configuration.IsAdministrator;
+ user.Policy.IsDisabled = user.Configuration.IsDisabled;
+ user.Policy.IsHidden = user.Configuration.IsHidden;
+ user.Policy.MaxParentalRating = user.Configuration.MaxParentalRating;
+
+ await UpdateUserPolicy(user.Id.ToString("N"), user.Policy);
+
+ user.Configuration.HasMigratedToPolicy = true;
+ await UpdateConfiguration(user, user.Configuration, true).ConfigureAwait(false);
+ }
+ }
+
public UserDto GetUserDto(User user, string remoteEndPoint = null)
{
if (user == null)
@@ -449,6 +496,11 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentNullException("name");
}
+ if (!IsValidUsername(name))
+ {
+ throw new ArgumentException("Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)");
+ }
+
if (Users.Any(u => u.Name.Equals(name, StringComparison.OrdinalIgnoreCase)))
{
throw new ArgumentException(string.Format("A user with the name '{0}' already exists.", name));
@@ -509,7 +561,7 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentException(string.Format("The user '{0}' cannot be deleted because there must be at least one user in the system.", user.Name));
}
- if (user.Configuration.IsAdministrator && allUsers.Count(i => i.Configuration.IsAdministrator) == 1)
+ if (user.Policy.IsAdministrator && allUsers.Count(i => i.Policy.IsAdministrator) == 1)
{
throw new ArgumentException(string.Format("The user '{0}' cannot be deleted because there must be at least one admin user in the system.", user.Name));
}
@@ -518,17 +570,17 @@ namespace MediaBrowser.Server.Implementations.Library
try
{
- await UserRepository.DeleteUser(user, CancellationToken.None).ConfigureAwait(false);
+ var configPath = GetConfigurationFilePath(user);
- var path = user.ConfigurationFilePath;
+ await UserRepository.DeleteUser(user, CancellationToken.None).ConfigureAwait(false);
try
{
- File.Delete(path);
+ File.Delete(configPath);
}
catch (IOException ex)
{
- _logger.ErrorException("Error deleting file {0}", ex, path);
+ _logger.ErrorException("Error deleting file {0}", ex, configPath);
}
DeleteUserPolicy(user);
@@ -613,15 +665,6 @@ namespace MediaBrowser.Server.Implementations.Library
};
}
- public void UpdateConfiguration(User user, UserConfiguration newConfiguration)
- {
- var xmlPath = user.ConfigurationFilePath;
- Directory.CreateDirectory(Path.GetDirectoryName(xmlPath));
- _xmlSerializer.SerializeToFile(newConfiguration, xmlPath);
-
- EventHelper.FireEventIfNotNull(UserConfigurationUpdated, this, new GenericEventArgs<User> { Argument = user }, _logger);
- }
-
private string PasswordResetFile
{
get { return Path.Combine(ConfigurationManager.ApplicationPaths.ProgramDataPath, "passwordreset.txt"); }
@@ -689,7 +732,7 @@ namespace MediaBrowser.Server.Implementations.Library
string pinFile = null;
DateTime? expirationDate = null;
- if (user != null && !user.Configuration.IsAdministrator)
+ if (user != null && !user.Policy.IsAdministrator)
{
action = ForgotPasswordAction.ContactAdmin;
}
@@ -784,28 +827,72 @@ namespace MediaBrowser.Server.Implementations.Library
return (UserPolicy)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), path);
}
}
+ catch (DirectoryNotFoundException)
+ {
+ return GetDefaultPolicy(user);
+ }
+ catch (FileNotFoundException)
+ {
+ return GetDefaultPolicy(user);
+ }
catch (Exception ex)
{
_logger.ErrorException("Error reading policy file: {0}", ex, path);
- return new UserPolicy
- {
- EnableSync = !user.ConnectLinkType.HasValue || user.ConnectLinkType.Value != UserLinkType.Guest
- };
+ return GetDefaultPolicy(user);
}
}
+ private UserPolicy GetDefaultPolicy(User user)
+ {
+ return new UserPolicy
+ {
+ EnableSync = true
+ };
+ }
+
private readonly object _policySyncLock = new object();
- public async Task UpdateUserPolicy(string userId, UserPolicy userPolicy)
+ public Task UpdateUserPolicy(string userId, UserPolicy userPolicy)
{
var user = GetUserById(userId);
+ return UpdateUserPolicy(user, userPolicy, true);
+ }
+
+ private async Task UpdateUserPolicy(User user, UserPolicy userPolicy, bool fireEvent)
+ {
+ // The xml serializer will output differently if the type is not exact
+ if (userPolicy.GetType() != typeof(UserPolicy))
+ {
+ var json = _jsonSerializer.SerializeToString(userPolicy);
+ userPolicy = _jsonSerializer.DeserializeFromString<UserPolicy>(json);
+ }
+
+ var updateConfig = user.Policy.IsAdministrator != userPolicy.IsAdministrator ||
+ user.Policy.EnableLiveTvManagement != userPolicy.EnableLiveTvManagement ||
+ user.Policy.EnableLiveTvAccess != userPolicy.EnableLiveTvAccess ||
+ user.Policy.EnableMediaPlayback != userPolicy.EnableMediaPlayback ||
+ user.Policy.EnableContentDeletion != userPolicy.EnableContentDeletion;
+
var path = GetPolifyFilePath(user);
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+
lock (_policySyncLock)
{
_xmlSerializer.SerializeToFile(userPolicy, path);
user.Policy = userPolicy;
}
+
+ if (updateConfig)
+ {
+ user.Configuration.IsAdministrator = user.Policy.IsAdministrator;
+ user.Configuration.EnableLiveTvManagement = user.Policy.EnableLiveTvManagement;
+ user.Configuration.EnableLiveTvAccess = user.Policy.EnableLiveTvAccess;
+ user.Configuration.EnableMediaPlayback = user.Policy.EnableMediaPlayback;
+ user.Configuration.EnableContentDeletion = user.Policy.EnableContentDeletion;
+
+ await UpdateConfiguration(user, user.Configuration, true).ConfigureAwait(false);
+ }
}
private void DeleteUserPolicy(User user)
@@ -833,5 +920,69 @@ namespace MediaBrowser.Server.Implementations.Library
{
return Path.Combine(user.ConfigurationDirectoryPath, "policy.xml");
}
+
+ private string GetConfigurationFilePath(User user)
+ {
+ return Path.Combine(user.ConfigurationDirectoryPath, "config.xml");
+ }
+
+ public UserConfiguration GetUserConfiguration(User user)
+ {
+ var path = GetConfigurationFilePath(user);
+
+ try
+ {
+ lock (_configSyncLock)
+ {
+ return (UserConfiguration)_xmlSerializer.DeserializeFromFile(typeof(UserConfiguration), path);
+ }
+ }
+ catch (DirectoryNotFoundException)
+ {
+ return new UserConfiguration();
+ }
+ catch (FileNotFoundException)
+ {
+ return new UserConfiguration();
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error reading policy file: {0}", ex, path);
+
+ return new UserConfiguration();
+ }
+ }
+
+ private readonly object _configSyncLock = new object();
+ public Task UpdateConfiguration(string userId, UserConfiguration config)
+ {
+ var user = GetUserById(userId);
+ return UpdateConfiguration(user, config, true);
+ }
+
+ private async Task UpdateConfiguration(User user, UserConfiguration config, bool fireEvent)
+ {
+ var path = GetConfigurationFilePath(user);
+
+ // The xml serializer will output differently if the type is not exact
+ if (config.GetType() != typeof (UserConfiguration))
+ {
+ var json = _jsonSerializer.SerializeToString(config);
+ config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json);
+ }
+
+ Directory.CreateDirectory(Path.GetDirectoryName(path));
+
+ lock (_configSyncLock)
+ {
+ _xmlSerializer.SerializeToFile(config, path);
+ user.Configuration = config;
+ }
+
+ if (fireEvent)
+ {
+ EventHelper.FireEventIfNotNull(UserConfigurationUpdated, this, new GenericEventArgs<User> { Argument = user }, _logger);
+ }
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index 83fe992b6..ac742f04a 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -1846,7 +1846,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private bool IsLiveTvEnabled(User user)
{
- return user.Configuration.EnableLiveTvAccess && ActiveService != null;
+ return user.Policy.EnableLiveTvAccess && ActiveService != null;
}
public IEnumerable<User> GetEnabledUsers()
@@ -1854,7 +1854,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var service = ActiveService;
return _userManager.Users
- .Where(i => i.Configuration.EnableLiveTvAccess && service != null);
+ .Where(i => i.Policy.EnableLiveTvAccess && service != null);
}
/// <summary>
@@ -1872,12 +1872,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
var user = string.IsNullOrEmpty(userId) ? null : _userManager.GetUserById(userId);
- // Get everything
- var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
-
var folder = await GetInternalLiveTvFolder(userId, cancellationToken).ConfigureAwait(false);
- return _dtoService.GetBaseItemDto(folder, fields, user);
+ return _dtoService.GetBaseItemDto(folder, new DtoOptions(), user);
}
public async Task<Folder> GetInternalLiveTvFolder(string userId, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json
index 81f648728..b6087812f 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ar.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Movies",
"TabSeries": "Series",
"TabEpisodes": "\u0627\u0644\u062d\u0644\u0642\u0627\u062a",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json
index d0dfd608b..29de370ad 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ca.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Movies",
"TabSeries": "Series",
"TabEpisodes": "Episodes",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json
index 9f2da7797..fc416018d 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/cs.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(zru\u0161eno)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Filmy",
"TabSeries": "S\u00e9rie",
"TabEpisodes": "Epizody",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json
index 4bd7d3103..a56d2d5b8 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/da.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Film",
"TabSeries": "Serier",
"TabEpisodes": "Episoder",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json
index d8a8036b0..b69b744b3 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/de.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stoppe",
"LabelCancelled": "(abgebrochen)",
"LabelFailed": "(fehlgeschlagen)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Durch herunterfahrenden Server abgebrochen)",
"LabelScheduledTaskLastRan": "Zuletzt ausgef\u00fchrt vor: {0}. Ben\u00f6tigte Zeit: {1}.",
"HeaderDeleteTaskTrigger": "Entferne Aufgabenausl\u00f6ser",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Nach rechts",
"ButtonBrowseOnlineImages": "Durchsuche Onlinebilder",
"HeaderDeleteItem": "L\u00f6sche Element",
- "ConfirmDeleteItem": "Bist du dir sicher dieses Element aus deiner Bibliothek zu l\u00f6schen?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Bitte gib einen Namen oder eine externe Id an.",
"MessageValueNotCorrect": "Der eingegeben Wert ist nicht korrekt. Bitte versuche es noch einmal.",
"MessageItemSaved": "Element gespeichert",
@@ -396,6 +397,7 @@
"LabelYear": "Jahr:",
"LabelDateOfBirth": "Geburtsatum:",
"LabelBirthYear": "Geburtsjahr:",
+ "LabelBirthDate": "Geburtsdatum:",
"LabelDeathDate": "Todesdatum:",
"HeaderRemoveMediaLocation": "Entferne Medienquelle",
"MessageConfirmRemoveMediaLocation": "Bist du dir sicher diese Medienquelle entfernen zu wollen?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Medienquellen",
"LabelFolderTypeValue": "Verzeichnistyp: {0}",
"LabelPathSubstitutionHelp": "Optional: Die Pfadersetzung kann Serverpfade zu Netzwerkfreigaben umleiten, die von Endger\u00e4ten f\u00fcr die direkte Wiedergabe genutzt werden k\u00f6nnen.",
- "FolderTypeMixed": "Filme & Serien gemischt",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Filme",
"FolderTypeMusic": "Musik",
"FolderTypeAdultVideos": "Videos f\u00fcr Erwachsene",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Heimvideos",
"FolderTypeGames": "Spiele",
"FolderTypeBooks": "B\u00fccher",
- "FolderTypeTvShows": "TV Serien",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Filme",
"TabSeries": "Serie",
"TabEpisodes": "Episoden",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "und steuert einfach andere Ger\u00e4te und Media Browser Anwendungen",
"MessageEnjoyYourStay": "Genie\u00dfe deinen Aufenthalt",
"DashboardTourDashboard": "Die Server\u00fcbersicht erlaubt es dir deinen Server und dessen Benutzer im Blick zu behalten. Somit wei\u00dft du immer wer gerade was macht und wo er sich befindet.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Erstelle einfach Benutzeraccounts f\u00fcr Freunde und Familie. Jeder mit seinen individuellen Einstellungen bei Berechtigungen, Blibliothekenzugriff, Kindersicherung und mehr.",
"DashboardTourCinemaMode": "Der Kino-Modus bringt das Kinoerlebnis direkt in dein Wohnzimmer, mit der F\u00e4higkeit Trailer und benutzerdefinierte Intros vor dem Hauptfilm zu spielen.",
"DashboardTourChapters": "Aktiviere die Bildgenerierung f\u00fcr die Kapitel deiner Videos f\u00fcr eine bessere Darstellung w\u00e4hrend des Ansehens.",
@@ -642,7 +645,12 @@
"OptionLow": "Niedrig",
"HeaderSettings": "Einstellungen",
"OptionAutomaticallySyncNewContent": "Synchronisiere neue Inhalte automatisch",
- "OptionAutomaticallySyncNewContentHelp": "Neu hinzugef\u00fcgte Inhalte zu diesen Verzeichnissen werden automatisch zum Ger\u00e4t synchronisiert.",
+ "OptionAutomaticallySyncNewContentHelp": "Neue Inhalte dieser Kategorie werden automatisch mit dem Ger\u00e4t synchronisiert.",
"OptionSyncUnwatchedVideosOnly": "Synchronisiere nur ungesehene Videos.",
- "OptionSyncUnwatchedVideosOnlyHelp": "Nur ungesehene Video werden synchronisiert. Videos werden entfernt sobald diese auf dem Ger\u00e4t angeschaut wurden."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Nur ungesehene Video werden synchronisiert. Videos werden entfernt sobald diese auf dem Ger\u00e4t angeschaut wurden.",
+ "LabelItemLimit": "Maximale Anzahl:",
+ "LabelItemLimitHelp": "Optional. Legen Sie die maximale Anzahl der zu synchronisierenden Eintr\u00e4ge fest.",
+ "MessageBookPluginRequired": "Setzt die Installation des Bookshelf-Plugins voraus.",
+ "MessageGamePluginRequired": "Setzt die Installation des GameBrowser-Plugins voraus.",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json
index 20c9de1ef..455649264 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/el.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Movies",
"TabSeries": "Series",
"TabEpisodes": "\u0395\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json
index fec45e70c..a667f6df9 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_GB.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Movies",
"TabSeries": "Series",
"TabEpisodes": "Episodes",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json
index 369299be0..4c57d573b 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/en_US.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Movies",
"TabSeries": "Series",
"TabEpisodes": "Episodes",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json
index d2957340c..73b3098c1 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es.json
@@ -40,6 +40,7 @@
"LabelStopping": "Deteniendo",
"LabelCancelled": "(cancelado)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Abortado por cierre del servidor)",
"LabelScheduledTaskLastRan": "\u00daltima ejecuci\u00f3n {0}, teniendo {1}.",
"HeaderDeleteTaskTrigger": "Eliminar tarea de activaci\u00f3n",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Mover derecha",
"ButtonBrowseOnlineImages": "Navegar im\u00e1genes online",
"HeaderDeleteItem": "Borrar elemento",
- "ConfirmDeleteItem": "\u00bfEst\u00e1 seguro que desea borrar este elemento de su biblioteca?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Introduzca un nombre o un identificador externo.",
"MessageValueNotCorrect": "El valor introducido no es correcto. Intentelo de nuevo.",
"MessageItemSaved": "Elemento grabado.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Pel\u00edculas",
"TabSeries": "Series",
"TabEpisodes": "Episodios",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json
index fda5b65b3..67e107c1b 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/es_MX.json
@@ -40,6 +40,7 @@
"LabelStopping": "Deteniendo",
"LabelCancelled": "(cancelado)",
"LabelFailed": "(Fallido)",
+ "ButtonHelp": "Ayuda",
"LabelAbortedByServerShutdown": "(Abortada por apagado del servidor)",
"LabelScheduledTaskLastRan": "Ejecutado hace {0}, tomando {1}.",
"HeaderDeleteTaskTrigger": "Borrar Disparador de Tarea",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Mover a la derecha",
"ButtonBrowseOnlineImages": "Buscar im\u00e1genes en l\u00ednea",
"HeaderDeleteItem": "Eliminar \u00cdtem",
- "ConfirmDeleteItem": "\u00bfEst\u00e1 seguro de querer eleiminar este \u00edtem de su biblioteca?",
+ "ConfirmDeleteItem": "Al eliminar este \u00edtem se eliminar\u00e1 tanto del sistema de archivos como de su biblioteca de medios. \u00bfEsta seguro de querer continuar?",
"MessagePleaseEnterNameOrId": "Por favor ingrese un nombre o id externo.",
"MessageValueNotCorrect": "El valor ingresado no es correcto. Intente nuevamente por favor.",
"MessageItemSaved": "\u00cdtem guardado.",
@@ -396,6 +397,7 @@
"LabelYear": "A\u00f1o:",
"LabelDateOfBirth": "Fecha de nacimiento:",
"LabelBirthYear": "A\u00f1o de nacimiento:",
+ "LabelBirthDate": "Fecha de Nacimiento:",
"LabelDeathDate": "Fecha de defunci\u00f3n:",
"HeaderRemoveMediaLocation": "Eliminar Ubicaci\u00f3n de Medios",
"MessageConfirmRemoveMediaLocation": "\u00bfEst\u00e1 seguro de querer eliminar esta ubicaci\u00f3n?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Ubicaciones de Medios",
"LabelFolderTypeValue": "Tipo de carpeta: {0}",
"LabelPathSubstitutionHelp": "Opcional: La sustituci\u00f3n de trayectoras puede mapear trayectorias del servidor a recursos de red comaprtidos que los clientes pueden acceder para reproducir de manera directa.",
- "FolderTypeMixed": "Pel\u00edculas y TV mezclados",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Pel\u00edculas",
"FolderTypeMusic": "M\u00fasica",
"FolderTypeAdultVideos": "Videos para adultos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Videos caseros",
"FolderTypeGames": "Juegos",
"FolderTypeBooks": "Libros",
- "FolderTypeTvShows": "Programas de TV",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Pel\u00edculas",
"TabSeries": "Series",
"TabEpisodes": "Episodios",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "y controla f\u00e1cilmente otros dispositivos y apps de Media Browser",
"MessageEnjoyYourStay": "Disfrute su visita",
"DashboardTourDashboard": "El panel de control del servidor le permite monitorear su servidor y sus usuarios. Siempre sabr\u00e1 quien est\u00e1 haciendo qu\u00e9 y donde se encuentran.",
+ "DashboardTourHelp": "La ayuda dentro de la app proporciona botones simples para abrir p\u00e1ginas de la wiki relacionadas con el contenido en pantalla.",
"DashboardTourUsers": "Cree cuentas f\u00e1cilmente para sus amigos y familia, cada una con sus propios permisos, accesos a la biblioteca, controles parentales y m\u00e1s.",
"DashboardTourCinemaMode": "El modo cine trae la experiencia del cine directo a su sala de TV con la capacidad de reproducir avances e intros personalizados antes de la presentaci\u00f3n estelar.",
"DashboardTourChapters": "Active la generaci\u00f3n de im\u00e1genes de cap\u00edtulos de sus videos para una presentaci\u00f3n m\u00e1s agradable al desplegar.",
@@ -642,7 +645,12 @@
"OptionLow": "Baja",
"HeaderSettings": "Configuraci\u00f3n",
"OptionAutomaticallySyncNewContent": "Sincronizar autom\u00e1ticamente nuevos contenidos",
- "OptionAutomaticallySyncNewContentHelp": "Los contenidos nuevos que sean agregados a estas carpetas ser\u00e1n sincronizados autom\u00e1ticamente con el dispositivo.",
+ "OptionAutomaticallySyncNewContentHelp": "Los contenidos nuevos agregados a esta categor\u00eda ser\u00e1n sincronizados autom\u00e1ticamente con el dispositivo.",
"OptionSyncUnwatchedVideosOnly": "Sincronizar \u00fanicamente videos no vistos",
- "OptionSyncUnwatchedVideosOnlyHelp": "Solamente los videos a\u00fan no vistos ser\u00e1n sincronizados, se eliminar\u00e1n los videos del dispositivo conforme \u00e9stos sean vistos."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Solamente los videos a\u00fan no vistos ser\u00e1n sincronizados, se eliminar\u00e1n los videos del dispositivo conforme \u00e9stos sean vistos.",
+ "LabelItemLimit": "L\u00edmite de \u00cdtems:",
+ "LabelItemLimitHelp": "Opcional. Establece un l\u00edmite en el n\u00famero de \u00edtems que ser\u00e1n sincronizados.",
+ "MessageBookPluginRequired": "Requiere instalaci\u00f3n del complemento Bookshelf",
+ "MessageGamePluginRequired": "Requiere instalaci\u00f3n del complemento de GameBrowser",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json
index e9c6263e2..6173cfe78 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fi.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Movies",
"TabSeries": "Series",
"TabEpisodes": "Episodes",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json
index d3c95bfa4..3cb2cbd15 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/fr.json
@@ -40,6 +40,7 @@
"LabelStopping": "En cours d'arr\u00eat",
"LabelCancelled": "(annul\u00e9)",
"LabelFailed": "(\u00e9chou\u00e9)",
+ "ButtonHelp": "Aide",
"LabelAbortedByServerShutdown": "(Annul\u00e9 par fermeture du serveur)",
"LabelScheduledTaskLastRan": "Derni\u00e8re ex\u00e9cution {0}, dur\u00e9e {1}.",
"HeaderDeleteTaskTrigger": "Supprimer le d\u00e9clencheur de t\u00e2che",
@@ -55,7 +56,7 @@
"LabelForcedStream": "(Forc\u00e9)",
"LabelDefaultForcedStream": "(Par d\u00e9faut\/Forc\u00e9)",
"LabelUnknownLanguage": "Langue inconnue",
- "ButtonMute": "Sourdine",
+ "ButtonMute": "Muet",
"ButtonUnmute": "D\u00e9sactiver sourdine",
"ButtonStop": "Arr\u00eat",
"ButtonNextTrack": "Piste suivante",
@@ -77,7 +78,7 @@
"MessageInvalidUser": "Nom d'utilisateur ou mot de passe incorrect. R\u00e9essayer.",
"HeaderLoginFailure": "\u00c9chec de la connection",
"HeaderAllRecordings": "Tous les enregistrements",
- "RecommendationBecauseYouLike": "Parce-que vous aimez {0}",
+ "RecommendationBecauseYouLike": "Parce que vous aimez {0}",
"RecommendationBecauseYouWatched": "Parce que vous avez regard\u00e9 {0}",
"RecommendationDirectedBy": "R\u00e9alis\u00e9 par {0}",
"RecommendationStarring": "Mettant en vedette {0}",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "D\u00e9placer \u00e0 droite",
"ButtonBrowseOnlineImages": "Parcourir les images en ligne",
"HeaderDeleteItem": "Supprimer l'item",
- "ConfirmDeleteItem": "\u00cates-vous s\u00fbr de vouloir supprimer cet item de votre biblioth\u00e8que ?",
+ "ConfirmDeleteItem": "Supprimer cet \u00e9l\u00e9ment l'effacera \u00e0 la fois du syst\u00e8me de fichiers et de votre biblioth\u00e8que de media. Etes-vous s\u00fbr de vouloir continuer ?",
"MessagePleaseEnterNameOrId": "Merci de saisir un nom ou un ID externe.",
"MessageValueNotCorrect": "La valeur saisie est incorrecte. Merci de r\u00e9\u00e9ssayer.",
"MessageItemSaved": "Item sauvegard\u00e9.",
@@ -396,6 +397,7 @@
"LabelYear": "Ann\u00e9e :",
"LabelDateOfBirth": "Date de naissance :",
"LabelBirthYear": "Ann\u00e9e de naissance :",
+ "LabelBirthDate": "Date de naissance :",
"LabelDeathDate": "Date de d\u00e9c\u00e8s :",
"HeaderRemoveMediaLocation": "Supprimer l'emplacement m\u00e9dia",
"MessageConfirmRemoveMediaLocation": "Etes vous sur de vouloir supprimer cet emplacement?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Emplacement des M\u00e9dias",
"LabelFolderTypeValue": "Type de r\u00e9pertoire: {0}",
"LabelPathSubstitutionHelp": "Optionnel: La substitution de chemin peut rediriger les r\u00e9pertoires serveurs vers des partages r\u00e9seau afin que le client acc\u00e8de directement \u00e0 la lecture.",
- "FolderTypeMixed": "Film et TV m\u00e9lang\u00e9s",
+ "FolderTypeUnset": "Non d\u00e9fini (contenu m\u00e9lang\u00e9)",
"FolderTypeMovies": "Films",
"FolderTypeMusic": "Musique",
"FolderTypeAdultVideos": "Vid\u00e9os Adultes",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Vid\u00e9os personnelles",
"FolderTypeGames": "Jeux",
"FolderTypeBooks": "Livres",
- "FolderTypeTvShows": "S\u00e9ries TV",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Films",
"TabSeries": "S\u00e9ries",
"TabEpisodes": "\u00c9pisodes",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "et controles facilement les autres p\u00e9riph\u00e9riques et applications Medi Browser",
"MessageEnjoyYourStay": "Profitez en bien",
"DashboardTourDashboard": "Le tableau de bord du serveur vous permet de g\u00e9rer votre serveur et vos utilisateurs. Vous saurez toujours qui fait quoi et o\u00f9 ils sont.",
+ "DashboardTourHelp": "L'aide contextuelle de l'application permet d'ouvrir les pages du wiki relatives au contenu affich\u00e9.",
"DashboardTourUsers": "Cr\u00e9er facilement des comptes utilisateurs pour vos amis et votre famille, chacun avec ses propres droits, biblioth\u00e8ques accessibles, contr\u00f4le parental et plus encore.",
"DashboardTourCinemaMode": "Le mode cin\u00e9ma apporte l'exp\u00e9rience du cin\u00e9ma directement dans votre salon avec l'abilit\u00e9 de lire les bandes-annonces et les introductions personnalis\u00e9es avant le programme principal.",
"DashboardTourChapters": "Autoriser la g\u00e9n\u00e9ration des images des chapitres de vos vid\u00e9os pour une pr\u00e9sentation plus agr\u00e9able pendant le visionnage",
@@ -636,13 +639,18 @@
"MessageSyncJobCreated": "Job de synchronisation cr\u00e9\u00e9.",
"LabelSyncTo": "Synchronis\u00e9 avec:",
"LabelSyncJobName": "Nom du job de synchronisation:",
- "LabelQuality": "Quality:",
- "OptionHigh": "High",
- "OptionMedium": "Medium",
+ "LabelQuality": "Qualit\u00e9:",
+ "OptionHigh": "Haute",
+ "OptionMedium": "Moyenne",
"OptionLow": "Basse",
"HeaderSettings": "Param\u00e8tres",
"OptionAutomaticallySyncNewContent": "Synchroniser automatiquement le nouveau contenu",
- "OptionAutomaticallySyncNewContentHelp": "Le nouveau contenu ajout\u00e9 \u00e0 ces r\u00e9pertoires sera automatiquement synchronis\u00e9 \u00e0 votre p\u00e9riph\u00e9rique.",
+ "OptionAutomaticallySyncNewContentHelp": "Les nouveaux contenus ajout\u00e9s \u00e0 cette cat\u00e9gorie seront automatiquement synchronis\u00e9s avec le p\u00e9riph\u00e9rique.",
"OptionSyncUnwatchedVideosOnly": "Synchroniser seulement les vid\u00e9os non lus.",
- "OptionSyncUnwatchedVideosOnlyHelp": "Seulement les vid\u00e9os non lus seront synchronis\u00e9es et seront supprim\u00e9es du p\u00e9riph\u00e9rique au fur et \u00e0 mesure qu'elles sont lus."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Seulement les vid\u00e9os non lus seront synchronis\u00e9es et seront supprim\u00e9es du p\u00e9riph\u00e9rique au fur et \u00e0 mesure qu'elles sont lus.",
+ "LabelItemLimit": "Maximum d'\u00e9l\u00e9ments :",
+ "LabelItemLimitHelp": "Optionnel : d\u00e9finit le nombre maximum d'\u00e9l\u00e9ments qui seront synchronis\u00e9s.",
+ "MessageBookPluginRequired": "N\u00e9cessite l'installation du plugin Bookshelf",
+ "MessageGamePluginRequired": "N\u00e9cessite l'installation du plugin GameBrowser",
+ "MessageUnsetContentHelp": "Le contenu sera affich\u00e9 sous forme de r\u00e9pertoires. Pour un r\u00e9sultat optimal, utilisez le gestionnaire de m\u00e9tadonn\u00e9es pour d\u00e9finir le type de contenu des sous-r\u00e9pertoires."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json
index 7d268200b..adce0cb26 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/he.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "\u05e1\u05e8\u05d8\u05d9\u05dd",
"TabSeries": "\u05e1\u05d3\u05e8\u05d5\u05ea",
"TabEpisodes": "\u05e4\u05e8\u05e7\u05d9\u05dd",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json
index ef186d800..e849dd453 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/hr.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Filmovi",
"TabSeries": "Series",
"TabEpisodes": "Epizode",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json
index 8e324b335..d94d8adfd 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/it.json
@@ -40,6 +40,7 @@
"LabelStopping": "Sto fermando",
"LabelCancelled": "(cancellato)",
"LabelFailed": "(fallito)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Interrotto dalla chiusura del server)",
"LabelScheduledTaskLastRan": "Ultima esecuzione {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Elimina Operazione pianificata",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Muovi a destra",
"ButtonBrowseOnlineImages": "Sfoglia le immagini Online",
"HeaderDeleteItem": "Elimina elemento",
- "ConfirmDeleteItem": "Sei sicuro di voler eliminare questo elemento dalla tua libreria?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Inserisci il nome o id esterno.",
"MessageValueNotCorrect": "Il valore inserito non \u00e8 corretto.Riprova di nuovo.",
"MessageItemSaved": "Elemento salvato.",
@@ -396,6 +397,7 @@
"LabelYear": "Anno:",
"LabelDateOfBirth": "Data nascita:",
"LabelBirthYear": "Anno nascita:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Anno morte:",
"HeaderRemoveMediaLocation": "Rimuovi percorso media",
"MessageConfirmRemoveMediaLocation": "Sei sicuro di voler rimuovere questa posizione?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Posizioni Media",
"LabelFolderTypeValue": "Tipo cartella: {0}",
"LabelPathSubstitutionHelp": "Opzionale: cambio Path pu\u00f2 mappare i percorsi del server a condivisioni di rete che i clienti possono accedere per la riproduzione diretta.",
- "FolderTypeMixed": "Misto Film & Tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Film",
"FolderTypeMusic": "Musica",
"FolderTypeAdultVideos": "Video per adulti",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Video personali",
"FolderTypeGames": "Giochi",
"FolderTypeBooks": "Libri",
- "FolderTypeTvShows": "Serie TV",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Film",
"TabSeries": "Serie TV",
"TabEpisodes": "Episodi",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "e controlla facilmente altri dispositivi e applicazioni Media Browser",
"MessageEnjoyYourStay": "Godetevi il vostro soggiorno",
"DashboardTourDashboard": "Il pannello di controllo del server consente di monitorare il vostro server e gli utenti. Potrai sempre sapere chi sta facendo cosa e dove sono.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Facile creazione di account utente per i vostri amici e la famiglia, ognuno con le proprie autorizzazioni, accesso alla libreria, controlli parentali e altro ancora.",
"DashboardTourCinemaMode": "Modalit\u00e0 Cinema porta l'esperienza del teatro direttamente nel tuo salotto con la possibilit\u00e0 di giocare trailer e intro personalizzati prima la caratteristica principale.",
"DashboardTourChapters": "Abilita capitolo generazione di immagini per i vostri video per una presentazione pi\u00f9 gradevole durante la visualizzazione.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ 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 b90370246..ef1c8ca6b 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/javascript.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -251,7 +252,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -402,6 +403,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -418,7 +420,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -427,7 +429,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Movies",
"TabSeries": "Series",
"TabEpisodes": "Episodes",
@@ -595,6 +597,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -650,9 +653,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
"OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
"LabelItemLimit": "Item limit:",
- "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced."
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
}
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json
index 85cd90d11..9f6f9312c 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/kk.json
@@ -40,6 +40,7 @@
"LabelStopping": "\u0422\u043e\u049b\u0442\u0430\u0442\u044b\u043b\u0443\u0434\u0430",
"LabelCancelled": "(\u0431\u043e\u043b\u0434\u044b\u0440\u044b\u043b\u043c\u0430\u0434\u044b)",
"LabelFailed": "(\u0441\u04d9\u0442\u0441\u0456\u0437)",
+ "ButtonHelp": "\u0410\u043d\u044b\u049b\u0442\u0430\u043c\u0430",
"LabelAbortedByServerShutdown": "(\u0421\u0435\u0440\u0432\u0435\u0440 \u0436\u04b1\u043c\u044b\u0441\u044b \u0430\u044f\u049b\u0442\u0430\u043b\u0443\u044b\u043d\u0430 \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b \u04af\u0437\u0456\u043b\u0434\u0456)",
"LabelScheduledTaskLastRan": "\u0421\u043e\u04a3\u0493\u044b \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u044b {0}, {1} \u0443\u0430\u049b\u044b\u0442 \u0430\u043b\u0434\u044b.",
"HeaderDeleteTaskTrigger": "\u0422\u0430\u043f\u0441\u044b\u0440\u043c\u0430 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0456\u043d \u0436\u043e\u044e",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "\u041e\u04a3\u0493\u0430 \u0436\u044b\u043b\u0436\u044b\u0442\u0443",
"ButtonBrowseOnlineImages": "\u0416\u0435\u043b\u0456\u0434\u0435\u0433\u0456 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0434\u0456 \u0448\u043e\u043b\u0443",
"HeaderDeleteItem": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u0436\u043e\u044e",
- "ConfirmDeleteItem": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0456 \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u0434\u0430\u043d \u0436\u043e\u044e \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "\u0410\u0442\u044b\u043d \u043d\u0435\u043c\u0435\u0441\u0435 \u0441\u044b\u0440\u0442\u049b\u044b ID \u0435\u043d\u0433\u0456\u0437\u0456\u04a3\u0456\u0437.",
"MessageValueNotCorrect": "\u0415\u043d\u0433\u0456\u0437\u0456\u043b\u0433\u0435\u043d \u043c\u04d9\u043d \u0434\u04b1\u0440\u044b\u0441 \u0435\u043c\u0435\u0441. \u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0456 \u049b\u0430\u0439\u0442\u0430\u043b\u0430\u04a3\u044b\u0437.",
"MessageItemSaved": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u0430\u049b\u0442\u0430\u043b\u0434\u044b.",
@@ -396,6 +397,7 @@
"LabelYear": "\u0416\u044b\u043b\u044b:",
"LabelDateOfBirth": "\u0422\u0443\u0493\u0430\u043d \u043a\u04af\u043d\u0456:",
"LabelBirthYear": "\u0422\u0443\u0493\u0430\u043d \u0436\u044b\u043b\u044b:",
+ "LabelBirthDate": "\u0422\u0443\u0493\u0430\u043d \u043a\u04af\u043d\u0456:",
"LabelDeathDate": "\u04e8\u043b\u0433\u0435\u043d \u043a\u04af\u043d\u0456:",
"HeaderRemoveMediaLocation": "\u0422\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u043e\u0440\u043d\u0430\u043b\u0430\u0441\u0443\u044b\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u0443",
"MessageConfirmRemoveMediaLocation": "\u0428\u044b\u043d\u044b\u043c\u0435\u043d \u043e\u0441\u044b \u043e\u0440\u043d\u0430\u043b\u0430\u0441\u0443\u0434\u044b \u0430\u043b\u0430\u0441\u0442\u0430\u0443 \u049b\u0430\u0436\u0435\u0442 \u043f\u0435?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "\u0422\u0430\u0441\u0443\u0448\u044b \u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u043e\u0440\u043d\u0430\u043b\u0430\u0441\u0443\u043b\u0430\u0440\u044b",
"LabelFolderTypeValue": "\u049a\u0430\u043b\u0442\u0430 \u0442\u04af\u0440\u0456: {0}",
"LabelPathSubstitutionHelp": "\u049a\u0430\u043b\u0430\u0443 \u0431\u043e\u0439\u044b\u043d\u0448\u0430: \u0416\u043e\u043b \u0430\u043b\u043c\u0430\u0441\u0442\u044b\u0440\u0443 \u0430\u0440\u049b\u044b\u043b\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0435\u0433\u0456 \u0436\u043e\u043b\u0434\u0430\u0440\u0434\u044b \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u043a\u043b\u0438\u0435\u043d\u0442\u0442\u0435\u0440 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0430 \u0430\u043b\u0430\u0442\u044b\u043d \u0436\u0435\u043b\u0456\u043b\u0456\u043a \u049b\u043e\u0440 \u043a\u04e9\u0437\u0434\u0435\u0440\u0456\u043c\u0435\u043d \u0431\u0430\u0439\u043b\u0430\u043d\u044b\u0441\u0442\u044b\u0440\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d.",
- "FolderTypeMixed": "\u0410\u0440\u0430\u043b\u0430\u0441 (\u043a\u0438\u043d\u043e \u0436\u04d9\u043d\u0435 \u0442\u0434)",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
"FolderTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430",
"FolderTypeAdultVideos": "\u0415\u0440\u0435\u0441\u0435\u043a\u0442\u0456\u043a \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "\u04ae\u0439 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0456",
"FolderTypeGames": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440",
"FolderTypeBooks": "\u041a\u0456\u0442\u0430\u043f\u0442\u0430\u0440",
- "FolderTypeTvShows": "\u0422\u0414 \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c\u0434\u0435\u0440\u0456",
+ "FolderTypeTvShows": "\u0422\u0414",
"TabMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
"TabSeries": "\u0421\u0435\u0440\u0438\u0430\u043b",
"TabEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u0442\u0430\u0440",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "\u0441\u043e\u043d\u044b\u043c\u0435\u043d \u049b\u0430\u0442\u0430\u0440 \u0431\u0430\u0441\u049b\u0430 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440\u0434\u044b \u0436\u04d9\u043d\u0435 Media Browser \u049b\u043e\u043b\u0434\u0430\u043d\u0431\u0430\u043b\u0430\u0440\u044b\u043d \u0431\u0430\u0441\u049b\u0430\u0440\u0430\u0434\u044b",
"MessageEnjoyYourStay": "\u0416\u0430\u0493\u044b\u043c\u0434\u044b \u0435\u0440\u043c\u0435\u043a \u0435\u0442\u0456\u04a3\u0456\u0437",
"DashboardTourDashboard": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456\u04a3 \u0431\u0430\u049b\u044b\u043b\u0430\u0443 \u0442\u0430\u049b\u0442\u0430\u0441\u044b \u0441\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u0436\u04d9\u043d\u0435 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440\u0434\u044b \u0431\u0430\u049b\u044b\u043b\u0430\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d\u0434\u0456\u0433\u0456\u043d\u0435 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0435\u0434\u0456. \u041a\u0456\u043c \u043d\u0435 \u0456\u0441\u0442\u0435\u0433\u0435\u043d\u0456\u043d \u0436\u04d9\u043d\u0435 \u049b\u0430\u0439\u0434\u0430 \u0442\u04b1\u0440\u0493\u0430\u043d\u044b\u043d \u0431\u0456\u043b\u0456\u043f \u0436\u0430\u0442\u0430\u0441\u044b\u0437.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "\u0414\u043e\u0441\u0442\u0430\u0440\u044b\u04a3\u044b\u0437 \u0431\u0435\u043d \u043e\u0442\u0431\u0430\u0441\u044b\u04a3\u044b\u0437 \u04d9\u0440\u049b\u0430\u0439\u0441\u044b\u043d\u0430 \u04e9\u0437\u0456\u043d\u0456\u04a3 \u049b\u04b1\u049b\u044b\u049b\u0442\u0430\u0440\u044b, \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u049b\u0430\u0442\u044b\u043d\u0430\u0441\u0443\u044b, \u043c\u0430\u0437\u043c\u04b1\u043d \u0431\u0430\u0441\u049b\u0430\u0440\u0443\u044b \u0436\u04d9\u043d\u0435 \u0442.\u0431. \u0431\u0430\u0440 \u0442\u0456\u0440\u043a\u0435\u043b\u0433\u0456\u043b\u0435\u0440\u0456\u043d \u0436\u0435\u04a3\u0456\u043b \u0436\u0430\u0441\u0430\u04a3\u044b\u0437.",
"DashboardTourCinemaMode": "\u041a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440 \u0440\u0435\u0436\u0456\u043c\u0456 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0434\u0456 \u0436\u04d9\u043d\u0435 \u0442\u0435\u04a3\u0448\u0435\u043b\u0433\u0435\u043d \u043a\u04e9\u0440\u043d\u0435\u0443\u0434\u0456 \u0431\u0430\u0441\u0442\u044b \u049b\u0430\u0441\u0438\u0435\u0442\u0442\u0456\u04a3 \u0430\u043b\u0434\u044b\u043d\u0434\u0430 \u043e\u0439\u043d\u0430\u0442\u0443 \u049b\u0430\u0431\u0456\u043b\u0435\u0442\u0456\u043c\u0435\u043d \u043a\u0438\u043d\u043e \u043a\u04e9\u0440\u0441\u0435\u0442\u0435\u0442\u0456\u043d \u0437\u0430\u043b \u04d9\u0441\u0435\u0440\u0456\u043d \u049b\u043e\u043d\u0430\u049b\u0436\u0430\u0439\u044b\u04a3\u044b\u0437\u0493\u0430 \u0442\u0456\u043a\u0435\u043b\u0435\u0439 \u0436\u0435\u0442\u043a\u0456\u0437\u0435\u0434\u0456.",
"DashboardTourChapters": "\u0411\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0434\u0456 \u049b\u0430\u0440\u0430\u0493\u0430\u043d \u043a\u0435\u0437\u0434\u0435 \u04b1\u043d\u0430\u043c\u0434\u044b\u043b\u0430\u0443 \u043a\u04e9\u0440\u0441\u0435\u0442\u0456\u043c \u04af\u0448\u0456\u043d \u0441\u0430\u0445\u043d\u0430 \u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440\u0456\u043d \u0442\u0443\u0434\u044b\u0440\u0443\u044b\u043d \u049b\u043e\u0441\u044b\u04a3\u044b\u0437.",
@@ -642,7 +645,12 @@
"OptionLow": "\u0422\u04e9\u043c\u0435\u043d",
"HeaderSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043b\u0435\u0440",
"OptionAutomaticallySyncNewContent": "\u0416\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d\u0434\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443",
- "OptionAutomaticallySyncNewContentHelp": "\u041e\u0441\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u0493\u0430 \u04af\u0441\u0442\u0435\u043b\u0456\u043d\u0433\u0435\u043d \u0436\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043c\u0435\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u043b\u0430\u0434\u044b.",
+ "OptionAutomaticallySyncNewContentHelp": "\u041e\u0441\u044b \u0441\u0430\u043d\u0430\u0442\u049b\u0430 \u049b\u043e\u0441\u044b\u043b\u0493\u0430\u043d \u0436\u0430\u04a3\u0430 \u043c\u0430\u0437\u043c\u04b1\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0442\u044b \u0442\u04af\u0440\u0434\u0435 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043c\u0435\u043d \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u043b\u044b\u043d\u0430\u0434\u044b.",
"OptionSyncUnwatchedVideosOnly": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u043a\u04e9\u0440\u0456\u043b\u043c\u0435\u0433\u0435\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0434\u0456 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443",
- "OptionSyncUnwatchedVideosOnlyHelp": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u049b\u0430\u0440\u0430\u0440\u043c\u0430\u0493\u0430\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u043b\u0430\u0434\u044b, \u0436\u04d9\u043d\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440 \u049b\u0430\u0440\u0430\u043b\u0493\u0430\u043d\u043d\u0430\u043d \u043a\u0435\u0439\u0456\u043d \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u0434\u0430\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u043b\u0430\u0434\u044b."
+ "OptionSyncUnwatchedVideosOnlyHelp": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u049b\u0430\u0440\u0430\u0440\u043c\u0430\u0493\u0430\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u043b\u044b\u043d\u0430\u0434\u044b, \u0436\u04d9\u043d\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440 \u049b\u0430\u0440\u0430\u043b\u0493\u0430\u043d\u043d\u0430\u043d \u043a\u0435\u0439\u0456\u043d \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u0434\u0430\u043d \u0430\u043b\u0430\u0441\u0442\u0430\u043b\u0430\u0434\u044b.",
+ "LabelItemLimit": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440 \u0448\u0435\u0433\u0456:",
+ "LabelItemLimitHelp": "\u049a\u0430\u043b\u0430\u0443 \u0431\u043e\u0439\u044b\u043d\u0448\u0430: \u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u043b\u0430\u0442\u044b\u043d \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440 \u0441\u0430\u043d\u044b \u04af\u0448\u0456\u043d \u0448\u0435\u043a\u0442\u0456 \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437.",
+ "MessageBookPluginRequired": "Bookshelf \u043f\u043b\u0430\u0433\u0438\u043d\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u0443\u0434\u044b \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456",
+ "MessageGamePluginRequired": "GameBrowser \u043f\u043b\u0430\u0433\u0438\u043d\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u0443\u0434\u044b \u049b\u0430\u0436\u0435\u0442 \u0435\u0442\u0435\u0434\u0456",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json
index 89aefed9d..2be125954 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ms.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Movies",
"TabSeries": "Series",
"TabEpisodes": "Episodes",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json
index a5fd9bb9b..68f3430dc 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nb.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stoppe",
"LabelCancelled": "(kansellert)",
"LabelFailed": "(Feilet)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Avbrutt av server shutdown)",
"LabelScheduledTaskLastRan": "Sist kj\u00f8rt {0}, tar {1}.",
"HeaderDeleteTaskTrigger": "Slett Oppgave Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Flytt til h\u00f8yre",
"ButtonBrowseOnlineImages": "Bla igjennom bilder online",
"HeaderDeleteItem": "Slett element",
- "ConfirmDeleteItem": "Er du sikker p\u00e5 at du vil slette dette elementet fra ditt bibliotek?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Vennligst skriv ett navn eller en ekstern id.",
"MessageValueNotCorrect": "Verdien som ble skrevet er ikke korrekt. Vennligst pr\u00f8v igjen.",
"MessageItemSaved": "Element lagret.",
@@ -396,6 +397,7 @@
"LabelYear": "\u00c5r:",
"LabelDateOfBirth": "F\u00f8dseldato:",
"LabelBirthYear": "F\u00f8dsels\u00e5r:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "D\u00f8ds dato:",
"HeaderRemoveMediaLocation": "Fjern Media Mappe",
"MessageConfirmRemoveMediaLocation": "Er du sikker p\u00e5 at du vil slette dette stedet??",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Steder",
"LabelFolderTypeValue": "Mappe type: {0}",
"LabelPathSubstitutionHelp": "Valgfritt: Sti erstatter kan koble server stier til nettverkressurser som klienter har tilgang til for direkte avspilling.",
- "FolderTypeMixed": "Mikset filmer & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Filmer",
"FolderTypeMusic": "Musikk",
"FolderTypeAdultVideos": "Voksen videoer",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Hjemme videoer",
"FolderTypeGames": "Spill",
"FolderTypeBooks": "B\u00f8ker",
- "FolderTypeTvShows": "TV program",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Filmer",
"TabSeries": "Serier",
"TabEpisodes": "Episoder",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "og enkelt styrer andre enheter og mediabrowser apps",
"MessageEnjoyYourStay": "Nyt oppholdet",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Opprett bruker kontoer enkelt for dine venner og familie, hver med deres egne rettigheter, bibliotek tillgang, foreldre kontroll og mere til.",
"DashboardTourCinemaMode": "Kino-modus bringer kinoopplevelsen direkte til din stue med muligheten til \u00e5 spille trailere og tilpassede introer f\u00f8r filmen begynner.",
"DashboardTourChapters": "Aktiver generering av kapittel bilder for dine videoer for en mer behagelig presentasjon mens du ser p\u00e5.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json
index 53445c370..78554eed8 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/nl.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stoppen",
"LabelCancelled": "(Geannuleerd)",
"LabelFailed": "(mislukt)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Afgebroken door afsluiten van de server)",
"LabelScheduledTaskLastRan": "Laatste keer {0}, duur {1}.",
"HeaderDeleteTaskTrigger": "Verwijderen Taak Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Verplaats naar rechts",
"ButtonBrowseOnlineImages": "Blader door online afbeeldingen",
"HeaderDeleteItem": "Item verwijderen",
- "ConfirmDeleteItem": "Weet u zeker dat u dit item uit uw bibliotheek wilt verwijderen?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Voer een naam of een externe Id in",
"MessageValueNotCorrect": "De ingevoerde waarde is niet correct. Probeer het opnieuw.",
"MessageItemSaved": "Item opgeslagen.",
@@ -396,6 +397,7 @@
"LabelYear": "Jaar:",
"LabelDateOfBirth": "Geboortedatum:",
"LabelBirthYear": "Geboorte jaar:",
+ "LabelBirthDate": "Geboortedatum:",
"LabelDeathDate": "Overlijdens datum:",
"HeaderRemoveMediaLocation": "Verwijder media locatie",
"MessageConfirmRemoveMediaLocation": "Weet je zeker dat je deze locatie wilt verwijderen?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locaties",
"LabelFolderTypeValue": "Map type: {0}",
"LabelPathSubstitutionHelp": "Optioneel: Pad vervanging kan server paden naar netwerk locaties verwijzen zodat clients direct kunnen afspelen.",
- "FolderTypeMixed": "Gemixte films en TV",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Films",
"FolderTypeMusic": "Muziek",
"FolderTypeAdultVideos": "Adult video's",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Thuis video's",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Boeken",
- "FolderTypeTvShows": "TV programma's",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Films",
"TabSeries": "Serie",
"TabEpisodes": "Afleveringen",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "en kan elke andere Media Browser app bedienen",
"MessageEnjoyYourStay": "Geniet van uw verblijf",
"DashboardTourDashboard": "Het server-dashboard steld u in staat uw server en uw gebruikers te monitoren . U zult altijd weten wie wat doet en waar ze zijn.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Maak gemakkelijk gebruikersaccounts voor uw vrienden en familie, elk met hun eigen machtigingen, bibliotheek toegang, ouderlijk toezicht en meer.",
"DashboardTourCinemaMode": "Cinema mode brengt de theater ervaring naar je woonkamer met de mogelijkheid om trailers en eigen intro's voor de film af te spelen",
"DashboardTourChapters": "Schakel hoofdstuk afbeeldingen genereren in voor uw video's voor een aantrekkelijker presentatie tijdens het kijken.",
@@ -642,7 +645,12 @@
"OptionLow": "Laag",
"HeaderSettings": "Instellingen",
"OptionAutomaticallySyncNewContent": "Nieuwe inhoud automatisch synchroniseren",
- "OptionAutomaticallySyncNewContentHelp": "Nieuwe inhoud in deze mappen zal automatisch gesynchroniseerd worden met het apparaat.",
+ "OptionAutomaticallySyncNewContentHelp": "Nieuwe inhoud toegevoegd aan deze categorie wordt automatisch gesynchroniseerd met het apparaat.",
"OptionSyncUnwatchedVideosOnly": "Synchroniseer alleen ongeziene video's",
- "OptionSyncUnwatchedVideosOnlyHelp": "Alleen ongeziene video's zulle gesynchroniseerd worden en van het apparaat verwijderd worden als ze gezien zijn."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Alleen ongeziene video's zulle gesynchroniseerd worden en van het apparaat verwijderd worden als ze gezien zijn.",
+ "LabelItemLimit": "Item limiet:",
+ "LabelItemLimitHelp": "Optioneel. Een limiet stellen aan het aantal items die zullen worden gesynchroniseerd.",
+ "MessageBookPluginRequired": "Vereist installatie van de Bookshelf plugin",
+ "MessageGamePluginRequired": "Vereist installatie van de GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json
index 98a8b5947..d957ab01f 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pl.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Filmy",
"TabSeries": "Series",
"TabEpisodes": "Odcinki",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json
index 492b402ca..fc26642b7 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_BR.json
@@ -40,6 +40,7 @@
"LabelStopping": "Parando",
"LabelCancelled": "(cancelado)",
"LabelFailed": "(falhou)",
+ "ButtonHelp": "Ajuda",
"LabelAbortedByServerShutdown": "(Abortada pelo desligamento do servidor)",
"LabelScheduledTaskLastRan": "\u00daltima execu\u00e7\u00e3o {0}, demorando {1}.",
"HeaderDeleteTaskTrigger": "Excluir Disparador da Tarefa",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Mover \u00e0 direita",
"ButtonBrowseOnlineImages": "Procurar imagens online",
"HeaderDeleteItem": "Excluir item",
- "ConfirmDeleteItem": "Deseja realmente excluir este item de sua biblioteca?",
+ "ConfirmDeleteItem": "Excluir este item o excluir\u00e1 do sistema de arquivos e tamb\u00e9m da biblioteca de m\u00eddias. Deseja realmente continuar?",
"MessagePleaseEnterNameOrId": "Por favor, digite um nome ou Id externo.",
"MessageValueNotCorrect": "O valor digitado n\u00e3o est\u00e1 correto. Por favor, tente novamente.",
"MessageItemSaved": "Item salvo.",
@@ -396,6 +397,7 @@
"LabelYear": "Ano:",
"LabelDateOfBirth": "Data de nascimento:",
"LabelBirthYear": "Ano de nascimento:",
+ "LabelBirthDate": "Data de nascimento:",
"LabelDeathDate": "Data da morte:",
"HeaderRemoveMediaLocation": "Remover Localiza\u00e7\u00e3o da M\u00eddia",
"MessageConfirmRemoveMediaLocation": "Deseja realmente remover esta localiza\u00e7\u00e3o?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Localiza\u00e7\u00f5es de M\u00eddia",
"LabelFolderTypeValue": "Tipo de pasta: {0}",
"LabelPathSubstitutionHelp": "Opcional: Substitui\u00e7\u00e3o de caminho pode mapear caminhos do servidor para compartilhamentos de rede de forma a que os clientes possam acessar para reprodu\u00e7\u00e3o direta.",
- "FolderTypeMixed": "Filmes & tv misturados",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Filmes",
"FolderTypeMusic": "M\u00fasica",
"FolderTypeAdultVideos": "V\u00eddeos adultos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "V\u00eddeos caseiros",
"FolderTypeGames": "Jogos",
"FolderTypeBooks": "Livros",
- "FolderTypeTvShows": "S\u00e9ries de TV",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Filmes",
"TabSeries": "S\u00e9ries",
"TabEpisodes": "Epis\u00f3dios",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "e controle facilmente outros dispositivos e apps do Media Browser",
"MessageEnjoyYourStay": "Divirta-se",
"DashboardTourDashboard": "O painel do servidor permite monitorar seu servidor e seus usu\u00e1rios. Voc\u00ea sempre poder\u00e1 saber quem est\u00e1 fazendo o qu\u00ea e onde est\u00e3o.",
+ "DashboardTourHelp": "A ajuda dentro da app fornece bot\u00f5es para abrir p\u00e1ginas wiki relacionadas ao conte\u00fado na tela.",
"DashboardTourUsers": "Crie facilmente contas de usu\u00e1rios para seus amigos e fam\u00edlia, cada um com sua permiss\u00e3o, acesso \u00e0 biblioteca, controle parental e mais.",
"DashboardTourCinemaMode": "O modo cinema traz a experi\u00eancia do cinema para sua sala, permitindo reproduzir trailers e intros personalizadas antes da fun\u00e7\u00e3o principal.",
"DashboardTourChapters": "Ative a gera\u00e7\u00e3o de imagem do cap\u00edtulo para seus v\u00eddeos para ter uma apresenta\u00e7\u00e3o mais prazeirosa.",
@@ -642,7 +645,12 @@
"OptionLow": "Baixa",
"HeaderSettings": "Ajustes",
"OptionAutomaticallySyncNewContent": "Sincronizar novo conte\u00fado automaticamente",
- "OptionAutomaticallySyncNewContentHelp": "Novo conte\u00fado adicionado a estas pastas ser\u00e1 automaticamente sincronizado com o dispositivo.",
+ "OptionAutomaticallySyncNewContentHelp": "Novo conte\u00fado adicionado a esta categoria ser\u00e1 automaticamente sincronizado com o dispositivo.",
"OptionSyncUnwatchedVideosOnly": "Sincronizar apenas v\u00eddeos n\u00e3o assistidos",
- "OptionSyncUnwatchedVideosOnlyHelp": "Apenas v\u00eddeos n\u00e3o assistidos ser\u00e3o sincronizados, e os v\u00eddeos ser\u00e3o removidos do dispositivo assim que forem assistidos."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Apenas v\u00eddeos n\u00e3o assistidos ser\u00e3o sincronizados, e os v\u00eddeos ser\u00e3o removidos do dispositivo assim que forem assistidos.",
+ "LabelItemLimit": "Limite de itens:",
+ "LabelItemLimitHelp": "Opcional. Defina o n\u00famero limite de itens que ser\u00e3o sincronizados.",
+ "MessageBookPluginRequired": "Requer a instala\u00e7\u00e3o do plugin Bookshelf",
+ "MessageGamePluginRequired": "Requer a instala\u00e7\u00e3o do plugin GameBrowser",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json
index 5007ae444..099db56d1 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/pt_PT.json
@@ -36,10 +36,11 @@
"LabelMovie": "Movie",
"LabelMusicVideo": "Music Video",
"LabelEpisode": "Episode",
- "LabelSeries": "Series",
+ "LabelSeries": "S\u00e9rie",
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
- "LabelFailed": "(failed)",
+ "LabelFailed": "(falhou)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -63,7 +64,7 @@
"ButtonPlay": "Reproduzir",
"ButtonEdit": "Editar",
"ButtonQueue": "Queue",
- "ButtonPlayTrailer": "Play trailer",
+ "ButtonPlayTrailer": "Reproduzir trailer",
"ButtonPlaylist": "Playlist",
"ButtonPreviousTrack": "Faixa Anterior",
"LabelEnabled": "Enabled",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -384,7 +385,7 @@
"PersonTypePerson": "Person",
"LabelTitleDisplayOrder": "Title display order:",
"OptionSortName": "Sort name",
- "OptionReleaseDate": "Release date",
+ "OptionReleaseDate": "Data de lan\u00e7amento",
"LabelSeasonNumber": "N\u00famero da temporada:",
"LabelDiscNumber": "Disc number",
"LabelParentNumber": "Parent number",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Filmes",
"TabSeries": "S\u00e9ries",
"TabEpisodes": "Epis\u00f3dios",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json
index 15e489fb3..3ca96a3b0 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/ru.json
@@ -40,6 +40,7 @@
"LabelStopping": "\u041e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430",
"LabelCancelled": "(\u043e\u0442\u043c\u0435\u043d\u0435\u043d\u043e)",
"LabelFailed": "(\u043d\u0435\u0443\u0434\u0430\u0447\u043d\u043e)",
+ "ButtonHelp": "\u0421\u043f\u0440\u0430\u0432\u043a\u0430",
"LabelAbortedByServerShutdown": "(\u041f\u0440\u0435\u0440\u0432\u0430\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430)",
"LabelScheduledTaskLastRan": "\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0430\u0441\u044c {0}, \u0437\u0430\u043d\u044f\u043b\u0430 {1}.",
"HeaderDeleteTaskTrigger": "\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430 \u0437\u0430\u0434\u0430\u0447\u0438",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "\u0414\u0432\u0438\u0433\u0430\u0442\u044c \u0432\u043f\u0440\u0430\u0432\u043e",
"ButtonBrowseOnlineImages": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0438\u0441\u0443\u043d\u043a\u0438 \u0432 \u0441\u0435\u0442\u0438",
"HeaderDeleteItem": "\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430",
- "ConfirmDeleteItem": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0438\u0437 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438?",
+ "ConfirmDeleteItem": "\u041f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u043e\u043d \u0443\u0434\u0430\u043b\u0438\u0442\u0441\u044f \u0438 \u0438\u0437 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0438 \u0438\u0437 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438. \u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c?",
"MessagePleaseEnterNameOrId": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0438\u043b\u0438 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 ID.",
"MessageValueNotCorrect": "\u0412\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435 \u0432\u0435\u0440\u043d\u043e. \u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u0435 \u043f\u043e\u043f\u044b\u0442\u043a\u0443.",
"MessageItemSaved": "\u042d\u043b\u0435\u043c\u0435\u043d\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0451\u043d.",
@@ -396,6 +397,7 @@
"LabelYear": "\u0413\u043e\u0434:",
"LabelDateOfBirth": "\u0414\u0430\u0442\u0430 \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f:",
"LabelBirthYear": "\u0413\u043e\u0434 \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f:",
+ "LabelBirthDate": "\u0414\u0430\u0442\u0430 \u0440\u043e\u0436\u0434\u0435\u043d\u0438\u044f:",
"LabelDeathDate": "\u0414\u0430\u0442\u0430 \u0441\u043c\u0435\u0440\u0442\u0438:",
"HeaderRemoveMediaLocation": "\u0418\u0437\u044a\u044f\u0442\u0438\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
"MessageConfirmRemoveMediaLocation": "\u0412\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0438\u0437\u044a\u044f\u0442\u044c \u044d\u0442\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "\u0420\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
"LabelFolderTypeValue": "\u0422\u0438\u043f \u043f\u0430\u043f\u043a\u0438: {0}",
"LabelPathSubstitutionHelp": "\u041d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e: \u041f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u0443\u0442\u0435\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u043f\u0443\u0442\u0435\u0439 \u0441\u043e \u0441\u0435\u0442\u0435\u0432\u044b\u043c\u0438 \u043e\u0431\u0449\u0438\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0434\u043b\u044f \u043f\u0440\u044f\u043c\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f.",
- "FolderTypeMixed": "\u0421\u043c\u0435\u0448\u0430\u043d\u043d\u044b\u0439 (\u0444\u0438\u043b\u044c\u043c\u044b \u0438 \u0422\u0412)",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "\u0424\u0438\u043b\u044c\u043c\u044b",
"FolderTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430",
"FolderTypeAdultVideos": "\u0412\u0437\u0440\u043e\u0441\u043b\u044b\u0435 \u0432\u0438\u0434\u0435\u043e",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "\u0414\u043e\u043c\u0430\u0448\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u043e",
"FolderTypeGames": "\u0418\u0433\u0440\u044b",
"FolderTypeBooks": "\u041a\u043d\u0438\u0433\u0438",
- "FolderTypeTvShows": "\u0422\u0412 \u0446\u0438\u043a\u043b\u044b",
+ "FolderTypeTvShows": "\u0422\u0412",
"TabMovies": "\u0424\u0438\u043b\u044c\u043c\u044b",
"TabSeries": "\u0421\u0435\u0440\u0438\u0430\u043b\u044b",
"TabEpisodes": "\u042d\u043f\u0438\u0437\u043e\u0434\u044b",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "\u0438 \u0441 \u043b\u0435\u0433\u043a\u043e\u0441\u0442\u044c\u044e \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438 Media Browser",
"MessageEnjoyYourStay": "\u041f\u0440\u0438\u044f\u0442\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u044f\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u044f",
"DashboardTourDashboard": "\u0421\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0418\u043d\u0444\u043e\u043f\u0430\u043d\u0435\u043b\u044c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u0412\u044b \u0431\u0443\u0434\u0435\u0442\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u0437\u043d\u0430\u0442\u044c, \u043a\u0442\u043e \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u043c \u0438 \u0433\u0434\u0435 \u043e\u043d\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f.",
+ "DashboardTourHelp": "\u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u043a\u043d\u043e\u043f\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0432\u0438\u043a\u0438-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0438\u0445\u0441\u044f \u043a \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044e \u044d\u043a\u0440\u0430\u043d\u0430.",
"DashboardTourUsers": "\u0421\u0432\u043e\u0431\u043e\u0434\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0447\u0451\u0442\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0434\u043b\u044f \u0432\u0430\u0448\u0438\u0445 \u0434\u0440\u0443\u0437\u0435\u0439 \u0438 \u0447\u043b\u0435\u043d\u043e\u0432 \u0441\u0435\u043c\u044c\u0438, \u043a\u0430\u0436\u0434\u0443\u044e \u0441 \u0438\u0445 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u0430\u0432\u0430\u043c\u0438, \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u043a \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c \u0438 \u0442.\u0434.",
"DashboardTourCinemaMode": "\u0420\u0435\u0436\u0438\u043c \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430 \u043f\u0440\u0438\u0432\u043d\u043e\u0441\u0438\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043a\u0438\u043d\u043e\u0437\u0430\u043b\u0430 \u043f\u0440\u044f\u043c\u0438\u043a\u043e\u043c \u0432 \u0432\u0430\u0448\u0443 \u0433\u043e\u0441\u0442\u0438\u043d\u0443\u044e, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c\u044e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0438 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u0433\u043b\u0430\u0432\u043d\u044b\u043c \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u043c.",
"DashboardTourChapters": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u0435 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0441\u0446\u0435\u043d \u043a \u0432\u0438\u0434\u0435\u043e, \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430.",
@@ -641,8 +644,13 @@
"OptionMedium": "\u0421\u0440\u0435\u0434\u043d\u0435\u0435",
"OptionLow": "\u041d\u0438\u0437\u043a\u043e\u0435",
"HeaderSettings": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b",
- "OptionAutomaticallySyncNewContent": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435",
- "OptionAutomaticallySyncNewContentHelp": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0435 \u0432 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u043f\u043a\u0438, \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441 \u0434\u0430\u043d\u043d\u044b\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c.",
- "OptionSyncUnwatchedVideosOnly": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u044b.",
- "OptionSyncUnwatchedVideosOnlyHelp": "\u0422\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f, \u0430 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u044b \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u044b\u043c\u0430\u0442\u044c\u0441\u044f \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u043e\u0441\u043b\u0435 \u0438\u0445 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430."
+ "OptionAutomaticallySyncNewContent": "\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0438\u043d\u0445\u0440-\u0442\u044c \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435",
+ "OptionAutomaticallySyncNewContentHelp": "\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435, \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0435 \u0432 \u0434\u0430\u043d\u043d\u0443\u044e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044e, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c.",
+ "OptionSyncUnwatchedVideosOnly": "\u0421\u0438\u043d\u0445\u0440-\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e",
+ "OptionSyncUnwatchedVideosOnlyHelp": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e, \u0430 \u0441\u0430\u043c\u0438 \u0432\u0438\u0434\u0435\u043e \u0438\u0437\u044b\u043c\u0430\u044e\u0442\u0441\u044f \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u043e\u0441\u043b\u0435 \u0438\u0445 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430.",
+ "LabelItemLimit": "\u041f\u0440\u0435\u0434\u0435\u043b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432:",
+ "LabelItemLimitHelp": "\u041d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e. \u0417\u0430\u0434\u0430\u0442\u044c \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f.",
+ "MessageBookPluginRequired": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 Bookshelf",
+ "MessageGamePluginRequired": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 GameBrowser",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json
index a0b86f576..5a3facbb6 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/sv.json
@@ -40,6 +40,7 @@
"LabelStopping": "Avbryter",
"LabelCancelled": "(avbr\u00f6ts)",
"LabelFailed": "(misslyckades)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(avbr\u00f6ts eftersom servern st\u00e4ngdes av)",
"LabelScheduledTaskLastRan": "Senast k\u00f6rd {0}, tog {1}",
"HeaderDeleteTaskTrigger": "Ta bort aktivitetsutl\u00f6sare",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "H\u00f6ger",
"ButtonBrowseOnlineImages": "Bl\u00e4ddra bland bilder online",
"HeaderDeleteItem": "Radera objekt",
- "ConfirmDeleteItem": "\u00c4r du s\u00e4ker p\u00e5 att du vill radera det h\u00e4r objektet fr\u00e5n biblioteket?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Ange ett namn eller externt id.",
"MessageValueNotCorrect": "Det angivna v\u00e4rdet \u00e4r felaktigt. Var god f\u00f6rs\u00f6k igen.",
"MessageItemSaved": "Objektet har sparats.",
@@ -396,6 +397,7 @@
"LabelYear": "\u00c5r:",
"LabelDateOfBirth": "F\u00f6delsedatum:",
"LabelBirthYear": "F\u00f6delse\u00e5r:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "D\u00f6d:",
"HeaderRemoveMediaLocation": "Ta bort mediaplats",
"MessageConfirmRemoveMediaLocation": "\u00c4r du s\u00e4ker p\u00e5 att du vill ta bort den h\u00e4r platsen?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Lagringsplatser f\u00f6r media",
"LabelFolderTypeValue": "Typ av mapp: {0}",
"LabelPathSubstitutionHelp": "Tillval: S\u00f6kv\u00e4gsutbyte betyder att en plats p\u00e5 servern kopplas till en lokal fils\u00f6kv\u00e4g p\u00e5 en klient. P\u00e5 s\u00e5 s\u00e4tt f\u00e5r klienten direkt tillg\u00e5ng till material p\u00e5 servern och kan spela upp det direkt via n\u00e4tverket.",
- "FolderTypeMixed": "Blandat film & TV",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Filmer",
"FolderTypeMusic": "Musik",
"FolderTypeAdultVideos": "Inneh\u00e5ll f\u00f6r vuxna",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Hemvideor",
"FolderTypeGames": "Spel",
"FolderTypeBooks": "B\u00f6cker",
- "FolderTypeTvShows": "TV-serier",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Filmer",
"TabSeries": "Serie",
"TabEpisodes": "Avsnitt",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "och kan enkelt fj\u00e4rrstyra andra enheter och Media Browser-appar",
"MessageEnjoyYourStay": "Ha ett trevligt bes\u00f6k",
"DashboardTourDashboard": "Via serverns kontrollpanel kan du \u00f6vervaka din server och alla anv\u00e4ndare. Du kommer alltid att kunna veta vem som g\u00f6r vad och var de \u00e4r.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Skapa enkelt anv\u00e4ndarkonton f\u00f6r dina v\u00e4nner och familj, alla med sina egna beh\u00f6righeter, biblioteks \u00e5tkomst, f\u00f6r\u00e4ldrakontroll och mycket mer.",
"DashboardTourCinemaMode": "Biol\u00e4get g\u00f6r ditt vardagsrum till en biograf genom m\u00f6jligheten att visa trailers och egna vinjetter innan filmen b\u00f6rjar.",
"DashboardTourChapters": "Ta fram kapitelbildrutor fr\u00e5n videofiler f\u00f6r att f\u00e5 en snyggare presentation.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json
index e8ecf0de0..e6f5b4d79 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/tr.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "Filmler",
"TabSeries": "Seriler",
"TabEpisodes": "B\u00f6l\u00fcmler",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json
index e94761156..22ccfacc2 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/vi.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "C\u00e1c phim",
"TabSeries": "Series",
"TabEpisodes": "C\u00e1c t\u1eadp phim",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json
index ad9a6c6a5..3bf1bf2a7 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_CN.json
@@ -40,6 +40,7 @@
"LabelStopping": "\u505c\u6b62",
"LabelCancelled": "(\u5df2\u53d6\u6d88)",
"LabelFailed": "(\u5931\u8d25)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(\u56e0\u4e3a\u670d\u52a1\u5668\u5173\u95ed\u88ab\u4e2d\u6b62)",
"LabelScheduledTaskLastRan": "\u6700\u540e\u8fd0\u884c {0}, \u82b1\u8d39\u65f6\u95f4 {1}.",
"HeaderDeleteTaskTrigger": "\u5220\u9664\u4efb\u52a1\u89e6\u53d1\u6761\u4ef6",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "\u53f3\u79fb",
"ButtonBrowseOnlineImages": "\u6d4f\u89c8\u5728\u7ebf\u56fe\u7247",
"HeaderDeleteItem": "\u5220\u9664\u9879\u76ee",
- "ConfirmDeleteItem": "\u4f60\u786e\u5b9a\u5e0c\u671b\u4ece\u5a92\u4f53\u5e93\u91cc\u5220\u9664\u8fd9\u4e2a\u9879\u76ee\uff1f",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "\u8bf7\u8f93\u5165\u4e00\u4e2a\u540d\u79f0\u6216\u4e00\u4e2a\u5916\u90e8ID\u3002",
"MessageValueNotCorrect": "\u8f93\u5165\u7684\u503c\u4e0d\u6b63\u786e\u3002\u8bf7\u91cd\u8bd5\u3002",
"MessageItemSaved": "\u9879\u76ee\u5df2\u4fdd\u5b58\u3002",
@@ -396,6 +397,7 @@
"LabelYear": "\u5e74\uff1a",
"LabelDateOfBirth": "\u51fa\u751f\u65e5\u671f\uff1a",
"LabelBirthYear": "\u51fa\u751f\u5e74\u4efd\uff1a",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "\u53bb\u4e16\u65e5\u671f\uff1a",
"HeaderRemoveMediaLocation": "\u79fb\u9664\u5a92\u4f53\u4f4d\u7f6e",
"MessageConfirmRemoveMediaLocation": "\u4f60\u786e\u5b9a\u8981\u79fb\u9664\u6b64\u4f4d\u7f6e\uff1f",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "\u5a92\u4f53\u4f4d\u7f6e",
"LabelFolderTypeValue": "\u6587\u4ef6\u5939\u7c7b\u578b\uff1a {0}",
"LabelPathSubstitutionHelp": "\u53ef\u9009\uff1a\u66ff\u4ee3\u8def\u5f84\u80fd\u628a\u670d\u52a1\u5668\u8def\u5f84\u6620\u5c04\u5230\u7f51\u7edc\u5171\u4eab\uff0c\u4ece\u800c\u4f7f\u5ba2\u6237\u7aef\u53ef\u4ee5\u76f4\u63a5\u64ad\u653e\u3002",
- "FolderTypeMixed": "\u6df7\u5408\u7684\u7535\u5f71\u548c\u7535\u89c6",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "\u7535\u5f71",
"FolderTypeMusic": "\u97f3\u4e50",
"FolderTypeAdultVideos": "\u6210\u4eba\u89c6\u9891",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "\u5bb6\u5ead\u89c6\u9891",
"FolderTypeGames": "\u6e38\u620f",
"FolderTypeBooks": "\u4e66\u7c4d",
- "FolderTypeTvShows": "\u7535\u89c6\u8282\u76ee",
+ "FolderTypeTvShows": "TV",
"TabMovies": "\u7535\u5f71",
"TabSeries": "\u7535\u89c6\u5267",
"TabEpisodes": "\u5267\u96c6",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json
index 706299704..c7c4ecd88 100644
--- a/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json
+++ b/MediaBrowser.Server.Implementations/Localization/JavaScript/zh_TW.json
@@ -40,6 +40,7 @@
"LabelStopping": "Stopping",
"LabelCancelled": "(cancelled)",
"LabelFailed": "(failed)",
+ "ButtonHelp": "Help",
"LabelAbortedByServerShutdown": "(Aborted by server shutdown)",
"LabelScheduledTaskLastRan": "Last ran {0}, taking {1}.",
"HeaderDeleteTaskTrigger": "Delete Task Trigger",
@@ -249,7 +250,7 @@
"ButtonMoveRight": "Move right",
"ButtonBrowseOnlineImages": "Browse online images",
"HeaderDeleteItem": "Delete Item",
- "ConfirmDeleteItem": "Are you sure you wish to delete this item from your library?",
+ "ConfirmDeleteItem": "Deleting this item will delete it from both the file system and your media library. Are you sure you wish to continue?",
"MessagePleaseEnterNameOrId": "Please enter a name or an external Id.",
"MessageValueNotCorrect": "The value entered is not correct. Please try again.",
"MessageItemSaved": "Item saved.",
@@ -396,6 +397,7 @@
"LabelYear": "Year:",
"LabelDateOfBirth": "Date of birth:",
"LabelBirthYear": "Birth year:",
+ "LabelBirthDate": "Birth date:",
"LabelDeathDate": "Death date:",
"HeaderRemoveMediaLocation": "Remove Media Location",
"MessageConfirmRemoveMediaLocation": "Are you sure you wish to remove this location?",
@@ -411,7 +413,7 @@
"HeaderMediaLocations": "Media Locations",
"LabelFolderTypeValue": "Folder type: {0}",
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
- "FolderTypeMixed": "Mixed movies & tv",
+ "FolderTypeUnset": "Unset (mixed content)",
"FolderTypeMovies": "Movies",
"FolderTypeMusic": "Music",
"FolderTypeAdultVideos": "Adult videos",
@@ -420,7 +422,7 @@
"FolderTypeHomeVideos": "Home videos",
"FolderTypeGames": "Games",
"FolderTypeBooks": "Books",
- "FolderTypeTvShows": "TV shows",
+ "FolderTypeTvShows": "TV",
"TabMovies": "\u96fb\u5f71",
"TabSeries": "\u96fb\u8996\u5287",
"TabEpisodes": "\u55ae\u5143",
@@ -587,6 +589,7 @@
"WebClientTourMobile2": "and easily controls other devices and Media Browser apps",
"MessageEnjoyYourStay": "Enjoy your stay",
"DashboardTourDashboard": "The server dashboard allows you to monitor your server and your users. You'll always know who is doing what and where they are.",
+ "DashboardTourHelp": "In-app help provides easy buttons to open wiki pages relating to the on-screen content.",
"DashboardTourUsers": "Easily create user accounts for your friends and family, each with their own permissions, library access, parental controls and more.",
"DashboardTourCinemaMode": "Cinema mode brings the theater experience straight to your living room with the ability to play trailers and custom intros before the main feature.",
"DashboardTourChapters": "Enable chapter image generation for your videos for a more pleasing presentation while viewing.",
@@ -642,7 +645,12 @@
"OptionLow": "Low",
"HeaderSettings": "Settings",
"OptionAutomaticallySyncNewContent": "Automatically sync new content",
- "OptionAutomaticallySyncNewContentHelp": "New content added to these folders will be automatically synced to the device.",
+ "OptionAutomaticallySyncNewContentHelp": "New content added to this category will be automatically synced to the device.",
"OptionSyncUnwatchedVideosOnly": "Sync unwatched videos only",
- "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched."
+ "OptionSyncUnwatchedVideosOnlyHelp": "Only unwatched videos will be synced, and videos will be removed from the device as they are watched.",
+ "LabelItemLimit": "Item limit:",
+ "LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
+ "MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
+ "MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
+ "MessageUnsetContentHelp": "Content will be displayed as plain folders. For best results use the metadata manager to set the content types of sub-folders."
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ar.json b/MediaBrowser.Server.Implementations/Localization/Server/ar.json
index 97302a0ff..2b2eea03f 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ar.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ar.json
@@ -37,10 +37,21 @@
"ButtonOk": "\u0645\u0648\u0627\u0641\u0642",
"ButtonCancel": "\u0627\u0644\u063a\u0627\u0621",
"ButtonNew": "New",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "\u0627\u0639\u062f\u0627\u062f \u0645\u0643\u062a\u0628\u0629 \u0627\u0644\u0648\u0633\u0627\u0626\u0637",
"ButtonAddMediaFolder": "\u0627\u0636\u0627\u0641\u0629 \u0645\u062c\u0644\u062f \u0644\u0644\u0648\u0633\u0627\u0626\u0637",
"LabelFolderType": "\u0646\u0648\u0639 \u0627\u0644\u0645\u062c\u0644\u062f:",
- "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
"ReferToMediaLibraryWiki": "\u0627\u0644\u0631\u062c\u0648\u0639 \u0627\u0644\u0649 wiki \u0644\u0645\u0643\u062a\u0628\u0629 \u0627\u0644\u0648\u0633\u0627\u0626\u0637",
"LabelCountry": "\u0627\u0644\u0628\u0644\u062f:",
"LabelLanguage": "\u0627\u0644\u0644\u063a\u0629:",
@@ -365,8 +376,8 @@
"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",
+ "ButtonAddScheduledTaskTrigger": "Add Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Trigger",
"ButtonAdd": "Add",
"LabelTriggerType": "Trigger Type:",
"OptionDaily": "Daily",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 655cabcaf..9492845d3 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ca.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ca.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonNew": "New",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"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:",
@@ -365,8 +376,8 @@
"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",
+ "ButtonAddScheduledTaskTrigger": "Add Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Trigger",
"ButtonAdd": "Add",
"LabelTriggerType": "Trigger Type:",
"OptionDaily": "Daily",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 74aa0cd37..ca3a1c064 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/cs.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/cs.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Zru\u0161it",
"ButtonNew": "Nov\u00e9",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "Nastaven\u00ed Va\u0161i knihovny m\u00e9di\u00ed",
"ButtonAddMediaFolder": "P\u0159idat slo\u017eku m\u00e9di\u00ed",
"LabelFolderType": "Typ slo\u017eky:",
- "MediaFolderHelpPluginRequired": "* Vy\u017eaduje pou\u017eit\u00ed pluginu, nap\u0159. GameBrowser nebo MB Bookshelf",
"ReferToMediaLibraryWiki": "Pod\u00edvejte se na wiki knihovny m\u00e9di\u00ed.",
"LabelCountry": "Zem\u011b:",
"LabelLanguage": "Jazyk:",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/da.json b/MediaBrowser.Server.Implementations/Localization/Server/da.json
index db4c6d535..f03e3cdbd 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/da.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/da.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Annuller",
"ButtonNew": "Ny",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "Konfigurer dit medie bibliotek",
"ButtonAddMediaFolder": "Tilf\u00f8j medie mappe",
"LabelFolderType": "Mappe type:",
- "MediaFolderHelpPluginRequired": "* Kr\u00e6ver brug af en tilf\u00f8jelse, fx GameBrowser eller MB Bookshelf.",
"ReferToMediaLibraryWiki": "Der henvises til medie bibliotekets wiki.",
"LabelCountry": "Land:",
"LabelLanguage": "Sprog:",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 c5e0715ff..cd1626f58 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/de.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/de.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Abbrechen",
"ButtonNew": "Neu",
+ "FolderTypeMixed": "Gemischte Inhalte",
+ "FolderTypeMovies": "Filme",
+ "FolderTypeMusic": "Musik",
+ "FolderTypeAdultVideos": "Videos f\u00fcr Erwachsene",
+ "FolderTypePhotos": "Fotos",
+ "FolderTypeMusicVideos": "Musikvideos",
+ "FolderTypeHomeVideos": "Heimvideos",
+ "FolderTypeGames": "Spiele",
+ "FolderTypeBooks": "B\u00fccher",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "\u00dcbernehmen",
+ "LabelContentType": "Inhalte-Typ:",
"HeaderSetupLibrary": "Medienbibliothek einrichten",
"ButtonAddMediaFolder": "Medienverzeichnis hinzuf\u00fcgen",
"LabelFolderType": "Verzeichnistyp:",
- "MediaFolderHelpPluginRequired": "* Ben\u00f6tigt ein Plugin, wie GameBrowser oder MB Bookshelf.",
"ReferToMediaLibraryWiki": "Siehe die Medienbibliothek Wiki",
"LabelCountry": "Land:",
"LabelLanguage": "Sprache:",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Rolle",
"OptionPlayUnwatchedTrailersOnly": "Spiele nur bisher nicht gesehene Trailer",
"HeaderTrailerReelHelp": "Starte eine Trailer Rolle, um dir eine lang andauernde Playlist mit Trailern anzuschauen.",
- "MessageNoTrailersFound": "Keine Trailer gefunden. Installiere das Trailer Channel Plugin, um eine Bibliothek aus Trailern vom Internet zu importieren.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "Neue Benutzer",
"ButtonSignUp": "Anmeldung",
"ButtonForgotPassword": "Passwort vergessen?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Begrenze auf ein eingebundenes Bild",
"LabelEnableSingleImageInDidlLimitHelp": "Einige Ger\u00e4te zeigen m\u00f6glicherweise Darstellungsfehler wenn mehrere Bilder mit Didl eingebunden wurden.",
"TabActivity": "Aktivit\u00e4t",
- "TitleSync": "Synchronisation"
+ "TitleSync": "Synchronisation",
+ "OptionAllowSyncContent": "Erlaube das Synchronisieren zu Ger\u00e4ten.",
+ "NameSeasonUnknown": "Staffel unbekannt",
+ "NameSeasonNumber": "Staffel {0}",
+ "LabelNewUserNameHelp": "Benutzernamen k\u00f6nnen Zeichen (a-z), Zahlen (0-9), Striche (-), Unterstriche (_), Apostrophe (') und Punkte (.) enthalten."
} \ 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 41239b912..767ae9720 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/el.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/el.json
@@ -37,10 +37,21 @@
"ButtonOk": "\u03b5\u03bd\u03c4\u03ac\u03be\u03b5\u03b9",
"ButtonCancel": "\u0391\u03ba\u03cd\u03c1\u03c9\u03c3\u03b7 ",
"ButtonNew": "New",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "Setup your media library",
"ButtonAddMediaFolder": "\u03a0\u03c1\u03bf\u03c3\u03b8\u03ad\u03c3\u03c4\u03b5 \u03c4\u03bf \u03c6\u03ac\u03ba\u03b5\u03bb\u03bf \u03c4\u03bf\u03c5 Media",
"LabelFolderType": "\u03a4\u03cd\u03c0\u03bf \u03c6\u03b1\u03ba\u03ad\u03bb\u03bf\u03c5 ",
- "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",
@@ -365,8 +376,8 @@
"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",
+ "ButtonAddScheduledTaskTrigger": "Add Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Trigger",
"ButtonAdd": "Add",
"LabelTriggerType": "Trigger Type:",
"OptionDaily": "Daily",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 9eeac0f85..52b11fead 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/en_GB.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonNew": "New",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"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:",
@@ -365,8 +376,8 @@
"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",
+ "ButtonAddScheduledTaskTrigger": "Add Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Trigger",
"ButtonAdd": "Add",
"LabelTriggerType": "Trigger Type:",
"OptionDaily": "Daily",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 9cb4fb6c5..b14e8fcaa 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/en_US.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/en_US.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonNew": "New",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"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:",
@@ -365,8 +376,8 @@
"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",
+ "ButtonAddScheduledTaskTrigger": "Add Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Trigger",
"ButtonAdd": "Add",
"LabelTriggerType": "Trigger Type:",
"OptionDaily": "Daily",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 a720a1510..4cd9d799b 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/es.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/es.json
@@ -37,10 +37,21 @@
"ButtonOk": "OK",
"ButtonCancel": "Cancelar",
"ButtonNew": "Nuevo",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "Configurar biblioteca de medios",
"ButtonAddMediaFolder": "Agregar una carpeta de medios",
"LabelFolderType": "Tipo de carpeta:",
- "MediaFolderHelpPluginRequired": "* Requiere el uso de un plugin, por ejemplo GameBrowser o MB Bookshelf",
"ReferToMediaLibraryWiki": "Consultar el wiki de la biblioteca de medios",
"LabelCountry": "Pa\u00eds:",
"LabelLanguage": "Idioma:",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 7c532182b..3b5c5add5 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/es_MX.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Cancelar",
"ButtonNew": "Nuevo",
+ "FolderTypeMixed": "Contenido mezclado",
+ "FolderTypeMovies": "Pel\u00edculas",
+ "FolderTypeMusic": "M\u00fasica",
+ "FolderTypeAdultVideos": "Videos para adultos",
+ "FolderTypePhotos": "Fotos",
+ "FolderTypeMusicVideos": "Videos musicales",
+ "FolderTypeHomeVideos": "Videos caseros",
+ "FolderTypeGames": "Juegos",
+ "FolderTypeBooks": "Libros",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Heredar",
+ "LabelContentType": "Tipo de Contenido:",
"HeaderSetupLibrary": "Configurar su biblioteca de medios",
"ButtonAddMediaFolder": "Agregar carpeta de medios",
"LabelFolderType": "Tipo de carpeta:",
- "MediaFolderHelpPluginRequired": "* Requiere el uso de un complemento, p. ej. GameBrowser o MB Bookshelf.",
"ReferToMediaLibraryWiki": "Consultar la wiki de la biblioteca de medios.",
"LabelCountry": "Pa\u00eds:",
"LabelLanguage": "Idioma:",
@@ -232,10 +243,10 @@
"HeaderFeatureAccess": "Permisos de acceso",
"OptionAllowMediaPlayback": "Permitir reproducci\u00f3n de medios",
"OptionAllowBrowsingLiveTv": "Permitir acceder a TV en vivo",
- "OptionAllowDeleteLibraryContent": "Allow deletion of library content",
+ "OptionAllowDeleteLibraryContent": "Permitir eliminar contenido de la biblioteca",
"OptionAllowManageLiveTv": "Permitir administrar grabaciones de TV en vivo",
- "OptionAllowRemoteControlOthers": "Allow remote control of other users",
- "OptionAllowRemoteSharedDevices": "Allow remote control of shared devices",
+ "OptionAllowRemoteControlOthers": "Permitir control remoto de otros usuarios",
+ "OptionAllowRemoteSharedDevices": "Permitir control remoto de dispositivos compartidos",
"OptionAllowRemoteSharedDevicesHelp": "Los dispositivos dnla son considerados como compartidos hasta que alg\u00fan usuario comienza a controlarlo.",
"HeaderRemoteControl": "Control Remoto",
"OptionMissingTmdbId": "Falta Id de Tmdb",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Carrete de Avances",
"OptionPlayUnwatchedTrailersOnly": "Reproducir \u00fanicamente avances no vistos",
"HeaderTrailerReelHelp": "Iniciar un carrete de avances para reproducir una lista de reproducci\u00f3n de larga duraci\u00f3n de avances.",
- "MessageNoTrailersFound": "No se encontraron avances. Instalar el complemento \"Canal trailers\" para importar una biblioteca de avances de internet.",
+ "MessageNoTrailersFound": "No se encontraron avances. Instale el canal de avances para mejorar su experiencia con pel\u00edculas al agregar una biblioteca de avances desde el Internet.",
"HeaderNewUsers": "Nuevos Usuarios",
"ButtonSignUp": "Registrarse",
"ButtonForgotPassword": "\u00bfOlvidaste la contrase\u00f1a?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limitar a una sola imagen incrustada.",
"LabelEnableSingleImageInDidlLimitHelp": "Algunos dispositivos no renderisaran apropiadamente si hay m\u00faltiples im\u00e1genes incrustadas en el Didl",
"TabActivity": "Actividad",
- "TitleSync": "Sinc"
+ "TitleSync": "Sinc",
+ "OptionAllowSyncContent": "Permitir sincronizaci\u00f3n de medios con dispositivos",
+ "NameSeasonUnknown": "Temporada Desconocida",
+ "NameSeasonNumber": "Temporada {0}",
+ "LabelNewUserNameHelp": "Los nombres de usuario pueden contener letras (a-z), n\u00fameros (0-9), guiones (-), guiones bajos (_) y puntos (.)"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/fi.json b/MediaBrowser.Server.Implementations/Localization/Server/fi.json
index c2c6c8612..3386f4da5 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/fi.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/fi.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Lopeta",
"ButtonNew": "New",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "Aseta sinun media kirjasto",
"ButtonAddMediaFolder": "Lis\u00e4\u00e4 media kansio",
"LabelFolderType": "Kansion tyyppi:",
- "MediaFolderHelpPluginRequired": "* Vaatii lis\u00e4osan, kuten GameBrowser tai MB Bookshelf.",
"ReferToMediaLibraryWiki": "Viittus media kirjaston wikiin.",
"LabelCountry": "Maa:",
"LabelLanguage": "Kieli:",
@@ -365,8 +376,8 @@
"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",
+ "ButtonAddScheduledTaskTrigger": "Add Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Trigger",
"ButtonAdd": "Add",
"LabelTriggerType": "Trigger Type:",
"OptionDaily": "Daily",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 b3f6ead82..f5fd910e8 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/fr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/fr.json
@@ -15,7 +15,7 @@
"LabelFinish": "Terminer",
"LabelNext": "Suivant",
"LabelYoureDone": "Vous avez Termin\u00e9!",
- "WelcomeToMediaBrowser": "Bienvenue \u00e0 Media Browser!",
+ "WelcomeToMediaBrowser": "Bienvenue sur Media Browser!",
"TitleMediaBrowser": "Media Browser",
"ThisWizardWillGuideYou": "Cet assistant vous guidera dans le processus de configuration. Pour commencer, merci de s\u00e9lectionner votre langue pr\u00e9f\u00e9r\u00e9e.",
"TellUsAboutYourself": "Parlez-nous de vous",
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Annuler",
"ButtonNew": "Nouveau",
+ "FolderTypeMixed": "Contenus m\u00e9lang\u00e9s",
+ "FolderTypeMovies": "Films",
+ "FolderTypeMusic": "Musique",
+ "FolderTypeAdultVideos": "Vid\u00e9os Adultes",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Vid\u00e9os Musical",
+ "FolderTypeHomeVideos": "Vid\u00e9os personnelles",
+ "FolderTypeGames": "Jeux",
+ "FolderTypeBooks": "Livres",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "H\u00e9rite",
+ "LabelContentType": "Type de contenu :",
"HeaderSetupLibrary": "Configurer votre biblioth\u00e8que de m\u00e9dia",
"ButtonAddMediaFolder": "Ajouter un r\u00e9pertoire de m\u00e9dia",
"LabelFolderType": "Type de r\u00e9pertoire:",
- "MediaFolderHelpPluginRequired": "* N\u00e9cessite l'utilisation d'un plugin, par exemple : \"GameBrowser\" ou \"MB BookShelf\".",
"ReferToMediaLibraryWiki": "Se r\u00e9f\u00e9rer au wiki des biblioth\u00e8ques de m\u00e9dia",
"LabelCountry": "Pays:",
"LabelLanguage": "Langue:",
@@ -232,10 +243,10 @@
"HeaderFeatureAccess": "Acc\u00e8s aux caract\u00e9ristiques",
"OptionAllowMediaPlayback": "Autoriser la lecture du m\u00e9dia",
"OptionAllowBrowsingLiveTv": "Autoriser la TV en direct",
- "OptionAllowDeleteLibraryContent": "Allow deletion of library content",
+ "OptionAllowDeleteLibraryContent": "Autoriser la suppression de contenu dans la biblioth\u00e8que",
"OptionAllowManageLiveTv": "Autoriser la gestion des enregistrements de la TV en direct",
- "OptionAllowRemoteControlOthers": "Allow remote control of other users",
- "OptionAllowRemoteSharedDevices": "Allow remote control of shared devices",
+ "OptionAllowRemoteControlOthers": "Autoriser le contr\u00f4le \u00e0 distance d'autres utilisateurs",
+ "OptionAllowRemoteSharedDevices": "Autoriser le contr\u00f4le \u00e0 distance des disques partag\u00e9s",
"OptionAllowRemoteSharedDevicesHelp": "Les p\u00e9riph\u00e9riques Dlna sont consid\u00e9r\u00e9s comme partag\u00e9s tant qu'un utilisateur ne commence pas \u00e0 le contr\u00f4ler.",
"HeaderRemoteControl": "Contr\u00f4le \u00e0 distance",
"OptionMissingTmdbId": "ID TMDb manquant",
@@ -450,7 +461,7 @@
"CustomDlnaProfilesHelp": "Cr\u00e9er un profil personnalis\u00e9 pour cibler un nouveau p\u00e9riph\u00e9rique ou surpasser un profil syst\u00e8me.",
"SystemDlnaProfilesHelp": "Les profils syst\u00e8mes sont en lecture seule. Les modifications apport\u00e9es \u00e0 un profil syst\u00e8me seront enregistr\u00e9es sous un nouveau profil personnalis\u00e9.",
"TitleDashboard": "Tableau de bord",
- "TabHome": "Portail",
+ "TabHome": "Accueil",
"TabInfo": "Info",
"HeaderLinks": "Liens",
"HeaderSystemPaths": "Chemins d'acc\u00e8s syst\u00e8mes",
@@ -529,7 +540,7 @@
"LabelDeleteEmptyFoldersHelp": "Activer cette option pour garder le r\u00e9pertoire de t\u00e9l\u00e9chargement vide.",
"LabelDeleteLeftOverFiles": "Supprimer le reste des fichiers avec les extensions suivantes:",
"LabelDeleteLeftOverFilesHelp": "S\u00e9parer par ;. Par exemple: .nfo;.txt",
- "OptionOverwriteExistingEpisodes": "\u00c9craser les \u00e9pisodes existantes",
+ "OptionOverwriteExistingEpisodes": "\u00c9craser les \u00e9pisodes existants",
"LabelTransferMethod": "M\u00e9thode de transfert",
"OptionCopy": "Copier",
"OptionMove": "D\u00e9placer",
@@ -657,7 +668,7 @@
"NotificationOptionPluginError": "\u00c9chec de plugin",
"ButtonVolumeUp": "Volume haut",
"ButtonVolumeDown": "Volume bas",
- "ButtonMute": "Sourdine",
+ "ButtonMute": "Muet",
"HeaderLatestMedia": "Derniers m\u00e9dias",
"OptionSpecialFeatures": "Bonus",
"HeaderCollections": "Collections",
@@ -1214,7 +1225,7 @@
"TabCameraUpload": "Upload de la cam\u00e9ra",
"TabDevices": "P\u00e9riph\u00e9riques",
"HeaderCameraUploadHelp": "Uploader automatiquement les photos et les vid\u00e9os depuis vos p\u00e9riph\u00e9riques mobiles dans Media Browser.",
- "MessageNoDevicesSupportCameraUpload": "Vous n'avez actuellement aucun p\u00e9riph\u00e9riques support\u00e9 par l'upload de la cam\u00e9ra.",
+ "MessageNoDevicesSupportCameraUpload": "Vous n'avez actuellement aucun p\u00e9riph\u00e9riques supportant l'upload du flux vid\u00e9o de la cam\u00e9ra.",
"LabelCameraUploadPath": "R\u00e9pertoire de l'upload de la camera:",
"LabelCameraUploadPathHelp": "Si vous le souhaitez, vous pouvez choisir un r\u00e9pertoire d'upload personnalis\u00e9. Si vous ne mettez rien, le r\u00e9pertoire par d\u00e9faut sera utilis\u00e9. Si vous utilisez un r\u00e9pertoire personnalis\u00e9, vous devrez le rajouter \u00e0 la biblioth\u00e8que.",
"LabelCreateCameraUploadSubfolder": "Cr\u00e9er un sous-dossier pour chaque p\u00e9riph\u00e9rique",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer reel",
"OptionPlayUnwatchedTrailersOnly": "Lire seulement les bandes-annonces non lus.",
"HeaderTrailerReelHelp": "Commencer un \"trailer reel\" pour lire une longue liste de lecture de bandes-annonces.",
- "MessageNoTrailersFound": "Aucune bande-annonce trouv\u00e9e. Installer le plugin \"Trailer channel\" pour importer une biblioth\u00e8que de bandes-annonces Internet.",
+ "MessageNoTrailersFound": "Aucune bande-annonce trouv\u00e9e. Installez la cha\u00eene Bande-annonces pour am\u00e9liorer votre exp\u00e9rience, par l'ajout d'une biblioth\u00e8que de bandes-annonces disponibles sur Internet.",
"HeaderNewUsers": "Nouveaux utilisateurs",
"ButtonSignUp": "S'inscrire",
"ButtonForgotPassword": "Mot de passe oubli\u00e9 ?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limiter \u00e0 une seule image int\u00e9gr\u00e9e",
"LabelEnableSingleImageInDidlLimitHelp": "Quelques p\u00e9riph\u00e9riques ne fourniront pas un rendu correct si plusieurs images sont int\u00e9gr\u00e9es dans Didl",
"TabActivity": "Activit\u00e9",
- "TitleSync": "Sync."
+ "TitleSync": "Sync.",
+ "OptionAllowSyncContent": "Autoriser la synchronisation des media sur les p\u00e9riph\u00e9riques",
+ "NameSeasonUnknown": "Saison inconnue",
+ "NameSeasonNumber": "Saison {0}",
+ "LabelNewUserNameHelp": "Les noms d'utilisateur peuvent contenir des lettres (a-z), des chiffres (0-9), des tirets (-), des tirets bas (_), des apostrophes (') et des points (.)."
} \ 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 cecde2022..af862900b 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/he.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/he.json
@@ -37,10 +37,21 @@
"ButtonOk": "\u05d0\u05e9\u05e8",
"ButtonCancel": "\u05d1\u05d8\u05dc",
"ButtonNew": "\u05d7\u05d3\u05e9",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "\u05d4\u05d2\u05d3\u05e8 \u05d0\u05ea \u05e1\u05e4\u05e8\u05d9\u05d9\u05ea \u05d4\u05de\u05d3\u05d9\u05d4 \u05e9\u05dc\u05da",
"ButtonAddMediaFolder": "\u05d4\u05d5\u05e1\u05e3 \u05ea\u05d9\u05e7\u05d9\u05d9\u05ea \u05de\u05d3\u05d9\u05d4",
"LabelFolderType": "\u05e1\u05d5\u05d2 \u05d4\u05ea\u05d9\u05e7\u05d9\u05d9\u05d4:",
- "MediaFolderHelpPluginRequired": "* \u05de\u05e6\u05e8\u05d9\u05da \u05de\u05d4\u05de\u05e9\u05ea\u05de\u05e9 \u05ea\u05d5\u05e1\u05e3, \u05dc\u05d3\u05d5\u05d2\u05de\u05d0 GameBrowser \u05d0\u05d5 MB Bookshelf",
"ReferToMediaLibraryWiki": "\u05e4\u05e0\u05d4 \u05dc\u05de\u05d9\u05d3\u05e2 \u05d0\u05d5\u05d3\u05d5\u05ea \u05e1\u05e4\u05e8\u05d9\u05d9\u05ea \u05d4\u05de\u05d3\u05d9\u05d4.",
"LabelCountry": "\u05de\u05d3\u05d9\u05e0\u05d4:",
"LabelLanguage": "\u05e9\u05e4\u05d4:",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/hr.json b/MediaBrowser.Server.Implementations/Localization/Server/hr.json
index f7589ff00..683e91a34 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/hr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/hr.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Odustani",
"ButtonNew": "Novo",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "Postavi svoju medijsku biblioteku",
"ButtonAddMediaFolder": "Dodaj mapu sa medijem",
"LabelFolderType": "Tip mape:",
- "MediaFolderHelpPluginRequired": "* Zahtjeva kori\u0161tenje dodatka, npr. GameBrowser ili MB Bookshelf.",
"ReferToMediaLibraryWiki": "Informirajte se o medijskoj bibilioteci wiki",
"LabelCountry": "Zemlja:",
"LabelLanguage": "Jezik:",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 5daab33d8..e01e0d3f3 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/it.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/it.json
@@ -37,10 +37,21 @@
"ButtonOk": "OK",
"ButtonCancel": "Annulla",
"ButtonNew": "Nuovo",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Film",
+ "FolderTypeMusic": "Musica",
+ "FolderTypeAdultVideos": "Video per adulti",
+ "FolderTypePhotos": "Foto",
+ "FolderTypeMusicVideos": "Video musicali",
+ "FolderTypeHomeVideos": "Video personali",
+ "FolderTypeGames": "Giochi",
+ "FolderTypeBooks": "Libri",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "Configura la tua libreria",
"ButtonAddMediaFolder": "Aggiungi cartella",
"LabelFolderType": "Tipo cartella",
- "MediaFolderHelpPluginRequired": "* Richiede l'uso di un plugin, ad esempio GameBrowser o MB Bookshelf.",
"ReferToMediaLibraryWiki": "Fare riferimento alla wiki libreria multimediale.",
"LabelCountry": "Nazione:",
"LabelLanguage": "lingua:",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer b.",
"OptionPlayUnwatchedTrailersOnly": "Riproduci solo i trailer non visti",
"HeaderTrailerReelHelp": "Inizia a riprodurre una lunga playlist di trailer",
- "MessageNoTrailersFound": "Nessun Trailer trovato.Installa Il plug in dei traler per importare la libreria dei trailer da internet",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "Nuovo Utente",
"ButtonSignUp": "Iscriviti",
"ButtonForgotPassword": "Dimenticato la password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 2d9e4053d..0f26e5211 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/kk.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/kk.json
@@ -37,10 +37,21 @@
"ButtonOk": "\u0416\u0430\u0440\u0430\u0439\u0434\u044b",
"ButtonCancel": "\u0411\u043e\u043b\u0434\u044b\u0440\u043c\u0430\u0443",
"ButtonNew": "\u0416\u0430\u0441\u0430\u0443",
+ "FolderTypeMixed": "\u0410\u0440\u0430\u043b\u0430\u0441 \u043c\u0430\u0437\u043c\u04b1\u043d",
+ "FolderTypeMovies": "\u0424\u0438\u043b\u044c\u043c\u0434\u0435\u0440",
+ "FolderTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430",
+ "FolderTypeAdultVideos": "\u0415\u0440\u0435\u0441\u0435\u043a\u0442\u0456\u043a \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440",
+ "FolderTypePhotos": "\u0424\u043e\u0442\u043e\u0441\u0443\u0440\u0435\u0442\u0442\u0435\u0440",
+ "FolderTypeMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044b\u049b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440",
+ "FolderTypeHomeVideos": "\u04ae\u0439 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0456",
+ "FolderTypeGames": "\u041e\u0439\u044b\u043d\u0434\u0430\u0440",
+ "FolderTypeBooks": "\u041a\u0456\u0442\u0430\u043f\u0442\u0430\u0440",
+ "FolderTypeTvShows": "\u0422\u0414",
+ "FolderTypeInherit": "\u041c\u04b1\u0440\u0430\u0493\u0430 \u0438\u0435\u043b\u0435\u043d\u0443",
+ "LabelContentType": "\u041c\u0430\u0437\u043c\u04b1\u043d \u0442\u04af\u0440\u0456:",
"HeaderSetupLibrary": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043d\u044b \u043e\u0440\u043d\u0430\u0442\u0443 \u0436\u04d9\u043d\u0435 \u0442\u0435\u04a3\u0448\u0435\u0443",
"ButtonAddMediaFolder": "\u0422\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u0441\u044b\u043d \u04af\u0441\u0442\u0435\u0443",
"LabelFolderType": "\u049a\u0430\u043b\u0442\u0430 \u0442\u04af\u0440\u0456:",
- "MediaFolderHelpPluginRequired": "* \u041f\u043b\u0430\u0433\u0438\u043d\u0434\u0456 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u044b\u04a3\u044b\u0437, \u043c\u044b\u0441\u0430\u043b\u044b, GameBrowser, \u043d\u0435 MB Bookshelf.",
"ReferToMediaLibraryWiki": "\u0422\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430 \u0442\u0443\u0440\u0430\u043b\u044b \u0443\u0438\u043a\u0438 \u0456\u0448\u0456\u043d\u0435\u043d \u049b\u0430\u0440\u0430\u04a3\u044b\u0437.",
"LabelCountry": "\u0415\u043b:",
"LabelLanguage": "\u0422\u0456\u043b:",
@@ -683,9 +694,9 @@
"OptionProfilePhoto": "\u0424\u043e\u0442\u043e",
"LabelUserLibrary": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u0441\u044b",
"LabelUserLibraryHelp": "\u049a\u04b1\u0440\u044b\u043b\u0493\u044b\u0434\u0430 \u049b\u0430\u0439 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u0441\u044b\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443\u0456\u043d \u0442\u0430\u04a3\u0434\u0430\u04a3\u044b\u0437. \u04d8\u0434\u0435\u043f\u043a\u0456 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u043c\u04b1\u0440\u0430\u0441\u044b\u043d\u0430 \u0438\u0435\u043b\u0435\u043d\u0443 \u04af\u0448\u0456\u043d \u0431\u043e\u0441 \u049b\u0430\u043b\u0434\u044b\u0440\u044b\u04a3\u044b\u0437.",
- "OptionPlainStorageFolders": "\u0411\u0430\u0440\u043b\u044b\u049b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u0434\u044b \u0436\u0430\u0439 \u0441\u0430\u049b\u0442\u0430\u0443 \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
+ "OptionPlainStorageFolders": "\u0411\u0430\u0440\u043b\u044b\u049b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u0434\u044b \u043a\u04d9\u0434\u0456\u043c\u0433\u0456 \u0441\u0430\u049b\u0442\u0430\u0443 \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
"OptionPlainStorageFoldersHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0431\u0430\u0440\u043b\u044b\u049b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440 DIDL \u0456\u0448\u0456\u043d\u0434\u0435 \"object.container.person.musicArtist\" \u0441\u0438\u044f\u049b\u0442\u044b \u043d\u0430\u049b\u0442\u044b\u043b\u0430\u0443 \u0442\u04af\u0440\u0456\u043d\u0456\u04a3 \u043e\u0440\u043d\u044b\u043d\u0430 \"object.container.storageFolder\" \u0431\u043e\u043b\u044b\u043f \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456.",
- "OptionPlainVideoItems": "\u0411\u0430\u0440\u043b\u044b\u049b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0434\u0456 \u0436\u0430\u0439 \u0431\u0435\u0439\u043d\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440\u0456 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
+ "OptionPlainVideoItems": "\u0411\u0430\u0440\u043b\u044b\u049b \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0440\u0434\u0456 \u043a\u04d9\u0434\u0456\u043c\u0433\u0456 \u0431\u0435\u0439\u043d\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0442\u0435\u0440\u0456 \u0440\u0435\u0442\u0456\u043d\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
"OptionPlainVideoItemsHelp": "\u049a\u043e\u0441\u044b\u043b\u0493\u0430\u043d\u0434\u0430, \u0431\u0430\u0440\u043b\u044b\u049b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440 DIDL \u0456\u0448\u0456\u043d\u0434\u0435 \"object.item.videoItem.movie\" \u0441\u0438\u044f\u049b\u0442\u044b \u043d\u0430\u049b\u0442\u044b\u043b\u0430\u0443 \u0442\u04af\u0440\u0456\u043d\u0456\u04a3 \u043e\u0440\u043d\u044b\u043d\u0430 \"object.item.videoItem\" \u0431\u043e\u043b\u044b\u043f \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0435\u0434\u0456.",
"LabelSupportedMediaTypes": "\u049a\u043e\u043b\u0434\u0430\u0443\u0434\u0430\u0493\u044b \u0442\u0430\u0441\u0443\u0448\u044b\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440 \u0442\u04af\u0440\u043b\u0435\u0440\u0456:",
"TabIdentification": "\u0410\u043d\u044b\u049b\u0442\u0430\u0443",
@@ -1050,7 +1061,7 @@
"OptionOthers": "\u0411\u0430\u0441\u049b\u0430\u043b\u0430\u0440",
"HeaderDownloadPeopleMetadataForHelp": "\u049a\u043e\u0441\u044b\u043c\u0448\u0430 \u0442\u0435\u04a3\u0448\u0435\u043b\u0456\u043c\u0434\u0435\u0440\u0434\u0456 \u049b\u043e\u0441\u049b\u0430\u043d\u0434\u0430 \u044d\u043a\u0440\u0430\u043d\u0434\u0430\u0493\u044b \u0430\u049b\u043f\u0430\u0440\u0430\u0442\u0442\u044b \u043a\u04e9\u0431\u0456\u0440\u0435\u043a \u04b1\u0441\u044b\u043d\u0430\u0434\u044b, \u0431\u0456\u0440\u0430\u049b \u0442\u0430\u0441\u0443\u0448\u044b\u0445\u0430\u043d\u0430\u043d\u044b\u04a3 \u0441\u043a\u0430\u043d\u0435\u0440\u043b\u0435\u0443\u043b\u0435\u0440\u0456 \u0431\u0430\u044f\u0443\u043b\u0430\u0439\u0434\u044b.",
"ViewTypeFolders": "\u049a\u0430\u043b\u0442\u0430\u043b\u0430\u0440",
- "LabelDisplayFoldersView": "\u0416\u0430\u0439 \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04af\u0448\u0456\u043d \u049a\u0430\u043b\u0442\u0430\u043b\u0430\u0440 \u0430\u0441\u043f\u0435\u043a\u0442\u0456\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
+ "LabelDisplayFoldersView": "\u041a\u04d9\u0434\u0456\u043c\u0433\u0456 \u0442\u0430\u0441\u0443\u0448\u044b \u049b\u0430\u043b\u0442\u0430\u043b\u0430\u0440\u044b\u043d \u043a\u04e9\u0440\u0441\u0435\u0442\u0443 \u04af\u0448\u0456\u043d \u049a\u0430\u043b\u0442\u0430\u043b\u0430\u0440 \u0430\u0441\u043f\u0435\u043a\u0442\u0456\u043d \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u0443",
"ViewTypeLiveTvRecordingGroups": "\u0416\u0430\u0437\u0431\u0430\u043b\u0430\u0440",
"ViewTypeLiveTvChannels": "\u0410\u0440\u043d\u0430\u043b\u0430\u0440",
"LabelAllowLocalAccessWithoutPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0441\u0456\u0437 \u0436\u0435\u0440\u0433\u0456\u043b\u0456\u043a\u0442\u0456 \u049b\u0430\u0442\u044b\u043d\u0441\u0443 \u04af\u0448\u0456\u043d \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0434\u0456 \u0436\u0430\u043f\u0441\u044b\u0440\u0443",
"OptionPlayUnwatchedTrailersOnly": "\u0422\u0435\u043a \u049b\u0430\u043d\u0430 \u049b\u0430\u0440\u0430\u043b\u043c\u0430\u0493\u0430\u043d \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0434\u0456 \u043e\u0439\u043d\u0430\u0442\u0443",
"HeaderTrailerReelHelp": "\u04b0\u0437\u0430\u049b \u043e\u0440\u044b\u043d\u0434\u0430\u043b\u0430\u0442\u044b\u043d \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440 \u043e\u0439\u043d\u0430\u0442\u0443 \u0442\u0456\u0437\u0456\u043c\u0456\u043d \u043e\u0439\u043d\u0430\u0442\u0443 \u04af\u0448\u0456\u043d \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440\u0434\u0456 \u0436\u0430\u043f\u0441\u044b\u0440\u0443\u0434\u044b \u0431\u0430\u0441\u0442\u0430\u04a3\u044b\u0437.",
- "MessageNoTrailersFound": "\u0415\u0448\u049b\u0430\u043d\u0434\u0430\u0439 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440 \u0442\u0430\u0431\u044b\u043b\u043c\u0430\u0434\u044b. \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440 \u049b\u043e\u0440\u044b\u043d \u0438\u043c\u043f\u043e\u0440\u0442\u0442\u0430\u0443 \u04af\u0448\u0456\u043d \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043b\u0435\u0440 \u0430\u0440\u043d\u0430\u0441\u044b \u043f\u043b\u0430\u0433\u0438\u043d\u0456\u043d \u043e\u0440\u043d\u0430\u0442\u044b\u04a3\u044b\u0437.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "\u0416\u0430\u04a3\u0430 \u043f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b\u043b\u0430\u0440",
"ButtonSignUp": "\u0422\u0456\u0440\u043a\u0435\u043b\u0443",
"ButtonForgotPassword": "\u049a\u04b1\u043f\u0438\u044f \u0441\u04e9\u0437\u0434\u0456 \u04b1\u043c\u044b\u0442\u044b\u04a3\u044b\u0437 \u0431\u0430?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "\u0416\u0430\u043b\u0493\u044b\u0437 \u043a\u0456\u0440\u0456\u0441\u0442\u0456\u0440\u0456\u043b\u0433\u0435\u043d \u0441\u0443\u0440\u0435\u0442\u043a\u0435 \u0448\u0435\u043a\u0442\u0435\u0443",
"LabelEnableSingleImageInDidlLimitHelp": "\u0415\u0433\u0435\u0440 \u0431\u0456\u0440\u043d\u0435\u0448\u0435 \u0441\u0443\u0440\u0435\u0442 Didl \u0456\u0448\u0456\u043d\u0435 \u043a\u0456\u0440\u0456\u0441\u0442\u0456\u0440\u0456\u043b\u0441\u0435, \u043a\u0435\u0439\u0431\u0456\u0440 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043b\u0430\u0440\u0434\u0430 \u0442\u0438\u0456\u0441\u0442\u0456 \u0442\u04af\u0440\u0434\u0435 \u0431\u0435\u0439\u043d\u0435\u043b\u0435\u043d\u0431\u0435\u0439\u0434\u0456.",
"TabActivity": "\u04d8\u0440\u0435\u043a\u0435\u0442\u0442\u0435\u0440",
- "TitleSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443"
+ "TitleSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443",
+ "OptionAllowSyncContent": "\u041c\u0435\u0434\u0438\u0430\u0434\u0435\u0440\u0435\u043a\u0442\u0435\u0440\u0434\u0456 \u049b\u04b1\u0440\u044b\u043b\u0493\u044b\u043c\u0435\u043d \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0434\u0430\u0443\u0493\u0430 \u0440\u04b1\u049b\u0441\u0430\u0442 \u0435\u0442\u0443",
+ "NameSeasonUnknown": "\u0411\u0435\u043b\u0433\u0456\u0441\u0456\u0437 \u043c\u0430\u0443\u0441\u044b\u043c",
+ "NameSeasonNumber": "{0}-\u0441\u0435\u0437\u043e\u043d",
+ "LabelNewUserNameHelp": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b \u0430\u0442\u0442\u0430\u0440\u044b\u043d\u0434\u0430 \u04d9\u0440\u0456\u043f\u0442\u0435\u0440 (a-z), \u0441\u0430\u043d\u0434\u0430\u0440 (0-9), \u0441\u044b\u0437\u044b\u049b\u0448\u0430\u043b\u0430\u0440 (-), \u0430\u0441\u0442\u044b\u04a3\u0493\u044b \u0441\u044b\u0437\u044b\u049b\u0442\u0430\u0440 (_), \u0434\u04d9\u0439\u0435\u043a\u0448\u0435\u043b\u0435\u0440 (') \u0436\u04d9\u043d\u0435 \u043d\u04af\u043a\u0442\u0435\u043b\u0435\u0440 (.) \u0431\u043e\u043b\u0443\u044b \u043c\u04af\u043c\u043a\u0456\u043d"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/ko.json b/MediaBrowser.Server.Implementations/Localization/Server/ko.json
index 2a0bcc74f..48852cdfe 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ko.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ko.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonNew": "New",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"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:",
@@ -365,8 +376,8 @@
"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",
+ "ButtonAddScheduledTaskTrigger": "Add Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Trigger",
"ButtonAdd": "Add",
"LabelTriggerType": "Trigger Type:",
"OptionDaily": "Daily",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 adbe36a92..a64d3b584 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ms.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ms.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonNew": "New",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"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:",
@@ -365,8 +376,8 @@
"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",
+ "ButtonAddScheduledTaskTrigger": "Add Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Trigger",
"ButtonAdd": "Add",
"LabelTriggerType": "Trigger Type:",
"OptionDaily": "Daily",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 a6a1fa3c4..cd6228bc4 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/nb.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/nb.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "avbryt",
"ButtonNew": "Ny",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Filmer",
+ "FolderTypeMusic": "Musikk",
+ "FolderTypeAdultVideos": "Voksen videoer",
+ "FolderTypePhotos": "Foto",
+ "FolderTypeMusicVideos": "Musikk videoer",
+ "FolderTypeHomeVideos": "Hjemme videoer",
+ "FolderTypeGames": "Spill",
+ "FolderTypeBooks": "B\u00f8ker",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "Konfigurer media-biblioteket",
"ButtonAddMediaFolder": "Legg til media-mappe",
"LabelFolderType": "Mappe typpe",
- "MediaFolderHelpPluginRequired": "* Krever bruk av et programtillegg f.eks GameBrowser eller MB Bookshelf.",
"ReferToMediaLibraryWiki": "Se i media-bibliotek wikien",
"LabelCountry": "LAnd",
"LabelLanguage": "Spr\u00e5k:",
@@ -232,9 +243,9 @@
"HeaderFeatureAccess": "Funksjon Tilgang",
"OptionAllowMediaPlayback": "Tillatt medieavspilling",
"OptionAllowBrowsingLiveTv": "Tillat surfing av Live TV",
- "OptionAllowDeleteLibraryContent": "Allow deletion of library content",
+ "OptionAllowDeleteLibraryContent": "Tillat sletting av bibliotek innhold",
"OptionAllowManageLiveTv": "Tillat styring av Live TV opptak",
- "OptionAllowRemoteControlOthers": "Allow remote control of other users",
+ "OptionAllowRemoteControlOthers": "Tillat fjernstyring av andre brukere",
"OptionAllowRemoteSharedDevices": "Allow remote control of shared devices",
"OptionAllowRemoteSharedDevicesHelp": "Dlna devices are considered shared until a user begins controlling it.",
"HeaderRemoteControl": "Remote Control",
@@ -459,7 +470,7 @@
"LinkApiDocumentation": "Api Dokumentasjon",
"LabelFriendlyServerName": "Vennlig server navn:",
"LabelFriendlyServerNameHelp": "Dette navnet vil bli brukt for \u00e5 identifisere denne serveren. Hvis feltet er tomt, vil maskinens navn bli brukt.",
- "LabelPreferredDisplayLanguage": "Preferred display language:",
+ "LabelPreferredDisplayLanguage": "Foretrukket skjerm spr\u00e5k:",
"LabelPreferredDisplayLanguageHelp": "Oversetting av Media Browser er ett p\u00e5g\u00e5ende prosjekt og er enda ikke fullstendig ferdig.",
"LabelReadHowYouCanContribute": "Les mer om hvordan du kan bidra.",
"HeaderNewCollection": "Ny Samling",
@@ -1228,7 +1239,7 @@
"HeaderSignInWithConnect": "Sign in with Media Browser Connect",
"HeaderGuests": "Gjester",
"HeaderLocalUsers": "Lokale Brukere",
- "HeaderPendingInvitations": "Pending Invitations",
+ "HeaderPendingInvitations": "Ventende invitasjoner",
"TabParentalControl": "Foreldrekontroll",
"HeaderAccessSchedule": "Access Schedule",
"HeaderAccessScheduleHelp": "Create an access schedule to limit access to certain hours.",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "Nye Brukere",
"ButtonSignUp": "Registrering",
"ButtonForgotPassword": "Glemt passord?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 c4f65de2c..2a8eb8fe4 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/nl.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/nl.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Annuleren",
"ButtonNew": "Nieuw",
+ "FolderTypeMixed": "Gemengde inhoud",
+ "FolderTypeMovies": "Films",
+ "FolderTypeMusic": "Muziek",
+ "FolderTypeAdultVideos": "Adult video's",
+ "FolderTypePhotos": "Foto's",
+ "FolderTypeMusicVideos": "Muziek video's",
+ "FolderTypeHomeVideos": "Thuis video's",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Boeken",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "overerven",
+ "LabelContentType": "Inhoud type:",
"HeaderSetupLibrary": "Stel uw mediabibliotheek in",
"ButtonAddMediaFolder": "Mediamap toevoegen",
"LabelFolderType": "Maptype:",
- "MediaFolderHelpPluginRequired": "* Hiervoor is het gebruik van een Plug-in vereist, bijvoorbeeld GameBrowser of MB Bookshelf.",
"ReferToMediaLibraryWiki": "Raadpleeg de mediabibliotheek wiki.",
"LabelCountry": "Land:",
"LabelLanguage": "Taal:",
@@ -232,10 +243,10 @@
"HeaderFeatureAccess": "Functie toegang",
"OptionAllowMediaPlayback": "Afspelen van media toestaan",
"OptionAllowBrowsingLiveTv": "Bladeren door live tv toestaan",
- "OptionAllowDeleteLibraryContent": "Allow deletion of library content",
+ "OptionAllowDeleteLibraryContent": "Verwijderen van bibliotheek inhoud toestaan",
"OptionAllowManageLiveTv": "Beheer van live tv-opnames toestaan",
- "OptionAllowRemoteControlOthers": "Allow remote control of other users",
- "OptionAllowRemoteSharedDevices": "Allow remote control of shared devices",
+ "OptionAllowRemoteControlOthers": "Op afstand besturen van andere gebruikers toestaan",
+ "OptionAllowRemoteSharedDevices": "Op afstand besturen van gedeelde apparaten toestaan",
"OptionAllowRemoteSharedDevicesHelp": "Dlna apparaten worden als gedeeld apparaat gezien totdat een gebruiker deze gaat gebruiken.",
"HeaderRemoteControl": "Gebruik op afstand",
"OptionMissingTmdbId": "TMDB Id ontbreekt",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer reel",
"OptionPlayUnwatchedTrailersOnly": "Speel alleen ongeziene trailers",
"HeaderTrailerReelHelp": "Start trailer reel om een afspeellijst met trailers af te spelen.",
- "MessageNoTrailersFound": "Geen trailers gevonden. Installeer het trailer kanaal om internet trailers te importeren.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "Nieuwe gebruikers",
"ButtonSignUp": "Aanmelden",
"ButtonForgotPassword": "Wachtwoord vergeten?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Beperk tot \u00e9\u00e9n enkele ingesloten afbeelding",
"LabelEnableSingleImageInDidlLimitHelp": "Sommige apparaten zullen niet goed weergeven als er meerdere afbeeldingen ingesloten zijn in Didl.",
"TabActivity": "Activiteit",
- "TitleSync": "Synchroniseer"
+ "TitleSync": "Synchroniseer",
+ "OptionAllowSyncContent": "Synchroniseren van media naar apparaten toestaan",
+ "NameSeasonUnknown": "Seizoen Onbekend",
+ "NameSeasonNumber": "Seizoen {0}",
+ "LabelNewUserNameHelp": "Gebruikersnamen kunnen letters (az), cijfers (0-9), streepjes, underscores (_), apostrofs (') en punten (.) bevatten\n"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/pl.json b/MediaBrowser.Server.Implementations/Localization/Server/pl.json
index a0d70f6c6..1abcb52ff 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/pl.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/pl.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Anuluj",
"ButtonNew": "New",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "Ustaw swoj\u0105 bibliotek\u0119",
"ButtonAddMediaFolder": "Dodaj folder",
"LabelFolderType": "Typ folderu:",
- "MediaFolderHelpPluginRequired": "* Wymaga u\u017cycia wtyczki takiej jak GameBrowser lub MB Bookshelf.",
"ReferToMediaLibraryWiki": "Odnie\u015b si\u0119 do wiki biblioteki.",
"LabelCountry": "Kraj:",
"LabelLanguage": "J\u0119zyk:",
@@ -365,8 +376,8 @@
"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",
+ "ButtonAddScheduledTaskTrigger": "Add Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Trigger",
"ButtonAdd": "Add",
"LabelTriggerType": "Trigger Type:",
"OptionDaily": "Daily",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 134059faf..4eb9be8c2 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_BR.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Cancelar",
"ButtonNew": "Novo",
+ "FolderTypeMixed": "Conte\u00fado misto",
+ "FolderTypeMovies": "Filmes",
+ "FolderTypeMusic": "M\u00fasica",
+ "FolderTypeAdultVideos": "V\u00eddeos adultos",
+ "FolderTypePhotos": "Fotos",
+ "FolderTypeMusicVideos": "V\u00eddeos musicais",
+ "FolderTypeHomeVideos": "V\u00eddeos caseiros",
+ "FolderTypeGames": "Jogos",
+ "FolderTypeBooks": "Livros",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Herdar",
+ "LabelContentType": "Tipo de conte\u00fado:",
"HeaderSetupLibrary": "Configurar sua biblioteca de m\u00eddias",
"ButtonAddMediaFolder": "Adicionar pasta de m\u00eddias",
"LabelFolderType": "Tipo de pasta:",
- "MediaFolderHelpPluginRequired": "* Requer o uso de um plugin, ex. GameBrowser ou MB Bookshelf.",
"ReferToMediaLibraryWiki": "Consultar wiki da biblioteca de m\u00eddias",
"LabelCountry": "Pa\u00eds:",
"LabelLanguage": "Idioma:",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Carrossel de Trailers",
"OptionPlayUnwatchedTrailersOnly": "Reproduzir apenas trailers n\u00e3o assistidos",
"HeaderTrailerReelHelp": "Inicie um carrossel de trailers para reproduzir uma longa lista de reprodu\u00e7\u00e3o de trailers.",
- "MessageNoTrailersFound": "Nenhum trailer encontrado. Instale o plugin de canal para importar uma biblioteca de trailers da internet.",
+ "MessageNoTrailersFound": "Nenhum trailer encontrado. Instale o canal Trailer para melhorar sua experi\u00eancia com filmes, adicionando uma biblioteca de trailers da internet.",
"HeaderNewUsers": "Novos Usu\u00e1rios",
"ButtonSignUp": "Entrar",
"ButtonForgotPassword": "Esqueceu a senha?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limitar a uma imagem incorporada",
"LabelEnableSingleImageInDidlLimitHelp": "Alguns dispositivos n\u00e3o interpretar\u00e3o apropriadamente se m\u00faltiplas imagens estiverem incorporadas dentro do Didl.",
"TabActivity": "Atividade",
- "TitleSync": "Sinc"
+ "TitleSync": "Sinc",
+ "OptionAllowSyncContent": "Permitir sincroniza\u00e7\u00e3o de m\u00eddia com os dispositivos",
+ "NameSeasonUnknown": "Temporada Desconhecida",
+ "NameSeasonNumber": "Temporada {0}",
+ "LabelNewUserNameHelp": "Nomes de usu\u00e1rios podem conter letras (a-z), n\u00fameros (0-9), tra\u00e7os (-), sublinhados (_), ap\u00f3strofes (') e pontos (.)"
} \ 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 792a9eb0f..3ce498c35 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/pt_PT.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Cancelar",
"ButtonNew": "Novo",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "Configurar biblioteca",
"ButtonAddMediaFolder": "Adicionar pasta de media",
"LabelFolderType": "Tipo de pasta",
- "MediaFolderHelpPluginRequired": "* Requer o uso de uma extens\u00e3o, e.g. GameBrowser ou MB Bookshelf",
"ReferToMediaLibraryWiki": "Consulte a wiki",
"LabelCountry": "Pa\u00eds:",
"LabelLanguage": "Idioma:",
@@ -232,9 +243,9 @@
"HeaderFeatureAccess": "Acesso a Caracter\u00edsticas",
"OptionAllowMediaPlayback": "Permitir reprodu\u00e7\u00e3o de multim\u00e9dia",
"OptionAllowBrowsingLiveTv": "Permitir navega\u00e7\u00e3o da tv ao vivo",
- "OptionAllowDeleteLibraryContent": "Allow deletion of library content",
+ "OptionAllowDeleteLibraryContent": "Permitir que conte\u00fado da biblioteca seja apagado",
"OptionAllowManageLiveTv": "Permitir gest\u00e3o das grava\u00e7\u00f5es da tv ao vivo",
- "OptionAllowRemoteControlOthers": "Allow remote control of other users",
+ "OptionAllowRemoteControlOthers": "Permitir controlo remoto de outros utilizadores",
"OptionAllowRemoteSharedDevices": "Allow remote control of shared devices",
"OptionAllowRemoteSharedDevicesHelp": "Dlna devices are considered shared until a user begins controlling it.",
"HeaderRemoteControl": "Remote Control",
@@ -552,10 +563,10 @@
"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:",
"LabelDownMixAudioScaleHelp": "Aumentar o \u00e1udio ao fazer downmix. Defina como 1 para preservar o volume original.",
- "ButtonLinkKeys": "Transfer Key",
+ "ButtonLinkKeys": "Transferir Chave",
"LabelOldSupporterKey": "Chave de apoiante antiga",
"LabelNewSupporterKey": "Chave de apoiante nova",
- "HeaderMultipleKeyLinking": "Transfer to New Key",
+ "HeaderMultipleKeyLinking": "Transferir para Nova Chave",
"MultipleKeyLinkingHelp": "If you received a new supporter key, use this form to transfer the old key's registrations to your new one.",
"LabelCurrentEmailAddress": "Endere\u00e7o de email atual",
"LabelCurrentEmailAddressHelp": "O endere\u00e7o de email atual para o qual a sua nova chave foi enviada.",
@@ -677,9 +688,9 @@
"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",
+ "OptionProfileVideo": "V\u00eddeo",
+ "OptionProfileAudio": "\u00c1udio",
+ "OptionProfileVideoAudio": "\u00c1udio do V\u00eddeo",
"OptionProfilePhoto": "Photo",
"LabelUserLibrary": "User library:",
"LabelUserLibraryHelp": "Select which user library to display to the device. Leave empty to inherit the default setting.",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 e35d8a097..3c0df4acd 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/ru.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/ru.json
@@ -37,10 +37,21 @@
"ButtonOk": "\u041e\u041a",
"ButtonCancel": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c",
"ButtonNew": "\u0421\u043e\u0437\u0434\u0430\u0442\u044c",
+ "FolderTypeMixed": "\u0420\u0430\u0437\u043d\u043e\u0442\u0438\u043f\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435",
+ "FolderTypeMovies": "\u0424\u0438\u043b\u044c\u043c\u044b",
+ "FolderTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430",
+ "FolderTypeAdultVideos": "\u0412\u0437\u0440\u043e\u0441\u043b\u044b\u0435 \u0432\u0438\u0434\u0435\u043e",
+ "FolderTypePhotos": "\u0424\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438",
+ "FolderTypeMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e",
+ "FolderTypeHomeVideos": "\u0414\u043e\u043c\u0430\u0448\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u043e",
+ "FolderTypeGames": "\u0418\u0433\u0440\u044b",
+ "FolderTypeBooks": "\u041a\u043d\u0438\u0433\u0438",
+ "FolderTypeTvShows": "\u0422\u0412",
+ "FolderTypeInherit": "\u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c\u044b\u0439",
+ "LabelContentType": "\u0422\u0438\u043f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f:",
"HeaderSetupLibrary": "\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438",
"ButtonAddMediaFolder": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0434\u0438\u0430\u043f\u0430\u043f\u043a\u0443",
"LabelFolderType": "\u0422\u0438\u043f \u043f\u0430\u043f\u043a\u0438:",
- "MediaFolderHelpPluginRequired": "* \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d, \u043d\u043f\u0440., GameBrowser \u0438\u043b\u0438 MB Bookshelf.",
"ReferToMediaLibraryWiki": "\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435\u0441\u044c \u043a \u0432\u0438\u043a\u0438 \u043f\u043e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435.",
"LabelCountry": "\u0421\u0442\u0440\u0430\u043d\u0430:",
"LabelLanguage": "\u042f\u0437\u044b\u043a:",
@@ -225,17 +236,17 @@
"VisitMediaBrowserWebsiteLong": "\u041f\u043e\u0441\u0435\u0442\u0438\u0442\u0435 \u0441\u0430\u0439\u0442 Media Browser, \u0447\u0442\u043e\u0431\u044b \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c\u0438 \u043d\u043e\u0432\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043e\u0441\u0432\u0435\u0434\u043e\u043c\u043b\u0451\u043d\u043d\u043e\u0441\u0442\u044c \u043f\u043e \u0431\u043b\u043e\u0433\u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.",
"OptionHideUser": "\u0421\u043a\u0440\u044b\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441 \u044d\u043a\u0440\u0430\u043d\u043e\u0432 \u0432\u0445\u043e\u0434\u0430",
"OptionDisableUser": "\u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f",
- "OptionDisableUserHelp": "\u041f\u0440\u0438 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438, \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u043b\u044e\u0431\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0437\u043a\u043e \u043e\u0431\u043e\u0440\u0432\u0430\u043d\u044b.",
+ "OptionDisableUserHelp": "\u041f\u0440\u0438 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438, \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442 \u043b\u044e\u0431\u044b\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043e\u0442 \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0437\u043a\u043e \u043e\u0431\u043e\u0440\u0432\u0430\u043d\u044b.",
"HeaderAdvancedControl": "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435",
"LabelName": "\u0418\u043c\u044f (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435):",
- "OptionAllowUserToManageServer": "\u042d\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c",
+ "OptionAllowUserToManageServer": "\u042d\u0442\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0440\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c",
"HeaderFeatureAccess": "\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438",
"OptionAllowMediaPlayback": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445",
"OptionAllowBrowsingLiveTv": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440 \u0422\u0412-\u044d\u0444\u0438\u0440\u0430",
- "OptionAllowDeleteLibraryContent": "\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438",
+ "OptionAllowDeleteLibraryContent": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438",
"OptionAllowManageLiveTv": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u044f\u043c\u0438 \u0441 \u0422\u0412-\u044d\u0444\u0438\u0440\u0430",
- "OptionAllowRemoteControlOthers": "\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438",
- "OptionAllowRemoteSharedDevices": "\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u0449\u0438\u043c\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438",
+ "OptionAllowRemoteControlOthers": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438",
+ "OptionAllowRemoteSharedDevices": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0431\u0449\u0438\u043c\u0438 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438",
"OptionAllowRemoteSharedDevicesHelp": "DLNA-\u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0441\u0447\u0438\u0442\u0430\u044e\u0442\u0441\u044f \u043e\u0431\u0449\u0438\u043c\u0438, \u043f\u043e\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043c\u0438.",
"HeaderRemoteControl": "\u0423\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435",
"OptionMissingTmdbId": "\u041d\u0435\u0442 TMDb Id",
@@ -258,7 +269,7 @@
"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\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u0430\u044f (\u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e)",
- "LabelAllowServerAutoRestart": "\u0421\u0435\u0440\u0432\u0435\u0440\u0443 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0439",
+ "LabelAllowServerAutoRestart": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \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\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043f\u0435\u0440\u0438\u043e\u0434\u044b \u043f\u0440\u043e\u0441\u0442\u043e\u044f, \u043a\u043e\u0433\u0434\u0430 \u043d\u0438\u043a\u0430\u043a\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u044b.",
"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 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b",
@@ -435,7 +446,7 @@
"OptionMaxQualityTranscoding": "\u041a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e",
"OptionEnableDebugTranscodingLogging": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438 \u0432 \u0416\u0443\u0440\u043d\u0430\u043b\u0435",
"OptionEnableDebugTranscodingLoggingHelp": "\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0444\u0430\u0439\u043b\u044b \u0416\u0443\u0440\u043d\u0430\u043b\u0430 \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043e\u0431\u044a\u0451\u043c\u0430, \u0430 \u044d\u0442\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u0438\u043b\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0443\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0435\u043f\u043e\u043b\u0430\u0434\u043e\u043a.",
- "OptionUpscaling": "\u041a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0437\u0430\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u044b\u0441\u043e\u043a\u043e\u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u0438\u0434\u0435\u043e",
+ "OptionUpscaling": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u043c \u0437\u0430\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u0438\u0434\u0435\u043e",
"OptionUpscalingHelp": "\u0412 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445, \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044e \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u0438\u0434\u0435\u043e, \u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u0441\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430.",
"EditCollectionItemsHelp": "\u0414\u043e\u0431\u0430\u0432\u044c\u0442\u0435 \u0438\u043b\u0438 \u0438\u0437\u044b\u043c\u0438\u0442\u0435 \u043b\u044e\u0431\u044b\u0435 \u0444\u0438\u043b\u044c\u043c\u044b, \u0441\u0435\u0440\u0438\u0430\u043b\u044b, \u0430\u043b\u044c\u0431\u043e\u043c\u044b, \u043a\u043d\u0438\u0433\u0438 \u0438\u043b\u0438 \u0438\u0433\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0434\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438.",
"HeaderAddTitles": "\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0439",
@@ -690,7 +701,7 @@
"LabelSupportedMediaTypes": "\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0435 \u0442\u0438\u043f\u044b \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445:",
"TabIdentification": "\u0420\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u0438\u0435",
"HeaderIdentification": "\u0420\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u0438\u0435",
- "TabDirectPlay": "\u041f\u0440\u044f\u043c\u043e\u0435 \u0432\u043e\u0441\u043f\u0440-\u0438\u0435",
+ "TabDirectPlay": "\u041f\u0440\u044f\u043c\u043e\u0435 \u0432\u043e\u0441\u043f\u0440.",
"TabContainers": "\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b",
"TabCodecs": "\u041a\u043e\u0434\u0435\u043a\u0438",
"TabResponses": "\u041e\u0442\u043a\u043b\u0438\u043a\u0438",
@@ -944,7 +955,7 @@
"TabSort": "\u041f\u043e\u0440\u044f\u0434\u043e\u043a",
"TabFilter": "\u0424\u0438\u043b\u044c\u0442\u0440\u044b",
"ButtonView": "\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c",
- "LabelPageSize": "\u041c\u0430\u043a\u0441. \u0447\u0438\u0441\u043b\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432:",
+ "LabelPageSize": "\u041f\u0440\u0435\u0434\u0435\u043b \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432:",
"LabelPath": "\u041f\u0443\u0442\u044c:",
"LabelView": "\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435:",
"TabUsers": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438",
@@ -1021,9 +1032,9 @@
"ItemAddedWithName": "{0} (\u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0432 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0443)",
"ItemRemovedWithName": "{0} (\u0438\u0437\u044a\u044f\u0442\u043e \u0438\u0437 \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0438)",
"DeviceOnlineWithName": "{0} - \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e",
- "UserOnlineFromDevice": "{0} - \u043f\u043e\u0434\u043a\u043b-\u0438\u0435 \u0441 {1} \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e",
+ "UserOnlineFromDevice": "{0} - \u043f\u043e\u0434\u043a\u043b. \u0441 {1} \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e",
"DeviceOfflineWithName": "{0} - \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0440\u0432\u0430\u043d\u043e",
- "UserOfflineFromDevice": "{0} - \u043f\u043e\u0434\u043a\u043b-\u0438\u0435 \u0441 {1} \u043f\u0440\u0435\u0440\u0432\u0430\u043d\u043e",
+ "UserOfflineFromDevice": "{0} - \u043f\u043e\u0434\u043a\u043b. \u0441 {1} \u043f\u0440\u0435\u0440\u0432\u0430\u043d\u043e",
"SubtitlesDownloadedForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u0434\u043b\u044f {0} \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b\u0438\u0441\u044c",
"SubtitleDownloadFailureForItem": "\u0421\u0443\u0431\u0442\u0438\u0442\u0440\u044b \u043a {0} \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c",
"LabelRunningTimeValue": "\u0412\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f: {0}",
@@ -1037,9 +1048,9 @@
"MessageApplicationUpdated": "Media Browser Server \u0431\u044b\u043b \u043e\u0431\u043d\u043e\u0432\u043b\u0451\u043d",
"AuthenticationSucceededWithUserName": "{0} - \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0443\u0441\u043f\u0435\u0448\u043d\u0430",
"FailedLoginAttemptWithUserName": "{0} - \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u043d\u0435\u0443\u0434\u0430\u0447\u043d\u0430",
- "UserStartedPlayingItemWithValues": "{0} - \u0432\u043e\u0441\u043f\u0440-\u0438\u0435 \u00ab{1}\u00bb \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e",
- "UserStoppedPlayingItemWithValues": "{0} - \u0432\u043e\u0441\u043f\u0440-\u0438\u0435 \u00ab{1}\u00bb \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e",
- "AppDeviceValues": "\u041f\u0440\u0438\u043b-\u0438\u0435: {0}, \u0423\u0441\u0442\u0440-\u0432\u043e: {1}",
+ "UserStartedPlayingItemWithValues": "{0} - \u0432\u043e\u0441\u043f\u0440. \u00ab{1}\u00bb \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e",
+ "UserStoppedPlayingItemWithValues": "{0} - \u0432\u043e\u0441\u043f\u0440. \u00ab{1}\u00bb \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e",
+ "AppDeviceValues": "\u041f\u0440\u0438\u043b.: {0}, \u0423\u0441\u0442\u0440.: {1}",
"ProviderValue": "\u041f\u043e\u0441\u0442\u0430\u0432\u0449\u0438\u043a: {0}",
"LabelChannelDownloadSizeLimit": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e, \u0413\u0411:",
"LabelChannelDownloadSizeLimitHelpText": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u044c\u0442\u0435 \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u0430\u043f\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0445 \u043a\u0430\u043d\u0430\u043b\u043e\u0432.",
@@ -1191,8 +1202,8 @@
"LabelLimitIntrosToUnwatchedContent": "\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043a \u043d\u0435\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u043e\u043c\u0443 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044e",
"LabelEnableIntroParentalControl": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c",
"LabelEnableIntroParentalControlHelp": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0441 \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u043d\u043e\u0439 \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0435\u0439 \u0440\u0430\u0432\u043d\u043e\u0439 \u0438\u043b\u0438 \u043c\u0435\u043d\u044c\u0448\u0435\u0439, \u0447\u0435\u043c \u043f\u0440\u043e\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u0435\u043c\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435.",
- "LabelTheseFeaturesRequireSupporterHelpAndTrailers": "\u0414\u0430\u043d\u043d\u044b\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u043e \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0430 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.",
- "OptionTrailersFromMyMoviesHelp": "\u041f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.",
+ "LabelTheseFeaturesRequireSupporterHelpAndTrailers": "\u0414\u0430\u043d\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0447\u043b\u0435\u043d\u0441\u0442\u0432\u0430 \u0441\u043f\u043e\u043d\u0441\u043e\u0440\u0430 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u043a\u0430\u043d\u0430\u043b\u0430 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.",
+ "OptionTrailersFromMyMoviesHelp": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.",
"LabelCustomIntrosPath": "\u041f\u0443\u0442\u044c \u043a \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u0437\u0430\u0441\u0442\u0430\u0432\u043a\u0430\u043c:",
"LabelCustomIntrosPathHelp": "\u041f\u0430\u043f\u043a\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0430\u044f \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u044b. \u0412\u0438\u0434\u0435\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043e \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.",
"ValueSpecialEpisodeName": "\u0421\u043f\u0435\u0446\u044d\u043f\u0438\u0437\u043e\u0434 - {0}",
@@ -1200,7 +1211,7 @@
"OptionUpcomingDvdMovies": "\u041e\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u043a \u043d\u043e\u0432\u044b\u043c \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0444\u0438\u043b\u044c\u043c\u0430\u043c \u043d\u0430 DVD \u0438 BluRay",
"OptionUpcomingStreamingMovies": "\u041e\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u043a \u043d\u043e\u0432\u044b\u043c \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c \u0444\u0438\u043b\u044c\u043c\u0430\u043c \u043d\u0430 Netflix",
"LabelDisplayTrailersWithinMovieSuggestions": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c\u044b\u0445 \u0444\u0438\u043b\u044c\u043c\u043e\u0432",
- "LabelDisplayTrailersWithinMovieSuggestionsHelp": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043a\u0430\u043d\u0430\u043b\u0430 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432",
+ "LabelDisplayTrailersWithinMovieSuggestionsHelp": "\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043a\u0430\u043d\u0430\u043b\u0430 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.",
"CinemaModeConfigurationHelp2": "\u041e\u0431\u043e\u0441\u043e\u0431\u043b\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0431\u0443\u0434\u0443\u0442 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0440\u0435\u0436\u0438\u043c \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u0441\u0432\u043e\u0438\u0445 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a.",
"LabelEnableCinemaMode": "\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0440\u0435\u0436\u0438\u043c \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430",
"HeaderCinemaMode": "\u0420\u0435\u0436\u0438\u043c \u043a\u0438\u043d\u043e\u0442\u0435\u0430\u0442\u0440\u0430",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "\u0421\u043a\u043b\u0435\u0439\u043a\u0430 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432",
"OptionPlayUnwatchedTrailersOnly": "\u0412\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u044b\u0435 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u044b",
"HeaderTrailerReelHelp": "\u0417\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u0441\u043a\u043b\u0435\u0439\u043a\u0443 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0434\u043e\u043b\u0433\u043e\u0438\u0433\u0440\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.",
- "MessageNoTrailersFound": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043e. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u043b\u0430\u0433\u0438\u043d \u043a\u0430\u043d\u0430\u043b\u0430 \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432 \u0434\u043b\u044f \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0441\u043e\u0431\u0440\u0430\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.",
+ "MessageNoTrailersFound": "\u0422\u0440\u0435\u0439\u043b\u0435\u0440\u044b \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u044b. \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043a\u0430\u043d\u0430\u043b \u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0443\u0441\u0438\u043b\u0438\u0442\u044c \u0432\u0430\u0448\u0435 \u0432\u043f\u0435\u0447\u0430\u0442\u043b\u0435\u043d\u0438\u0435 \u043e\u0442 \u0444\u0438\u043b\u044c\u043c\u0430, \u043f\u0443\u0442\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0431\u0440\u0430\u043d\u0438\u044f \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442-\u0442\u0440\u0435\u0439\u043b\u0435\u0440\u043e\u0432.",
"HeaderNewUsers": "\u041d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438",
"ButtonSignUp": "\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f",
"ButtonForgotPassword": "\u0417\u0430\u0431\u044b\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c?",
@@ -1277,7 +1288,11 @@
"LabelBlockItemsWithTags": "\u0411\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0441 \u0442\u0435\u0433\u0430\u043c\u0438:",
"LabelTag": "\u0422\u0435\u0433:",
"LabelEnableSingleImageInDidlLimit": "\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u0434\u043e \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u043d\u0435\u0434\u0440\u0451\u043d\u043d\u043e\u0433\u043e \u0440\u0438\u0441\u0443\u043d\u043a\u0430",
- "LabelEnableSingleImageInDidlLimitHelp": "\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043d\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e, \u0435\u0441\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0432\u043d\u0435\u0434\u0440\u044f\u044e\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 Didl.",
+ "LabelEnableSingleImageInDidlLimitHelp": "\u041d\u0430 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445 \u043d\u0435 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e, \u0435\u0441\u043b\u0438 \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u044b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0438\u0441\u0443\u043d\u043a\u043e\u0432 \u0432\u043d\u0443\u0442\u0440\u0438 Didl.",
"TabActivity": "\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f",
- "TitleSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f"
+ "TitleSync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f",
+ "OptionAllowSyncContent": "\u0420\u0430\u0437\u0440\u0435\u0448\u0438\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438",
+ "NameSeasonUnknown": "\u0421\u0435\u0437\u043e\u043d \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043d",
+ "NameSeasonNumber": "\u0421\u0435\u0437\u043e\u043d {0}",
+ "LabelNewUserNameHelp": "\u0418\u043c\u0435\u043d\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043c\u043e\u0433\u0443\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0431\u0443\u043a\u0432\u044b (a-z), \u0446\u0438\u0444\u0440\u044b (0-9), \u0434\u0435\u0444\u0438\u0441\u044b (-), \u043f\u043e\u0434\u0447\u0451\u0440\u043a\u0438\u0432\u0430\u043d\u0438\u044f (_), \u0430\u043f\u043e\u0441\u0442\u0440\u043e\u0444\u044b (') \u0438 \u0442\u043e\u0447\u043a\u0438 (.)"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json
index 09cd286b4..7f0809897 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/server.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonNew": "New",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"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:",
@@ -366,8 +377,8 @@
"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",
+ "ButtonAddScheduledTaskTrigger": "Add Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Trigger",
"ButtonAdd": "Add",
"LabelTriggerType": "Trigger Type:",
"OptionDaily": "Daily",
@@ -1262,7 +1273,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1295,5 +1306,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
}
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/sv.json b/MediaBrowser.Server.Implementations/Localization/Server/sv.json
index b3831a097..9d3ad70c2 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/sv.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/sv.json
@@ -37,10 +37,21 @@
"ButtonOk": "OK",
"ButtonCancel": "Avbryt",
"ButtonNew": "Nytillkommet",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Filmer",
+ "FolderTypeMusic": "Musik",
+ "FolderTypeAdultVideos": "Inneh\u00e5ll f\u00f6r vuxna",
+ "FolderTypePhotos": "Foton",
+ "FolderTypeMusicVideos": "Musikvideor",
+ "FolderTypeHomeVideos": "Hemvideor",
+ "FolderTypeGames": "Spel",
+ "FolderTypeBooks": "B\u00f6cker",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "Konfigurera mediabiblioteket",
"ButtonAddMediaFolder": "Skapa mediamapp",
"LabelFolderType": "Typ av mapp:",
- "MediaFolderHelpPluginRequired": "* Kr\u00e4ver att ett till\u00e4gg, t ex GameBrowser eller MB Bookshelf, \u00e4r installerat.",
"ReferToMediaLibraryWiki": "Se avsnittet om mediabibliotek i v\u00e5r Wiki.",
"LabelCountry": "Land:",
"LabelLanguage": "Spr\u00e5k:",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/tr.json b/MediaBrowser.Server.Implementations/Localization/Server/tr.json
index 51644f389..baa91c959 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/tr.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/tr.json
@@ -37,10 +37,21 @@
"ButtonOk": "Tamam",
"ButtonCancel": "\u0130ptal",
"ButtonNew": "Yeni",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "Medya k\u00fct\u00fcphaneni kur",
"ButtonAddMediaFolder": "Yeni Media Klas\u00f6r\u00fc",
"LabelFolderType": "Klas\u00f6r T\u00fcr\u00fc:",
- "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
"ReferToMediaLibraryWiki": "Refer to the media library wiki.",
"LabelCountry": "\u00dclke",
"LabelLanguage": "Dil",
@@ -365,8 +376,8 @@
"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",
+ "ButtonAddScheduledTaskTrigger": "Add Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Trigger",
"ButtonAdd": "Ekle",
"LabelTriggerType": "Trigger Type:",
"OptionDaily": "G\u00fcnl\u00fck",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/vi.json b/MediaBrowser.Server.Implementations/Localization/Server/vi.json
index 93a725d19..0636e0a81 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/vi.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/vi.json
@@ -37,10 +37,21 @@
"ButtonOk": "Ok",
"ButtonCancel": "Tho\u00e1t",
"ButtonNew": "M\u1edbi",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "C\u00e0i \u0111\u1eb7t th\u01b0 vi\u1ec7n media c\u1ee7a b\u1ea1n",
"ButtonAddMediaFolder": "Th\u00eam m\u1ed9t th\u01b0 m\u1ee5c media",
"LabelFolderType": "Lo\u1ea1i th\u01b0 m\u1ee5c",
- "MediaFolderHelpPluginRequired": "* Requires the use of a plugin, e.g. GameBrowser or MB Bookshelf.",
"ReferToMediaLibraryWiki": "Tham kh\u1ea3o th\u01b0 vi\u1ec7n wiki media.",
"LabelCountry": "Qu\u1ed1c gia:",
"LabelLanguage": "Ng\u00f4n ng\u1eef",
@@ -365,8 +376,8 @@
"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",
+ "ButtonAddScheduledTaskTrigger": "Add Trigger",
+ "HeaderAddScheduledTaskTrigger": "Add Trigger",
"ButtonAdd": "Th\u00eam",
"LabelTriggerType": "Trigger Type:",
"OptionDaily": "Daily",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json b/MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json
index bfc16efb8..bc76e6575 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/zh_CN.json
@@ -1,5 +1,5 @@
{
- "LabelExit": "\u79bb\u5f00",
+ "LabelExit": "\u9000\u51fa",
"LabelVisitCommunity": "\u8bbf\u95ee\u793e\u533a",
"LabelGithub": "Github",
"LabelSwagger": "Swagger",
@@ -7,40 +7,51 @@
"LabelApiDocumentation": "Api Documentation",
"LabelDeveloperResources": "Developer Resources",
"LabelBrowseLibrary": "\u6d4f\u89c8\u5a92\u4f53\u5e93",
- "LabelConfigureMediaBrowser": "\u914d\u7f6eMedia Browser",
+ "LabelConfigureMediaBrowser": "\u914d\u7f6e Media Browser",
"LabelOpenLibraryViewer": "\u6253\u5f00\u5a92\u4f53\u5e93\u6d4f\u89c8\u5668",
"LabelRestartServer": "\u91cd\u542f\u670d\u52a1\u5668",
"LabelShowLogWindow": "\u663e\u793a\u65e5\u5fd7\u7a97\u53e3",
"LabelPrevious": "\u4e0a\u4e00\u4e2a",
- "LabelFinish": "\u7ed3\u675f",
+ "LabelFinish": "\u5b8c\u6210",
"LabelNext": "\u4e0b\u4e00\u4e2a",
"LabelYoureDone": "\u5b8c\u6210\uff01",
- "WelcomeToMediaBrowser": "\u6b22\u8fce\u8fdb\u5165Media Browser\uff01",
+ "WelcomeToMediaBrowser": "\u6b22\u8fce\u4f7f\u7528 Media Browser\uff01",
"TitleMediaBrowser": "Media Browser",
- "ThisWizardWillGuideYou": "\u8be5\u5411\u5bfc\u5c06\u6307\u5bfc\u4f60\u5b8c\u6210\u5b89\u88c5\u8fc7\u7a0b\u3002\u9996\u5148\uff0c\u8bf7\u9009\u62e9\u4f60\u7684\u8bed\u8a00\u3002",
+ "ThisWizardWillGuideYou": "\u8be5\u5411\u5bfc\u5c06\u6307\u5bfc\u4f60\u5b8c\u6210\u5b89\u88c5\u8fc7\u7a0b\u3002\u9996\u5148\uff0c\u8bf7\u9009\u62e9\u4f60\u7684\u9996\u9009\u8bed\u8a00\u3002",
"TellUsAboutYourself": "\u8bf7\u4ecb\u7ecd\u4e00\u4e0b\u4f60\u81ea\u5df1",
"LabelYourFirstName": "\u4f60\u7684\u540d\u5b57\uff1a",
"MoreUsersCanBeAddedLater": "\u7a0d\u540e\u5728\u63a7\u5236\u53f0\u4e2d\u53ef\u4ee5\u6dfb\u52a0\u66f4\u591a\u7528\u6237\u3002",
- "UserProfilesIntro": "Media Browser\u652f\u6301\u591a\u4e2a\u7528\u6237\u8bbe\u5b9a\uff0c\u80fd\u4f7f\u6bcf\u4e2a\u7528\u6237\u90fd\u62e5\u6709\u81ea\u5df1\u4e13\u5c5e\u7684\u663e\u793a\u8bbe\u7f6e\uff0c\u64ad\u653e\u72b6\u6001\u548c\u5bb6\u957f\u63a7\u5236\u8bbe\u7f6e\u3002",
+ "UserProfilesIntro": "Media Browser \u652f\u6301\u591a\u4e2a\u7528\u6237\u8bbe\u5b9a\uff0c\u80fd\u4f7f\u6bcf\u4e2a\u7528\u6237\u90fd\u62e5\u6709\u81ea\u5df1\u4e13\u5c5e\u7684\u663e\u793a\u8bbe\u7f6e\uff0c\u64ad\u653e\u72b6\u6001\u548c\u5bb6\u957f\u63a7\u5236\u8bbe\u7f6e\u3002",
"LabelWindowsService": "Windows \u670d\u52a1",
"AWindowsServiceHasBeenInstalled": "Windows \u670d\u52a1\u5b89\u88c5\u5b8c\u6210",
- "WindowsServiceIntro1": "Media Browser\u670d\u52a1\u5668\u4f5c\u4e3a\u684c\u9762\u5e94\u7528\u7a0b\u5e8f\u901a\u5e38\u4ee5\u4e00\u4e2a\u6258\u76d8\u56fe\u6807\u8fd0\u884c\uff0c\u4f46\u5982\u679c\u4f60\u559c\u6b22\u5b83\u4f5c\u4e3a\u540e\u53f0\u670d\u52a1\u8fd0\u884c\uff0c\u5b83\u53ef\u4ee5\u4eceWindows\u63a7\u5236\u9762\u677f\u542f\u52a8\u3002",
+ "WindowsServiceIntro1": "Media Browser \u670d\u52a1\u5668\u901a\u5e38\u4ee5\u6258\u76d8\u56fe\u6807\u7684\u5f62\u5f0f\u4ee5\u684c\u9762\u5e94\u7528\u7a0b\u5e8f\u8fd0\u884c\uff0c\u4f46\u5982\u679c\u4f60\u559c\u6b22\u5b83\u4f5c\u4e3a\u540e\u53f0\u670d\u52a1\u8fd0\u884c\uff0c\u5b83\u53ef\u4ee5\u4ece Windows \u63a7\u5236\u9762\u677f\u542f\u52a8\u3002",
"WindowsServiceIntro2": "\u5982\u679c\u4f7f\u7528Windows\u670d\u52a1\uff0c\u8bf7\u6ce8\u610f\uff0c\u5b83\u4e0d\u80fd\u540c\u65f6\u4e3a\u6258\u76d8\u56fe\u6807\u8fd0\u884c\uff0c\u6240\u4ee5\u4f60\u9700\u8981\u9000\u51fa\u6258\u76d8\u4ee5\u8fd0\u884c\u670d\u52a1\u3002\u8be5\u670d\u52a1\u8fd8\u5c06\u9700\u8981\u7ba1\u7406\u5458\u6743\u9650\uff0c\u8be5\u6743\u9650\u53ef\u4ee5\u901a\u8fc7\u63a7\u5236\u9762\u677f\u914d\u7f6e\u3002\u8bf7\u6ce8\u610f\uff0c\u6b64\u65f6\u670d\u52a1\u65e0\u6cd5\u81ea\u52a8\u66f4\u65b0\uff0c\u6240\u4ee5\u65b0\u7684\u7248\u672c\u5c06\u9700\u8981\u624b\u52a8\u66f4\u65b0\u3002",
"WizardCompleted": "\u8fd9\u662f\u73b0\u5728\u6211\u4eec\u6240\u8981\u77e5\u9053\u7684\u3002Media Browser\u5df2\u7ecf\u5f00\u59cb\u6574\u5408\u4f60\u5a92\u4f53\u5e93\u4e2d\u7684\u4fe1\u606f\u3002\u4f60\u53ef\u4ee5\u7ee7\u7eed\u67e5\u770b\u6211\u4eec\u7684\u5176\u4ed6\u5e94\u7528\u7a0b\u5e8f\uff0c\u7136\u540e<b>\u5b8c\u6210<\/b>\u6765\u67e5\u770b <b>\u63a7\u5236\u53f0<\/b>.",
"LabelConfigureSettings": "\u914d\u7f6e\u8bbe\u7f6e",
- "LabelEnableVideoImageExtraction": "\u542f\u7528\u89c6\u9891\u56fe\u7247\u63d0\u53d6",
+ "LabelEnableVideoImageExtraction": "\u542f\u7528\u89c6\u9891\u622a\u56fe\u529f\u80fd",
"VideoImageExtractionHelp": "\u5bf9\u4e8e\u8fd8\u6ca1\u6709\u56fe\u7247\uff0c\u4ee5\u53ca\u6211\u4eec\u65e0\u6cd5\u627e\u5230\u7f51\u7edc\u56fe\u7247\u7684\u89c6\u9891\u3002\u8fd9\u4f1a\u989d\u5916\u589e\u52a0\u4e00\u4e9b\u521d\u59cb\u5316\u5a92\u4f53\u5e93\u7684\u626b\u63cf\u65f6\u95f4\uff0c\u4f46\u4f1a\u4f7f\u5a92\u4f53\u4ecb\u7ecd\u754c\u9762\u66f4\u52a0\u8d4f\u5fc3\u60a6\u76ee\u3002",
- "LabelEnableChapterImageExtractionForMovies": "\u63d0\u53d6\u7535\u5f71\u7ae0\u8282\u56fe\u7247",
+ "LabelEnableChapterImageExtractionForMovies": "\u622a\u53d6\u7535\u5f71\u7ae0\u8282\u56fe\u7247",
"LabelChapterImageExtractionForMoviesHelp": "\u4ece\u7ae0\u8282\u4e2d\u63d0\u53d6\u7684\u56fe\u7247\u5c06\u5141\u8bb8\u5ba2\u6237\u7aef\u663e\u793a\u56fe\u5f62\u9009\u62e9\u83dc\u5355\u3002\u8fd9\u4e2a\u8fc7\u7a0b\u53ef\u80fd\u4f1a\u5f88\u6162\uff0c \u66f4\u591a\u7684\u5360\u7528CPU\u8d44\u6e90\uff0c\u5e76\u4e14\u4f1a\u9700\u8981\u51e0\u4e2aGB\u7684\u786c\u76d8\u7a7a\u95f4\u3002\u5b83\u88ab\u9ed8\u8ba4\u8bbe\u7f6e\u4e8e\u6bcf\u665a\u51cc\u66684\u70b9\u8fd0\u884c\uff0c\u867d\u7136\u8fd9\u53ef\u4ee5\u5728\u8ba1\u5212\u4efb\u52a1\u4e2d\u914d\u7f6e\uff0c\u4f46\u6211\u4eec\u4e0d\u5efa\u8bae\u5728\u9ad8\u5cf0\u4f7f\u7528\u65f6\u95f4\u8fd0\u884c\u8be5\u4efb\u52a1\u3002",
"LabelEnableAutomaticPortMapping": "\u542f\u7528\u81ea\u52a8\u7aef\u53e3\u6620\u5c04",
"LabelEnableAutomaticPortMappingHelp": "UPNP\u5141\u8bb8\u81ea\u52a8\u8def\u7531\u5668\u914d\u7f6e\uff0c\u4ece\u800c\u66f4\u65b9\u4fbf\u7684\u8fdb\u884c\u8fdc\u7a0b\u8bbf\u95ee\u3002\u4f46\u8fd9\u53ef\u80fd\u4e0d\u9002\u7528\u4e8e\u67d0\u4e9b\u578b\u53f7\u7684\u8def\u7531\u5668\u3002",
"ButtonOk": "\u786e\u5b9a",
"ButtonCancel": "\u53d6\u6d88",
"ButtonNew": "\u65b0\u589e",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "\u7535\u5f71",
+ "FolderTypeMusic": "\u97f3\u4e50",
+ "FolderTypeAdultVideos": "\u6210\u4eba\u89c6\u9891",
+ "FolderTypePhotos": "\u56fe\u7247",
+ "FolderTypeMusicVideos": "\u97f3\u4e50\u89c6\u9891",
+ "FolderTypeHomeVideos": "\u5bb6\u5ead\u89c6\u9891",
+ "FolderTypeGames": "\u6e38\u620f",
+ "FolderTypeBooks": "\u4e66\u7c4d",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "\u8bbe\u7f6e\u4f60\u7684\u5a92\u4f53\u5e93",
"ButtonAddMediaFolder": "\u6dfb\u52a0\u5a92\u4f53\u6587\u4ef6\u5939",
"LabelFolderType": "\u6587\u4ef6\u5939\u7c7b\u578b\uff1a",
- "MediaFolderHelpPluginRequired": "* \u9700\u8981\u4f7f\u7528\u4e00\u4e2a\u63d2\u4ef6\uff0c\u4f8b\u5982\uff1aGameBrowser \u6216\u8005 MB Bookshelf\u3002",
"ReferToMediaLibraryWiki": "\u8bf7\u53c2\u9605\u5a92\u4f53\u5e93\u7ef4\u57fa\u3002",
"LabelCountry": "\u56fd\u5bb6\uff1a",
"LabelLanguage": "\u8bed\u8a00\uff1a",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 8d87c6897..29fb94c4b 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/zh_TW.json
@@ -37,10 +37,21 @@
"ButtonOk": "OK",
"ButtonCancel": "\u53d6\u6d88",
"ButtonNew": "\u5275\u5efa",
+ "FolderTypeMixed": "Mixed content",
+ "FolderTypeMovies": "Movies",
+ "FolderTypeMusic": "Music",
+ "FolderTypeAdultVideos": "Adult videos",
+ "FolderTypePhotos": "Photos",
+ "FolderTypeMusicVideos": "Music videos",
+ "FolderTypeHomeVideos": "Home videos",
+ "FolderTypeGames": "Games",
+ "FolderTypeBooks": "Books",
+ "FolderTypeTvShows": "TV",
+ "FolderTypeInherit": "Inherit",
+ "LabelContentType": "Content type:",
"HeaderSetupLibrary": "\u8a2d\u7f6e\u4f60\u7684\u5a92\u9ad4\u5eab",
"ButtonAddMediaFolder": "\u6dfb\u52a0\u5a92\u9ad4\u6587\u4ef6\u593e",
"LabelFolderType": "\u5a92\u9ad4\u6587\u4ef6\u593e\u985e\u578b\uff1a",
- "MediaFolderHelpPluginRequired": "*\u9700\u8981\u4f7f\u7528\u4e00\u500b\u63d2\u4ef6\uff0c\u4f8b\u5982GameBrowser\u6216MB Bookshelf\u3002",
"ReferToMediaLibraryWiki": "\u53c3\u7167\u5a92\u9ad4\u5eab\u7ef4\u57fa",
"LabelCountry": "\u570b\u5bb6\uff1a",
"LabelLanguage": "\u8a9e\u8a00\uff1a",
@@ -1246,7 +1257,7 @@
"HeaderTrailerReel": "Trailer Reel",
"OptionPlayUnwatchedTrailersOnly": "Play only unwatched trailers",
"HeaderTrailerReelHelp": "Start a trailer reel to play a long running playlist of trailers.",
- "MessageNoTrailersFound": "No trailers found. Install the Trailer channel plugin to import a library of internet trailers.",
+ "MessageNoTrailersFound": "No trailers found. Install the Trailer channel to enhance your movie experience by adding a library of internet trailers.",
"HeaderNewUsers": "New Users",
"ButtonSignUp": "Sign up",
"ButtonForgotPassword": "Forgot password?",
@@ -1279,5 +1290,9 @@
"LabelEnableSingleImageInDidlLimit": "Limit to single embedded image",
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity",
- "TitleSync": "Sync"
+ "TitleSync": "Sync",
+ "OptionAllowSyncContent": "Allow syncing media to devices",
+ "NameSeasonUnknown": "Season Unknown",
+ "NameSeasonNumber": "Season {0}",
+ "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
} \ 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 ed014fff7..59196d0bb 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -51,7 +51,7 @@
</Reference>
<Reference Include="MediaBrowser.Naming, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
- <HintPath>..\packages\MediaBrowser.Naming.1.0.0.18\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
+ <HintPath>..\packages\MediaBrowser.Naming.1.0.0.23\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll</HintPath>
</Reference>
<Reference Include="Mono.Nat, Version=1.2.21.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
@@ -183,6 +183,7 @@
<Compile Include="Library\LocalTrailerPostScanTask.cs" />
<Compile Include="Library\MusicManager.cs" />
<Compile Include="Library\PathExtensions.cs" />
+ <Compile Include="Library\Resolvers\SpecialFolderResolver.cs" />
<Compile Include="Library\Resolvers\BaseVideoResolver.cs" />
<Compile Include="Library\Resolvers\PhotoAlbumResolver.cs" />
<Compile Include="Library\Resolvers\PhotoResolver.cs" />
diff --git a/MediaBrowser.Server.Implementations/News/NewsService.cs b/MediaBrowser.Server.Implementations/News/NewsService.cs
index 9eeadfab7..684363d01 100644
--- a/MediaBrowser.Server.Implementations/News/NewsService.cs
+++ b/MediaBrowser.Server.Implementations/News/NewsService.cs
@@ -26,6 +26,14 @@ namespace MediaBrowser.Server.Implementations.News
{
return GetProductNewsInternal(query);
}
+ catch (DirectoryNotFoundException)
+ {
+ // No biggie
+ return new QueryResult<NewsItem>
+ {
+ Items = new NewsItem[] { }
+ };
+ }
catch (FileNotFoundException)
{
// No biggie
diff --git a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs
index 3f8b61a45..e74225887 100644
--- a/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs
+++ b/MediaBrowser.Server.Implementations/Notifications/NotificationManager.cs
@@ -78,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.Notifications
switch (request.SendToUserMode.Value)
{
case SendToUserType.Admins:
- return _userManager.Users.Where(i => i.Configuration.IsAdministrator)
+ return _userManager.Users.Where(i => i.Policy.IsAdministrator)
.Select(i => i.Id.ToString("N"));
case SendToUserType.All:
return _userManager.Users.Select(i => i.Id.ToString("N"));
diff --git a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
index 3c3d7740a..9f75d522c 100644
--- a/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
+++ b/MediaBrowser.Server.Implementations/ServerManager/WebSocketConnection.cs
@@ -1,5 +1,5 @@
using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index 1f294c325..4c587d1ab 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -68,12 +68,6 @@ namespace MediaBrowser.Server.Implementations.Session
private readonly IDeviceManager _deviceManager;
/// <summary>
- /// Gets or sets the configuration manager.
- /// </summary>
- /// <value>The configuration manager.</value>
- private readonly IServerConfigurationManager _configurationManager;
-
- /// <summary>
/// The _active connections
/// </summary>
private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections =
@@ -105,18 +99,9 @@ namespace MediaBrowser.Server.Implementations.Session
private readonly SemaphoreSlim _sessionLock = new SemaphoreSlim(1, 1);
- /// <summary>
- /// Initializes a new instance of the <see cref="SessionManager" /> class.
- /// </summary>
- /// <param name="userDataRepository">The user data repository.</param>
- /// <param name="configurationManager">The configuration manager.</param>
- /// <param name="logger">The logger.</param>
- /// <param name="userRepository">The user repository.</param>
- /// <param name="libraryManager">The library manager.</param>
- public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient, IAuthenticationRepository authRepo, IDeviceManager deviceManager)
+ public SessionManager(IUserDataManager userDataRepository, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient, IAuthenticationRepository authRepo, IDeviceManager deviceManager)
{
_userDataRepository = userDataRepository;
- _configurationManager = configurationManager;
_logger = logger;
_userRepository = userRepository;
_libraryManager = libraryManager;
@@ -689,7 +674,7 @@ namespace MediaBrowser.Server.Implementations.Session
if (positionTicks.HasValue)
{
- UpdatePlayState(item, data, positionTicks.Value);
+ _userDataRepository.UpdatePlayState(item, data, positionTicks.Value);
await _userDataRepository.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackProgress, CancellationToken.None).ConfigureAwait(false);
}
@@ -779,7 +764,7 @@ namespace MediaBrowser.Server.Implementations.Session
if (positionTicks.HasValue)
{
- playedToCompletion = UpdatePlayState(item, data, positionTicks.Value);
+ playedToCompletion = _userDataRepository.UpdatePlayState(item, data, positionTicks.Value);
}
else
{
@@ -796,65 +781,6 @@ namespace MediaBrowser.Server.Implementations.Session
}
/// <summary>
- /// Updates playstate position for an item but does not save
- /// </summary>
- /// <param name="item">The item</param>
- /// <param name="data">User data for the item</param>
- /// <param name="positionTicks">The current playback position</param>
- private bool UpdatePlayState(BaseItem item, UserItemData data, long positionTicks)
- {
- var playedToCompletion = false;
-
- var hasRuntime = item.RunTimeTicks.HasValue && item.RunTimeTicks > 0;
-
- // If a position has been reported, and if we know the duration
- if (positionTicks > 0 && hasRuntime)
- {
- var pctIn = Decimal.Divide(positionTicks, item.RunTimeTicks.Value) * 100;
-
- // Don't track in very beginning
- if (pctIn < _configurationManager.Configuration.MinResumePct)
- {
- positionTicks = 0;
- }
-
- // If we're at the end, assume completed
- else if (pctIn > _configurationManager.Configuration.MaxResumePct || positionTicks >= item.RunTimeTicks.Value)
- {
- positionTicks = 0;
- data.Played = playedToCompletion = true;
- }
-
- else
- {
- // Enforce MinResumeDuration
- var durationSeconds = TimeSpan.FromTicks(item.RunTimeTicks.Value).TotalSeconds;
-
- if (durationSeconds < _configurationManager.Configuration.MinResumeDurationSeconds)
- {
- positionTicks = 0;
- data.Played = playedToCompletion = true;
- }
- }
- }
- else if (!hasRuntime)
- {
- // If we don't know the runtime we'll just have to assume it was fully played
- data.Played = playedToCompletion = true;
- positionTicks = 0;
- }
-
- if (item is Audio)
- {
- positionTicks = 0;
- }
-
- data.PlaybackPositionTicks = positionTicks;
-
- return playedToCompletion;
- }
-
- /// <summary>
/// Gets the session.
/// </summary>
/// <param name="sessionId">The session identifier.</param>
diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
index ed590a1f2..36a7fcbd8 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
index 0756aa1ec..7d1057397 100644
--- a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
+++ b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs
@@ -1,4 +1,4 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@@ -73,17 +73,6 @@ namespace MediaBrowser.Server.Implementations.Session
_logger.ErrorException("Error reporting session ended.", ex);
}
}
- else
- {
- var capabilities = new ClientCapabilities
- {
- PlayableMediaTypes = Session.PlayableMediaTypes,
- SupportedCommands = Session.SupportedCommands,
- SupportsMediaControl = SupportsMediaControl
- };
-
- _sessionManager.ReportCapabilities(Session.Id, capabilities);
- }
}
private IWebSocketConnection GetActiveSocket()
diff --git a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs
index 94eed50f6..deef503ea 100644
--- a/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs
+++ b/MediaBrowser.Server.Implementations/Sync/AppSyncProvider.cs
@@ -8,7 +8,7 @@ using System.Linq;
namespace MediaBrowser.Server.Implementations.Sync
{
- public class AppSyncProvider : ISyncProvider
+ public class AppSyncProvider : ISyncProvider, IHasUniqueTargetIds
{
private readonly IDeviceManager _deviceManager;
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
index 6dda869ee..5e129d9a1 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
@@ -316,35 +316,26 @@ namespace MediaBrowser.Server.Implementations.Sync
var video = item as Video;
if (video != null)
{
- jobItem.OutputPath = await Sync(jobItem, video, deviceProfile, cancellationToken).ConfigureAwait(false);
+ await Sync(jobItem, video, deviceProfile, cancellationToken).ConfigureAwait(false);
}
else if (item is Audio)
{
- jobItem.OutputPath = await Sync(jobItem, (Audio)item, deviceProfile, cancellationToken).ConfigureAwait(false);
+ await Sync(jobItem, (Audio)item, deviceProfile, cancellationToken).ConfigureAwait(false);
}
else if (item is Photo)
{
- jobItem.OutputPath = await Sync(jobItem, (Photo)item, deviceProfile, cancellationToken).ConfigureAwait(false);
+ await Sync(jobItem, (Photo)item, deviceProfile, cancellationToken).ConfigureAwait(false);
}
- else if (item is Game)
- {
- jobItem.OutputPath = await Sync(jobItem, (Game)item, deviceProfile, cancellationToken).ConfigureAwait(false);
- }
-
- else if (item is Book)
+ else
{
- jobItem.OutputPath = await Sync(jobItem, (Book)item, deviceProfile, cancellationToken).ConfigureAwait(false);
+ await SyncGeneric(jobItem, item, deviceProfile, cancellationToken).ConfigureAwait(false);
}
-
- jobItem.Progress = 50;
- jobItem.Status = SyncJobItemStatus.Transferring;
- await _syncRepo.Update(jobItem).ConfigureAwait(false);
}
- private async Task<string> Sync(SyncJobItem jobItem, Video item, DeviceProfile profile, CancellationToken cancellationToken)
+ private async Task Sync(SyncJobItem jobItem, Video item, DeviceProfile profile, CancellationToken cancellationToken)
{
var options = new VideoOptions
{
@@ -358,24 +349,34 @@ namespace MediaBrowser.Server.Implementations.Sync
var streamInfo = new StreamBuilder().BuildVideoItem(options);
var mediaSource = streamInfo.MediaSource;
- if (streamInfo.PlayMethod != PlayMethod.Transcode)
+ jobItem.MediaSourceId = streamInfo.MediaSourceId;
+
+ if (streamInfo.PlayMethod == PlayMethod.Transcode)
+ {
+ await _syncRepo.Update(jobItem).ConfigureAwait(false);
+ }
+ else
{
if (mediaSource.Protocol == MediaProtocol.File)
{
- return mediaSource.Path;
+ jobItem.OutputPath = mediaSource.Path;
}
if (mediaSource.Protocol == MediaProtocol.Http)
{
- return await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false);
+ jobItem.OutputPath = await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false);
}
throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol));
}
// TODO: Transcode
- return mediaSource.Path;
+ jobItem.OutputPath = mediaSource.Path;
+
+ jobItem.Progress = 50;
+ jobItem.Status = SyncJobItemStatus.Transferring;
+ await _syncRepo.Update(jobItem).ConfigureAwait(false);
}
- private async Task<string> Sync(SyncJobItem jobItem, Audio item, DeviceProfile profile, CancellationToken cancellationToken)
+ private async Task Sync(SyncJobItem jobItem, Audio item, DeviceProfile profile, CancellationToken cancellationToken)
{
var options = new AudioOptions
{
@@ -389,36 +390,49 @@ namespace MediaBrowser.Server.Implementations.Sync
var streamInfo = new StreamBuilder().BuildAudioItem(options);
var mediaSource = streamInfo.MediaSource;
- if (streamInfo.PlayMethod != PlayMethod.Transcode)
+ jobItem.MediaSourceId = streamInfo.MediaSourceId;
+
+ if (streamInfo.PlayMethod == PlayMethod.Transcode)
+ {
+ await _syncRepo.Update(jobItem).ConfigureAwait(false);
+ }
+ else
{
if (mediaSource.Protocol == MediaProtocol.File)
{
- return mediaSource.Path;
+ jobItem.OutputPath = mediaSource.Path;
}
if (mediaSource.Protocol == MediaProtocol.Http)
{
- return await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false);
+ jobItem.OutputPath = await DownloadFile(jobItem, mediaSource, cancellationToken).ConfigureAwait(false);
}
throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol));
}
// TODO: Transcode
- return mediaSource.Path;
- }
+ jobItem.OutputPath = mediaSource.Path;
- private async Task<string> Sync(SyncJobItem jobItem, Photo item, DeviceProfile profile, CancellationToken cancellationToken)
- {
- return item.Path;
+ jobItem.Progress = 50;
+ jobItem.Status = SyncJobItemStatus.Transferring;
+ await _syncRepo.Update(jobItem).ConfigureAwait(false);
}
- private async Task<string> Sync(SyncJobItem jobItem, Game item, DeviceProfile profile, CancellationToken cancellationToken)
+ private async Task Sync(SyncJobItem jobItem, Photo item, DeviceProfile profile, CancellationToken cancellationToken)
{
- return item.Path;
+ jobItem.OutputPath = item.Path;
+
+ jobItem.Progress = 50;
+ jobItem.Status = SyncJobItemStatus.Transferring;
+ await _syncRepo.Update(jobItem).ConfigureAwait(false);
}
- private async Task<string> Sync(SyncJobItem jobItem, Book item, DeviceProfile profile, CancellationToken cancellationToken)
+ private async Task SyncGeneric(SyncJobItem jobItem, BaseItem item, DeviceProfile profile, CancellationToken cancellationToken)
{
- return item.Path;
+ jobItem.OutputPath = item.Path;
+
+ jobItem.Progress = 50;
+ jobItem.Status = SyncJobItemStatus.Transferring;
+ await _syncRepo.Update(jobItem).ConfigureAwait(false);
}
private async Task<string> DownloadFile(SyncJobItem jobItem, MediaSourceInfo mediaSource, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
index 664ec4038..24b9b0b83 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
@@ -1,18 +1,25 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Sync;
using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Sync;
+using MediaBrowser.Model.Users;
using MoreLinq;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Threading.Tasks;
@@ -25,16 +32,20 @@ namespace MediaBrowser.Server.Implementations.Sync
private readonly IImageProcessor _imageProcessor;
private readonly ILogger _logger;
private readonly IUserManager _userManager;
+ private readonly Func<IDtoService> _dtoService;
+ private readonly IApplicationHost _appHost;
private ISyncProvider[] _providers = { };
- public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager)
+ public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func<IDtoService> dtoService, IApplicationHost appHost)
{
_libraryManager = libraryManager;
_repo = repo;
_imageProcessor = imageProcessor;
_logger = logger;
_userManager = userManager;
+ _dtoService = dtoService;
+ _appHost = appHost;
}
public void AddParts(IEnumerable<ISyncProvider> providers)
@@ -68,7 +79,12 @@ namespace MediaBrowser.Server.Implementations.Sync
}
var target = GetSyncTargets(request.UserId)
- .First(i => string.Equals(request.TargetId, i.Id));
+ .FirstOrDefault(i => string.Equals(request.TargetId, i.Id));
+
+ if (target == null)
+ {
+ throw new ArgumentException("Sync target not found.");
+ }
var jobId = Guid.NewGuid().ToString("N");
@@ -172,17 +188,23 @@ namespace MediaBrowser.Server.Implementations.Sync
private IEnumerable<SyncTarget> GetSyncTargets(ISyncProvider provider, string userId)
{
- var providerId = GetSyncProviderId(provider);
-
return provider.GetSyncTargets().Select(i => new SyncTarget
{
Name = i.Name,
- Id = GetSyncTargetId(providerId, i)
+ Id = GetSyncTargetId(provider, i)
});
}
- private string GetSyncTargetId(string providerId, SyncTarget target)
+ private string GetSyncTargetId(ISyncProvider provider, SyncTarget target)
{
+ var hasUniqueId = provider as IHasUniqueTargetIds;
+
+ if (hasUniqueId != null)
+ {
+ return target.Id;
+ }
+
+ var providerId = GetSyncProviderId(provider);
return (providerId + "-" + target.Id).GetMD5().ToString("N");
}
@@ -239,10 +261,21 @@ namespace MediaBrowser.Server.Implementations.Sync
}
}
+ if (item is LiveTvChannel || item is IChannelItem || item is ILiveTvRecording)
+ {
+ return false;
+ }
+
+ // It would be nice to support these later
+ if (item is Game || item is Book)
+ {
+ return false;
+ }
+
return true;
}
- return item.LocationType == LocationType.FileSystem || item is Season;
+ return item.LocationType == LocationType.FileSystem || item is Season || item is ILiveTvRecording;
}
private string GetDefaultName(BaseItem item)
@@ -289,5 +322,71 @@ namespace MediaBrowser.Server.Implementations.Sync
{
return _repo.GetJobItems(query);
}
+
+ private SyncedItem GetJobItemInfo(SyncJobItem jobItem)
+ {
+ var job = _repo.GetJob(jobItem.JobId);
+
+ var libraryItem = _libraryManager.GetItemById(jobItem.ItemId);
+
+ var syncedItem = new SyncedItem
+ {
+ SyncJobId = jobItem.JobId,
+ SyncJobItemId = jobItem.Id,
+ ServerId = _appHost.SystemId,
+ UserId = job.UserId
+ };
+
+ var dtoOptions = new DtoOptions();
+
+ // Remove some bloat
+ dtoOptions.Fields.Remove(ItemFields.MediaStreams);
+ dtoOptions.Fields.Remove(ItemFields.IndexOptions);
+ dtoOptions.Fields.Remove(ItemFields.MediaSourceCount);
+ dtoOptions.Fields.Remove(ItemFields.OriginalPrimaryImageAspectRatio);
+ dtoOptions.Fields.Remove(ItemFields.Path);
+ dtoOptions.Fields.Remove(ItemFields.SeriesGenres);
+ dtoOptions.Fields.Remove(ItemFields.Settings);
+ dtoOptions.Fields.Remove(ItemFields.SyncInfo);
+
+ syncedItem.Item = _dtoService().GetBaseItemDto(libraryItem, dtoOptions);
+
+ // TODO: this should be the media source of the transcoded output
+ syncedItem.Item.MediaSources = syncedItem.Item.MediaSources
+ .Where(i => string.Equals(i.Id, jobItem.MediaSourceId))
+ .ToList();
+
+ var mediaSource = syncedItem.Item.MediaSources
+ .FirstOrDefault(i => string.Equals(i.Id, jobItem.MediaSourceId));
+
+ // This will be null for items that are not audio/video
+ if (mediaSource == null)
+ {
+ syncedItem.OriginalFileName = Path.GetFileName(libraryItem.Path);
+ }
+ else
+ {
+ syncedItem.OriginalFileName = Path.GetFileName(mediaSource.Path);
+ }
+
+ return syncedItem;
+ }
+
+ public Task ReportOfflineAction(UserAction action)
+ {
+ return Task.FromResult(true);
+ }
+
+ public List<SyncedItem> GetReadySyncItems(string targetId)
+ {
+ var jobItemResult = GetJobItems(new SyncJobItemQuery
+ {
+ TargetId = targetId,
+ Status = SyncJobItemStatus.Transferring
+ });
+
+ return jobItemResult.Items.Select(GetJobItemInfo)
+ .ToList();
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
index 7825b9e9a..e5b323725 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
@@ -24,6 +24,7 @@ namespace MediaBrowser.Server.Implementations.Sync
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private IDbCommand _deleteJobCommand;
+ private IDbCommand _deleteJobItemsCommand;
private IDbCommand _saveJobCommand;
private IDbCommand _saveJobItemCommand;
@@ -35,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Sync
public async Task Initialize()
{
- var dbFile = Path.Combine(_appPaths.DataPath, "sync6.db");
+ var dbFile = Path.Combine(_appPaths.DataPath, "sync8.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
@@ -44,7 +45,7 @@ namespace MediaBrowser.Server.Implementations.Sync
"create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Quality TEXT NOT NULL, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)",
"create index if not exists idx_SyncJobs on SyncJobs(Id)",
- "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, JobId TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT)",
+ "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, MediaSourceId TEXT, JobId TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT)",
"create index if not exists idx_SyncJobItems on SyncJobs(Id)",
//pragmas
@@ -61,9 +62,13 @@ namespace MediaBrowser.Server.Implementations.Sync
private void PrepareStatements()
{
_deleteJobCommand = _connection.CreateCommand();
- _deleteJobCommand.CommandText = "delete from SyncJobs where Id=@Id; delete from SyncJobItems where JobId=@Id";
+ _deleteJobCommand.CommandText = "delete from SyncJobs where Id=@Id";
_deleteJobCommand.Parameters.Add(_deleteJobCommand, "@Id");
+ _deleteJobItemsCommand = _connection.CreateCommand();
+ _deleteJobItemsCommand.CommandText = "delete from SyncJobItems where JobId=@JobId";
+ _deleteJobItemsCommand.Parameters.Add(_deleteJobItemsCommand, "@JobId");
+
_saveJobCommand = _connection.CreateCommand();
_saveJobCommand.CommandText = "replace into SyncJobs (Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount) values (@Id, @TargetId, @Name, @Quality, @Status, @Progress, @UserId, @ItemIds, @Category, @ParentId, @UnwatchedOnly, @ItemLimit, @SyncNewContent, @DateCreated, @DateLastModified, @ItemCount)";
@@ -85,10 +90,11 @@ namespace MediaBrowser.Server.Implementations.Sync
_saveJobCommand.Parameters.Add(_saveJobCommand, "@ItemCount");
_saveJobItemCommand = _connection.CreateCommand();
- _saveJobItemCommand.CommandText = "replace into SyncJobItems (Id, ItemId, JobId, OutputPath, Status, TargetId, DateCreated, Progress) values (@Id, @ItemId, @JobId, @OutputPath, @Status, @TargetId, @DateCreated, @Progress)";
+ _saveJobItemCommand.CommandText = "replace into SyncJobItems (Id, ItemId, MediaSourceId, JobId, OutputPath, Status, TargetId, DateCreated, Progress) values (@Id, @ItemId, @MediaSourceId, @JobId, @OutputPath, @Status, @TargetId, @DateCreated, @Progress)";
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@Id");
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@ItemId");
+ _saveJobItemCommand.Parameters.Add(_saveJobCommand, "@MediaSourceId");
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@JobId");
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@OutputPath");
_saveJobItemCommand.Parameters.Add(_saveJobCommand, "@Status");
@@ -98,7 +104,7 @@ namespace MediaBrowser.Server.Implementations.Sync
}
private const string BaseJobSelectText = "select Id, TargetId, Name, Quality, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount from SyncJobs";
- private const string BaseJobItemSelectText = "select Id, ItemId, JobId, OutputPath, Status, TargetId, DateCreated, Progress from SyncJobItems";
+ private const string BaseJobItemSelectText = "select Id, ItemId, MediaSourceId, JobId, OutputPath, Status, TargetId, DateCreated, Progress from SyncJobItems";
public SyncJob GetJob(string id)
{
@@ -221,7 +227,7 @@ namespace MediaBrowser.Server.Implementations.Sync
_saveJobCommand.GetParameter(index++).Value = job.TargetId;
_saveJobCommand.GetParameter(index++).Value = job.Name;
_saveJobCommand.GetParameter(index++).Value = job.Quality;
- _saveJobCommand.GetParameter(index++).Value = job.Status;
+ _saveJobCommand.GetParameter(index++).Value = job.Status.ToString();
_saveJobCommand.GetParameter(index++).Value = job.Progress;
_saveJobCommand.GetParameter(index++).Value = job.UserId;
_saveJobCommand.GetParameter(index++).Value = string.Join(",", job.RequestedItemIds.ToArray());
@@ -289,11 +295,14 @@ namespace MediaBrowser.Server.Implementations.Sync
var index = 0;
_deleteJobCommand.GetParameter(index++).Value = new Guid(id);
-
_deleteJobCommand.Transaction = transaction;
-
_deleteJobCommand.ExecuteNonQuery();
+ index = 0;
+ _deleteJobItemsCommand.GetParameter(index++).Value = id;
+ _deleteJobItemsCommand.Transaction = transaction;
+ _deleteJobItemsCommand.ExecuteNonQuery();
+
transaction.Commit();
}
catch (OperationCanceledException)
@@ -457,13 +466,14 @@ namespace MediaBrowser.Server.Implementations.Sync
whereClauses.Add("TargetId=@TargetId");
cmd.Parameters.Add(cmd, "@TargetId", DbType.String).Value = query.TargetId;
}
+
if (query.Status.HasValue)
{
whereClauses.Add("Status=@Status");
cmd.Parameters.Add(cmd, "@Status", DbType.String).Value = query.Status.Value.ToString();
}
- if (query.IsCompleted.HasValue)
+ else if (query.IsCompleted.HasValue)
{
if (query.IsCompleted.Value)
{
@@ -549,9 +559,10 @@ namespace MediaBrowser.Server.Implementations.Sync
_saveJobItemCommand.GetParameter(index++).Value = new Guid(jobItem.Id);
_saveJobItemCommand.GetParameter(index++).Value = jobItem.ItemId;
+ _saveJobItemCommand.GetParameter(index++).Value = jobItem.MediaSourceId;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.JobId;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.OutputPath;
- _saveJobItemCommand.GetParameter(index++).Value = jobItem.Status;
+ _saveJobItemCommand.GetParameter(index++).Value = jobItem.Status.ToString();
_saveJobItemCommand.GetParameter(index++).Value = jobItem.TargetId;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.DateCreated;
_saveJobItemCommand.GetParameter(index++).Value = jobItem.Progress;
@@ -598,27 +609,33 @@ namespace MediaBrowser.Server.Implementations.Sync
var info = new SyncJobItem
{
Id = reader.GetGuid(0).ToString("N"),
- ItemId = reader.GetString(1),
- JobId = reader.GetString(2)
+ ItemId = reader.GetString(1)
};
- if (!reader.IsDBNull(3))
+ if (!reader.IsDBNull(2))
{
- info.OutputPath = reader.GetString(3);
+ info.MediaSourceId = reader.GetString(2);
}
-
+
+ info.JobId = reader.GetString(3);
+
if (!reader.IsDBNull(4))
{
- info.Status = (SyncJobItemStatus)Enum.Parse(typeof(SyncJobItemStatus), reader.GetString(4), true);
+ info.OutputPath = reader.GetString(4);
}
- info.TargetId = reader.GetString(5);
+ if (!reader.IsDBNull(5))
+ {
+ info.Status = (SyncJobItemStatus)Enum.Parse(typeof(SyncJobItemStatus), reader.GetString(5), true);
+ }
- info.DateCreated = reader.GetDateTime(6);
+ info.TargetId = reader.GetString(6);
- if (!reader.IsDBNull(7))
+ info.DateCreated = reader.GetDateTime(7);
+
+ if (!reader.IsDBNull(8))
{
- info.Progress = reader.GetDouble(7);
+ info.Progress = reader.GetDouble(8);
}
return info;
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs b/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs
index df03ab6f7..2127e9c46 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncScheduledTask.cs
@@ -28,7 +28,7 @@ namespace MediaBrowser.Server.Implementations.Sync
public string Name
{
- get { return "Sync"; }
+ get { return "Sync preparation"; }
}
public string Description
@@ -61,7 +61,7 @@ namespace MediaBrowser.Server.Implementations.Sync
public bool IsHidden
{
- get { return true; }
+ get { return false; }
}
public bool IsEnabled
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index 0c79ba387..f4406913b 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="MediaBrowser.Naming" version="1.0.0.18" targetFramework="net45" />
+ <package id="MediaBrowser.Naming" version="1.0.0.23" targetFramework="net45" />
<package id="Mono.Nat" version="1.2.21.0" targetFramework="net45" />
<package id="morelinq" version="1.1.0" targetFramework="net45" />
</packages> \ No newline at end of file
diff --git a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs
index a2c860413..576b5b75f 100644
--- a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs
+++ b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs
@@ -67,7 +67,7 @@ namespace MediaBrowser.Server.Mac
return list;
}
- public void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int udpPort, string tempDirectory)
+ public void AuthorizeServer(int udpPort, int httpServerPort, string tempDirectory)
{
}
diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
index c53654e4f..e780f447f 100644
--- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
+++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj
@@ -131,10 +131,6 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
- <None Include="..\ThirdParty\libgdiplus\osx\libgdiplus.dylib">
- <Link>libgdiplus.dylib</Link>
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </None>
<None Include="..\ThirdParty\libwebp\osx\libwebp.5.dylib">
<Link>libwebp\osx\libwebp.5.dylib</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs
index 39d2d52d7..7f61570a4 100644
--- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs
+++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs
@@ -83,7 +83,7 @@ namespace MediaBrowser.Server.Mono.Native
return list;
}
- public void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int udpPort, string tempDirectory)
+ public void AuthorizeServer(int udpPort, int httpServerPort, string tempDirectory)
{
}
diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
index eca600b33..8398c63cb 100644
--- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
+++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
@@ -224,7 +224,7 @@ namespace MediaBrowser.Server.Startup.Common
private readonly StartupOptions _startupOptions;
private readonly string _remotePackageName;
- private readonly bool _supportsNativeWebSocket;
+ private bool _supportsNativeWebSocket;
internal INativeApp NativeApp { get; set; }
@@ -238,12 +238,12 @@ namespace MediaBrowser.Server.Startup.Common
/// <param name="remotePackageName">Name of the remote package.</param>
/// <param name="supportsNativeWebSocket">if set to <c>true</c> [supports native web socket].</param>
/// <param name="nativeApp">The native application.</param>
- public ApplicationHost(ServerApplicationPaths applicationPaths,
- ILogManager logManager,
- StartupOptions options,
+ public ApplicationHost(ServerApplicationPaths applicationPaths,
+ ILogManager logManager,
+ StartupOptions options,
IFileSystem fileSystem,
- string remotePackageName,
- bool supportsNativeWebSocket,
+ string remotePackageName,
+ bool supportsNativeWebSocket,
INativeApp nativeApp)
: base(applicationPaths, logManager, fileSystem)
{
@@ -353,17 +353,18 @@ namespace MediaBrowser.Server.Startup.Common
public override async Task Init(IProgress<double> progress)
{
- PerformVersionMigration();
+ PerformPreInitMigrations();
await base.Init(progress).ConfigureAwait(false);
+
+ PerformPostInitMigrations();
}
- private void PerformVersionMigration()
+ private void PerformPreInitMigrations()
{
var migrations = new List<IVersionMigration>
{
new MigrateUserFolders(ApplicationPaths),
- new PlaylistImages(ServerConfigurationManager),
new RenameXbmcOptions(ServerConfigurationManager),
new RenameXmlOptions(ServerConfigurationManager),
new DeprecatePlugins(ApplicationPaths),
@@ -376,6 +377,19 @@ namespace MediaBrowser.Server.Startup.Common
}
}
+ private void PerformPostInitMigrations()
+ {
+ var migrations = new List<IVersionMigration>
+ {
+ new MigrateTranscodingPath(ServerConfigurationManager)
+ };
+
+ foreach (var task in migrations)
+ {
+ task.Run();
+ }
+ }
+
/// <summary>
/// Registers resources that classes will depend on
/// </summary>
@@ -384,7 +398,7 @@ namespace MediaBrowser.Server.Startup.Common
{
await base.RegisterResources(progress).ConfigureAwait(false);
- RegisterSingleInstance<IHttpResultFactory>(new HttpResultFactory(LogManager, FileSystemManager, JsonSerializer));
+ RegisterSingleInstance<IHttpResultFactory>(new HttpResultFactory(LogManager, FileSystemManager, JsonSerializer));
RegisterSingleInstance<IServerApplicationHost>(this);
RegisterSingleInstance<IServerApplicationPaths>(ApplicationPaths);
@@ -396,10 +410,10 @@ namespace MediaBrowser.Server.Startup.Common
RegisterSingleInstance<IBlurayExaminer>(() => new BdInfoExaminer());
- UserDataManager = new UserDataManager(LogManager);
+ UserDataManager = new UserDataManager(LogManager, ServerConfigurationManager);
RegisterSingleInstance(UserDataManager);
- UserRepository = await GetUserRepository().ConfigureAwait(false);
+ UserRepository = await GetUserRepository().ConfigureAwait(false);
RegisterSingleInstance(UserRepository);
DisplayPreferencesRepository = new SqliteDisplayPreferencesRepository(ApplicationPaths, JsonSerializer, LogManager);
@@ -420,7 +434,7 @@ namespace MediaBrowser.Server.Startup.Common
SyncRepository = await GetSyncRepository().ConfigureAwait(false);
RegisterSingleInstance(SyncRepository);
- UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, () => ConnectManager, this);
+ UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, () => ConnectManager, this, JsonSerializer);
RegisterSingleInstance(UserManager);
LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager);
@@ -440,7 +454,19 @@ namespace MediaBrowser.Server.Startup.Common
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
- HttpServer = ServerFactory.CreateServer(this, LogManager, "Media Browser", WebApplicationName, "dashboard/index.html", _supportsNativeWebSocket);
+ if (IsFirstRun)
+ {
+ ServerConfigurationManager.Configuration.EnableWin8HttpListener = false;
+ ServerConfigurationManager.SaveConfiguration();
+ _supportsNativeWebSocket = false;
+ }
+
+ if (!ServerConfigurationManager.Configuration.EnableWin8HttpListener)
+ {
+ _supportsNativeWebSocket = false;
+ }
+
+ HttpServer = ServerFactory.CreateServer(this, LogManager, "Media Browser", WebApplicationName, "dashboard/index.html", _supportsNativeWebSocket);
RegisterSingleInstance(HttpServer, false);
progress.Report(10);
@@ -456,7 +482,7 @@ namespace MediaBrowser.Server.Startup.Common
ImageProcessor = new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, MediaEncoder);
RegisterSingleInstance(ImageProcessor);
- SyncManager = new SyncManager(LibraryManager, SyncRepository, ImageProcessor, LogManager.GetLogger("SyncManager"), UserManager);
+ SyncManager = new SyncManager(LibraryManager, SyncRepository, ImageProcessor, LogManager.GetLogger("SyncManager"), UserManager, () => DtoService, this);
RegisterSingleInstance(SyncManager);
DtoService = new DtoService(Logger, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager, SyncManager, this);
@@ -471,7 +497,7 @@ namespace MediaBrowser.Server.Startup.Common
DeviceManager = new DeviceManager(new DeviceRepository(ApplicationPaths, JsonSerializer, Logger), UserManager, FileSystemManager, LibraryMonitor, ConfigurationManager, LogManager.GetLogger("DeviceManager"));
RegisterSingleInstance(DeviceManager);
- SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager);
+ SessionManager = new SessionManager(UserDataManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager);
RegisterSingleInstance(SessionManager);
var newsService = new Implementations.News.NewsService(ApplicationPaths, JsonSerializer);
@@ -534,12 +560,12 @@ namespace MediaBrowser.Server.Startup.Common
RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
RegisterSingleInstance<IAuthService>(new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager, SessionManager));
- RegisterSingleInstance<ISubtitleEncoder>(new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer));
+ RegisterSingleInstance<ISubtitleEncoder>(new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer));
await ConfigureDisplayPreferencesRepositories().ConfigureAwait(false);
await ConfigureItemRepositories().ConfigureAwait(false);
await ConfigureUserDataRepositories().ConfigureAwait(false);
- await ConfigureNotificationsRepository().ConfigureAwait(false);
+ await ConfigureNotificationsRepository().ConfigureAwait(false);
progress.Report(100);
SetStaticProperties();
@@ -721,7 +747,7 @@ namespace MediaBrowser.Server.Startup.Common
ServerManager.AddWebSocketListeners(GetExports<IWebSocketListener>(false));
- StartServer(true);
+ StartServer();
LibraryManager.AddParts(GetExports<IResolverIgnoreRule>(),
GetExports<IVirtualFolderCreator>(),
@@ -759,8 +785,7 @@ namespace MediaBrowser.Server.Startup.Common
/// <summary>
/// Starts the server.
/// </summary>
- /// <param name="retryOnFailure">if set to <c>true</c> [retry on failure].</param>
- private void StartServer(bool retryOnFailure)
+ private void StartServer()
{
try
{
@@ -770,16 +795,7 @@ namespace MediaBrowser.Server.Startup.Common
{
Logger.ErrorException("Error starting http server", ex);
- if (retryOnFailure)
- {
- RegisterServerWithAdministratorAccess();
-
- StartServer(false);
- }
- else
- {
- throw;
- }
+ throw;
}
}
@@ -1056,9 +1072,8 @@ namespace MediaBrowser.Server.Startup.Common
try
{
NativeApp.AuthorizeServer(
- ServerConfigurationManager.Configuration.HttpServerPortNumber,
- HttpServerUrlPrefixes.First(),
UdpServerEntryPoint.PortNumber,
+ ServerConfigurationManager.Configuration.HttpServerPortNumber,
ConfigurationManager.CommonApplicationPaths.TempDirectory);
}
catch (Exception ex)
diff --git a/MediaBrowser.Server.Startup.Common/INativeApp.cs b/MediaBrowser.Server.Startup.Common/INativeApp.cs
index 5042e1cea..4abea57fb 100644
--- a/MediaBrowser.Server.Startup.Common/INativeApp.cs
+++ b/MediaBrowser.Server.Startup.Common/INativeApp.cs
@@ -16,11 +16,10 @@ namespace MediaBrowser.Server.Startup.Common
/// <summary>
/// Authorizes the server.
/// </summary>
- /// <param name="httpServerPort">The HTTP server port.</param>
- /// <param name="httpServerUrlPrefix">The HTTP server URL prefix.</param>
/// <param name="udpPort">The UDP port.</param>
+ /// <param name="httpServerPort">The HTTP server port.</param>
/// <param name="tempDirectory">The temporary directory.</param>
- void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int udpPort, string tempDirectory);
+ void AuthorizeServer(int udpPort, int httpServerPort, string tempDirectory);
/// <summary>
/// Gets the environment.
diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
index b133f78e7..38e07fde4 100644
--- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
+++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
@@ -66,8 +66,8 @@
<Compile Include="Migrations\DeleteDlnaProfiles.cs" />
<Compile Include="Migrations\DeprecatePlugins.cs" />
<Compile Include="Migrations\IVersionMigration.cs" />
+ <Compile Include="Migrations\MigrateTranscodingPath.cs" />
<Compile Include="Migrations\MigrateUserFolders.cs" />
- <Compile Include="Migrations\PlaylistImages.cs" />
<Compile Include="Migrations\RenameXbmcOptions.cs" />
<Compile Include="Migrations\RenameXmlOptions.cs" />
<Compile Include="NativeEnvironment.cs" />
diff --git a/MediaBrowser.Server.Startup.Common/Migrations/MigrateTranscodingPath.cs b/MediaBrowser.Server.Startup.Common/Migrations/MigrateTranscodingPath.cs
new file mode 100644
index 000000000..88f60841d
--- /dev/null
+++ b/MediaBrowser.Server.Startup.Common/Migrations/MigrateTranscodingPath.cs
@@ -0,0 +1,30 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Configuration;
+
+namespace MediaBrowser.Server.Startup.Common.Migrations
+{
+ public class MigrateTranscodingPath : IVersionMigration
+ {
+ private readonly IServerConfigurationManager _config;
+
+ public MigrateTranscodingPath(IServerConfigurationManager config)
+ {
+ _config = config;
+ }
+
+ public void Run()
+ {
+ if (!string.IsNullOrWhiteSpace(_config.Configuration.TranscodingTempPath))
+ {
+ var newConfig = _config.GetConfiguration<EncodingOptions>("encoding");
+
+ newConfig.TranscodingTempPath = _config.Configuration.TranscodingTempPath;
+ _config.SaveConfiguration("encoding", newConfig);
+
+ _config.Configuration.TranscodingTempPath = null;
+ _config.SaveConfiguration();
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Startup.Common/Migrations/PlaylistImages.cs b/MediaBrowser.Server.Startup.Common/Migrations/PlaylistImages.cs
deleted file mode 100644
index f6ddf5847..000000000
--- a/MediaBrowser.Server.Startup.Common/Migrations/PlaylistImages.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using System.IO;
-using System.Linq;
-
-namespace MediaBrowser.Server.Startup.Common.Migrations
-{
- public class PlaylistImages : IVersionMigration
- {
- private readonly IServerConfigurationManager _config;
-
- public PlaylistImages(IServerConfigurationManager config)
- {
- _config = config;
- }
-
- public void Run()
- {
- if (!_config.Configuration.PlaylistImagesDeleted)
- {
- DeletePlaylistImages();
- _config.Configuration.PlaylistImagesDeleted = true;
- _config.SaveConfiguration();
- }
- }
-
- private void DeletePlaylistImages()
- {
- try
- {
- var path = Path.Combine(_config.ApplicationPaths.DataPath, "playlists");
-
- var files = Directory.GetFiles(path, "*", SearchOption.AllDirectories)
- .Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i) ?? string.Empty))
- .ToList();
-
- foreach (var file in files)
- {
- try
- {
- File.Delete(file);
- }
- catch (IOException)
- {
-
- }
- }
- }
- catch (IOException)
- {
-
- }
- }
- }
-}
diff --git a/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs b/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs
index a955b57ea..be8ae2f81 100644
--- a/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs
+++ b/MediaBrowser.Server.Startup.Common/Migrations/RenameXmlOptions.cs
@@ -42,9 +42,9 @@ namespace MediaBrowser.Server.Startup.Common.Migrations
{
for (var i = 0; i < options.Length; i++)
{
- if (string.Equals(options[i], "Media Browser Xml", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(options[i], "Media Browser Legacy Xml", StringComparison.OrdinalIgnoreCase))
{
- options[i] = "Media Browser Legacy Xml";
+ options[i] = "Media Browser Xml";
changed = true;
}
}
diff --git a/MediaBrowser.ServerApplication/Native/RegisterServer.bat b/MediaBrowser.ServerApplication/Native/RegisterServer.bat
index 350412344..3346ecb31 100644
--- a/MediaBrowser.ServerApplication/Native/RegisterServer.bat
+++ b/MediaBrowser.ServerApplication/Native/RegisterServer.bat
@@ -1,21 +1,15 @@
-rem %1 = http server port
-rem %2 = http server url
-rem %3 = udp server port
+rem %1 = udp server port
+rem %2 = http server port
if [%1]==[] GOTO DONE
-netsh advfirewall firewall delete rule name="Port %1" protocol=TCP localport=%1
-netsh advfirewall firewall add rule name="Port %1" dir=in action=allow protocol=TCP localport=%1
+netsh advfirewall firewall delete rule name="Port %1" protocol=UDP localport=%1
+netsh advfirewall firewall add rule name="Port %1" dir=in action=allow protocol=UDP localport=%1
if [%2]==[] GOTO DONE
-netsh http del urlacl url="%2" user="NT AUTHORITY\Authenticated Users"
-netsh http add urlacl url="%2" user="NT AUTHORITY\Authenticated Users"
-
-if [%3]==[] GOTO DONE
-
-netsh advfirewall firewall delete rule name="Port %3" protocol=UDP localport=%3
-netsh advfirewall firewall add rule name="Port %3" dir=in action=allow protocol=UDP localport=%3
+netsh advfirewall firewall delete rule name="Port %2" protocol=TCP localport=%2
+netsh advfirewall firewall add rule name="Port %2" dir=in action=allow protocol=TCP localport=%2
:DONE
diff --git a/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs b/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs
index e5989db3b..d9063aa58 100644
--- a/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs
+++ b/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs
@@ -13,11 +13,10 @@ namespace MediaBrowser.ServerApplication.Native
/// <summary>
/// Authorizes the server.
/// </summary>
- /// <param name="httpServerPort">The HTTP server port.</param>
- /// <param name="httpServerUrlPrefix">The HTTP server URL prefix.</param>
/// <param name="udpPort">The UDP port.</param>
+ /// <param name="httpServerPort">The HTTP server port.</param>
/// <param name="tempDirectory">The temp directory.</param>
- public static void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int udpPort, string tempDirectory)
+ public static void AuthorizeServer(int udpPort, int httpServerPort, string tempDirectory)
{
Directory.CreateDirectory(tempDirectory);
@@ -37,9 +36,7 @@ namespace MediaBrowser.ServerApplication.Native
{
FileName = tmpFile,
- Arguments = string.Format("{0} {1} {2}", httpServerPort,
- httpServerUrlPrefix,
- udpPort),
+ Arguments = string.Format("{0} {1}", udpPort, httpServerPort),
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs
index 9a37c268c..0970d6537 100644
--- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs
+++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs
@@ -21,9 +21,9 @@ namespace MediaBrowser.ServerApplication.Native
return list;
}
- public void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int udpPort, string tempDirectory)
+ public void AuthorizeServer(int httpServerPort, int udpPort, string tempDirectory)
{
- ServerAuthorization.AuthorizeServer(httpServerPort, httpServerUrlPrefix, udpPort, tempDirectory);
+ ServerAuthorization.AuthorizeServer(udpPort, httpServerPort, tempDirectory);
}
public NativeEnvironment Environment
diff --git a/MediaBrowser.Tests/MediaBrowser.Tests.csproj b/MediaBrowser.Tests/MediaBrowser.Tests.csproj
index f93a2612a..e9cec61d6 100644
--- a/MediaBrowser.Tests/MediaBrowser.Tests.csproj
+++ b/MediaBrowser.Tests/MediaBrowser.Tests.csproj
@@ -53,7 +53,6 @@
<Compile Include="MediaEncoding\Subtitles\AssParserTests.cs" />
<Compile Include="MediaEncoding\Subtitles\SrtParserTests.cs" />
<Compile Include="MediaEncoding\Subtitles\VttWriterTest.cs" />
- <Compile Include="Resolvers\TvUtilTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
diff --git a/MediaBrowser.Tests/Resolvers/TvUtilTests.cs b/MediaBrowser.Tests/Resolvers/TvUtilTests.cs
deleted file mode 100644
index ec9356dad..000000000
--- a/MediaBrowser.Tests/Resolvers/TvUtilTests.cs
+++ /dev/null
@@ -1,246 +0,0 @@
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Server.Implementations.Library.Resolvers.TV;
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-namespace MediaBrowser.Tests.Resolvers
-{
- [TestClass]
- public class TvUtilTests
- {
- [TestMethod]
- public void TestGetEpisodeNumberFromFile()
- {
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\S02E03 blah.avi", true));
-
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\01x02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\S01x02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\S01E02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\S01xE02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\seriesname 01x02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\seriesname S01x02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\seriesname S01E02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\seriesname S01xE02 blah.avi", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\Elementary - 02x03 - 02x04 - 02x15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\02x03 - 02x04 - 02x15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\02x03-04-15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\Elementary - 02x03-04-15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\02x03-E15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\Elementary - 02x03-E15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\02x03 - x04 - x15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\Elementary - 02x03 - x04 - x15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\02x03x04x15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 02\Elementary - 02x03x04x15 - Ep Name.ext", true));
- Assert.AreEqual(23, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\Elementary - S01E23-E24-E26 - The Woman.mp4", true));
- Assert.AreEqual(23, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\S01E23-E24-E26 - The Woman.mp4", true));
- Assert.AreEqual(9, SeriesResolver.GetEpisodeNumberFromFile(@"Season 25\The Simpsons.S25E09.Steal this episode.mp4", true));
- Assert.AreEqual(8, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons.S25E08.Steal this episode.mp4", false));
- Assert.AreEqual(136, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\[HorribleSubs] Hunter X Hunter - 136 [720p].mkv",true));
-
- //Four Digits seasons
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\2009x02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\S2009x02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\S2009E02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\S2009xE02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\seriesname 2009x02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\seriesname S2009x02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\seriesname S2009E02 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\seriesname S2009xE02 blah.avi", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\2009x03 - 2009x04 - 2009x15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\2009x03-04-15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03-04-15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\2009x03-E15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03-E15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\2009x03 - x04 - x15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03 - x04 - x15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\2009x03x04x15 - Ep Name.ext", true));
- Assert.AreEqual(03, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03x04x15 - Ep Name.ext", true));
- Assert.AreEqual(23, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\Elementary - S2009E23-E24-E26 - The Woman.mp4", true));
- Assert.AreEqual(23, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2009\S2009E23-E24-E26 - The Woman.mp4", true));
-
- //Without season number
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\02 - blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\02 - blah 14 blah.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 1\02 - blah-02 a.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"Season 2\02.avi", true));
-
- //Without seasons
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\02.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\02 - Ep Name.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\02-Ep Name.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\02.EpName.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons - 02.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons - 02 - Ep Name.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons - 02 Ep Name.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons 5 - 02 - Ep Name.avi", true));
- Assert.AreEqual(02, SeriesResolver.GetEpisodeNumberFromFile(@"The Simpsons\The Simpsons 5 - 02 Ep Name.avi", true));
- }
-
- [TestMethod]
- public void TestGetEndingEpisodeNumberFromFile()
- {
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\4x01 20 Hours in America (1).mkv"));
-
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\01x02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\S01x02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\S01E02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\S01xE02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\seriesname 01x02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\seriesname S01x02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\seriesname S01E02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\seriesname S01xE02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02x03 - 04 Ep Name.ext"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\My show name 02x03 - 04 Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\Elementary - 02x03 - 02x04 - 02x15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02x03 - 02x04 - 02x15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02x03-04-15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\Elementary - 02x03-04-15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 02\02x03-E15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 02\Elementary - 02x03-E15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 02\02x03 - x04 - x15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 02\Elementary - 02x03 - x04 - x15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 02\02x03x04x15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 02\Elementary - 02x03x04x15 - Ep Name.ext"));
- Assert.AreEqual(26, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\Elementary - S01E23-E24-E26 - The Woman.mp4"));
- Assert.AreEqual(26, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\S01E23-E24-E26 - The Woman.mp4"));
-
-
- //Four Digits seasons
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\2009x02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\S2009x02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\S2009E02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\S2009xE02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\seriesname 2009x02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\seriesname S2009x02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\seriesname S2009E02 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\seriesname S2009xE02 blah.avi"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\2009x03 - 2009x04 - 2009x15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\2009x03-04-15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03-04-15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\2009x03-E15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03-E15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\2009x03 - x04 - x15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03 - x04 - x15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\2009x03x04x15 - Ep Name.ext"));
- Assert.AreEqual(15, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\Elementary - 2009x03x04x15 - Ep Name.ext"));
- Assert.AreEqual(26, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\Elementary - S2009E23-E24-E26 - The Woman.mp4"));
- Assert.AreEqual(26, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2009\S2009E23-E24-E26 - The Woman.mp4"));
-
- //Without season number
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\02 - blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02 - blah 14 blah.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\02 - blah-02 a.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02.avi"));
-
- Assert.AreEqual(3, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\02-03 - blah.avi"));
- Assert.AreEqual(4, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02-04 - blah 14 blah.avi"));
- Assert.AreEqual(5, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 1\02-05 - blah-02 a.avi"));
- Assert.AreEqual(4, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\02-04.avi"));
- Assert.AreEqual(null, SeriesResolver.GetEndingEpisodeNumberFromFile(@"Season 2\[HorribleSubs] Hunter X Hunter - 136 [720p].mkv"));
-
- }
-
- [TestMethod]
- public void TestGetSeasonNumberFromPath() {
-
- Assert.AreEqual(02, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"\Show\Season 02\S02E03 blah.avi"));
-
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 02"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 02"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 02"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 02"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 02"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 02"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 1"));
-
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Seinfeld\S02"));
-
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Seinfeld\2"));
-
- //Four Digits seasons
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromPath(@"\Drive\Season 2009"));
- }
-
- [TestMethod]
- public void TestGetSeasonNumberFromEpisodeFile()
- {
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\01x02 blah.avi"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\S01x02 blah.avi"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\S01E02 blah.avi"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\S01xE02 blah.avi"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\seriesname 01x02 blah.avi"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\seriesname S01x02 blah.avi"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\seriesname S01E02 blah.avi"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\seriesname S01xE02 blah.avi"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2\Elementary - 02x03 - 02x04 - 02x15 - Ep Name.ext"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2\02x03 - 02x04 - 02x15 - Ep Name.ext"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2\02x03-04-15 - Ep Name.ext"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2\Elementary - 02x03-04-15 - Ep Name.ext"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 02\02x03-E15 - Ep Name.ext"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 02\Elementary - 02x03-E15 - Ep Name.ext"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 02\02x03 - x04 - x15 - Ep Name.ext"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 02\Elementary - 02x03 - x04 - x15 - Ep Name.ext"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 02\02x03x04x15 - Ep Name.ext"));
- Assert.AreEqual(2, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 02\Elementary - 02x03x04x15 - Ep Name.ext"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\Elementary - S01E23-E24-E26 - The Woman.mp4"));
- Assert.AreEqual(1, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 1\S01E23-E24-E26 - The Woman.mp4"));
-
- //Four Digits seasons
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\2009x02 blah.avi"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\S2009x02 blah.avi"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\S2009E02 blah.avi"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\S2009xE02 blah.avi"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\seriesname 2009x02 blah.avi"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\seriesname S2009x02 blah.avi"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\seriesname S2009E02 blah.avi"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\seriesname S2009xE02 blah.avi"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.ext"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\2009x03 - 2009x04 - 2009x15 - Ep Name.ext"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\2009x03-04-15 - Ep Name.ext"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\Elementary - 2009x03-04-15 - Ep Name.ext"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\2009x03-E15 - Ep Name.ext"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\Elementary - 2009x03-E15 - Ep Name.ext"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\2009x03 - x04 - x15 - Ep Name.ext"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\Elementary - 2009x03 - x04 - x15 - Ep Name.ext"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\2009x03x04x15 - Ep Name.ext"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\Elementary - 2009x03x04x15 - Ep Name.ext"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\Elementary - S2009E23-E24-E26 - The Woman.mp4"));
- Assert.AreEqual(2009, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 2009\S2009E23-E24-E26 - The Woman.mp4"));
- Assert.AreEqual(25, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"Season 25\The Simpsons.S25E09.Steal this episode.mp4"));
- Assert.AreEqual(25, SeriesResolver.GetSeasonNumberFromEpisodeFile(@"The Simpsons\The Simpsons.S25E09.Steal this episode.mp4"));
- }
- }
-}
diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs
index eb44f6d35..6e3439079 100644
--- a/MediaBrowser.WebDashboard/Api/DashboardService.cs
+++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs
@@ -8,6 +8,7 @@ using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
using ServiceStack;
using ServiceStack.Web;
diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
index b3a1bf84a..d727dda6e 100644
--- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs
+++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
@@ -197,6 +197,8 @@ namespace MediaBrowser.WebDashboard.Api
{
"thirdparty/jquerymobile-1.4.5/jquery.mobile-1.4.5.min.css",
"thirdparty/swipebox-master/css/swipebox.min.css" + versionString,
+ "thirdparty/fontawesome/css/font-awesome.min.css" + versionString,
+ "thirdparty/jstree3.0.8/themes/default/style.min.css",
"css/all.css" + versionString
};
@@ -219,7 +221,7 @@ namespace MediaBrowser.WebDashboard.Api
var files = new[]
{
"scripts/all.js" + versionString,
- "thirdparty/jstree1.0/jquery.jstree.min.js",
+ "thirdparty/jstree3.0.8/jstree.min.js",
"thirdparty/swipebox-master/js/jquery.swipebox.min.js" + versionString
};
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index d8e6561ab..dc552c518 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -210,9 +210,6 @@
<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\icons\ellipsis-v.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -228,9 +225,6 @@
<Content Include="dashboard-ui\css\images\items\folders\report.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\icons\audiocd.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -594,9 +588,6 @@
<Content Include="dashboard-ui\css\images\rotten.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\css\images\currentuserdefaultwhite.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\css\images\items\detail\person.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -963,625 +954,19 @@
<Content Include="dashboard-ui\thirdparty\cast_sender.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquery-2.1.1.min.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquery.unveil-custom.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\ajax-loader.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\action-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\action-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\alert-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\alert-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-d-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-d-l-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-d-l-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-d-r-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-d-r-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-d-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-l-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-l-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-r-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-r-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-u-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-u-l-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-u-l-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-u-r-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-u-r-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\arrow-u-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\audio-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\audio-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\back-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\back-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\bars-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\bars-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\bullets-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\bullets-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\calendar-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\calendar-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\camera-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\camera-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\carat-d-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\carat-d-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\carat-l-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\carat-l-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\carat-r-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\carat-r-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\carat-u-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\carat-u-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\check-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\check-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\clock-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\clock-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\cloud-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\cloud-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\comment-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\comment-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\delete-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\delete-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\edit-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\edit-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\eye-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\eye-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\forbidden-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\forbidden-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\forward-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\forward-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\gear-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\gear-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\grid-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\grid-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\heart-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\heart-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\home-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\home-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\info-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\info-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\location-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\location-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\lock-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\lock-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\mail-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\mail-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\minus-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\minus-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\navigation-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\navigation-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\phone-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\phone-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\plus-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\plus-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\power-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\power-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\recycle-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\recycle-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\refresh-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\refresh-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\search-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\search-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\shop-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\shop-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\star-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\star-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\tag-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\tag-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\user-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\user-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\video-black.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-png\video-white.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\action-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\action-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\alert-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\alert-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-d-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-d-l-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-d-l-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-d-r-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-d-r-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-d-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-l-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-l-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-r-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-r-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-u-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-u-l-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-u-l-white.svg">
+ <Content Include="dashboard-ui\thirdparty\fontawesome\css\font-awesome.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-u-r-black.svg">
+ <Content Include="dashboard-ui\thirdparty\fontawesome\css\font-awesome.min.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-u-r-white.svg">
+ <Content Include="dashboard-ui\thirdparty\fontawesome\fonts\fontawesome-webfont.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\arrow-u-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\audio-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\audio-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\back-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\back-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\bars-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\bars-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\bullets-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\bullets-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\calendar-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\calendar-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\camera-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\camera-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\carat-d-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\carat-d-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\carat-l-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\carat-l-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\carat-r-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\carat-r-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\carat-u-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\carat-u-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\check-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\check-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\clock-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\clock-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\cloud-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\cloud-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\comment-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\comment-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\delete-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\delete-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\edit-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\edit-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\eye-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\eye-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\forbidden-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\forbidden-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\forward-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\forward-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\gear-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\gear-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\grid-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\grid-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\heart-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\heart-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\home-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\home-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\info-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\info-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\location-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\location-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\lock-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\lock-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\mail-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\mail-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\minus-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\minus-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\navigation-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\navigation-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\phone-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\phone-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\plus-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\plus-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\power-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\power-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\recycle-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\recycle-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\refresh-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\refresh-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\search-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\search-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\shop-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\shop-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\star-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\star-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\tag-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\tag-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\user-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\user-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\video-black.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\images\icons-svg\video-white.svg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\jquery.mobile-1.4.3.min.css">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\jquery.mobile-1.4.3.min.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\jquery.mobile-1.4.4.min.css">
+ <Content Include="dashboard-ui\thirdparty\jquery-2.1.1.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\jquery.mobile-1.4.4.min.js">
+ <Content Include="dashboard-ui\thirdparty\jquery.unveil-custom.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\images\ajax-loader.gif">
@@ -2193,15 +1578,48 @@
<Content Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jquery.mobile-1.4.5.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\jquery.jstree.min.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\livetvsuggested.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\thirdparty\apiclient\md5.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
+ <Content Include="dashboard-ui\thirdparty\jstree3.0.8\jstree.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jstree3.0.8\jstree.min.js">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jstree3.0.8\themes\default-dark\32px.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jstree3.0.8\themes\default-dark\40px.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jstree3.0.8\themes\default-dark\style.css">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jstree3.0.8\themes\default-dark\style.min.css">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jstree3.0.8\themes\default-dark\throbber.gif">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jstree3.0.8\themes\default\32px.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jstree3.0.8\themes\default\40px.png">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jstree3.0.8\themes\default\style.css">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jstree3.0.8\themes\default\style.min.css">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
+ <Content Include="dashboard-ui\thirdparty\jstree3.0.8\themes\default\throbber.gif">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </Content>
<Content Include="dashboard-ui\thirdparty\swipebox-master\css\swipebox.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -2438,78 +1856,6 @@
<Content Include="dashboard-ui\scripts\tvstudios.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\jquery.jstree.js">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\apple\bg.jpg">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\apple\d.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\apple\dot_for_ie.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\apple\style.css">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\apple\throbber.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\classic\d.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\classic\d.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\classic\dot_for_ie.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\classic\style.css">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\classic\throbber.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\default-rtl\d.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\default-rtl\d.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\default-rtl\dots.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\default-rtl\style.css">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\default-rtl\throbber.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\default\d.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\default\d.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\default\style.css">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\default\throbber.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\mb3\d.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\mb3\d.png">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\mb3\style.css">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
- <Content Include="dashboard-ui\thirdparty\jstree1.0\themes\mb3\throbber.gif">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </Content>
<Content Include="dashboard-ui\tvgenres.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -2917,10 +2263,16 @@
<None Include="dashboard-ui\css\fonts\RobotoThin.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
- <None Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\jquery.mobile-1.4.3.min.map">
+ <None Include="dashboard-ui\thirdparty\fontawesome\fonts\fontawesome-webfont.eot">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="dashboard-ui\thirdparty\fontawesome\fonts\fontawesome-webfont.ttf">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ <None Include="dashboard-ui\thirdparty\fontawesome\fonts\fontawesome-webfont.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
- <None Include="dashboard-ui\thirdparty\jquerymobile-1.4.4\jquery.mobile-1.4.4.min.map">
+ <None Include="dashboard-ui\thirdparty\fontawesome\fonts\FontAwesome.otf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="dashboard-ui\thirdparty\jquerymobile-1.4.5\jquery.mobile-1.4.5.min.map">
diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
index 86e92530f..0f1d53ea6 100644
--- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
+++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
@@ -257,6 +257,10 @@ namespace MediaBrowser.XbmcMetadata.Savers
{
}
+ catch (DirectoryNotFoundException)
+ {
+
+ }
writer.WriteEndElement();
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index 22c2fdc24..c081917fb 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -7,7 +7,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{F0E0E6
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8C5D6ABC-D277-407B-8061-3AA04251D539}"
ProjectSection(SolutionItems) = preProject
+ Performance1.psess = Performance1.psess
Performance19.psess = Performance19.psess
+ Performance2.psess = Performance2.psess
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget (2)", ".nuget (2)", "{E60FB157-87E2-4A41-8B04-27EA49B63B4D}"
@@ -516,4 +518,7 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(Performance) = preSolution
+ HasPerformanceSessions = true
+ EndGlobalSection
EndGlobal
diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec
index 3ecc9f9a9..f637622ef 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.521</version>
+ <version>3.0.534</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@@ -12,7 +12,7 @@
<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.521" />
+ <dependency id="MediaBrowser.Common" version="3.0.534" />
<dependency id="NLog" version="3.1.0.0" />
<dependency id="SimpleInjector" version="2.6.1" />
<dependency id="sharpcompress" version="0.10.2" />
diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec
index da3e29b2a..eddbcd0d2 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.521</version>
+ <version>3.0.534</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec
index b0fe2b2c4..7e10950b0 100644
--- a/Nuget/MediaBrowser.Model.Signed.nuspec
+++ b/Nuget/MediaBrowser.Model.Signed.nuspec
@@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Model.Signed</id>
- <version>3.0.521</version>
+ <version>3.0.534</version>
<title>MediaBrowser.Model - Signed Edition</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 57d224fd4..7fde54fe4 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.521</version>
+ <version>3.0.534</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.521" />
+ <dependency id="MediaBrowser.Common" version="3.0.534" />
</dependencies>
</metadata>
<files>
diff --git a/SharedVersion.cs b/SharedVersion.cs
index d323dc7bc..ac09f77b3 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,4 +1,4 @@
using System.Reflection;
-//[assembly: AssemblyVersion("3.0.*")]
-[assembly: AssemblyVersion("3.0.5464.40000")]
+[assembly: AssemblyVersion("3.0.*")]
+//[assembly: AssemblyVersion("3.0.5464.40000")]