From 0d28929e171992e55ab220b878edaec59e81b0ae Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 3 Nov 2017 14:11:04 -0400 Subject: update download progress reporting --- .../Localization/Core/ar.json | 7 +--- .../Localization/Core/bg-BG.json | 45 ++++++++++------------ .../Localization/Core/ca.json | 7 +--- .../Localization/Core/cs.json | 7 +--- .../Localization/Core/da.json | 7 +--- .../Localization/Core/de.json | 7 +--- .../Localization/Core/en-GB.json | 7 +--- .../Localization/Core/es-AR.json | 7 +--- .../Localization/Core/es-MX.json | 7 +--- .../Localization/Core/es.json | 13 ++----- .../Localization/Core/fr-CA.json | 7 +--- .../Localization/Core/fr.json | 7 +--- .../Localization/Core/he.json | 7 +--- .../Localization/Core/hr.json | 7 +--- .../Localization/Core/hu.json | 7 +--- .../Localization/Core/it.json | 7 +--- .../Localization/Core/kk.json | 7 +--- .../Localization/Core/ko.json | 7 +--- .../Localization/Core/lt-LT.json | 7 +--- .../Localization/Core/ms.json | 7 +--- .../Localization/Core/nb.json | 7 +--- .../Localization/Core/nl.json | 7 +--- .../Localization/Core/pl.json | 9 +---- .../Localization/Core/pt-BR.json | 7 +--- .../Localization/Core/pt-PT.json | 7 +--- .../Localization/Core/ru.json | 7 +--- .../Localization/Core/sk.json | 7 +--- .../Localization/Core/sl-SI.json | 7 +--- .../Localization/Core/sv.json | 7 +--- .../Localization/Core/tr.json | 7 +--- .../Localization/Core/zh-CN.json | 7 +--- .../Localization/Core/zh-HK.json | 7 +--- 32 files changed, 55 insertions(+), 215 deletions(-) (limited to 'Emby.Server.Implementations/Localization/Core') diff --git a/Emby.Server.Implementations/Localization/Core/ar.json b/Emby.Server.Implementations/Localization/Core/ar.json index 0c2ab1f6d..54200605d 100644 --- a/Emby.Server.Implementations/Localization/Core/ar.json +++ b/Emby.Server.Implementations/Localization/Core/ar.json @@ -87,10 +87,5 @@ "User": "\u0627\u0644\u0645\u0633\u062a\u062e\u062f\u0645", "System": "\u0627\u0644\u0646\u0638\u0627\u0645", "Application": "\u0627\u0644\u062a\u0637\u0628\u064a\u0642", - "Plugin": "\u0627\u0644\u0645\u0644\u062d\u0642", - "LabelExit": "\u062e\u0631\u0648\u062c", - "LabelVisitCommunity": "\u0632\u064a\u0627\u0631\u0629 \u0627\u0644\u0645\u062c\u062a\u0645\u0639", - "LabelBrowseLibrary": "\u062a\u0635\u0641\u062d \u0627\u0644\u0645\u0643\u062a\u0628\u0629", - "LabelConfigureServer": "\u0636\u0628\u0637 \u0625\u0639\u062f\u0627\u062f\u0627\u062a \u0623\u0645\u0628\u064a", - "LabelRestartServer": "\u0625\u0639\u0627\u062f\u0629 \u062a\u0634\u063a\u064a\u0644 \u0627\u0644\u062e\u0627\u062f\u0645" + "Plugin": "\u0627\u0644\u0645\u0644\u062d\u0642" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/bg-BG.json b/Emby.Server.Implementations/Localization/Core/bg-BG.json index 40899caab..cc7611bf4 100644 --- a/Emby.Server.Implementations/Localization/Core/bg-BG.json +++ b/Emby.Server.Implementations/Localization/Core/bg-BG.json @@ -6,7 +6,7 @@ "Music": "\u041c\u0443\u0437\u0438\u043a\u0430", "Games": "\u0418\u0433\u0440\u0438", "Photos": "\u0421\u043d\u0438\u043c\u043a\u0438", - "MixedContent": "Mixed content", + "MixedContent": "\u0421\u043c\u0435\u0441\u0435\u043d\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435", "MusicVideos": "\u041c\u0443\u0437\u0438\u043a\u0430\u043b\u043d\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", "HomeVideos": "\u0414\u043e\u043c\u0430\u0448\u043d\u0438 \u043a\u043b\u0438\u043f\u043e\u0432\u0435", "Playlists": "\u0421\u043f\u0438\u0441\u044a\u0446\u0438", @@ -17,8 +17,8 @@ "HeaderAlbumArtists": "\u0418\u0437\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u0438 \u043d\u0430 \u0430\u043b\u0431\u0443\u043c\u0438", "HeaderFavoriteAlbums": "\u041b\u044e\u0431\u0438\u043c\u0438 \u0430\u043b\u0431\u0443\u043c\u0438", "HeaderFavoriteEpisodes": "\u041b\u044e\u0431\u0438\u043c\u0438 \u0435\u043f\u0438\u0437\u043e\u0434\u0438", - "HeaderFavoriteShows": "Favorite Shows", - "HeaderNextUp": "Next Up", + "HeaderFavoriteShows": "\u041b\u044e\u0431\u0438\u043c\u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u0438", + "HeaderNextUp": "\u0421\u043b\u0435\u0434\u0432\u0430", "Favorites": "\u041b\u044e\u0431\u0438\u043c\u0438", "Collections": "\u041a\u043e\u043b\u0435\u043a\u0446\u0438\u0438", "Channels": "\u041a\u0430\u043d\u0430\u043b\u0438", @@ -27,28 +27,28 @@ "Artists": "\u0418\u0437\u043f\u044a\u043b\u043d\u0438\u0442\u0435\u043b\u0438", "Folders": "\u041f\u0430\u043f\u043a\u0438", "Songs": "\u041f\u0435\u0441\u043d\u0438", - "TvShows": "TV Shows", + "TvShows": "\u0422\u0435\u043b\u0435\u0432\u0438\u0437\u0438\u043e\u043d\u043d\u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u0438", "Shows": "\u0421\u0435\u0440\u0438\u0430\u043b\u0438", "Genres": "\u0416\u0430\u043d\u0440\u043e\u0432\u0435", "NameSeasonNumber": "\u0421\u0435\u0437\u043e\u043d {0}", - "AppDeviceValues": "App: {0}, Device: {1}", + "AppDeviceValues": "\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u0430: {0}, \u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e: {1}", "UserDownloadingItemWithValues": "{0} is downloading {1}", - "HeaderLiveTV": "Live TV", - "ChapterNameValue": "Chapter {0}", + "HeaderLiveTV": "\u0422\u0435\u043b\u0435\u0432\u0438\u0437\u0438\u044f \u043d\u0430 \u0436\u0438\u0432\u043e", + "ChapterNameValue": "\u0413\u043b\u0430\u0432\u0430 {0}", "ScheduledTaskFailedWithName": "{0} failed", "LabelRunningTimeValue": "Running time: {0}", "ScheduledTaskStartedWithName": "{0} \u0437\u0430\u043f\u043e\u0447\u043d\u0430", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly.", - "PluginUpdatedWithName": "{0} was updated", + "VersionNumber": "\u0412\u0435\u0440\u0441\u0438\u044f {0}", + "PluginInstalledWithName": "{0} \u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u043e", + "StartupEmbyServerIsLoading": "\u0421\u044a\u0440\u0432\u044a\u0440\u044a\u0442 \u0437\u0430\u0440\u0435\u0436\u0434\u0430. \u041c\u043e\u043b\u044f, \u043e\u043f\u0438\u0442\u0430\u0439\u0442\u0435 \u043e\u0442\u043d\u043e\u0432\u043e \u0441\u043b\u0435\u0434 \u043c\u0430\u043b\u043a\u043e.", + "PluginUpdatedWithName": "{0} \u0435 \u043e\u0431\u043d\u043e\u0432\u0435\u043d\u043e", "PluginUninstalledWithName": "{0} \u0435 \u0434\u0435\u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u043e", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", + "ItemAddedWithName": "{0} \u0435 \u0434\u043e\u0431\u0430\u0432\u0435\u043d\u043e \u043a\u044a\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0442\u0430", + "ItemRemovedWithName": "{0} \u0435 \u043f\u0440\u0435\u043c\u0430\u0445\u043d\u0430\u0442\u043e \u043e\u0442 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0442\u0430", + "LabelIpAddressValue": "\u0418\u041f \u0430\u0434\u0440\u0435\u0441: {0}", + "DeviceOnlineWithName": "{0} \u0435 \u0441\u0432\u044a\u0440\u0437\u0430\u043d", + "UserOnlineFromDevice": "{0} \u0435 \u043d\u0430 \u043b\u0438\u043d\u0438\u044f \u043e\u0442 {1}", + "ProviderValue": "\u0414\u043e\u0441\u0442\u0430\u0432\u0447\u0438\u043a: {0}", "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", "UserCreatedWithName": "User {0} has been created", "UserPasswordChangedWithName": "Password has been changed for user {0}", @@ -77,7 +77,7 @@ "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionTaskFailed": "Scheduled task failure", "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", + "NotificationOptionNewLibraryContent": "\u0414\u043e\u0431\u0430\u0432\u0435\u043d\u043e \u0435 \u043d\u043e\u0432\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435", "NotificationOptionCameraImageUploaded": "Camera image uploaded", "NotificationOptionUserLockedOut": "User locked out", "NotificationOptionServerRestartRequired": "\u041d\u0443\u0436\u043d\u043e \u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0443\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u0430", @@ -86,11 +86,6 @@ "Sync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0430\u043d\u0435", "User": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b", "System": "\u0421\u0438\u0441\u0442\u0435\u043c\u0430", - "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "\u041f\u043e\u0441\u0435\u0442\u0435\u0442\u0435 \u043e\u0431\u0449\u043d\u043e\u0441\u0442\u0442\u0430", - "LabelBrowseLibrary": "\u0420\u0430\u0437\u0433\u043b\u0435\u0436\u0434\u0430\u043d\u0435 \u043d\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0442\u0430", - "LabelConfigureServer": "\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0415\u043c\u0431\u0438", - "LabelRestartServer": "\u041f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0443\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u0430" + "Application": "\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u0430", + "Plugin": "\u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/ca.json b/Emby.Server.Implementations/Localization/Core/ca.json index cc2c00234..f21a0b295 100644 --- a/Emby.Server.Implementations/Localization/Core/ca.json +++ b/Emby.Server.Implementations/Localization/Core/ca.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/cs.json b/Emby.Server.Implementations/Localization/Core/cs.json index abbfde380..82d8699a7 100644 --- a/Emby.Server.Implementations/Localization/Core/cs.json +++ b/Emby.Server.Implementations/Localization/Core/cs.json @@ -87,10 +87,5 @@ "User": "U\u017eivatel", "System": "Syst\u00e9m", "Application": "Aplikace", - "Plugin": "Z\u00e1suvn\u00fd modul", - "LabelExit": "Uko\u010dit", - "LabelVisitCommunity": "Nav\u0161t\u00edvit komunitu", - "LabelBrowseLibrary": "Proch\u00e1zet knihovnu", - "LabelConfigureServer": "Konfigurovat Emby", - "LabelRestartServer": "Restartovat Server" + "Plugin": "Z\u00e1suvn\u00fd modul" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json index ed9652c33..eb05943f9 100644 --- a/Emby.Server.Implementations/Localization/Core/da.json +++ b/Emby.Server.Implementations/Localization/Core/da.json @@ -87,10 +87,5 @@ "User": "Bruger", "System": "System", "Application": "Applikation", - "Plugin": "Plugin", - "LabelExit": "Afslut", - "LabelVisitCommunity": "Bes\u00f8g F\u00e6llesskab", - "LabelBrowseLibrary": "Gennemse Bibliotek", - "LabelConfigureServer": "Konfigurer Emby", - "LabelRestartServer": "Genstart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json index 183b4aaf8..7bab689eb 100644 --- a/Emby.Server.Implementations/Localization/Core/de.json +++ b/Emby.Server.Implementations/Localization/Core/de.json @@ -87,10 +87,5 @@ "User": "Benutzer", "System": "System", "Application": "Anwendung", - "Plugin": "Plugin", - "LabelExit": "Beenden", - "LabelVisitCommunity": "Besuche die Community", - "LabelBrowseLibrary": "Bibliothek durchsuchen", - "LabelConfigureServer": "Konfiguriere Emby", - "LabelRestartServer": "Server neustarten" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/en-GB.json b/Emby.Server.Implementations/Localization/Core/en-GB.json index 8dc9abf01..62db5a358 100644 --- a/Emby.Server.Implementations/Localization/Core/en-GB.json +++ b/Emby.Server.Implementations/Localization/Core/en-GB.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/es-AR.json b/Emby.Server.Implementations/Localization/Core/es-AR.json index e4a49abf6..c48042d9a 100644 --- a/Emby.Server.Implementations/Localization/Core/es-AR.json +++ b/Emby.Server.Implementations/Localization/Core/es-AR.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/es-MX.json b/Emby.Server.Implementations/Localization/Core/es-MX.json index 45cc2c69b..303df142a 100644 --- a/Emby.Server.Implementations/Localization/Core/es-MX.json +++ b/Emby.Server.Implementations/Localization/Core/es-MX.json @@ -87,10 +87,5 @@ "User": "Usuario", "System": "Sistema", "Application": "Aplicaci\u00f3n", - "Plugin": "Complemento", - "LabelExit": "Salir", - "LabelVisitCommunity": "Visitar la Comunidad", - "LabelBrowseLibrary": "Explorar Biblioteca", - "LabelConfigureServer": "Configurar Emby", - "LabelRestartServer": "Reiniciar el Servidor" + "Plugin": "Complemento" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/es.json b/Emby.Server.Implementations/Localization/Core/es.json index 68975d632..c7fa51c03 100644 --- a/Emby.Server.Implementations/Localization/Core/es.json +++ b/Emby.Server.Implementations/Localization/Core/es.json @@ -27,7 +27,7 @@ "Artists": "Artistas", "Folders": "Carpetas", "Songs": "Canciones", - "TvShows": "TV Shows", + "TvShows": "Series TV", "Shows": "Series", "Genres": "G\u00e9neros", "NameSeasonNumber": "Temporada {0}", @@ -61,8 +61,8 @@ "AuthenticationSucceededWithUserName": "{0} autenticado correctamente", "UserOfflineFromDevice": "{0} se ha desconectado de {1}", "DeviceOfflineWithName": "{0} se ha desconectado", - "UserStartedPlayingItemWithValues": "{0} ha comenzado jugando {1}", - "UserStoppedPlayingItemWithValues": "{0} ha dejado de reproducir {1}", + "UserStartedPlayingItemWithValues": "{0} ha comenzado reproducir {1}", + "UserStoppedPlayingItemWithValues": "{0} ha parado de reproducir {1}", "NotificationOptionPluginError": "Error en plugin", "NotificationOptionApplicationUpdateAvailable": "Actualizaci\u00f3n de la aplicaci\u00f3n disponible", "NotificationOptionApplicationUpdateInstalled": "Actualizaci\u00f3n de la aplicaci\u00f3n instalada", @@ -87,10 +87,5 @@ "User": "Usuario", "System": "Sistema", "Application": "Aplicaci\u00f3n", - "Plugin": "Plugin", - "LabelExit": "Salida", - "LabelVisitCommunity": "Visita la Comunidad", - "LabelBrowseLibrary": "Navegar la biblioteca", - "LabelConfigureServer": "Configurar Emby", - "LabelRestartServer": "Configurar Emby" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/fr-CA.json b/Emby.Server.Implementations/Localization/Core/fr-CA.json index 795bc98cc..7743905f0 100644 --- a/Emby.Server.Implementations/Localization/Core/fr-CA.json +++ b/Emby.Server.Implementations/Localization/Core/fr-CA.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json index 5ea01fcdb..953d7f434 100644 --- a/Emby.Server.Implementations/Localization/Core/fr.json +++ b/Emby.Server.Implementations/Localization/Core/fr.json @@ -87,10 +87,5 @@ "User": "Utilisateur", "System": "Syst\u00e8me", "Application": "Application", - "Plugin": "Extension", - "LabelExit": "Quitter", - "LabelVisitCommunity": "Visiter la communaut\u00e9", - "LabelBrowseLibrary": "Parcourir la m\u00e9diath\u00e8que", - "LabelConfigureServer": "Configurer Emby", - "LabelRestartServer": "Red\u00e9marrer le serveur" + "Plugin": "Extension" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/he.json b/Emby.Server.Implementations/Localization/Core/he.json index f287dc422..c679ed289 100644 --- a/Emby.Server.Implementations/Localization/Core/he.json +++ b/Emby.Server.Implementations/Localization/Core/he.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/hr.json b/Emby.Server.Implementations/Localization/Core/hr.json index 143e3ab82..c807e53b4 100644 --- a/Emby.Server.Implementations/Localization/Core/hr.json +++ b/Emby.Server.Implementations/Localization/Core/hr.json @@ -87,10 +87,5 @@ "User": "Korisnik", "System": "Sistem", "Application": "Aplikacija", - "Plugin": "Dodatak", - "LabelExit": "Izlaz", - "LabelVisitCommunity": "Posjeti zajednicu", - "LabelBrowseLibrary": "Pregledaj biblioteku", - "LabelConfigureServer": "Podesi Emby", - "LabelRestartServer": "Restartiraj Server" + "Plugin": "Dodatak" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/hu.json b/Emby.Server.Implementations/Localization/Core/hu.json index 39d0f8061..dc8f2b702 100644 --- a/Emby.Server.Implementations/Localization/Core/hu.json +++ b/Emby.Server.Implementations/Localization/Core/hu.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Kil\u00e9p\u00e9s", - "LabelVisitCommunity": "K\u00f6z\u00f6ss\u00e9g", - "LabelBrowseLibrary": "M\u00e9diat\u00e1r tall\u00f3z\u00e1sa", - "LabelConfigureServer": "Emby konfigur\u00e1l\u00e1sa", - "LabelRestartServer": "Szerver \u00fajraindit\u00e1sa" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/it.json b/Emby.Server.Implementations/Localization/Core/it.json index 4ff0d98d8..42605acdb 100644 --- a/Emby.Server.Implementations/Localization/Core/it.json +++ b/Emby.Server.Implementations/Localization/Core/it.json @@ -87,10 +87,5 @@ "User": "Utente", "System": "Sistema", "Application": "Applicazione", - "Plugin": "Plug-in", - "LabelExit": "Esci", - "LabelVisitCommunity": "Visita il forum di discussione", - "LabelBrowseLibrary": "Esplora la libreria", - "LabelConfigureServer": "Configura Emby", - "LabelRestartServer": "Riavvia Server" + "Plugin": "Plug-in" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/kk.json b/Emby.Server.Implementations/Localization/Core/kk.json index c24ee3d13..a991fe363 100644 --- a/Emby.Server.Implementations/Localization/Core/kk.json +++ b/Emby.Server.Implementations/Localization/Core/kk.json @@ -87,10 +87,5 @@ "User": "\u041f\u0430\u0439\u0434\u0430\u043b\u0430\u043d\u0443\u0448\u044b", "System": "\u0416\u04af\u0439\u0435", "Application": "\u049a\u043e\u043b\u0434\u0430\u043d\u0431\u0430", - "Plugin": "\u041f\u043b\u0430\u0433\u0438\u043d", - "LabelExit": "\u0428\u044b\u0493\u0443", - "LabelVisitCommunity": "\u049a\u0430\u0443\u044b\u043c\u0434\u0430\u0441\u0442\u044b\u049b\u049b\u0430 \u0431\u0430\u0440\u0443", - "LabelBrowseLibrary": "\u0422\u0430\u0441\u044b\u0493\u044b\u0448\u0445\u0430\u043d\u0430\u043d\u044b \u0448\u043e\u043b\u0443", - "LabelConfigureServer": "Emby \u0442\u0435\u04a3\u0448\u0435\u0443", - "LabelRestartServer": "\u0421\u0435\u0440\u0432\u0435\u0440\u0434\u0456 \u049b\u0430\u0439\u0442\u0430 \u0456\u0441\u043a\u0435 \u049b\u043e\u0441\u0443" + "Plugin": "\u041f\u043b\u0430\u0433\u0438\u043d" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/ko.json b/Emby.Server.Implementations/Localization/Core/ko.json index 6c5ed0260..0f99c8432 100644 --- a/Emby.Server.Implementations/Localization/Core/ko.json +++ b/Emby.Server.Implementations/Localization/Core/ko.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/lt-LT.json b/Emby.Server.Implementations/Localization/Core/lt-LT.json index 21ed36d7c..9e1fede1d 100644 --- a/Emby.Server.Implementations/Localization/Core/lt-LT.json +++ b/Emby.Server.Implementations/Localization/Core/lt-LT.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/ms.json b/Emby.Server.Implementations/Localization/Core/ms.json index e4a49abf6..c48042d9a 100644 --- a/Emby.Server.Implementations/Localization/Core/ms.json +++ b/Emby.Server.Implementations/Localization/Core/ms.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/nb.json b/Emby.Server.Implementations/Localization/Core/nb.json index d0482315d..5cd9894be 100644 --- a/Emby.Server.Implementations/Localization/Core/nb.json +++ b/Emby.Server.Implementations/Localization/Core/nb.json @@ -87,10 +87,5 @@ "User": "Bruker", "System": "System", "Application": "Applikasjon", - "Plugin": "Plugin", - "LabelExit": "Avslutt", - "LabelVisitCommunity": "Bes\u00f8k Samfunnet", - "LabelBrowseLibrary": "Bla i biblioteket", - "LabelConfigureServer": "Konfigurere Emby", - "LabelRestartServer": "Start om serveren" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json index daba9bed5..d79fcf747 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -87,10 +87,5 @@ "User": "Gebruiker", "System": "Systeem", "Application": "Toepassing", - "Plugin": "Plug-in", - "LabelExit": "Afsluiten", - "LabelVisitCommunity": "Bezoek Gemeenschap", - "LabelBrowseLibrary": "Bekijk bibliotheek", - "LabelConfigureServer": "Emby Configureren", - "LabelRestartServer": "Server herstarten" + "Plugin": "Plug-in" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/pl.json b/Emby.Server.Implementations/Localization/Core/pl.json index 24ac0d973..896df24dd 100644 --- a/Emby.Server.Implementations/Localization/Core/pl.json +++ b/Emby.Server.Implementations/Localization/Core/pl.json @@ -27,7 +27,7 @@ "Artists": "Wykonawcy", "Folders": "Foldery", "Songs": "Utwory", - "TvShows": "TV Shows", + "TvShows": "Seriale", "Shows": "Seriale", "Genres": "Gatunki", "NameSeasonNumber": "Sezon {0}", @@ -87,10 +87,5 @@ "User": "U\u017cytkownik", "System": "System", "Application": "Aplikacja", - "Plugin": "Wtyczka", - "LabelExit": "Wyj\u015bcie", - "LabelVisitCommunity": "Odwied\u017a spo\u0142eczno\u015b\u0107", - "LabelBrowseLibrary": "Przegl\u0105daj bibliotek\u0119", - "LabelConfigureServer": "Konfiguracja Emby", - "LabelRestartServer": "Uruchom serwer ponownie" + "Plugin": "Wtyczka" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/pt-BR.json b/Emby.Server.Implementations/Localization/Core/pt-BR.json index 196a6b78b..fa4eac1c4 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-BR.json +++ b/Emby.Server.Implementations/Localization/Core/pt-BR.json @@ -87,10 +87,5 @@ "User": "Usu\u00e1rio", "System": "Sistema", "Application": "Aplicativo", - "Plugin": "Plugin", - "LabelExit": "Sair", - "LabelVisitCommunity": "Visite a Comunidade", - "LabelBrowseLibrary": "Explorar Biblioteca", - "LabelConfigureServer": "Configurar Emby", - "LabelRestartServer": "Reiniciar Servidor" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/pt-PT.json b/Emby.Server.Implementations/Localization/Core/pt-PT.json index 7a6b8f419..ac20fa1e5 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-PT.json +++ b/Emby.Server.Implementations/Localization/Core/pt-PT.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Aplica\u00e7\u00e3o", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json index d27b1ca93..12345ca14 100644 --- a/Emby.Server.Implementations/Localization/Core/ru.json +++ b/Emby.Server.Implementations/Localization/Core/ru.json @@ -87,10 +87,5 @@ "User": "\u041f\u043e\u043b\u044c\u0437-\u043b\u044c", "System": "\u0421\u0438\u0441\u0442\u0435\u043c\u0430", "Application": "\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435", - "Plugin": "\u041f\u043b\u0430\u0433\u0438\u043d", - "LabelExit": "\u0412\u044b\u0445\u043e\u0434", - "LabelVisitCommunity": "\u041f\u043e\u0441\u0435\u0449\u0435\u043d\u0438\u0435 \u0421\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430", - "LabelBrowseLibrary": "\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f \u043f\u043e \u043c\u0435\u0434\u0438\u0430\u0442\u0435\u043a\u0435", - "LabelConfigureServer": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Emby", - "LabelRestartServer": "\u041f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0430" + "Plugin": "\u041f\u043b\u0430\u0433\u0438\u043d" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/sk.json b/Emby.Server.Implementations/Localization/Core/sk.json index 98f60e5e1..aa6ada912 100644 --- a/Emby.Server.Implementations/Localization/Core/sk.json +++ b/Emby.Server.Implementations/Localization/Core/sk.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/sl-SI.json b/Emby.Server.Implementations/Localization/Core/sl-SI.json index cb8e080e4..27561a890 100644 --- a/Emby.Server.Implementations/Localization/Core/sl-SI.json +++ b/Emby.Server.Implementations/Localization/Core/sl-SI.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/sv.json b/Emby.Server.Implementations/Localization/Core/sv.json index a03881183..c43bd79a6 100644 --- a/Emby.Server.Implementations/Localization/Core/sv.json +++ b/Emby.Server.Implementations/Localization/Core/sv.json @@ -87,10 +87,5 @@ "User": "Anv\u00e4ndare", "System": "System", "Application": "App", - "Plugin": "Till\u00e4gg", - "LabelExit": "Avsluta", - "LabelVisitCommunity": "Bes\u00f6k v\u00e5rt diskussionsforum", - "LabelBrowseLibrary": "Bl\u00e4ddra i biblioteket", - "LabelConfigureServer": "Konfigurera Emby", - "LabelRestartServer": "Starta om servern" + "Plugin": "Till\u00e4gg" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/tr.json b/Emby.Server.Implementations/Localization/Core/tr.json index a0a515170..71af4110d 100644 --- a/Emby.Server.Implementations/Localization/Core/tr.json +++ b/Emby.Server.Implementations/Localization/Core/tr.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/zh-CN.json b/Emby.Server.Implementations/Localization/Core/zh-CN.json index 42126ca1b..0f248f3cd 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-CN.json +++ b/Emby.Server.Implementations/Localization/Core/zh-CN.json @@ -87,10 +87,5 @@ "User": "\u7528\u6237", "System": "\u7cfb\u7edf", "Application": "\u5e94\u7528\u7a0b\u5e8f", - "Plugin": "\u63d2\u4ef6", - "LabelExit": "\u9000\u51fa", - "LabelVisitCommunity": "\u8bbf\u95ee\u793e\u533a", - "LabelBrowseLibrary": "\u6d4f\u89c8\u5a92\u4f53\u5e93", - "LabelConfigureServer": "\u914d\u7f6e Emby", - "LabelRestartServer": "\u91cd\u542f\u670d\u52a1\u5668" + "Plugin": "\u63d2\u4ef6" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/zh-HK.json b/Emby.Server.Implementations/Localization/Core/zh-HK.json index 37afc47e6..b60edb176 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-HK.json +++ b/Emby.Server.Implementations/Localization/Core/zh-HK.json @@ -87,10 +87,5 @@ "User": "User", "System": "System", "Application": "Application", - "Plugin": "Plugin", - "LabelExit": "Exit", - "LabelVisitCommunity": "\u8a2a\u554f\u8a0e\u8ad6\u5340", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server" + "Plugin": "Plugin" } \ No newline at end of file -- cgit v1.2.3 From 5cb74690284105db70a467ab77c2af3f44e42348 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 5 Nov 2017 16:51:23 -0500 Subject: support track selection before playback --- Emby.Dlna/DlnaManager.cs | 1 - Emby.Dlna/Emby.Dlna.csproj | 2 - Emby.Dlna/Profiles/DefaultProfile.cs | 6 +- Emby.Dlna/Profiles/Xbox360Profile.cs | 326 --------------------- Emby.Dlna/Profiles/XboxOneProfile.cs | 4 +- Emby.Dlna/Profiles/Xml/Default.xml | 4 +- Emby.Dlna/Profiles/Xml/Xbox 360.xml | 116 -------- Emby.Dlna/Profiles/Xml/Xbox One.xml | 4 +- Emby.Server.Implementations/ApplicationHost.cs | 2 +- .../Channels/ChannelManager.cs | 16 +- Emby.Server.Implementations/Dto/DtoService.cs | 2 + .../IO/SharpCifsFileSystem.cs | 42 ++- .../Library/Resolvers/BaseVideoResolver.cs | 2 +- .../LiveTv/EmbyTV/EmbyTV.cs | 4 + .../LiveTv/LiveTvManager.cs | 22 +- .../TunerHosts/HdHomerun/HdHomerunHttpStream.cs | 5 +- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 5 +- .../LiveTv/TunerHosts/LiveStream.cs | 11 +- .../Localization/Core/bg-BG.json | 46 +-- .../Localization/Core/sk.json | 36 +-- .../Localization/Core/sv.json | 2 +- .../Localization/LocalizationManager.cs | 28 +- .../MediaEncoder/EncodingManager.cs | 9 +- .../ScheduledTasks/ChapterImagesTask.cs | 5 +- MediaBrowser.Controller/Entities/Audio/Audio.cs | 5 + MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- .../Entities/IHasMediaSources.cs | 1 + MediaBrowser.Controller/Entities/Video.cs | 5 + MediaBrowser.Controller/LiveTv/LiveTvChannel.cs | 5 + .../MediaEncoding/EncodingHelper.cs | 16 +- .../MediaEncoding/IEncodingManager.cs | 3 +- .../Providers/DirectoryService.cs | 52 ++-- .../Providers/IDirectoryService.cs | 3 + MediaBrowser.Model/Dto/BaseItemDto.cs | 3 +- MediaBrowser.Model/Providers/SubtitleOptions.cs | 2 + MediaBrowser.Model/Session/GeneralCommandType.cs | 3 +- MediaBrowser.Providers/Manager/MetadataService.cs | 6 +- .../MediaInfo/FFProbeVideoInfo.cs | 6 +- .../MediaInfo/SubtitleResolver.cs | 115 ++++---- .../Subtitles/SubtitleManager.cs | 97 ++++-- SharedVersion.cs | 2 +- 41 files changed, 353 insertions(+), 673 deletions(-) delete mode 100644 Emby.Dlna/Profiles/Xbox360Profile.cs delete mode 100644 Emby.Dlna/Profiles/Xml/Xbox 360.xml (limited to 'Emby.Server.Implementations/Localization/Core') diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index bdc523c8b..8caa086ee 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -554,7 +554,6 @@ namespace Emby.Dlna var list = new List { new SamsungSmartTvProfile(), - new Xbox360Profile(), new XboxOneProfile(), new SonyPs3Profile(), new SonyPs4Profile(), diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 365774b0d..eb8b178a8 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -105,7 +105,6 @@ - @@ -175,7 +174,6 @@ - diff --git a/Emby.Dlna/Profiles/DefaultProfile.cs b/Emby.Dlna/Profiles/DefaultProfile.cs index 46639ee42..75204b234 100644 --- a/Emby.Dlna/Profiles/DefaultProfile.cs +++ b/Emby.Dlna/Profiles/DefaultProfile.cs @@ -65,13 +65,15 @@ namespace Emby.Dlna.Profiles { new DirectPlayProfile { - Container = "m4v,mpegts,ts,3gp,mov,xvid,vob,mkv,wmv,asf,ogm,ogv,m2v,avi,mpg,mpeg,mp4,webm,wtv,m2ts,dvr-ms", + // play all + Container = "", Type = DlnaProfileType.Video }, new DirectPlayProfile { - Container = "aac,mp3,mpa,wav,wma,mp2,ogg,oga,webma,ape,opus,flac,m4a", + // play all + Container = "", Type = DlnaProfileType.Audio } }; diff --git a/Emby.Dlna/Profiles/Xbox360Profile.cs b/Emby.Dlna/Profiles/Xbox360Profile.cs deleted file mode 100644 index 7bdcd2a6f..000000000 --- a/Emby.Dlna/Profiles/Xbox360Profile.cs +++ /dev/null @@ -1,326 +0,0 @@ -using MediaBrowser.Model.Dlna; -using System.Xml.Serialization; - -namespace Emby.Dlna.Profiles -{ - /// - /// Good info on xbox 360 requirements: https://code.google.com/p/jems/wiki/XBox360Notes - /// - [XmlRoot("Profile")] - public class Xbox360Profile : DefaultProfile - { - public Xbox360Profile() - { - Name = "Xbox 360"; - - // Required according to above - ModelName = "Windows Media Player Sharing"; - - ModelNumber = "12.0"; - - FriendlyName = "${HostName}: 1"; - - ModelUrl = "http://go.microsoft.com/fwlink/?LinkId=105926"; - Manufacturer = "Microsoft Corporation"; - ManufacturerUrl = "http://www.microsoft.com"; - XDlnaDoc = "DMS-1.50"; - ModelDescription = "Emby : UPnP Media Server"; - - TimelineOffsetSeconds = 40; - RequiresPlainFolders = true; - RequiresPlainVideoItems = true; - EnableMSMediaReceiverRegistrar = true; - - Identification = new DeviceIdentification - { - ModelName = "Xbox 360", - - Headers = new[] - { - new HttpHeaderInfo {Name = "User-Agent", Value = "Xbox", Match = HeaderMatchType.Substring}, - new HttpHeaderInfo {Name = "User-Agent", Value = "Xenon", Match = HeaderMatchType.Substring} - } - }; - - TranscodingProfiles = new[] - { - new TranscodingProfile - { - Container = "mp3", - AudioCodec = "mp3", - Type = DlnaProfileType.Audio - }, - new TranscodingProfile - { - Container = "asf", - VideoCodec = "wmv2", - AudioCodec = "wmav2", - Type = DlnaProfileType.Video, - TranscodeSeekInfo = TranscodeSeekInfo.Bytes, - EstimateContentLength = true - }, - new TranscodingProfile - { - Container = "jpeg", - Type = DlnaProfileType.Photo - } - }; - - DirectPlayProfiles = new[] - { - new DirectPlayProfile - { - Container = "avi", - VideoCodec = "mpeg4", - AudioCodec = "ac3,mp3", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "avi", - VideoCodec = "h264", - AudioCodec = "aac", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mp4,mov", - VideoCodec = "h264,mpeg4", - AudioCodec = "aac,ac3", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "asf", - VideoCodec = "wmv2,wmv3,vc1", - AudioCodec = "wmav2,wmapro", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "asf", - AudioCodec = "wmav2,wmapro,wmavoice", - Type = DlnaProfileType.Audio - }, - new DirectPlayProfile - { - Container = "mp3", - AudioCodec = "mp3", - Type = DlnaProfileType.Audio - }, - new DirectPlayProfile - { - Container = "jpeg", - Type = DlnaProfileType.Photo - } - }; - - ResponseProfiles = new[] - { - new ResponseProfile - { - Container = "avi", - MimeType = "video/avi", - Type = DlnaProfileType.Video - } - }; - - ContainerProfiles = new[] - { - new ContainerProfile - { - Type = DlnaProfileType.Video, - Container = "mp4,mov", - - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.Equals, - Property = ProfileConditionValue.Has64BitOffsets, - Value = "false", - IsRequired = false - } - } - }, - - new ContainerProfile - { - Type = DlnaProfileType.Photo, - - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Width, - Value = "1920" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Height, - Value = "1080" - } - } - } - }; - - CodecProfiles = new[] - { - new CodecProfile - { - Type = CodecType.Video, - Codec = "mpeg4", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Width, - Value = "1280" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Height, - Value = "720" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoFramerate, - Value = "30", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoBitrate, - Value = "5120000", - IsRequired = false - } - } - }, - - new CodecProfile - { - Type = CodecType.Video, - Codec = "h264", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Width, - Value = "1920" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Height, - Value = "1080" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoLevel, - Value = "41", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoBitrate, - Value = "10240000", - IsRequired = false - } - } - }, - - new CodecProfile - { - Type = CodecType.Video, - Codec = "wmv2,wmv3,vc1", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Width, - Value = "1920" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Height, - Value = "1080" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoFramerate, - Value = "30", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoBitrate, - Value = "15360000", - IsRequired = false - } - } - }, - - new CodecProfile - { - Type = CodecType.VideoAudio, - Codec = "ac3,wmav2,wmapro", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioChannels, - Value = "6", - IsRequired = false - } - } - }, - - new CodecProfile - { - Type = CodecType.VideoAudio, - Codec = "aac", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioChannels, - Value = "2", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.Equals, - Property = ProfileConditionValue.AudioProfile, - Value = "lc", - IsRequired = false - } - } - } - }; - - SubtitleProfiles = new[] - { - new SubtitleProfile - { - Format = "srt", - Method = SubtitleDeliveryMethod.Embed - } - }; - } - } -} diff --git a/Emby.Dlna/Profiles/XboxOneProfile.cs b/Emby.Dlna/Profiles/XboxOneProfile.cs index e17640f2f..99e52510f 100644 --- a/Emby.Dlna/Profiles/XboxOneProfile.cs +++ b/Emby.Dlna/Profiles/XboxOneProfile.cs @@ -60,7 +60,7 @@ namespace Emby.Dlna.Profiles new DirectPlayProfile { Container = "ts", - VideoCodec = "h264,mpeg2video", + VideoCodec = "h264,mpeg2video,hevc", AudioCodec = "ac3,aac,mp3", Type = DlnaProfileType.Video }, @@ -81,7 +81,7 @@ namespace Emby.Dlna.Profiles new DirectPlayProfile { Container = "mp4,mov,mkv,m4v", - VideoCodec = "h264,mpeg4,mpeg2video", + VideoCodec = "h264,mpeg4,mpeg2video,hevc", AudioCodec = "aac,ac3", Type = DlnaProfileType.Video }, diff --git a/Emby.Dlna/Profiles/Xml/Default.xml b/Emby.Dlna/Profiles/Xml/Default.xml index b07a2f7c2..133f4abf1 100644 --- a/Emby.Dlna/Profiles/Xml/Default.xml +++ b/Emby.Dlna/Profiles/Xml/Default.xml @@ -29,8 +29,8 @@ false - - + + diff --git a/Emby.Dlna/Profiles/Xml/Xbox 360.xml b/Emby.Dlna/Profiles/Xml/Xbox 360.xml deleted file mode 100644 index 3b7d2963f..000000000 --- a/Emby.Dlna/Profiles/Xml/Xbox 360.xml +++ /dev/null @@ -1,116 +0,0 @@ - - - Xbox 360 - - Xbox 360 - - - - - - ${HostName}: 1 - Microsoft Corporation - http://www.microsoft.com - Windows Media Player Sharing - Emby : UPnP Media Server - 12.0 - http://go.microsoft.com/fwlink/?LinkId=105926 - false - false - false - Audio,Photo,Video - JPEG_SM - 480 - 480 - 48 - 48 - 40000000 - 40000000 - 192000 - - DMS-1.50 - http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 - 40 - true - true - true - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Emby.Dlna/Profiles/Xml/Xbox One.xml b/Emby.Dlna/Profiles/Xml/Xbox One.xml index 423327a38..635423234 100644 --- a/Emby.Dlna/Profiles/Xml/Xbox One.xml +++ b/Emby.Dlna/Profiles/Xml/Xbox One.xml @@ -36,10 +36,10 @@ false - + - + diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index c1ab9ec22..2aeb4b971 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -996,7 +996,7 @@ namespace Emby.Server.Implementations NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager); RegisterSingleInstance(NotificationManager); - SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, MediaSourceManager); + SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, MediaSourceManager, ServerConfigurationManager); RegisterSingleInstance(SubtitleManager); RegisterSingleInstance(new DeviceDiscovery(LogManager.GetLogger("IDeviceDiscovery"), ServerConfigurationManager, SocketFactory, TimerFactory)); diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index c42f22804..c566ca25b 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -296,7 +296,7 @@ namespace Emby.Server.Implementations.Channels if (requiresCallback != null) { - results = await GetChannelItemMediaSourcesInternal(requiresCallback, GetItemExternalId(item), cancellationToken) + results = await GetChannelItemMediaSourcesInternal(requiresCallback, item.ExternalId, cancellationToken) .ConfigureAwait(false); } else @@ -990,18 +990,6 @@ namespace Emby.Server.Implementations.Channels return result; } - private string GetItemExternalId(BaseItem item) - { - var externalId = item.ExternalId; - - if (string.IsNullOrWhiteSpace(externalId)) - { - externalId = item.GetProviderId("ProviderExternalId"); - } - - return externalId; - } - private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1); private async Task GetChannelItems(IChannel channel, User user, @@ -1080,7 +1068,7 @@ namespace Emby.Server.Implementations.Channels { var categoryItem = _libraryManager.GetItemById(new Guid(folderId)); - query.FolderId = GetItemExternalId(categoryItem); + query.FolderId = categoryItem.ExternalId; } var result = await channel.GetChannelItems(query, cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 0a316fcf1..2fa09c2b1 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -373,6 +373,8 @@ namespace Emby.Server.Implementations.Dto } NormalizeMediaSourceContainers(dto); + + dto.SupportsMediaSourceSelection = hasMediaSources.SupportsMediaSourceSelection(); } } diff --git a/Emby.Server.Implementations/IO/SharpCifsFileSystem.cs b/Emby.Server.Implementations/IO/SharpCifsFileSystem.cs index 1d21796b1..0e1f6bb00 100644 --- a/Emby.Server.Implementations/IO/SharpCifsFileSystem.cs +++ b/Emby.Server.Implementations/IO/SharpCifsFileSystem.cs @@ -487,14 +487,17 @@ namespace Emby.Server.Implementations.IO AssertDirectoryExists(dir, path); var list = ListFiles(dir, recursive); + var result = new List(); foreach (var file in list) { if (file.IsDirectory()) { - yield return ToMetadata(file); + result.Add(ToMetadata(file)); } } + + return result; } public IEnumerable GetFiles(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) @@ -503,6 +506,7 @@ namespace Emby.Server.Implementations.IO AssertDirectoryExists(dir, path); var list = ListFiles(dir, recursive); + var result = new List(); foreach (var file in list) { @@ -513,10 +517,12 @@ namespace Emby.Server.Implementations.IO if (extensions == null || extensions.Length == 0 || extensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { - yield return ToMetadata(file); + result.Add(ToMetadata(file)); } } } + + return result; } public IEnumerable GetFileSystemEntries(string path, bool recursive = false) @@ -525,15 +531,19 @@ namespace Emby.Server.Implementations.IO AssertDirectoryExists(dir, path); var list = ListFiles(dir, recursive); + var result = new List(); foreach (var file in list) { - yield return ToMetadata(file); + result.Add(ToMetadata(file)); } + + return result; } - public IEnumerable GetFileSystemEntryPaths(string path, bool recursive = false) + public List GetFileSystemEntryPaths(string path, bool recursive = false) { + var result = new List(); var dir = CreateSmbDirectoryForListFiles(path); AssertDirectoryExists(dir, path); @@ -541,16 +551,18 @@ namespace Emby.Server.Implementations.IO foreach (var file in list) { - yield return GetReturnPath(file); + result.Add(GetReturnPath(file)); } + return result; } - public IEnumerable GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) + public List GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) { var dir = CreateSmbDirectoryForListFiles(path); AssertDirectoryExists(dir, path); var list = ListFiles(dir, recursive); + var result = new List(); foreach (var file in list) { @@ -561,44 +573,52 @@ namespace Emby.Server.Implementations.IO if (extensions == null || extensions.Length == 0 || extensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { - yield return filePath; + result.Add(filePath); } } } + + return result; } - public IEnumerable GetDirectoryPaths(string path, bool recursive = false) + public List GetDirectoryPaths(string path, bool recursive = false) { var dir = CreateSmbDirectoryForListFiles(path); AssertDirectoryExists(dir, path); var list = ListFiles(dir, recursive); + var result = new List(); foreach (var file in list) { if (file.IsDirectory()) { - yield return GetReturnPath(file); + result.Add(GetReturnPath(file)); } } + + return result; } private IEnumerable ListFiles(SmbFile dir, bool recursive) { var list = dir.ListFiles(); + var result = new List(); foreach (var file in list) { - yield return file; + result.Add(file); if (recursive && file.IsDirectory()) { foreach (var subFile in ListFiles(file, recursive)) { - yield return subFile; + result.Add(subFile); } } } + + return result; } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index e3200a099..7e960f85e 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -274,7 +274,7 @@ namespace Emby.Server.Implementations.Library.Resolvers return false; } - return FileSystem.GetFilePaths(fullPath).Any(i => string.Equals(Path.GetExtension(i), ".vob", StringComparison.OrdinalIgnoreCase)); + return directoryService.GetFilePaths(fullPath).Any(i => string.Equals(Path.GetExtension(i), ".vob", StringComparison.OrdinalIgnoreCase)); } /// diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index be5e57539..b469966f5 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -2445,6 +2445,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { existingTimer.Status = RecordingStatus.Cancelled; } + else if (!existingTimer.IsManual) + { + existingTimer.Status = RecordingStatus.New; + } if (existingTimer.Status != RecordingStatus.Cancelled) { diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 718620ab5..7e72d1b1a 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1232,6 +1232,8 @@ namespace Emby.Server.Implementations.LiveTv var newChannelIdList = new List(); var newProgramIdList = new List(); + var cleanDatabase = true; + foreach (var service in _services) { cancellationToken.ThrowIfCancellationRequested(); @@ -1254,6 +1256,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { + cleanDatabase = false; _logger.ErrorException("Error refreshing channels for service", ex); } @@ -1264,8 +1267,11 @@ namespace Emby.Server.Implementations.LiveTv progress.Report(100 * percent); } - await CleanDatabaseInternal(newChannelIdList.ToArray(), new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false); - await CleanDatabaseInternal(newProgramIdList.ToArray(), new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false); + if (cleanDatabase) + { + await CleanDatabaseInternal(newChannelIdList.ToArray(), new[] { typeof(LiveTvChannel).Name }, progress, cancellationToken).ConfigureAwait(false); + await CleanDatabaseInternal(newProgramIdList.ToArray(), new[] { typeof(LiveTvProgram).Name }, progress, cancellationToken).ConfigureAwait(false); + } var coreService = _services.OfType().FirstOrDefault(); @@ -1291,8 +1297,9 @@ namespace Emby.Server.Implementations.LiveTv { progress.Report(10); - var allChannels = await GetChannels(service, cancellationToken).ConfigureAwait(false); - var allChannelsList = allChannels.ToList(); + var allChannelsList = (await service.GetChannelsAsync(cancellationToken).ConfigureAwait(false)) + .Select(i => new Tuple(service.Name, i)) + .ToList(); var list = new List(); @@ -1507,13 +1514,6 @@ namespace Emby.Server.Implementations.LiveTv return 7; } - private async Task>> GetChannels(ILiveTvService service, CancellationToken cancellationToken) - { - var channels = await service.GetChannelsAsync(cancellationToken).ConfigureAwait(false); - - return channels.Select(i => new Tuple(service.Name, i)); - } - private DateTime _lastRecordingRefreshTime; private async Task RefreshRecordings(Guid internalLiveTvFolderId, CancellationToken cancellationToken) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs index 7e0e5fc5c..1ea77d505 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs @@ -73,9 +73,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun //OpenedMediaSource.SupportsTranscoding = true; } - public override void Close() + protected override void CloseInternal() { - Logger.Info("Closing HDHR live stream"); LiveStreamCancellationTokenSource.Cancel(); } @@ -106,7 +105,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { Logger.ErrorException("Error copying live stream.", ex); } - + EnableStreamSharing = false; await DeleteTempFile(TempFilePath).ConfigureAwait(false); }); } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 06326d26c..8b46b78be 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -105,9 +105,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun await taskCompletionSource.Task.ConfigureAwait(false); } - public override void Close() + protected override void CloseInternal() { - Logger.Info("Closing HDHR UDP live stream"); LiveStreamCancellationTokenSource.Cancel(); } @@ -134,6 +133,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun openTaskCompletionSource.TrySetException(ex); } + EnableStreamSharing = false; + try { await hdHomerunManager.StopStreaming().ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs index 862098735..cead1def0 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs @@ -52,7 +52,16 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return Task.FromResult(true); } - public virtual void Close() + public void Close() + { + EnableStreamSharing = false; + + Logger.Info("Closing " + GetType().Name); + + CloseInternal(); + } + + protected virtual void CloseInternal() { } diff --git a/Emby.Server.Implementations/Localization/Core/bg-BG.json b/Emby.Server.Implementations/Localization/Core/bg-BG.json index cc7611bf4..02c03f578 100644 --- a/Emby.Server.Implementations/Localization/Core/bg-BG.json +++ b/Emby.Server.Implementations/Localization/Core/bg-BG.json @@ -1,7 +1,7 @@ { "Latest": "\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438", "ValueSpecialEpisodeName": "\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u043d\u0438 - {0}", - "Inherit": "Inherit", + "Inherit": "\u041d\u0430\u0441\u043b\u0435\u0434\u044f\u0432\u0430\u043d\u0435", "Books": "\u041a\u043d\u0438\u0433\u0438", "Music": "\u041c\u0443\u0437\u0438\u043a\u0430", "Games": "\u0418\u0433\u0440\u0438", @@ -35,7 +35,7 @@ "UserDownloadingItemWithValues": "{0} is downloading {1}", "HeaderLiveTV": "\u0422\u0435\u043b\u0435\u0432\u0438\u0437\u0438\u044f \u043d\u0430 \u0436\u0438\u0432\u043e", "ChapterNameValue": "\u0413\u043b\u0430\u0432\u0430 {0}", - "ScheduledTaskFailedWithName": "{0} failed", + "ScheduledTaskFailedWithName": "{0} \u0441\u0435 \u043f\u0440\u043e\u0432\u0430\u043b\u0438", "LabelRunningTimeValue": "Running time: {0}", "ScheduledTaskStartedWithName": "{0} \u0437\u0430\u043f\u043e\u0447\u043d\u0430", "VersionNumber": "\u0412\u0435\u0440\u0441\u0438\u044f {0}", @@ -49,40 +49,40 @@ "DeviceOnlineWithName": "{0} \u0435 \u0441\u0432\u044a\u0440\u0437\u0430\u043d", "UserOnlineFromDevice": "{0} \u0435 \u043d\u0430 \u043b\u0438\u043d\u0438\u044f \u043e\u0442 {1}", "ProviderValue": "\u0414\u043e\u0441\u0442\u0430\u0432\u0447\u0438\u043a: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", + "SubtitlesDownloadedForItem": "\u0418\u0437\u0442\u0435\u0433\u043b\u0435\u043d\u0438 \u0441\u0430 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u0438 \u0437\u0430 {0}", + "UserCreatedWithName": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f\u0442 {0} \u0435 \u0441\u044a\u0437\u0434\u0430\u0434\u0435\u043d", + "UserPasswordChangedWithName": "\u041f\u0430\u0440\u043e\u043b\u0430\u0442\u0430 \u043d\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f {0} \u0435 \u043f\u0440\u043e\u043c\u0435\u043d\u0435\u043d\u0430", + "UserDeletedWithName": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f\u0442 {0} \u0435 \u0438\u0437\u0442\u0440\u0438\u0442", "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", "MessageServerConfigurationUpdated": "Server configuration has been updated", "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", + "MessageApplicationUpdated": "\u0421\u044a\u0440\u0432\u044a\u0440\u044a\u0442 \u0435 \u043e\u0431\u043d\u043e\u0432\u0435\u043d", "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "DeviceOfflineWithName": "{0} has disconnected", + "AuthenticationSucceededWithUserName": "{0} \u0441\u0435 \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e", + "UserOfflineFromDevice": "{0} \u0441\u0435 \u0440\u0430\u0437\u043a\u0430\u0447\u0438 \u043e\u0442 {1}", + "DeviceOfflineWithName": "{0} \u0441\u0435 \u0440\u0430\u0437\u043a\u0430\u0447\u0438", "UserStartedPlayingItemWithValues": "{0} has started playing {1}", "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", + "NotificationOptionPluginError": "\u0413\u0440\u0435\u0448\u043a\u0430 \u0432 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430", + "NotificationOptionApplicationUpdateAvailable": "\u041d\u0430\u043b\u0438\u0447\u043d\u043e \u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430\u0442\u0430", + "NotificationOptionApplicationUpdateInstalled": "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u0430\u0442\u0430 \u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u043e", "NotificationOptionPluginUpdateInstalled": "\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u0442\u043e \u043d\u0430 \u043f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430\u0442\u0430 \u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u043e", "NotificationOptionPluginInstalled": "\u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430\u0442\u0430 \u0435 \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0430", "NotificationOptionPluginUninstalled": "\u041f\u0440\u0438\u0441\u0442\u0430\u0432\u043a\u0430\u0442\u0430 \u0435 \u0434\u0435\u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0430", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", + "NotificationOptionVideoPlayback": "\u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0432\u0438\u0434\u0435\u043e \u0437\u0430\u043f\u043e\u0447\u043d\u0430", + "NotificationOptionAudioPlayback": "\u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0437\u0432\u0443\u043a \u0437\u0430\u043f\u043e\u0447\u043d\u0430", + "NotificationOptionGamePlayback": "\u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0438\u0433\u0440\u0430\u0442\u0430 \u0437\u0430\u043f\u043e\u0447\u043d\u0430", + "NotificationOptionVideoPlaybackStopped": "\u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0432\u0438\u0434\u0435\u043e \u0435 \u0441\u043f\u0440\u044f\u043d\u043e", + "NotificationOptionAudioPlaybackStopped": "\u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0437\u0432\u0443\u043a \u0435 \u0441\u043f\u0440\u044f\u043d\u043e", + "NotificationOptionGamePlaybackStopped": "\u0412\u044a\u0437\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0436\u0434\u0430\u043d\u0435\u0442\u043e \u043d\u0430 \u0438\u0433\u0440\u0430\u0442\u0430 \u0435 \u0441\u043f\u0440\u044f\u043d\u0430", + "NotificationOptionTaskFailed": "\u0413\u0440\u0435\u0448\u043a\u0430 \u0432 \u043f\u043b\u0430\u043d\u0438\u0440\u0430\u043d\u0430 \u0437\u0430\u0434\u0430\u0447\u0430", + "NotificationOptionInstallationFailed": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u043d\u0441\u0442\u0430\u043b\u0438\u0440\u0430\u043d\u0435", "NotificationOptionNewLibraryContent": "\u0414\u043e\u0431\u0430\u0432\u0435\u043d\u043e \u0435 \u043d\u043e\u0432\u043e \u0441\u044a\u0434\u044a\u0440\u0436\u0430\u043d\u0438\u0435", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", + "NotificationOptionCameraImageUploaded": "\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u0442\u043e \u043e\u0442 \u0444\u043e\u0442\u043e\u0430\u043f\u0430\u0440\u0430\u0442\u0430 \u0435 \u043a\u0430\u0447\u0435\u043d\u043e", "NotificationOptionUserLockedOut": "User locked out", "NotificationOptionServerRestartRequired": "\u041d\u0443\u0436\u043d\u043e \u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u043f\u0443\u0441\u043a\u0430\u043d\u0435 \u043d\u0430 \u0441\u044a\u0440\u0432\u044a\u0440\u0430", "UserLockedOutWithName": "User {0} has been locked out", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", + "SubtitleDownloadFailureForItem": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0438\u0437\u0442\u0435\u0433\u043b\u044f\u043d\u0435 \u043d\u0430 \u0441\u0443\u0431\u0442\u0438\u0442\u0440\u0438 \u0437\u0430 {0}", "Sync": "\u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0430\u043d\u0435", "User": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b", "System": "\u0421\u0438\u0441\u0442\u0435\u043c\u0430", diff --git a/Emby.Server.Implementations/Localization/Core/sk.json b/Emby.Server.Implementations/Localization/Core/sk.json index aa6ada912..0c7bce1da 100644 --- a/Emby.Server.Implementations/Localization/Core/sk.json +++ b/Emby.Server.Implementations/Localization/Core/sk.json @@ -2,13 +2,13 @@ "Latest": "Latest", "ValueSpecialEpisodeName": "Special - {0}", "Inherit": "Inherit", - "Books": "Books", - "Music": "Music", - "Games": "Games", - "Photos": "Photos", - "MixedContent": "Mixed content", - "MusicVideos": "Music videos", - "HomeVideos": "Home videos", + "Books": "Knihy", + "Music": "Hudba", + "Games": "Hry", + "Photos": "Fotky", + "MixedContent": "Zmie\u0161an\u00fd obsah", + "MusicVideos": "Hudobn\u00e9 vide\u00e1", + "HomeVideos": "Dom\u00e1ce vide\u00e1", "Playlists": "Playlists", "HeaderRecordingGroups": "Recording Groups", "HeaderContinueWatching": "Continue Watching", @@ -16,20 +16,20 @@ "HeaderFavoriteSongs": "Ob\u013e\u00faben\u00e9 pesni\u010dky", "HeaderAlbumArtists": "Album Artists", "HeaderFavoriteAlbums": "Favorite Albums", - "HeaderFavoriteEpisodes": "Favorite Episodes", + "HeaderFavoriteEpisodes": "Ob\u013e\u00faben\u00e9 epiz\u00f3dy", "HeaderFavoriteShows": "Ob\u013e\u00faben\u00e9 seri\u00e1ly", - "HeaderNextUp": "Next Up", + "HeaderNextUp": "Nasleduje", "Favorites": "Ob\u013e\u00faben\u00e9", - "Collections": "Collections", - "Channels": "Channels", - "Movies": "Movies", - "Albums": "Albums", - "Artists": "Artists", - "Folders": "Folders", - "Songs": "Songs", + "Collections": "Zbierky", + "Channels": "Kan\u00e1ly", + "Movies": "Filmy", + "Albums": "Albumy", + "Artists": "Umelci", + "Folders": "Prie\u010dinky", + "Songs": "Skladby", "TvShows": "TV Shows", "Shows": "Series", - "Genres": "Genres", + "Genres": "\u017d\u00e1nre", "NameSeasonNumber": "Season {0}", "AppDeviceValues": "App: {0}, Device: {1}", "UserDownloadingItemWithValues": "{0} is downloading {1}", @@ -86,6 +86,6 @@ "Sync": "Sync", "User": "User", "System": "System", - "Application": "Application", + "Application": "Aplik\u00e1cia", "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Localization/Core/sv.json b/Emby.Server.Implementations/Localization/Core/sv.json index c43bd79a6..ed1867024 100644 --- a/Emby.Server.Implementations/Localization/Core/sv.json +++ b/Emby.Server.Implementations/Localization/Core/sv.json @@ -27,7 +27,7 @@ "Artists": "Artister", "Folders": "Mappar", "Songs": "L\u00e5tar", - "TvShows": "TV Shows", + "TvShows": "TV-serier", "Shows": "Serier", "Genres": "Genrer", "NameSeasonNumber": "S\u00e4song {0}", diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 2eb4743cd..6d271c0e1 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.Localization var localizationPath = LocalizationPath; - _fileSystem.CreateDirectory(localizationPath); + _fileSystem.CreateDirectory(localizationPath); var existingFiles = GetRatingsFiles(localizationPath) .Select(Path.GetFileName) @@ -91,7 +91,7 @@ namespace Emby.Server.Implementations.Localization } } } - + foreach (var file in GetRatingsFiles(localizationPath)) { LoadRatings(file); @@ -128,12 +128,20 @@ namespace Emby.Server.Implementations.Localization return _textLocalizer.NormalizeFormKD(text); } + private CultureDto[] _cultures; + /// /// Gets the cultures. /// /// IEnumerable{CultureDto}. public CultureDto[] GetCultures() { + var result = _cultures; + if (result != null) + { + return result; + } + var type = GetType(); var path = type.Namespace + ".iso6392.txt"; @@ -166,10 +174,14 @@ namespace Emby.Server.Implementations.Localization } } - return list.Where(i => !string.IsNullOrWhiteSpace(i.Name) && - !string.IsNullOrWhiteSpace(i.DisplayName) && - !string.IsNullOrWhiteSpace(i.ThreeLetterISOLanguageName) && - !string.IsNullOrWhiteSpace(i.TwoLetterISOLanguageName)).ToArray(); + result = list.Where(i => !string.IsNullOrWhiteSpace(i.Name) && + !string.IsNullOrWhiteSpace(i.DisplayName) && + !string.IsNullOrWhiteSpace(i.ThreeLetterISOLanguageName) && + !string.IsNullOrWhiteSpace(i.TwoLetterISOLanguageName)).ToArray(); + + _cultures = result; + + return result; } /// @@ -239,7 +251,7 @@ namespace Emby.Server.Implementations.Localization /// Dictionary{System.StringParentalRating}. private void LoadRatings(string file) { - var dict = _fileSystem.ReadAllLines(file).Select(i => + var dict = _fileSystem.ReadAllLines(file).Select(i => { if (!string.IsNullOrWhiteSpace(i)) { @@ -269,7 +281,7 @@ namespace Emby.Server.Implementations.Localization _allParentalRatings.TryAdd(countryCode, dict); } - private readonly string[] _unratedValues = {"n/a", "unrated", "not rated"}; + private readonly string[] _unratedValues = { "n/a", "unrated", "not rated" }; /// /// Gets the rating level. diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index 9a9e619a6..6e0e55bef 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -17,6 +17,7 @@ using System.Threading.Tasks; using MediaBrowser.Controller.IO; using MediaBrowser.Model.IO; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; namespace Emby.Server.Implementations.MediaEncoder { @@ -89,7 +90,7 @@ namespace Emby.Server.Implementations.MediaEncoder /// private static readonly long FirstChapterTicks = TimeSpan.FromSeconds(15).Ticks; - public async Task RefreshChapterImages(Video video, List chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken) + public async Task RefreshChapterImages(Video video, IDirectoryService directoryService, List chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken) { if (!IsEligibleForChapterImageExtraction(video)) { @@ -101,7 +102,7 @@ namespace Emby.Server.Implementations.MediaEncoder var runtimeTicks = video.RunTimeTicks ?? 0; - var currentImages = GetSavedChapterImages(video); + var currentImages = GetSavedChapterImages(video, directoryService); foreach (var chapter in chapters) { @@ -194,13 +195,13 @@ namespace Emby.Server.Implementations.MediaEncoder return Path.Combine(GetChapterImagesPath(video), filename); } - private List GetSavedChapterImages(Video video) + private List GetSavedChapterImages(Video video, IDirectoryService directoryService) { var path = GetChapterImagesPath(video); try { - return _fileSystem.GetFilePaths(path) + return directoryService.GetFilePaths(path) .ToList(); } catch (IOException) diff --git a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs index bf7bf9ff8..fe0652f66 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs @@ -16,6 +16,7 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Extensions; +using MediaBrowser.Controller.Providers; namespace Emby.Server.Implementations.ScheduledTasks { @@ -120,6 +121,8 @@ namespace Emby.Server.Implementations.ScheduledTasks previouslyFailedImages = new List(); } + var directoryService = new DirectoryService(_fileSystem); + foreach (var video in videos) { cancellationToken.ThrowIfCancellationRequested(); @@ -132,7 +135,7 @@ namespace Emby.Server.Implementations.ScheduledTasks { var chapters = _itemRepo.GetChapters(video.Id); - var success = await _encodingManager.RefreshChapterImages(video, chapters, extract, true, CancellationToken.None); + var success = await _encodingManager.RefreshChapterImages(video, directoryService, chapters, extract, true, CancellationToken.None); if (!success) { diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 16fd75d2e..8ef1060d1 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -51,6 +51,11 @@ namespace MediaBrowser.Controller.Entities.Audio return 1; } + public bool SupportsMediaSourceSelection() + { + return false; + } + [IgnoreDataMember] public override bool SupportsPlayedStatus { diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 7f6949feb..f6a8f1d5a 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2040,7 +2040,7 @@ namespace MediaBrowser.Controller.Entities .Where(i => i.IsLocalFile) .Select(i => FileSystem.GetDirectoryName(i.Path)) .Distinct(StringComparer.OrdinalIgnoreCase) - .SelectMany(i => FileSystem.GetFilePaths(i)) + .SelectMany(i => directoryService.GetFilePaths(i)) .ToList(); var deletedImages = ImageInfos diff --git a/MediaBrowser.Controller/Entities/IHasMediaSources.cs b/MediaBrowser.Controller/Entities/IHasMediaSources.cs index 54786134f..399fe9f5a 100644 --- a/MediaBrowser.Controller/Entities/IHasMediaSources.cs +++ b/MediaBrowser.Controller/Entities/IHasMediaSources.cs @@ -13,5 +13,6 @@ namespace MediaBrowser.Controller.Entities /// Task{IEnumerable{MediaSourceInfo}}. List GetMediaSources(bool enablePathSubstitution); List GetMediaStreams(); + bool SupportsMediaSourceSelection(); } } diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 52f1dd051..60db53f79 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -109,6 +109,11 @@ namespace MediaBrowser.Controller.Entities get { return true; } } + public bool SupportsMediaSourceSelection() + { + return SourceType == SourceType.Library; + } + /// /// Gets or sets the timestamp. /// diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 16010b7f5..ac961d757 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -24,6 +24,11 @@ namespace MediaBrowser.Controller.LiveTv return list; } + public bool SupportsMediaSourceSelection() + { + return false; + } + public override UnratedItem GetBlockUnratedType() { return UnratedItem.LiveTvChannel; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index bddafe9a6..8f8791922 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1325,6 +1325,8 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.VideoStream != null && state.VideoStream.Width.HasValue && state.VideoStream.Height.HasValue) { videoSizeParam = string.Format("scale={0}:{1}", state.VideoStream.Width.Value.ToString(_usCulture), state.VideoStream.Height.Value.ToString(_usCulture)); + + videoSizeParam += ":force_original_aspect_ratio=decrease"; } var mapPrefix = state.SubtitleStream.IsExternal ? @@ -1335,7 +1337,7 @@ namespace MediaBrowser.Controller.MediaEncoding ? 0 : state.SubtitleStream.Index; - return string.Format(" -filter_complex \"[{0}:{1}]{4}[sub] ; [0:{2}] [sub] overlay{3}\"", + return string.Format(" -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay{3}\"", mapPrefix.ToString(_usCulture), subtitleStreamIndex.ToString(_usCulture), state.VideoStream.Index.ToString(_usCulture), @@ -2094,6 +2096,12 @@ namespace MediaBrowser.Controller.MediaEncoding args += " -avoid_negative_ts disabled -start_at_zero"; } + // This is for internal graphical subs + if (hasGraphicalSubs) + { + args += GetGraphicalSubtitleParam(state, encodingOptions, videoCodec); + } + var qualityParam = GetVideoQualityParam(state, videoCodec, encodingOptions, defaultH264Preset); if (!string.IsNullOrEmpty(qualityParam)) @@ -2101,12 +2109,6 @@ namespace MediaBrowser.Controller.MediaEncoding args += " " + qualityParam.Trim(); } - // This is for internal graphical subs - if (hasGraphicalSubs) - { - args += GetGraphicalSubtitleParam(state, encodingOptions, videoCodec); - } - if (!state.RunTimeTicks.HasValue) { args += " -flags -global_header"; diff --git a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs index 81269fe3f..7d50efd5e 100644 --- a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs +++ b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Entities; +using MediaBrowser.Controller.Providers; namespace MediaBrowser.Controller.MediaEncoding { @@ -11,6 +12,6 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Refreshes the chapter images. /// - Task RefreshChapterImages(Video video, List chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken); + Task RefreshChapterImages(Video video, IDirectoryService directoryService, List chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs index d957470d3..d673198fd 100644 --- a/MediaBrowser.Controller/Providers/DirectoryService.cs +++ b/MediaBrowser.Controller/Providers/DirectoryService.cs @@ -14,11 +14,11 @@ namespace MediaBrowser.Controller.Providers private readonly ILogger _logger; private readonly IFileSystem _fileSystem; - private readonly ConcurrentDictionary _cache = - new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _cache = new Dictionary(StringComparer.OrdinalIgnoreCase); - private readonly ConcurrentDictionary _fileCache = - new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _fileCache = new Dictionary(StringComparer.OrdinalIgnoreCase); + + private readonly Dictionary> _filePathCache = new Dictionary>(StringComparer.OrdinalIgnoreCase); public DirectoryService(ILogger logger, IFileSystem fileSystem) { @@ -32,11 +32,6 @@ namespace MediaBrowser.Controller.Providers } public FileSystemMetadata[] GetFileSystemEntries(string path) - { - return GetFileSystemEntries(path, false); - } - - private FileSystemMetadata[] GetFileSystemEntries(string path, bool clearCache) { if (string.IsNullOrWhiteSpace(path)) { @@ -45,13 +40,6 @@ namespace MediaBrowser.Controller.Providers FileSystemMetadata[] entries; - if (clearCache) - { - FileSystemMetadata[] removed; - - _cache.TryRemove(path, out removed); - } - if (!_cache.TryGetValue(path, out entries)) { //_logger.Debug("Getting files for " + path); @@ -66,21 +54,17 @@ namespace MediaBrowser.Controller.Providers entries = new FileSystemMetadata[] { }; } - _cache.TryAdd(path, entries); + //_cache.TryAdd(path, entries); + _cache[path] = entries; } return entries; } public List GetFiles(string path) - { - return GetFiles(path, false); - } - - public List GetFiles(string path, bool clearCache) { var list = new List(); - var items = GetFileSystemEntries(path, clearCache); + var items = GetFileSystemEntries(path); foreach (var item in items) { if (!item.IsDirectory) @@ -100,7 +84,8 @@ namespace MediaBrowser.Controller.Providers if (file != null && file.Exists) { - _fileCache.TryAdd(path, file); + //_fileCache.TryAdd(path, file); + _fileCache[path] = file; } else { @@ -111,5 +96,24 @@ namespace MediaBrowser.Controller.Providers return file; //return _fileSystem.GetFileInfo(path); } + + public List GetFilePaths(string path) + { + return GetFilePaths(path, false); + } + + public List GetFilePaths(string path, bool clearCache) + { + List result; + if (clearCache || !_filePathCache.TryGetValue(path, out result)) + { + result = _fileSystem.GetFilePaths(path).ToList(); + + _filePathCache[path] = result; + } + + return result; + } + } } diff --git a/MediaBrowser.Controller/Providers/IDirectoryService.cs b/MediaBrowser.Controller/Providers/IDirectoryService.cs index 6f864f4be..0b4574f6e 100644 --- a/MediaBrowser.Controller/Providers/IDirectoryService.cs +++ b/MediaBrowser.Controller/Providers/IDirectoryService.cs @@ -8,5 +8,8 @@ namespace MediaBrowser.Controller.Providers FileSystemMetadata[] GetFileSystemEntries(string path); List GetFiles(string path); FileSystemMetadata GetFile(string path); + + List GetFilePaths(string path); + List GetFilePaths(string path, bool clearCache); } } \ No newline at end of file diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 8bad650b5..7cacb96ee 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -75,7 +75,8 @@ namespace MediaBrowser.Model.Dto public bool? CanDownload { get; set; } public bool? HasSubtitles { get; set; } - + public bool? SupportsMediaSourceSelection { get; set; } + public string PreferredMetadataLanguage { get; set; } public string PreferredMetadataCountryCode { get; set; } diff --git a/MediaBrowser.Model/Providers/SubtitleOptions.cs b/MediaBrowser.Model/Providers/SubtitleOptions.cs index 5587e897f..d0d81e1fb 100644 --- a/MediaBrowser.Model/Providers/SubtitleOptions.cs +++ b/MediaBrowser.Model/Providers/SubtitleOptions.cs @@ -13,6 +13,7 @@ namespace MediaBrowser.Model.Providers public bool IsOpenSubtitleVipAccount { get; set; } public bool RequirePerfectMatch { get; set; } + public bool SaveSubtitlesInMediaFolders { get; set; } public SubtitleOptions() { @@ -20,6 +21,7 @@ namespace MediaBrowser.Model.Providers SkipIfAudioTrackMatches = true; RequirePerfectMatch = true; + SaveSubtitlesInMediaFolders = true; } } } \ No newline at end of file diff --git a/MediaBrowser.Model/Session/GeneralCommandType.cs b/MediaBrowser.Model/Session/GeneralCommandType.cs index 8dd0c29e4..616d5f9b4 100644 --- a/MediaBrowser.Model/Session/GeneralCommandType.cs +++ b/MediaBrowser.Model/Session/GeneralCommandType.cs @@ -39,6 +39,7 @@ ChannelDown = 31, SetMaxStreamingBitrate = 31, Guide = 32, - ToggleStats = 33 + ToggleStats = 33, + PlayMediaSource = 34 } } \ No newline at end of file diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index af03e21b2..32b9a9ae2 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -27,6 +27,7 @@ namespace MediaBrowser.Providers.Manager protected readonly IFileSystem FileSystem; protected readonly IUserDataManager UserDataManager; protected readonly ILibraryManager LibraryManager; + private readonly SubtitleResolver _subtitleResolver; protected MetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) { @@ -36,6 +37,8 @@ namespace MediaBrowser.Providers.Manager FileSystem = fileSystem; UserDataManager = userDataManager; LibraryManager = libraryManager; + + _subtitleResolver = new SubtitleResolver(BaseItem.LocalizationManager, fileSystem); } public async Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) @@ -76,8 +79,7 @@ namespace MediaBrowser.Providers.Manager if (video != null && !video.IsPlaceHolder) { requiresRefresh = !video.SubtitleFiles - .SequenceEqual(SubtitleResolver.GetSubtitleFiles(video, refreshOptions.DirectoryService, FileSystem, false) - .OrderBy(i => i), StringComparer.OrdinalIgnoreCase); + .SequenceEqual(_subtitleResolver.GetExternalSubtitleFiles(video, refreshOptions.DirectoryService, false), StringComparer.Ordinal); } } } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index a6a363ffd..158238557 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -229,7 +229,7 @@ namespace MediaBrowser.Providers.MediaInfo extractDuringScan = libraryOptions.ExtractChapterImagesDuringLibraryScan; } - await _encodingManager.RefreshChapterImages(video, chapters, extractDuringScan, false, cancellationToken).ConfigureAwait(false); + await _encodingManager.RefreshChapterImages(video, options.DirectoryService, chapters, extractDuringScan, false, cancellationToken).ConfigureAwait(false); _chapterManager.SaveChapters(video.Id.ToString(), chapters); } @@ -472,7 +472,7 @@ namespace MediaBrowser.Providers.MediaInfo var subtitleResolver = new SubtitleResolver(_localization, _fileSystem); var startIndex = currentStreams.Count == 0 ? 0 : (currentStreams.Select(i => i.Index).Max() + 1); - var externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, startIndex, options.DirectoryService, false).ToList(); + var externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, startIndex, options.DirectoryService, false); var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.Default || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh; @@ -497,7 +497,7 @@ namespace MediaBrowser.Providers.MediaInfo // Rescan if (downloadedLanguages.Count > 0) { - externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, startIndex, options.DirectoryService, true).ToList(); + externalSubtitleStreams = subtitleResolver.GetExternalSubtitleStreams(video, startIndex, options.DirectoryService, true); } } diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs index a2c10d6a8..4e264bd22 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs @@ -16,29 +16,91 @@ namespace MediaBrowser.Providers.MediaInfo private readonly ILocalizationManager _localization; private readonly IFileSystem _fileSystem; + private string[] SubtitleExtensions = new[] + { + ".srt", + ".ssa", + ".ass", + ".sub", + ".smi", + ".sami", + ".vtt" + }; + public SubtitleResolver(ILocalizationManager localization, IFileSystem fileSystem) { _localization = localization; _fileSystem = fileSystem; } - public IEnumerable GetExternalSubtitleStreams(Video video, + public List GetExternalSubtitleStreams(Video video, int startIndex, IDirectoryService directoryService, bool clearCache) { - var files = GetSubtitleFiles(video, directoryService, _fileSystem, clearCache); - var streams = new List(); - var videoFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(video.Path); + GetExternalSubtitleStreams(streams, video.ContainingFolderPath, video.Path, startIndex, directoryService, clearCache); + + startIndex += streams.Count; + + try + { + GetExternalSubtitleStreams(streams, video.GetInternalMetadataPath(), video.Path, startIndex, directoryService, clearCache); + } + catch (IOException) + { + + } + + return streams; + } + + public List GetExternalSubtitleFiles(Video video, + IDirectoryService directoryService, + bool clearCache) + { + var streams = GetExternalSubtitleStreams(video, 0, directoryService, clearCache); + + var list = new List(); + + foreach (var stream in streams) + { + list.Add(stream.Path); + } + + return list; + } + + private void GetExternalSubtitleStreams(List streams, string folder, + string videoPath, + int startIndex, + IDirectoryService directoryService, + bool clearCache) + { + var videoFileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(videoPath); videoFileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(videoFileNameWithoutExtension); + var files = directoryService.GetFilePaths(folder, clearCache); + foreach (var fullName in files) { + var extension = Path.GetExtension(fullName); + + if (!SubtitleExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) + { + continue; + } + var fileNameWithoutExtension = _fileSystem.GetFileNameWithoutExtension(fullName); fileNameWithoutExtension = NormalizeFilenameForSubtitleComparison(fileNameWithoutExtension); + if (!string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase) && + !fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase)) + { + continue; + } + var codec = Path.GetExtension(fullName).ToLower().TrimStart('.'); if (string.Equals(codec, "txt", StringComparison.OrdinalIgnoreCase)) @@ -98,8 +160,6 @@ namespace MediaBrowser.Providers.MediaInfo }); } } - - return streams; } private string NormalizeFilenameForSubtitleComparison(string filename) @@ -115,48 +175,5 @@ namespace MediaBrowser.Providers.MediaInfo return filename; } - - private static IEnumerable SubtitleExtensions - { - get - { - return new[] { ".srt", ".ssa", ".ass", ".sub", ".smi", ".sami", ".vtt" }; - } - } - - public static IEnumerable GetSubtitleFiles(Video video, IDirectoryService directoryService, IFileSystem fileSystem, bool clearCache) - { - var containingPath = video.ContainingFolderPath; - - if (string.IsNullOrEmpty(containingPath)) - { - throw new ArgumentException(string.Format("Cannot search for items that don't have a path: {0} {1}", video.Name, video.Id)); - } - - var files = fileSystem.GetFilePaths(containingPath, clearCache); - - var videoFileNameWithoutExtension = fileSystem.GetFileNameWithoutExtension(video.Path); - - return files.Where(i => - { - var extension = Path.GetExtension(i); - - if (SubtitleExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) - { - var fileNameWithoutExtension = fileSystem.GetFileNameWithoutExtension(i); - - if (string.Equals(videoFileNameWithoutExtension, fileNameWithoutExtension, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - if (fileNameWithoutExtension.StartsWith(videoFileNameWithoutExtension + ".", StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - - return false; - }); - } } } diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index fe655759e..945498966 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -16,8 +16,8 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; - -using MediaBrowser.Controller.IO; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.IO; namespace MediaBrowser.Providers.Subtitles @@ -30,17 +30,19 @@ namespace MediaBrowser.Providers.Subtitles private readonly ILibraryMonitor _monitor; private readonly ILibraryManager _libraryManager; private readonly IMediaSourceManager _mediaSourceManager; + private readonly IServerConfigurationManager _config; public event EventHandler SubtitlesDownloaded; public event EventHandler SubtitleDownloadFailure; - public SubtitleManager(ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager) + public SubtitleManager(ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager, IServerConfigurationManager config) { _logger = logger; _fileSystem = fileSystem; _monitor = monitor; _libraryManager = libraryManager; _mediaSourceManager = mediaSourceManager; + _config = config; } public void AddParts(IEnumerable subtitleProviders) @@ -102,6 +104,11 @@ namespace MediaBrowser.Providers.Subtitles return results.SelectMany(i => i).ToArray(); } + private SubtitleOptions GetOptions() + { + return _config.GetConfiguration("subtitles"); + } + public async Task DownloadSubtitles(Video video, string subtitleId, CancellationToken cancellationToken) @@ -109,49 +116,37 @@ namespace MediaBrowser.Providers.Subtitles var parts = subtitleId.Split(new[] { '_' }, 2); var provider = GetProvider(parts.First()); + var saveInMediaFolder = GetOptions().SaveSubtitlesInMediaFolders && video.SupportsLocalMetadata; + try { var response = await GetRemoteSubtitles(subtitleId, cancellationToken).ConfigureAwait(false); using (var stream = response.Stream) { - var savePath = Path.Combine(_fileSystem.GetDirectoryName(video.Path), - _fileSystem.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower()); - - if (response.IsForced) + using (var memoryStream = new MemoryStream()) { - savePath += ".forced"; - } - - savePath += "." + response.Format.ToLower(); + await stream.CopyToAsync(memoryStream).ConfigureAwait(false); + memoryStream.Position = 0; - _logger.Info("Saving subtitles to {0}", savePath); + var savePaths = new List(); + var saveFileName = _fileSystem.GetFileNameWithoutExtension(video.Path) + "." + response.Language.ToLower(); - _monitor.ReportFileSystemChangeBeginning(savePath); + if (response.IsForced) + { + saveFileName += ".forced"; + } - try - { - //var isText = MediaStream.IsTextFormat(response.Format); + saveFileName += "." + response.Format.ToLower(); - using (var fs = _fileSystem.GetFileStream(savePath, FileOpenMode.Create, FileAccessMode.Write, - FileShareMode.Read, true)) + if (saveInMediaFolder) { - await stream.CopyToAsync(fs).ConfigureAwait(false); + savePaths.Add(Path.Combine(video.ContainingFolderPath, saveFileName)); } - EventHelper.FireEventIfNotNull(SubtitlesDownloaded, this, new SubtitleDownloadEventArgs - { - Item = video, - Format = response.Format, - Language = response.Language, - IsForced = response.IsForced, - Provider = provider.Name + savePaths.Add(Path.Combine(video.GetInternalMetadataPath(), saveFileName)); - }, _logger); - } - finally - { - _monitor.ReportFileSystemChangeComplete(savePath, false); + await TrySaveToFiles(memoryStream, savePaths).ConfigureAwait(false); } } } @@ -173,6 +168,46 @@ namespace MediaBrowser.Providers.Subtitles } } + private async Task TrySaveToFiles(Stream stream, List savePaths) + { + Exception exceptionToThrow = null; + + foreach (var savePath in savePaths) + { + _logger.Info("Saving subtitles to {0}", savePath); + + _monitor.ReportFileSystemChangeBeginning(savePath); + + try + { + using (var fs = _fileSystem.GetFileStream(savePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true)) + { + await stream.CopyToAsync(fs).ConfigureAwait(false); + } + + return; + } + catch (Exception ex) + { + if (exceptionToThrow == null) + { + exceptionToThrow = ex; + } + } + finally + { + _monitor.ReportFileSystemChangeComplete(savePath, false); + } + + stream.Position = 0; + } + + if (exceptionToThrow != null) + { + throw exceptionToThrow; + } + } + public Task SearchSubtitles(Video video, string language, bool? isPerfectMatch, CancellationToken cancellationToken) { if (video.LocationType != LocationType.FileSystem || diff --git a/SharedVersion.cs b/SharedVersion.cs index 74a0759e3..0750f469e 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.36.1")] +[assembly: AssemblyVersion("3.2.36.2")] -- cgit v1.2.3 From 901d7b509c712ababc489166e05bdfea1908fa0f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 9 Nov 2017 15:58:09 -0500 Subject: update play media source feature --- Emby.Dlna/PlayTo/PlayToController.cs | 2 +- .../Localization/Core/cs.json | 2 +- .../Localization/Core/fr.json | 2 +- .../Localization/Core/sk.json | 100 ++++++++++----------- .../Session/HttpSessionController.cs | 12 +++ .../Session/SessionManager.cs | 11 ++- MediaBrowser.Api/Session/SessionsService.cs | 33 +------ MediaBrowser.Model/Session/PlayRequest.cs | 10 ++- SharedVersion.cs | 2 +- 9 files changed, 82 insertions(+), 92 deletions(-) (limited to 'Emby.Server.Implementations/Localization/Core') diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index ba1d3a6de..bd0a9e1f4 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -328,7 +328,7 @@ namespace Emby.Dlna.PlayTo { if (isFirst && command.StartPositionTicks.HasValue) { - playlist.Add(CreatePlaylistItem(item, user, command.StartPositionTicks.Value, null, null, null)); + playlist.Add(CreatePlaylistItem(item, user, command.StartPositionTicks.Value, command.MediaSourceId, command.AudioStreamIndex, command.SubtitleStreamIndex)); isFirst = false; } else diff --git a/Emby.Server.Implementations/Localization/Core/cs.json b/Emby.Server.Implementations/Localization/Core/cs.json index 82d8699a7..d59e40ed3 100644 --- a/Emby.Server.Implementations/Localization/Core/cs.json +++ b/Emby.Server.Implementations/Localization/Core/cs.json @@ -27,7 +27,7 @@ "Artists": "Um\u011blci", "Folders": "Slo\u017eky", "Songs": "Skladby", - "TvShows": "TV Shows", + "TvShows": "TV seri\u00e1ly", "Shows": "Seri\u00e1ly", "Genres": "\u017d\u00e1nry", "NameSeasonNumber": "Sez\u00f3na {0}", diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json index 953d7f434..6552a47ab 100644 --- a/Emby.Server.Implementations/Localization/Core/fr.json +++ b/Emby.Server.Implementations/Localization/Core/fr.json @@ -27,7 +27,7 @@ "Artists": "Artistes", "Folders": "Dossiers", "Songs": "Chansons", - "TvShows": "TV Shows", + "TvShows": "S\u00e9ries T\u00e9l\u00e9", "Shows": "\u00c9missions", "Genres": "Genres", "NameSeasonNumber": "Saison {0}", diff --git a/Emby.Server.Implementations/Localization/Core/sk.json b/Emby.Server.Implementations/Localization/Core/sk.json index 0c7bce1da..f09eb1506 100644 --- a/Emby.Server.Implementations/Localization/Core/sk.json +++ b/Emby.Server.Implementations/Localization/Core/sk.json @@ -1,7 +1,7 @@ { - "Latest": "Latest", - "ValueSpecialEpisodeName": "Special - {0}", - "Inherit": "Inherit", + "Latest": "Najnov\u0161ie", + "ValueSpecialEpisodeName": "\u0160peci\u00e1l - {0}", + "Inherit": "Zdedi\u0165", "Books": "Knihy", "Music": "Hudba", "Games": "Hry", @@ -9,13 +9,13 @@ "MixedContent": "Zmie\u0161an\u00fd obsah", "MusicVideos": "Hudobn\u00e9 vide\u00e1", "HomeVideos": "Dom\u00e1ce vide\u00e1", - "Playlists": "Playlists", + "Playlists": "Zoznamy skladieb", "HeaderRecordingGroups": "Recording Groups", - "HeaderContinueWatching": "Continue Watching", - "HeaderFavoriteArtists": "Favorite Artists", + "HeaderContinueWatching": "Pokra\u010dujte v pozeran\u00ed", + "HeaderFavoriteArtists": "Ob\u013e\u00faben\u00ed umelci", "HeaderFavoriteSongs": "Ob\u013e\u00faben\u00e9 pesni\u010dky", "HeaderAlbumArtists": "Album Artists", - "HeaderFavoriteAlbums": "Favorite Albums", + "HeaderFavoriteAlbums": "Ob\u013e\u00faben\u00e9 albumy", "HeaderFavoriteEpisodes": "Ob\u013e\u00faben\u00e9 epiz\u00f3dy", "HeaderFavoriteShows": "Ob\u013e\u00faben\u00e9 seri\u00e1ly", "HeaderNextUp": "Nasleduje", @@ -30,62 +30,62 @@ "TvShows": "TV Shows", "Shows": "Series", "Genres": "\u017d\u00e1nre", - "NameSeasonNumber": "Season {0}", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", + "NameSeasonNumber": "Sez\u00f3na {0}", + "AppDeviceValues": "Aplik\u00e1cia: {0}, Zariadenie: {1}", + "UserDownloadingItemWithValues": "{0} s\u0165ahuje {1}", "HeaderLiveTV": "Live TV", - "ChapterNameValue": "Chapter {0}", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", + "ChapterNameValue": "Kapitola {0}", + "ScheduledTaskFailedWithName": "{0} zlyhalo", + "LabelRunningTimeValue": "D\u013a\u017eka: {0}", "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly.", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", + "VersionNumber": "Verzia {0}", + "PluginInstalledWithName": "{0} bol nain\u0161talovan\u00fd", + "StartupEmbyServerIsLoading": "Emby Server sa sp\u00fa\u0161\u0165a. Sk\u00faste to pros\u00edm o chv\u00ed\u013eu znova.", + "PluginUpdatedWithName": "{0} bol aktualizovan\u00fd", + "PluginUninstalledWithName": "{0} bol odin\u0161talovan\u00fd", + "ItemAddedWithName": "{0} bol pridan\u00fd do kni\u017enice", + "ItemRemovedWithName": "{0} bol odstr\u00e1nen\u00fd z kni\u017enice", + "LabelIpAddressValue": "IP adresa: {0}", + "DeviceOnlineWithName": "{0} je pripojen\u00fd", + "UserOnlineFromDevice": "{0} je online z {1}", "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", + "SubtitlesDownloadedForItem": "Titulky pre {0} stiahnut\u00e9", + "UserCreatedWithName": "Pou\u017e\u00edvate\u013e {0} bol vytvoren\u00fd", + "UserPasswordChangedWithName": "Heslo pou\u017e\u00edvate\u013ea {0} zmenen\u00e9", + "UserDeletedWithName": "Pou\u017e\u00edvate\u013e {0} bol vymazan\u00fd", "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "UserOfflineFromDevice": "{0} has disconnected from {1}", - "DeviceOfflineWithName": "{0} has disconnected", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", + "MessageServerConfigurationUpdated": "Konfigur\u00e1cia servera aktualizovan\u00e1", + "MessageNamedServerConfigurationUpdatedWithValue": "Sekcia {0} konfigur\u00e1cie servera bola aktualizovan\u00e1", + "MessageApplicationUpdated": "Emby Server bol aktualizovan\u00fd", + "FailedLoginAttemptWithUserName": "Ne\u00faspe\u0161n\u00fd pokus o prihl\u00e1senie z {0}", + "AuthenticationSucceededWithUserName": "{0} \u00faspe\u0161ne overen\u00fd", + "UserOfflineFromDevice": "{0} sa odpojil od {1}", + "DeviceOfflineWithName": "{0} je odpojen\u00fd", + "UserStartedPlayingItemWithValues": "{0} spustil prehr\u00e1vanie {1}", + "UserStoppedPlayingItemWithValues": "{0} zastavil prehr\u00e1vanie {1}", "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", + "NotificationOptionApplicationUpdateAvailable": "Je dostupn\u00e1 aktualiz\u00e1cia aplik\u00e1cie", + "NotificationOptionApplicationUpdateInstalled": "Aktualiz\u00e1cia aplik\u00e1cie nain\u0161talovan\u00e1", "NotificationOptionPluginUpdateInstalled": "Plugin update installed", "NotificationOptionPluginInstalled": "Plugin installed", "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", + "NotificationOptionVideoPlayback": "Spusten\u00e9 prehr\u00e1vanie videa", + "NotificationOptionAudioPlayback": "Spusten\u00e9 prehr\u00e1vanie audia", "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", + "NotificationOptionVideoPlaybackStopped": "Zastaven\u00e9 prehr\u00e1vanie videa", + "NotificationOptionAudioPlaybackStopped": "Zastaven\u00e9 prehr\u00e1vanie audia", + "NotificationOptionGamePlaybackStopped": "Hra ukon\u010den\u00e1", + "NotificationOptionTaskFailed": "Napl\u00e1novan\u00e1 \u00faloha zlyhala", + "NotificationOptionInstallationFailed": "Chyba in\u0161tal\u00e1cie", + "NotificationOptionNewLibraryContent": "Pridan\u00fd nov\u00fd obsah", "NotificationOptionCameraImageUploaded": "Camera image uploaded", "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", + "NotificationOptionServerRestartRequired": "Vy\u017eaduje sa re\u0161tart servera", "UserLockedOutWithName": "User {0} has been locked out", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", + "SubtitleDownloadFailureForItem": "S\u0165ahovanie titulkov pre {0} zlyhalo", "Sync": "Sync", - "User": "User", - "System": "System", + "User": "Pou\u017e\u00edvate\u013e", + "System": "Syst\u00e9m", "Application": "Aplik\u00e1cia", "Plugin": "Plugin" } \ No newline at end of file diff --git a/Emby.Server.Implementations/Session/HttpSessionController.cs b/Emby.Server.Implementations/Session/HttpSessionController.cs index 940c821e2..e1c1bbe2b 100644 --- a/Emby.Server.Implementations/Session/HttpSessionController.cs +++ b/Emby.Server.Implementations/Session/HttpSessionController.cs @@ -109,6 +109,18 @@ namespace Emby.Server.Implementations.Session { dict["StartPositionTicks"] = command.StartPositionTicks.Value.ToString(CultureInfo.InvariantCulture); } + if (command.AudioStreamIndex.HasValue) + { + dict["AudioStreamIndex"] = command.AudioStreamIndex.Value.ToString(CultureInfo.InvariantCulture); + } + if (command.SubtitleStreamIndex.HasValue) + { + dict["SubtitleStreamIndex"] = command.SubtitleStreamIndex.Value.ToString(CultureInfo.InvariantCulture); + } + if (!string.IsNullOrWhiteSpace(command.MediaSourceId)) + { + dict["MediaSourceId"] = command.MediaSourceId; + } return SendMessage(command.PlayCommand.ToString(), dict, cancellationToken); } diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 2c1535165..30f6e6521 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -972,7 +972,6 @@ namespace Emby.Server.Implementations.Session if (command.PlayCommand == PlayCommand.PlayInstantMix) { items = command.ItemIds.SelectMany(i => TranslateItemForInstantMix(i, user)) - .Where(i => i.LocationType != LocationType.Virtual) .ToList(); command.PlayCommand = PlayCommand.PlayNow; @@ -986,9 +985,7 @@ namespace Emby.Server.Implementations.Session list.AddRange(subItems); } - items = list - .Where(i => i.LocationType != LocationType.Virtual) - .ToList(); + items = list; } if (command.PlayCommand == PlayCommand.PlayShuffle) @@ -1074,7 +1071,8 @@ namespace Emby.Server.Implementations.Session { ItemFields.SortName } - } + }, + IsVirtualItem = false }); return FilterToSingleMediaType(items) @@ -1097,7 +1095,8 @@ namespace Emby.Server.Implementations.Session { ItemFields.SortName } - } + }, + IsVirtualItem = false }); diff --git a/MediaBrowser.Api/Session/SessionsService.cs b/MediaBrowser.Api/Session/SessionsService.cs index e961f9d51..35c29cd15 100644 --- a/MediaBrowser.Api/Session/SessionsService.cs +++ b/MediaBrowser.Api/Session/SessionsService.cs @@ -66,7 +66,7 @@ namespace MediaBrowser.Api.Session [Route("/Sessions/{Id}/Playing", "POST", Summary = "Instructs a session to play an item")] [Authenticated] - public class Play : IReturnVoid + public class Play : PlayRequest { /// /// Gets or sets the id. @@ -74,27 +74,6 @@ namespace MediaBrowser.Api.Session /// The id. [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] public string Id { get; set; } - - /// - /// Artist, Genre, Studio, Person, or any kind of BaseItem - /// - /// The type of the item. - [ApiMember(Name = "ItemIds", Description = "The ids of the items to play, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)] - public string ItemIds { get; set; } - - /// - /// Gets or sets the start position ticks that the first item should be played at - /// - /// The start position ticks. - [ApiMember(Name = "StartPositionTicks", Description = "The starting position of the first item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] - public long? StartPositionTicks { get; set; } - - /// - /// Gets or sets the play command. - /// - /// The play command. - [ApiMember(Name = "PlayCommand", Description = "The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public PlayCommand PlayCommand { get; set; } } [Route("/Sessions/{Id}/Playing/{Command}", "POST", Summary = "Issues a playstate command to a client")] @@ -471,15 +450,7 @@ namespace MediaBrowser.Api.Session /// The request. public void Post(Play request) { - var command = new PlayRequest - { - ItemIds = request.ItemIds.Split(','), - - PlayCommand = request.PlayCommand, - StartPositionTicks = request.StartPositionTicks - }; - - var task = _sessionManager.SendPlayCommand(GetSession(_sessionContext).Result.Id, request.Id, command, CancellationToken.None); + var task = _sessionManager.SendPlayCommand(GetSession(_sessionContext).Result.Id, request.Id, request, CancellationToken.None); Task.WaitAll(task); } diff --git a/MediaBrowser.Model/Session/PlayRequest.cs b/MediaBrowser.Model/Session/PlayRequest.cs index 5db5e90cb..d50cb5953 100644 --- a/MediaBrowser.Model/Session/PlayRequest.cs +++ b/MediaBrowser.Model/Session/PlayRequest.cs @@ -1,4 +1,5 @@ - +using MediaBrowser.Model.Services; + namespace MediaBrowser.Model.Session { /// @@ -10,18 +11,21 @@ namespace MediaBrowser.Model.Session /// Gets or sets the item ids. /// /// The item ids. + [ApiMember(Name = "ItemIds", Description = "The ids of the items to play, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)] public string[] ItemIds { get; set; } /// /// Gets or sets the start position ticks that the first item should be played at /// /// The start position ticks. + [ApiMember(Name = "StartPositionTicks", Description = "The starting position of the first item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] public long? StartPositionTicks { get; set; } /// /// Gets or sets the play command. /// /// The play command. + [ApiMember(Name = "PlayCommand", Description = "The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] public PlayCommand PlayCommand { get; set; } /// @@ -29,5 +33,9 @@ namespace MediaBrowser.Model.Session /// /// The controlling user identifier. public string ControllingUserId { get; set; } + + public int? SubtitleStreamIndex { get; set; } + public int? AudioStreamIndex { get; set; } + public string MediaSourceId { get; set; } } } \ No newline at end of file diff --git a/SharedVersion.cs b/SharedVersion.cs index f0a2b930d..1505ef0b8 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.36.5")] +[assembly: AssemblyVersion("3.2.36.6")] -- cgit v1.2.3 From b5ab7776f16196610f2b7d462e59c8851e5ebde2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 16 Nov 2017 16:25:18 -0500 Subject: 3.2.36.11 --- .../Library/Resolvers/Audio/AudioResolver.cs | 243 ++++++++++++++++++--- .../Library/Resolvers/Movies/MovieResolver.cs | 37 ++-- .../Library/Resolvers/VideoResolver.cs | 30 --- .../Localization/Core/es-MX.json | 2 +- MediaBrowser.Providers/Manager/MetadataService.cs | 2 +- MediaBrowser.Server.Mono/ImageEncoderHelper.cs | 4 +- SharedVersion.cs | 2 +- 7 files changed, 240 insertions(+), 80 deletions(-) (limited to 'Emby.Server.Implementations/Localization/Core') diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs index e2f2946db..84b4492cc 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs @@ -4,19 +4,26 @@ using MediaBrowser.Model.Entities; using System; using MediaBrowser.Controller.Entities; using System.IO; +using System.Linq; +using MediaBrowser.Controller.Providers; +using System.Collections.Generic; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Extensions; +using Emby.Naming.Video; +using Emby.Naming.AudioBook; namespace Emby.Server.Implementations.Library.Resolvers.Audio { /// /// Class AudioResolver /// - public class AudioResolver : ItemResolver + public class AudioResolver : ItemResolver, IMultiItemResolver { - private readonly ILibraryManager _libraryManager; + private readonly ILibraryManager LibraryManager; public AudioResolver(ILibraryManager libraryManager) { - _libraryManager = libraryManager; + LibraryManager = libraryManager; } /// @@ -28,6 +35,37 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio get { return ResolverPriority.Last; } } + public MultiItemResolverResult ResolveMultiple(Folder parent, + List files, + string collectionType, + IDirectoryService directoryService) + { + var result = ResolveMultipleInternal(parent, files, collectionType, directoryService); + + if (result != null) + { + foreach (var item in result.Items) + { + SetInitialItemValues((MediaBrowser.Controller.Entities.Audio.Audio)item, null); + } + } + + return result; + } + + private MultiItemResolverResult ResolveMultipleInternal(Folder parent, + List files, + string collectionType, + IDirectoryService directoryService) + { + if (string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase)) + { + return ResolveMultipleAudio(parent, files, directoryService, false, collectionType, true); + } + + return null; + } + /// /// Resolves the specified args. /// @@ -37,46 +75,193 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio { // Return audio if the path is a file and has a matching extension - if (!args.IsDirectory) + var libraryOptions = args.GetLibraryOptions(); + var collectionType = args.GetCollectionType(); + + var isBooksCollectionType = string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase); + + if (args.IsDirectory) { - var libraryOptions = args.GetLibraryOptions(); + if (!isBooksCollectionType) + { + return null; + } + + var files = args.FileSystemChildren + .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) + .ToList(); + + if (isBooksCollectionType) + { + return FindAudio(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false); + } + + return null; + } - if (_libraryManager.IsAudioFile(args.Path, libraryOptions)) + if (LibraryManager.IsAudioFile(args.Path, libraryOptions)) + { + if (string.Equals(Path.GetExtension(args.Path), ".cue", StringComparison.OrdinalIgnoreCase)) { - if (string.Equals(Path.GetExtension(args.Path), ".cue", StringComparison.OrdinalIgnoreCase)) - { - // if audio file exists of same name, return null + // if audio file exists of same name, return null + return null; + } - return null; - } + var isMixedCollectionType = string.IsNullOrWhiteSpace(collectionType); - var collectionType = args.GetCollectionType(); + // For conflicting extensions, give priority to videos + if (isMixedCollectionType && LibraryManager.IsVideoFile(args.Path, libraryOptions)) + { + return null; + } - var isMixed = string.IsNullOrWhiteSpace(collectionType); + MediaBrowser.Controller.Entities.Audio.Audio item = null; - // For conflicting extensions, give priority to videos - if (isMixed && _libraryManager.IsVideoFile(args.Path, libraryOptions)) - { - return null; - } + var isMusicCollectionType = string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase); - var isStandalone = args.Parent == null; + // Use regular audio type for mixed libraries, owned items and music + if (isMixedCollectionType || + args.Parent == null || + isMusicCollectionType) + { + item = new MediaBrowser.Controller.Entities.Audio.Audio(); + } - if (isStandalone || - string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase) || - isMixed) - { - return new MediaBrowser.Controller.Entities.Audio.Audio(); - } + else if (isBooksCollectionType) + { + item = new AudioBook(); + } - if (string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase)) - { - return new AudioBook(); - } + if (item != null) + { + item.IsInMixedFolder = true; } + + return item; } return null; } + + private T FindAudio(ItemResolveArgs args, string path, Folder parent, List fileSystemEntries, IDirectoryService directoryService, string collectionType, bool parseName) + where T : MediaBrowser.Controller.Entities.Audio.Audio, new() + { + var multiDiscFolders = new List(); + + var libraryOptions = args.GetLibraryOptions(); + var filesFromOtherItems = new List(); + + // TODO: Allow GetMultiDiscMovie in here + var supportsMultiVersion = false; + + var result = ResolveMultipleAudio(parent, fileSystemEntries, directoryService, supportsMultiVersion, collectionType, parseName) ?? + new MultiItemResolverResult(); + + if (result.Items.Count == 1) + { + var videoPath = result.Items[0].Path; + + // If we were supporting this we'd be checking filesFromOtherItems + var hasOtherItems = false; + + if (!hasOtherItems) + { + var item = (T)result.Items[0]; + item.IsInMixedFolder = false; + item.Name = Path.GetFileName(item.ContainingFolderPath); + return item; + } + } + + if (result.Items.Count == 0 && multiDiscFolders.Count > 0) + { + //return GetMultiDiscAudio(multiDiscFolders, directoryService); + } + + return null; + } + + private MultiItemResolverResult ResolveMultipleAudio(Folder parent, IEnumerable fileSystemEntries, IDirectoryService directoryService, bool suppportMultiEditions, string collectionType, bool parseName) + where T : MediaBrowser.Controller.Entities.Audio.Audio, new() + { + var files = new List(); + var items = new List(); + var leftOver = new List(); + + // Loop through each child file/folder and see if we find a video + foreach (var child in fileSystemEntries) + { + if (child.IsDirectory) + { + leftOver.Add(child); + } + else if (IsIgnored(child.Name)) + { + + } + else + { + files.Add(child); + } + } + + var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); + + var resolver = new AudioBookListResolver(namingOptions); + var resolverResult = resolver.Resolve(files).ToList(); + + var result = new MultiItemResolverResult + { + ExtraFiles = leftOver, + Items = items + }; + + var isInMixedFolder = resolverResult.Count > 1 || (parent != null && parent.IsTopParent); + + foreach (var resolvedItem in resolverResult) + { + var firstMedia = resolvedItem.Files.First(); + + var libraryItem = new T + { + Path = firstMedia.Path, + IsInMixedFolder = isInMixedFolder, + //ProductionYear = resolvedItem.Year, + Name = parseName ? + resolvedItem.Name : + Path.GetFileNameWithoutExtension(firstMedia.Path), + //AdditionalParts = resolvedItem.Files.Skip(1).Select(i => i.Path).ToArray(), + //LocalAlternateVersions = resolvedItem.AlternateVersions.Select(i => i.Path).ToArray() + }; + + result.Items.Add(libraryItem); + } + + result.ExtraFiles.AddRange(files.Where(i => !ContainsFile(resolverResult, i))); + + return result; + } + + private bool ContainsFile(List result, FileSystemMetadata file) + { + return result.Any(i => ContainsFile(i, file)); + } + + private bool ContainsFile(AudioBookInfo result, FileSystemMetadata file) + { + return result.Files.Any(i => ContainsFile(i, file)) || + result.AlternateVersions.Any(i => ContainsFile(i, file)) || + result.Extras.Any(i => ContainsFile(i, file)); + } + + private bool ContainsFile(AudioBookFileInfo result, FileSystemMetadata file) + { + return string.Equals(result.Path, file.FullName, StringComparison.OrdinalIgnoreCase); + } + + private bool IsIgnored(string filename) + { + return false; + } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index d69a2b240..667616414 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -202,14 +202,14 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies { var collectionType = args.GetCollectionType(); - if (IsInvalid(args.Parent, collectionType)) - { - return null; - } - // Find movies with their own folders if (args.IsDirectory) { + if (IsInvalid(args.Parent, collectionType)) + { + return null; + } + var files = args.FileSystemChildren .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) .ToList(); @@ -251,8 +251,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return null; } - // Owned items will be caught by the plain video resolver + // Handle owned items if (args.Parent == null) + { + return base.Resolve(args); + } + + if (IsInvalid(args.Parent, collectionType)) { return null; } @@ -528,6 +533,15 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return returnVideo; } + private string[] ValidCollectionTypes = new[] + { + CollectionType.Movies, + CollectionType.HomeVideos, + CollectionType.MusicVideos, + CollectionType.Movies, + CollectionType.Photos + }; + private bool IsInvalid(Folder parent, string collectionType) { if (parent != null) @@ -538,21 +552,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies } } - var validCollectionTypes = new[] - { - CollectionType.Movies, - CollectionType.HomeVideos, - CollectionType.MusicVideos, - CollectionType.Movies, - CollectionType.Photos - }; - if (string.IsNullOrWhiteSpace(collectionType)) { return false; } - return !validCollectionTypes.Contains(collectionType, StringComparer.OrdinalIgnoreCase); + return !ValidCollectionTypes.Contains(collectionType, StringComparer.OrdinalIgnoreCase); } private IImageProcessor _imageProcessor; diff --git a/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs index 5c7a528f5..030ff88f7 100644 --- a/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs @@ -5,36 +5,6 @@ using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers { - /// - /// Resolves a Path into a Video - /// - public class VideoResolver : BaseVideoResolver