From 5207067811afdd5e4c0f3bbcfcb254bfbb6d7ce9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 29 Nov 2017 15:50:18 -0500 Subject: [PATCH 1/2] fix live tv over dlna --- .../ApplicationHost.cs | 56 +++++--- .../Data/SqliteItemRepository.cs | 2 +- .../Emby.Server.Implementations.csproj | 2 + .../LiveTv/TunerHosts/M3UTunerHost.cs | 16 ++- .../LiveTv/TunerHosts/SharedHttpStream.cs | 3 +- .../Localization/Core/ca.json | 126 +++++++++--------- .../Localization/Core/de.json | 4 +- .../Localization/Core/el.json | 91 +++++++++++++ .../Localization/Core/es-MX.json | 2 +- .../Localization/Core/gsw.json | 91 +++++++++++++ .../Localization/Core/pt-BR.json | 2 +- .../Networking/NetworkManager.cs | 14 +- MediaBrowser.Common/Net/INetworkManager.cs | 4 +- MediaBrowser.Model/Dlna/StreamInfo.cs | 5 + 14 files changed, 327 insertions(+), 91 deletions(-) create mode 100644 Emby.Server.Implementations/Localization/Core/el.json create mode 100644 Emby.Server.Implementations/Localization/Core/gsw.json diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 2e5c4be90..9a159194e 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -393,6 +393,7 @@ namespace Emby.Server.Implementations ISystemEvents systemEvents, INetworkManager networkManager) { + // hack alert, until common can target .net core BaseExtensions.CryptographyProvider = CryptographyProvider; @@ -423,6 +424,13 @@ namespace Emby.Server.Implementations SetBaseExceptionMessage(); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); + + NetworkManager.NetworkChanged += NetworkManager_NetworkChanged; + } + + private void NetworkManager_NetworkChanged(object sender, EventArgs e) + { + _validAddressResults.Clear(); } private Version _version; @@ -1960,9 +1968,9 @@ namespace Emby.Server.Implementations try { // Return the first matched address, if found, or the first known local address - var address = (await GetLocalIpAddresses(cancellationToken).ConfigureAwait(false)).FirstOrDefault(i => !i.Equals(IpAddressInfo.Loopback) && !i.Equals(IpAddressInfo.IPv6Loopback)); + var addresses = await GetLocalIpAddressesInternal(false, 1, cancellationToken).ConfigureAwait(false); - if (address != null) + foreach (var address in addresses) { return GetLocalApiUrl(address); } @@ -1994,7 +2002,12 @@ namespace Emby.Server.Implementations HttpPort.ToString(CultureInfo.InvariantCulture)); } - public async Task> GetLocalIpAddresses(CancellationToken cancellationToken) + public Task> GetLocalIpAddresses(CancellationToken cancellationToken) + { + return GetLocalIpAddressesInternal(true, 0, cancellationToken); + } + + private async Task> GetLocalIpAddressesInternal(bool allowLoopback, int limit, CancellationToken cancellationToken) { var addresses = ServerConfigurationManager .Configuration @@ -2006,22 +2019,33 @@ namespace Emby.Server.Implementations if (addresses.Count == 0) { addresses.AddRange(NetworkManager.GetLocalIpAddresses()); + } - var list = new List(); + var resultList = new List(); - foreach (var address in addresses) + foreach (var address in addresses) + { + if (!allowLoopback) { - var valid = await IsIpAddressValidAsync(address, cancellationToken).ConfigureAwait(false); - if (valid) + if (address.Equals(IpAddressInfo.Loopback) || address.Equals(IpAddressInfo.IPv6Loopback)) { - list.Add(address); + continue; } } - addresses = list; + var valid = await IsIpAddressValidAsync(address, cancellationToken).ConfigureAwait(false); + if (valid) + { + resultList.Add(address); + + if (limit > 0 && resultList.Count >= limit) + { + return resultList; + } + } } - return addresses; + return resultList; } private IpAddressInfo NormalizeConfiguredLocalAddress(string address) @@ -2042,7 +2066,6 @@ namespace Emby.Server.Implementations } private readonly ConcurrentDictionary _validAddressResults = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - private DateTime _lastAddressCacheClear; private async Task IsIpAddressValidAsync(IpAddressInfo address, CancellationToken cancellationToken) { if (address.Equals(IpAddressInfo.Loopback) || @@ -2054,12 +2077,6 @@ namespace Emby.Server.Implementations var apiUrl = GetLocalApiUrl(address); apiUrl += "/system/ping"; - if ((DateTime.UtcNow - _lastAddressCacheClear).TotalMinutes >= 15) - { - _lastAddressCacheClear = DateTime.UtcNow; - _validAddressResults.Clear(); - } - bool cachedResult; if (_validAddressResults.TryGetValue(apiUrl, out cachedResult)) { @@ -2087,18 +2104,19 @@ namespace Emby.Server.Implementations var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase); _validAddressResults.AddOrUpdate(apiUrl, valid, (k, v) => valid); - //Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, valid); + Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, valid); return valid; } } } catch (OperationCanceledException) { + Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, "Cancelled"); throw; } catch { - //Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, false); + Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, false); _validAddressResults.AddOrUpdate(apiUrl, false, (k, v) => false); return false; diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index eb0f5150f..ddead897e 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -4286,7 +4286,7 @@ namespace Emby.Server.Implementations.Data if (query.MinParentalRating.HasValue) { - whereClauses.Add("InheritedParentalRatingValue<=@MinParentalRating"); + whereClauses.Add("InheritedParentalRatingValue>=@MinParentalRating"); if (statement != null) { statement.TryBind("@MinParentalRating", query.MinParentalRating.Value); diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 7ccf54d20..cef37910e 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -708,6 +708,8 @@ + + diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index e6c9b184e..04c5303f1 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -17,6 +17,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.System; +using System.IO; namespace Emby.Server.Implementations.LiveTv.TunerHosts { @@ -75,6 +76,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts return Task.FromResult(list); } + private string[] _disallowedSharedStreamExtensions = new string[] + { + ".mkv", + ".mp4", + ".m3u8", + ".mpd" + }; + protected override async Task GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken) { var tunerCount = info.TunerCount; @@ -95,7 +104,12 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (mediaSource.Protocol == MediaProtocol.Http && !mediaSource.RequiresLooping) { - return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _environment); + var extension = Path.GetExtension(mediaSource.Path) ?? string.Empty; + + if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) + { + return new SharedHttpStream(mediaSource, info, streamId, FileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost, _environment); + } } return new LiveStream(mediaSource, info, _environment, FileSystem, Logger, Config.ApplicationPaths); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index b8c7c7b18..af7491e86 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -71,7 +71,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } else if (contentType.IndexOf("mp4", StringComparison.OrdinalIgnoreCase) != -1 || contentType.IndexOf("dash", StringComparison.OrdinalIgnoreCase) != -1 || - contentType.IndexOf("mpegURL", StringComparison.OrdinalIgnoreCase) != -1) + contentType.IndexOf("mpegURL", StringComparison.OrdinalIgnoreCase) != -1 || + contentType.IndexOf("text/", StringComparison.OrdinalIgnoreCase) != -1) { requiresRemux = true; } diff --git a/Emby.Server.Implementations/Localization/Core/ca.json b/Emby.Server.Implementations/Localization/Core/ca.json index f21a0b295..7c55540e5 100644 --- a/Emby.Server.Implementations/Localization/Core/ca.json +++ b/Emby.Server.Implementations/Localization/Core/ca.json @@ -1,74 +1,74 @@ { "Latest": "Darreres", "ValueSpecialEpisodeName": "Especial - {0}", - "Inherit": "Inherit", - "Books": "Books", - "Music": "Music", - "Games": "Games", - "Photos": "Photos", - "MixedContent": "Mixed content", - "MusicVideos": "Music videos", - "HomeVideos": "Home videos", - "Playlists": "Playlists", - "HeaderRecordingGroups": "Recording Groups", + "Inherit": "Heretat", + "Books": "Llibres", + "Music": "M\u00fasica", + "Games": "Jocs", + "Photos": "Fotos", + "MixedContent": "Contingut mesclat", + "MusicVideos": "V\u00eddeos musicals", + "HomeVideos": "V\u00eddeos dom\u00e8stics", + "Playlists": "Llistes de reproducci\u00f3", + "HeaderRecordingGroups": "Grups d'Enregistrament", "HeaderContinueWatching": "Continua Veient", - "HeaderFavoriteArtists": "Favorite Artists", - "HeaderFavoriteSongs": "Favorite Songs", + "HeaderFavoriteArtists": "Artistes Preferits", + "HeaderFavoriteSongs": "Can\u00e7ons Preferides", "HeaderAlbumArtists": "Album Artists", - "HeaderFavoriteAlbums": "Favorite Albums", - "HeaderFavoriteEpisodes": "Favorite Episodes", + "HeaderFavoriteAlbums": "\u00c0lbums Preferits", + "HeaderFavoriteEpisodes": "Episodis Preferits", "HeaderFavoriteShows": "Programes Preferits", "HeaderNextUp": "A continuaci\u00f3", - "Favorites": "Favorites", - "Collections": "Collections", - "Channels": "Channels", - "Movies": "Movies", - "Albums": "Albums", - "Artists": "Artists", - "Folders": "Folders", - "Songs": "Songs", - "TvShows": "TV Shows", - "Shows": "Shows", + "Favorites": "Preferits", + "Collections": "Col\u00b7leccions", + "Channels": "Canals", + "Movies": "Pel\u00b7l\u00edcules", + "Albums": "\u00c0lbums", + "Artists": "Artistes", + "Folders": "Directoris", + "Songs": "Can\u00e7ons", + "TvShows": "Espectacles de TV", + "Shows": "Espectacles", "Genres": "G\u00e8neres", - "NameSeasonNumber": "Season {0}", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "HeaderLiveTV": "Live TV", - "ChapterNameValue": "Chapter {0}", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {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}", - "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", - "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}", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", + "NameSeasonNumber": "Temporada {0}", + "AppDeviceValues": "App: {0}, Dispositiu: {1}", + "UserDownloadingItemWithValues": "{0} est\u00e0 descarregant {1}", + "HeaderLiveTV": "TV en Directe", + "ChapterNameValue": "Episodi {0}", + "ScheduledTaskFailedWithName": "{0} ha fallat", + "LabelRunningTimeValue": "Temps en marxa: {0}", + "ScheduledTaskStartedWithName": "{0} iniciat", + "VersionNumber": "Versi\u00f3 {0}", + "PluginInstalledWithName": "{0} ha estat instal\u00b7lat", + "StartupEmbyServerIsLoading": "El Servidor d'Emby està carregant. Si et plau, prova de nou en breus.", + "PluginUpdatedWithName": "{0} ha estat actualitzat", + "PluginUninstalledWithName": "{0} ha estat desinstal\u00b7lat", + "ItemAddedWithName": "{0} afegit a la biblioteca", + "ItemRemovedWithName": "{0} eliminat de la biblioteca", + "LabelIpAddressValue": "Adre\u00e7a IP: {0}", + "DeviceOnlineWithName": "{0} est\u00e0 connectat", + "UserOnlineFromDevice": "{0} est\u00e0 connectat des de {1}", + "ProviderValue": "Prove\u00efdor: {0}", + "SubtitlesDownloadedForItem": "Subt\u00edtols descarregats per a {0}", + "UserCreatedWithName": "S'ha creat l'usuari {0}", + "UserPasswordChangedWithName": "La contrasenya ha estat canviada per a l'usuari {0}", + "UserDeletedWithName": "L'usuari {0} ha estat eliminat", + "UserConfigurationUpdatedWithName": "La configuraci\u00f3 d'usuari ha estat actualitzada per a {0}", + "MessageServerConfigurationUpdated": "S'ha actualitzat la configuraci\u00f3 del servidor", + "MessageNamedServerConfigurationUpdatedWithValue": "La secci\u00f3 de configuraci\u00f3 {0} ha estat actualitzada", + "MessageApplicationUpdated": "El Servidor d'Emby ha estat actualitzat", + "FailedLoginAttemptWithUserName": "Intent de connexi\u00f3 fallit des de {0}", + "AuthenticationSucceededWithUserName": "{0} s'ha autenticat correctament", + "UserOfflineFromDevice": "{0} s'ha desconnectat de {1}", + "DeviceOfflineWithName": "{0} s'ha desconnectat", + "UserStartedPlayingItemWithValues": "{0} ha comen\u00e7at a reproduir {1}", + "UserStoppedPlayingItemWithValues": "{0} ha parat de reproduir {1}", + "NotificationOptionPluginError": "Un component ha fallat", + "NotificationOptionApplicationUpdateAvailable": "Actualitzaci\u00f3 d'aplicaci\u00f3 disponible", + "NotificationOptionApplicationUpdateInstalled": "Actualitzaci\u00f3 d'aplicaci\u00f3 instal\u00b7lada", + "NotificationOptionPluginUpdateInstalled": "Actualitzaci\u00f3 de complement instal\u00b7lada", + "NotificationOptionPluginInstalled": "Complement instal\u00b7lat", + "NotificationOptionPluginUninstalled": "Complement desinstal\u00b7lat", "NotificationOptionVideoPlayback": "Video playback started", "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionGamePlayback": "Game playback started", diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json index 7bab689eb..bcfadb61c 100644 --- a/Emby.Server.Implementations/Localization/Core/de.json +++ b/Emby.Server.Implementations/Localization/Core/de.json @@ -7,7 +7,7 @@ "Games": "Spiele", "Photos": "Fotos", "MixedContent": "Gemischte Inhalte", - "MusicVideos": "Musik-Videos", + "MusicVideos": "Musikvideos", "HomeVideos": "Heimvideos", "Playlists": "Wiedergabelisten", "HeaderRecordingGroups": "Aufnahme-Gruppen", @@ -27,7 +27,7 @@ "Artists": "Interpreten", "Folders": "Verzeichnisse", "Songs": "Songs", - "TvShows": "TV Shows", + "TvShows": "TV Sendungen", "Shows": "Serien", "Genres": "Genres", "NameSeasonNumber": "Staffel {0}", diff --git a/Emby.Server.Implementations/Localization/Core/el.json b/Emby.Server.Implementations/Localization/Core/el.json new file mode 100644 index 000000000..ab229e111 --- /dev/null +++ b/Emby.Server.Implementations/Localization/Core/el.json @@ -0,0 +1,91 @@ +{ + "Latest": "\u03a4\u03b5\u03bb\u03b5\u03c5\u03c4\u03b1\u03af\u03b1", + "ValueSpecialEpisodeName": "\u0395\u03b9\u03b4\u03b9\u03ba\u03ac - {0} ", + "Inherit": "Inherit", + "Books": "\u0392\u03b9\u03b2\u03bb\u03af\u03b1", + "Music": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ae", + "Games": "\u03a0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9\u03b1", + "Photos": "\u03a6\u03c9\u03c4\u03bf\u03b3\u03c1\u03b1\u03c6\u03af\u03b5\u03c2", + "MixedContent": "\u0391\u03bd\u03ac\u03bc\u03b5\u03b9\u03ba\u03c4\u03bf \u03a0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03bf", + "MusicVideos": "\u039c\u03bf\u03c5\u03c3\u03b9\u03ba\u03ac \u03b2\u03af\u03bd\u03c4\u03b5\u03bf", + "HomeVideos": "\u03a0\u03c1\u03bf\u03c3\u03c9\u03c0\u03b9\u03ba\u03ac \u0392\u03af\u03bd\u03c4\u03b5\u03bf", + "Playlists": "\u039b\u03af\u03c3\u03c4\u03b5\u03c2 \u03b1\u03bd\u03b1\u03c0\u03b1\u03c1\u03b1\u03b3\u03c9\u03b3\u03ae\u03c2", + "HeaderRecordingGroups": "\u0393\u03ba\u03c1\u03bf\u03c5\u03c0 \u0395\u03b3\u03b3\u03c1\u03b1\u03c6\u03ce\u03bd", + "HeaderContinueWatching": "\u03a3\u03c5\u03bd\u03b5\u03c7\u03af\u03c3\u03c4\u03b5 \u03c4\u03b7\u03bd \u03c0\u03b1\u03c1\u03b1\u03ba\u03bf\u03bb\u03bf\u03cd\u03b8\u03b7\u03c3\u03b7", + "HeaderFavoriteArtists": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03bf\u03b9 \u039a\u03b1\u03bb\u03bb\u03b9\u03c4\u03ad\u03c7\u03bd\u03b5\u03c2", + "HeaderFavoriteSongs": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03b1 \u03a4\u03c1\u03b1\u03b3\u03bf\u03cd\u03b4\u03b9\u03b1", + "HeaderAlbumArtists": "\u0386\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc \u039a\u03b1\u03bb\u03bb\u03b9\u03c4\u03b5\u03c7\u03bd\u03ce\u03bd", + "HeaderFavoriteAlbums": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03b1 \u0386\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc", + "HeaderFavoriteEpisodes": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03b1 \u03b5\u03c0\u03b5\u03b9\u03c3\u03cc\u03b4\u03b9\u03b1", + "HeaderFavoriteShows": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03b5\u03c2 \u03a3\u03b5\u03b9\u03c1\u03ad\u03c2", + "HeaderNextUp": "\u0395\u03c0\u03cc\u03bc\u03b5\u03bd\u03bf", + "Favorites": "\u0391\u03b3\u03b1\u03c0\u03b7\u03bc\u03ad\u03bd\u03b1", + "Collections": "\u03a3\u03c5\u03bb\u03bb\u03bf\u03b3\u03ad\u03c2", + "Channels": "\u039a\u03b1\u03bd\u03ac\u03bb\u03b9\u03b1", + "Movies": "\u03a4\u03b1\u03b9\u03bd\u03af\u03b5\u03c2", + "Albums": "\u0386\u03bb\u03bc\u03c0\u03bf\u03c5\u03bc", + "Artists": "\u039a\u03b1\u03bb\u03bb\u03b9\u03c4\u03ad\u03c7\u03bd\u03b5\u03c2", + "Folders": "\u03a6\u03ac\u03ba\u03b5\u03bb\u03bf\u03b9", + "Songs": "\u03a4\u03c1\u03b1\u03b3\u03bf\u03cd\u03b4\u03b9\u03b1", + "TvShows": "\u03a4\u03b7\u03bb\u03b5\u03bf\u03c0\u03c4\u03b9\u03ba\u03ac \u03c0\u03c1\u03bf\u03b3\u03c1\u03ac\u03bc\u03bc\u03b1\u03c4\u03b1", + "Shows": "\u03a3\u03b5\u03b9\u03c1\u03ad\u03c2", + "Genres": "\u0395\u03af\u03b4\u03b7", + "NameSeasonNumber": "\u039a\u03cd\u03ba\u03bb\u03bf\u03c2 {0}", + "AppDeviceValues": "\u0395\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae: {0}, \u03a3\u03c5\u03c3\u03ba\u03b5\u03c5\u03ae: {1}", + "UserDownloadingItemWithValues": "{0} \u03ba\u03b1\u03c4\u03b5\u03b2\u03ac\u03b6\u03b5\u03b9 {1}", + "HeaderLiveTV": "\u0396\u03c9\u03bd\u03c4\u03b1\u03bd\u03ae \u03a4\u03b7\u03bb\u03b5\u03cc\u03c1\u03b1\u03c3\u03b7", + "ChapterNameValue": "\u039a\u03b5\u03c6\u03ac\u03bb\u03b1\u03b9\u03bf {0}", + "ScheduledTaskFailedWithName": "{0} \u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1", + "LabelRunningTimeValue": "\u0394\u03b9\u03ac\u03c1\u03ba\u03b5\u03b9\u03b1: {0}", + "ScheduledTaskStartedWithName": "{0} \u03ad\u03bd\u03b1\u03c1\u03be\u03b7", + "VersionNumber": "\u0388\u03ba\u03b4\u03bf\u03c3\u03b7 {0}", + "PluginInstalledWithName": "{0} \u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03ae\u03b8\u03b7\u03ba\u03b5", + "StartupEmbyServerIsLoading": "\u039f \u03a3\u03ad\u03c1\u03b2\u03b5\u03c1 \u03c6\u03bf\u03c1\u03c4\u03ce\u03bd\u03b5\u03b9. \u03a0\u03b1\u03c1\u03b1\u03ba\u03b1\u03bb\u03ce \u03b4\u03bf\u03ba\u03b9\u03bc\u03ac\u03c3\u03c4\u03b5 \u03c3\u03b5 \u03bb\u03af\u03b3\u03bf", + "PluginUpdatedWithName": "{0} \u03ad\u03c7\u03b5\u03b9 \u03b1\u03bd\u03b1\u03b2\u03b1\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af", + "PluginUninstalledWithName": "{0} \u03ad\u03c7\u03b5\u03b9 \u03b1\u03c0\u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03b1\u03b8\u03b5\u03af", + "ItemAddedWithName": "{0} \u03c0\u03c1\u03bf\u03c3\u03c4\u03ad\u03b8\u03b7\u03ba\u03b5 \u03c3\u03c4\u03b7 \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7", + "ItemRemovedWithName": "{0} \u03b4\u03b9\u03b1\u03b3\u03c1\u03ac\u03c6\u03b7\u03ba\u03b5 \u03b1\u03c0\u03cc \u03c4\u03b7 \u03b2\u03b9\u03b2\u03bb\u03b9\u03bf\u03b8\u03ae\u03ba\u03b7", + "LabelIpAddressValue": "\u0394\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 IP: {0}", + "DeviceOnlineWithName": "{0} \u03c3\u03c5\u03bd\u03b4\u03ad\u03b8\u03b7\u03ba\u03b5", + "UserOnlineFromDevice": "{0} \u03b5\u03af\u03bd\u03b1\u03b9 \u03c3\u03c5\u03bd\u03b4\u03b5\u03b4\u03b5\u03bc\u03ad\u03bd\u03bf\u03c2 \u03b1\u03c0\u03bf {1}", + "ProviderValue": "\u03a0\u03ac\u03c1\u03bf\u03c7\u03bf\u03c2: {0}", + "SubtitlesDownloadedForItem": "\u03a5\u03c0\u03cc\u03c4\u03b9\u03c4\u03bb\u03bf\u03b9 \u03bb\u03ae\u03c6\u03b8\u03b7\u03ba\u03b1\u03bd \u03b1\u03c0\u03cc {0}", + "UserCreatedWithName": "\u0394\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03b8\u03b7\u03ba\u03b5 \u03bf \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2 {0}", + "UserPasswordChangedWithName": "\u039f \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c4\u03bf\u03c5 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7 {0} \u03b1\u03bb\u03bb\u03ac\u03c7\u03b8\u03b7\u03ba\u03b5", + "UserDeletedWithName": "\u039f \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2 {0} \u03b4\u03b9\u03b5\u03b3\u03c1\u03ac\u03c6\u03b5\u03b9", + "UserConfigurationUpdatedWithName": "\u039f\u03b9 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u03c4\u03bf\u03c5 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7 {0} \u03ad\u03c7\u03bf\u03c5\u03bd \u03b1\u03bb\u03bb\u03ac\u03be\u03b5\u03b9", + "MessageServerConfigurationUpdated": "Server configuration has been updated", + "MessageNamedServerConfigurationUpdatedWithValue": "\u039f\u03b9 \u03c1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2 \u03c4\u03bf\u03bc\u03ad\u03b1 \u03c4\u03bf\u03c5 \u03b4\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae {0} \u03ad\u03c7\u03bf\u03c5\u03bd \u03b1\u03bb\u03bb\u03ac\u03be\u03b5\u03b9", + "MessageApplicationUpdated": "\u039f \u03a3\u03ad\u03c1\u03b2\u03b5\u03c1 \u03ad\u03c7\u03b5\u03b9 \u03b1\u03bd\u03b1\u03b2\u03b1\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af", + "FailedLoginAttemptWithUserName": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03c0\u03c1\u03bf\u03c3\u03c0\u03ac\u03b8\u03b5\u03b9\u03b1 \u03b5\u03b9\u03c3\u03cc\u03b4\u03bf\u03c5 \u03b1\u03c0\u03cc {0}", + "AuthenticationSucceededWithUserName": "{0} \u03b5\u03c0\u03b9\u03c4\u03c5\u03c7\u03b5\u03af\u03c2 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7", + "UserOfflineFromDevice": "{0} \u03b1\u03c0\u03bf\u03c3\u03c5\u03bd\u03b4\u03ad\u03b8\u03b7\u03ba\u03b5 \u03b1\u03c0\u03cc {1}", + "DeviceOfflineWithName": "{0} \u03b1\u03c0\u03bf\u03c3\u03c5\u03bd\u03b4\u03ad\u03b8\u03b7\u03ba\u03b5", + "UserStartedPlayingItemWithValues": "{0} \u03be\u03b5\u03ba\u03af\u03bd\u03b7\u03c3\u03b5 \u03bd\u03b1 \u03c0\u03b1\u03af\u03b6\u03b5\u03b9 {1}", + "UserStoppedPlayingItemWithValues": "{0} \u03c3\u03c4\u03b1\u03bc\u03ac\u03c4\u03b7\u03c3\u03b5 \u03bd\u03b1 \u03c0\u03b1\u03af\u03b6\u03b5\u03b9 {1}", + "NotificationOptionPluginError": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03c0\u03c1\u03bf\u03c3\u03b8\u03ad\u03c4\u03bf\u03c5", + "NotificationOptionApplicationUpdateAvailable": "\u03a5\u03c0\u03ac\u03c1\u03c7\u03b5\u03b9 \u03b1\u03bd\u03b1\u03b2\u03ac\u03b8\u03bc\u03b9\u03c3\u03b7", + "NotificationOptionApplicationUpdateInstalled": "\u0397 \u03b1\u03bd\u03b1\u03b2\u03ac\u03b8\u03bc\u03b9\u03c3\u03b7 \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5", + "NotificationOptionPluginUpdateInstalled": "\u0397 \u03b1\u03bd\u03b1\u03b2\u03ac\u03b8\u03bc\u03b9\u03c3\u03b7 \u03c4\u03bf\u03c5 plugin \u03bf\u03bb\u03bf\u03ba\u03bb\u03b7\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5", + "NotificationOptionPluginInstalled": "\u03a4\u03bf plugin \u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03ac\u03b8\u03b7\u03ba\u03b5", + "NotificationOptionPluginUninstalled": "\u03a4\u03bf plugin \u03b1\u03c0\u03b5\u03b3\u03ba\u03b1\u03c4\u03b1\u03c3\u03c4\u03ac\u03b8\u03b7\u03ba\u03b5", + "NotificationOptionVideoPlayback": "\u03a4\u03bf \u03b2\u03af\u03bd\u03c4\u03b5\u03bf \u03c0\u03c1\u03bf\u03b2\u03ac\u03bb\u03bb\u03b5\u03c4\u03b1\u03b9", + "NotificationOptionAudioPlayback": "\u0397 \u03bc\u03bf\u03c5\u03c3\u03b9\u03ba\u03ae \u03c0\u03b1\u03af\u03b6\u03b5\u03b9", + "NotificationOptionGamePlayback": "\u03a4\u03bf \u03c0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9 \u03be\u03b5\u03ba\u03af\u03bd\u03b7\u03c3\u03b5", + "NotificationOptionVideoPlaybackStopped": "\u03a4\u03bf \u03b2\u03af\u03bd\u03c4\u03b5\u03bf \u03c3\u03c4\u03b1\u03bc\u03ac\u03c4\u03b7\u03c3\u03b5", + "NotificationOptionAudioPlaybackStopped": "\u0397 \u03bc\u03bf\u03c5\u03c3\u03b9\u03ba\u03ae \u03c3\u03c4\u03b1\u03bc\u03ac\u03c4\u03b7\u03c3\u03b5", + "NotificationOptionGamePlaybackStopped": "\u03a4\u03bf \u03c0\u03b1\u03b9\u03c7\u03bd\u03af\u03b4\u03b9 \u03c3\u03c4\u03b1\u03bc\u03ac\u03c4\u03b7\u03c3\u03b5", + "NotificationOptionTaskFailed": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03c0\u03c1\u03bf\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1\u03c4\u03b9\u03c3\u03bc\u03ad\u03bd\u03b7\u03c2 \u03b5\u03c1\u03b3\u03b1\u03c3\u03af\u03b1\u03c2", + "NotificationOptionInstallationFailed": "\u0391\u03c0\u03bf\u03c4\u03c5\u03c7\u03af\u03b1 \u03b5\u03b3\u03ba\u03b1\u03c4\u03ac\u03c3\u03c4\u03b1\u03c3\u03b7\u03c2", + "NotificationOptionNewLibraryContent": "\u03a0\u03c1\u03bf\u03c3\u03c4\u03ad\u03b8\u03b7\u03ba\u03b5 \u03bd\u03ad\u03bf \u03c0\u03b5\u03c1\u03b9\u03b5\u03c7\u03cc\u03bc\u03b5\u03bd\u03bf", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", + "NotificationOptionUserLockedOut": "\u039f \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2 \u03b1\u03c0\u03bf\u03ba\u03bb\u03b5\u03af\u03c3\u03c4\u03b7\u03ba\u03b5", + "NotificationOptionServerRestartRequired": "\u0391\u03c0\u03b1\u03b9\u03c4\u03b5\u03af\u03c4\u03b1\u03b9 \u03b5\u03c0\u03b1\u03bd\u03b5\u03ba\u03ba\u03af\u03bd\u03b7\u03c3\u03b7 \u03c4\u03bf\u03c5 \u03b4\u03b9\u03b1\u03ba\u03bf\u03bc\u03b9\u03c3\u03c4\u03ae", + "UserLockedOutWithName": "\u039f \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2 {0} \u03b1\u03c0\u03bf\u03ba\u03bb\u03b5\u03af\u03c3\u03c4\u03b7\u03ba\u03b5", + "SubtitleDownloadFailureForItem": "\u0391\u03b4\u03c5\u03bd\u03b1\u03bc\u03af\u03b1 \u03bb\u03ae\u03c8\u03b7\u03c2 \u03c5\u03c0\u03bf\u03c4\u03af\u03c4\u03bb\u03c9\u03bd \u03b1\u03c0\u03cc {0}", + "Sync": "\u03a3\u03c5\u03b3\u03c7\u03c1\u03bf\u03bd\u03b9\u03c3\u03bc\u03cc\u03c2", + "User": "\u03a7\u03c1\u03ae\u03c3\u03c4\u03b7\u03c2", + "System": "\u03a3\u03cd\u03c3\u03c4\u03b7\u03bc\u03b1", + "Application": "\u0395\u03c6\u03b1\u03c1\u03bc\u03bf\u03b3\u03ae", + "Plugin": "\u03a0\u03c1\u03cc\u03c3\u03b8\u03b5\u03c4\u03bf" +} \ 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 2cc1dd759..8bfaffec8 100644 --- a/Emby.Server.Implementations/Localization/Core/es-MX.json +++ b/Emby.Server.Implementations/Localization/Core/es-MX.json @@ -83,7 +83,7 @@ "NotificationOptionServerRestartRequired": "Se necesita reiniciar el Servidor", "UserLockedOutWithName": "El usuario {0} ha sido bloqueado", "SubtitleDownloadFailureForItem": "Fall\u00f3 la descarga de subt\u00edtulos para {0}", - "Sync": "Sinc.", + "Sync": "Sincronizar", "User": "Usuario", "System": "Sistema", "Application": "Aplicaci\u00f3n", diff --git a/Emby.Server.Implementations/Localization/Core/gsw.json b/Emby.Server.Implementations/Localization/Core/gsw.json new file mode 100644 index 000000000..5c7ff5d6d --- /dev/null +++ b/Emby.Server.Implementations/Localization/Core/gsw.json @@ -0,0 +1,91 @@ +{ + "Latest": "Letschte", + "ValueSpecialEpisodeName": "Spezial - {0}", + "Inherit": "Hinzuef\u00fcege", + "Books": "B\u00fcecher", + "Music": "Musig", + "Games": "Spiel", + "Photos": "Fotis", + "MixedContent": "Gmischte Inhalt", + "MusicVideos": "Musigfilm", + "HomeVideos": "Heimfilmli", + "Playlists": "Abspielliste", + "HeaderRecordingGroups": "Ufnahmegruppe", + "HeaderContinueWatching": "Wiiterluege", + "HeaderFavoriteArtists": "Besti Interpret", + "HeaderFavoriteSongs": "Besti Lieder", + "HeaderAlbumArtists": "Albuminterprete", + "HeaderFavoriteAlbums": "Favorite Albums", + "HeaderFavoriteEpisodes": "Favorite Episodes", + "HeaderFavoriteShows": "Favorite Shows", + "HeaderNextUp": "Next Up", + "Favorites": "Favorites", + "Collections": "Collections", + "Channels": "Channels", + "Movies": "Movies", + "Albums": "Albums", + "Artists": "Artists", + "Folders": "Folders", + "Songs": "Songs", + "TvShows": "TV Shows", + "Shows": "Shows", + "Genres": "Genres", + "NameSeasonNumber": "Season {0}", + "AppDeviceValues": "App: {0}, Device: {1}", + "UserDownloadingItemWithValues": "{0} is downloading {1}", + "HeaderLiveTV": "Live TV", + "ChapterNameValue": "Chapter {0}", + "ScheduledTaskFailedWithName": "{0} failed", + "LabelRunningTimeValue": "Running time: {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}", + "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", + "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}", + "NotificationOptionPluginError": "Plugin failure", + "NotificationOptionApplicationUpdateAvailable": "Application update available", + "NotificationOptionApplicationUpdateInstalled": "Application update installed", + "NotificationOptionPluginUpdateInstalled": "Plugin update installed", + "NotificationOptionPluginInstalled": "Plugin installed", + "NotificationOptionPluginUninstalled": "Plugin uninstalled", + "NotificationOptionVideoPlayback": "Video playback started", + "NotificationOptionAudioPlayback": "Audio playback started", + "NotificationOptionGamePlayback": "Game playback started", + "NotificationOptionVideoPlaybackStopped": "Video playback stopped", + "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", + "NotificationOptionGamePlaybackStopped": "Game playback stopped", + "NotificationOptionTaskFailed": "Scheduled task failure", + "NotificationOptionInstallationFailed": "Installation failure", + "NotificationOptionNewLibraryContent": "New content added", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", + "NotificationOptionUserLockedOut": "User locked out", + "NotificationOptionServerRestartRequired": "Server restart required", + "UserLockedOutWithName": "User {0} has been locked out", + "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", + "Sync": "Sync", + "User": "User", + "System": "System", + "Application": "Application", + "Plugin": "Plugin" +} \ 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 fa4eac1c4..e0a375170 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-BR.json +++ b/Emby.Server.Implementations/Localization/Core/pt-BR.json @@ -27,7 +27,7 @@ "Artists": "Artistas", "Folders": "Pastas", "Songs": "M\u00fasicas", - "TvShows": "TV Shows", + "TvShows": "S\u00e9ries de TV", "Shows": "S\u00e9ries", "Genres": "G\u00eaneros", "NameSeasonNumber": "Temporada {0}", diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index 50e9135b0..30a3ff9e8 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -19,7 +19,9 @@ namespace Emby.Server.Implementations.Networking { protected ILogger Logger { get; private set; } private DateTime _lastRefresh; - private int NetworkCacheMinutes = 360; + private int NetworkCacheMinutes = 720; + + public event EventHandler NetworkChanged; public NetworkManager(ILogger logger) { @@ -50,12 +52,22 @@ namespace Emby.Server.Implementations.Networking { Logger.Debug("NetworkAvailabilityChanged"); _lastRefresh = DateTime.MinValue; + OnNetworkChanged(); } private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e) { Logger.Debug("NetworkAddressChanged"); _lastRefresh = DateTime.MinValue; + OnNetworkChanged(); + } + + private void OnNetworkChanged() + { + if (NetworkChanged != null) + { + NetworkChanged(this, EventArgs.Empty); + } } private List _localIpAddresses; diff --git a/MediaBrowser.Common/Net/INetworkManager.cs b/MediaBrowser.Common/Net/INetworkManager.cs index e2ab47322..6ddc2e799 100644 --- a/MediaBrowser.Common/Net/INetworkManager.cs +++ b/MediaBrowser.Common/Net/INetworkManager.cs @@ -1,13 +1,15 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; using System.Collections.Generic; -using System.Net; +using System; using System.Threading.Tasks; namespace MediaBrowser.Common.Net { public interface INetworkManager { + event EventHandler NetworkChanged; + /// /// Gets a random port number that is currently available /// diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 93a46aaf4..6ded1f6dd 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -186,6 +186,11 @@ namespace MediaBrowser.Model.Dlna return MediaSource.Path; } + if (string.IsNullOrWhiteSpace(PlaySessionId)) + { + PlaySessionId = Guid.NewGuid().ToString("N"); + } + string dlnaCommand = BuildDlnaParam(this, accessToken); return GetUrl(baseUrl, dlnaCommand); } From 5ca1b96c6f9afd8b6fc5e05abd984f5b78ec5696 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 29 Nov 2017 15:50:34 -0500 Subject: [PATCH 2/2] 3.2.40.5 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 14968dfa5..24c973d60 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.40.4")] +[assembly: AssemblyVersion("3.2.40.5")]