diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs
index 72966a7cdc..0ed4ee2a2d 100644
--- a/MediaBrowser.Api/Library/LibraryStructureService.cs
+++ b/MediaBrowser.Api/Library/LibraryStructureService.cs
@@ -112,6 +112,8 @@ namespace MediaBrowser.Api.Library
/// The name.
public string Path { get; set; }
+ public MediaPathInfo PathInfo { get; set; }
+
///
/// Gets or sets a value indicating whether [refresh library].
///
@@ -212,7 +214,12 @@ namespace MediaBrowser.Api.Library
{
var libraryOptions = request.LibraryOptions ?? new LibraryOptions();
- _libraryManager.AddVirtualFolder(request.Name, request.CollectionType, request.Paths, libraryOptions, request.RefreshLibrary);
+ if (request.Paths != null && request.Paths.Length > 0)
+ {
+ libraryOptions.PathInfos = request.Paths.Select(i => new MediaPathInfo { Path = i }).ToArray();
+ }
+
+ _libraryManager.AddVirtualFolder(request.Name, request.CollectionType, libraryOptions, request.RefreshLibrary);
}
///
@@ -308,7 +315,16 @@ namespace MediaBrowser.Api.Library
try
{
- _libraryManager.AddMediaPath(request.Name, request.Path);
+ var mediaPath = request.PathInfo;
+
+ if (mediaPath == null)
+ {
+ mediaPath = new MediaPathInfo
+ {
+ Path = request.Path
+ };
+ }
+ _libraryManager.AddMediaPath(request.Name, mediaPath);
}
finally
{
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 7ef9a1d5ba..371247ecd8 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -1241,7 +1241,7 @@ namespace MediaBrowser.Api.Playback
}
}
- protected virtual bool EnableThrottling(StreamState state)
+ private bool EnableThrottling(StreamState state)
{
// do not use throttling with hardware encoders
return state.InputProtocol == MediaProtocol.File &&
diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
index 7de3096997..9cd55528d3 100644
--- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs
@@ -922,11 +922,6 @@ namespace MediaBrowser.Api.Playback.Hls
).Trim();
}
- protected override bool EnableThrottling(StreamState state)
- {
- return true;
- }
-
///
/// Gets the segment file extension.
///
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 1af55a389f..599e72314d 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -262,7 +262,7 @@ namespace MediaBrowser.Controller.Entities.Audio
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
MediaStreams = MediaSourceManager.GetMediaStreams(i.Id).ToList(),
Name = i.Name,
- Path = enablePathSubstituion ? GetMappedPath(i.Path, locationType) : i.Path,
+ Path = enablePathSubstituion ? GetMappedPath(i, i.Path, locationType) : i.Path,
RunTimeTicks = i.RunTimeTicks,
Container = i.Container,
Size = i.Size
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 6e0a336207..30e0f3ee72 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -2121,11 +2121,11 @@ namespace MediaBrowser.Controller.Entities
return hasChanges;
}
- protected static string GetMappedPath(string path, LocationType locationType)
+ protected static string GetMappedPath(BaseItem item, string path, LocationType locationType)
{
if (locationType == LocationType.FileSystem || locationType == LocationType.Offline)
{
- return LibraryManager.GetPathAfterNetworkSubstitution(path);
+ return LibraryManager.GetPathAfterNetworkSubstitution(path, item);
}
return path;
diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index 30ea26eb66..77d7ca7f20 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -48,24 +48,14 @@ namespace MediaBrowser.Controller.Entities
private static readonly Dictionary LibraryOptions = new Dictionary();
public LibraryOptions GetLibraryOptions()
{
- lock (LibraryOptions)
- {
- LibraryOptions options;
- if (!LibraryOptions.TryGetValue(Path, out options))
- {
- options = LoadLibraryOptions();
- LibraryOptions[Path] = options;
- }
-
- return options;
- }
+ return GetLibraryOptions(Path);
}
- private LibraryOptions LoadLibraryOptions()
+ private static LibraryOptions LoadLibraryOptions(string path)
{
try
{
- var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(Path)) as LibraryOptions;
+ var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(path)) as LibraryOptions;
if (result == null)
{
@@ -100,6 +90,21 @@ namespace MediaBrowser.Controller.Entities
SaveLibraryOptions(Path, options);
}
+ public static LibraryOptions GetLibraryOptions(string path)
+ {
+ lock (LibraryOptions)
+ {
+ LibraryOptions options;
+ if (!LibraryOptions.TryGetValue(path, out options))
+ {
+ options = LoadLibraryOptions(path);
+ LibraryOptions[path] = options;
+ }
+
+ return options;
+ }
+ }
+
public static void SaveLibraryOptions(string path, LibraryOptions options)
{
lock (LibraryOptions)
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index 8809f155c3..1406a05cef 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -600,7 +600,7 @@ namespace MediaBrowser.Controller.Entities
Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File,
MediaStreams = mediaStreams,
Name = GetMediaSourceName(i, mediaStreams),
- Path = enablePathSubstitution ? GetMappedPath(i.Path, locationType) : i.Path,
+ Path = enablePathSubstitution ? GetMappedPath(i, i.Path, locationType) : i.Path,
RunTimeTicks = i.RunTimeTicks,
Video3DFormat = i.Video3DFormat,
VideoType = i.VideoType,
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index d5c2fcd20c..184a245c14 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -506,7 +506,7 @@ namespace MediaBrowser.Controller.Library
/// QueryResult<BaseItem>.
QueryResult QueryItems(InternalItemsQuery query);
- string GetPathAfterNetworkSubstitution(string path);
+ string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem = null);
///
/// Substitutes the path.
@@ -556,9 +556,9 @@ namespace MediaBrowser.Controller.Library
/// true if XXXX, false otherwise.
bool IgnoreFile(FileSystemMetadata file, BaseItem parent);
- void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, LibraryOptions options, bool refreshLibrary);
+ void AddVirtualFolder(string name, string collectionType, LibraryOptions options, bool refreshLibrary);
void RemoveVirtualFolder(string name, bool refreshLibrary);
- void AddMediaPath(string virtualFolderName, string path);
+ void AddMediaPath(string virtualFolderName, MediaPathInfo path);
void RemoveMediaPath(string virtualFolderName, string path);
QueryResult> GetGenres(InternalItemsQuery query);
diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs
index 17175f91cf..99402a9694 100644
--- a/MediaBrowser.Controller/Providers/MetadataResult.cs
+++ b/MediaBrowser.Controller/Providers/MetadataResult.cs
@@ -13,13 +13,15 @@ namespace MediaBrowser.Controller.Providers
public MetadataResult()
{
Images = new List();
+ ResultLanguage = "en";
}
public List People { get; set; }
public bool HasMetadata { get; set; }
public T Item { get; set; }
-
+ public string ResultLanguage { get; set; }
+ public bool QueriedById { get; set; }
public void AddPerson(PersonInfo p)
{
if (People == null)
diff --git a/MediaBrowser.Model/Configuration/LibraryOptions.cs b/MediaBrowser.Model/Configuration/LibraryOptions.cs
index 770ad433d6..460ee0918f 100644
--- a/MediaBrowser.Model/Configuration/LibraryOptions.cs
+++ b/MediaBrowser.Model/Configuration/LibraryOptions.cs
@@ -9,11 +9,19 @@
public bool EnableChapterImageExtraction { get; set; }
public bool ExtractChapterImagesDuringLibraryScan { get; set; }
public bool DownloadImagesInAdvance { get; set; }
+ public MediaPathInfo[] PathInfos { get; set; }
public LibraryOptions()
{
EnablePhotos = true;
EnableRealtimeMonitor = true;
+ PathInfos = new MediaPathInfo[] { };
}
}
+
+ public class MediaPathInfo
+ {
+ public string Path { get; set; }
+ public string NetworkPath { get; set; }
+ }
}
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index 18405aae91..9bbba73e01 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -651,6 +651,8 @@ namespace MediaBrowser.Providers.Manager
{
var refreshResult = new RefreshResult();
+ var results = new List>();
+
foreach (var provider in providers)
{
var providerName = provider.GetType().Name;
@@ -667,7 +669,7 @@ namespace MediaBrowser.Providers.Manager
if (result.HasMetadata)
{
- MergeData(result, temp, new List(), false, false);
+ results.Add(result);
refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataDownload;
}
@@ -688,9 +690,49 @@ namespace MediaBrowser.Providers.Manager
}
}
+ var orderedResults = new List>();
+ var preferredLanguage = NormalizeLanguage(id.MetadataLanguage);
+
+ // prioritize results with matching ResultLanguage
+ foreach (var result in results)
+ {
+ if (!result.QueriedById)
+ {
+ break;
+ }
+
+ if (string.Equals(NormalizeLanguage(result.ResultLanguage), preferredLanguage, StringComparison.OrdinalIgnoreCase) && result.QueriedById)
+ {
+ orderedResults.Add(result);
+ }
+ }
+
+ // add all other results
+ foreach (var result in results)
+ {
+ if (!orderedResults.Contains(result))
+ {
+ orderedResults.Add(result);
+ }
+ }
+
+ foreach (var result in results)
+ {
+ MergeData(result, temp, new List(), false, false);
+ }
+
return refreshResult;
}
+ private string NormalizeLanguage(string language)
+ {
+ if (string.IsNullOrWhiteSpace(language))
+ {
+ return "en";
+ }
+ return language;
+ }
+
private void MergeNewData(TItemType source, TIdType lookupInfo)
{
// Copy new provider id's that may have been obtained
diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
index 914b775af7..428bde2f28 100644
--- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
+++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
@@ -212,13 +212,15 @@ namespace MediaBrowser.Providers.Omdb
{
var result = new MetadataResult
{
- Item = new Series()
+ Item = new Series(),
+ QueriedById = true
};
var imdbId = info.GetProviderId(MetadataProviders.Imdb);
if (string.IsNullOrWhiteSpace(imdbId))
{
imdbId = await GetSeriesImdbId(info, cancellationToken).ConfigureAwait(false);
+ result.QueriedById = false;
}
if (!string.IsNullOrEmpty(imdbId))
@@ -251,13 +253,15 @@ namespace MediaBrowser.Providers.Omdb
{
var result = new MetadataResult
{
- Item = new T()
+ Item = new T(),
+ QueriedById = true
};
var imdbId = info.GetProviderId(MetadataProviders.Imdb);
if (string.IsNullOrWhiteSpace(imdbId))
{
imdbId = await GetMovieImdbId(info, cancellationToken).ConfigureAwait(false);
+ result.QueriedById = false;
}
if (!string.IsNullOrEmpty(imdbId))
diff --git a/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs
index 621f665146..78bce241f4 100644
--- a/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs
@@ -43,7 +43,8 @@ namespace MediaBrowser.Providers.TV
{
var result = new MetadataResult()
{
- Item = new Episode()
+ Item = new Episode(),
+ QueriedById = true
};
// Allowing this will dramatically increase scan times
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs
index bc9842b736..748124c033 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs
@@ -91,6 +91,13 @@ namespace MediaBrowser.Providers.TV
var response = await GetEpisodeInfo(seriesTmdbId, seasonNumber.Value, episodeNumber.Value, info.MetadataLanguage, cancellationToken).ConfigureAwait(false);
result.HasMetadata = true;
+ result.QueriedById = true;
+
+ if (!string.IsNullOrEmpty(response.overview))
+ {
+ // if overview is non-empty, we can assume that localized data was returned
+ result.ResultLanguage = info.MetadataLanguage;
+ }
var item = new Episode();
result.Item = item;
diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs
index 3245a2c85a..fb06780293 100644
--- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs
@@ -119,6 +119,7 @@ namespace MediaBrowser.Providers.TV
public async Task> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
{
var result = new MetadataResult();
+ result.QueriedById = true;
var tmdbId = info.GetProviderId(MetadataProviders.Tmdb);
@@ -154,6 +155,7 @@ namespace MediaBrowser.Providers.TV
if (string.IsNullOrEmpty(tmdbId))
{
+ result.QueriedById = false;
var searchResults = await new MovieDbSearch(_logger, _jsonSerializer, _libraryManager).GetSearchResults(info, cancellationToken).ConfigureAwait(false);
var searchResult = searchResults.FirstOrDefault();
@@ -168,7 +170,7 @@ namespace MediaBrowser.Providers.TV
{
cancellationToken.ThrowIfCancellationRequested();
- result.Item = await FetchSeriesData(tmdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
+ result = await FetchMovieData(tmdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false);
result.HasMetadata = result.Item != null;
}
@@ -176,7 +178,7 @@ namespace MediaBrowser.Providers.TV
return result;
}
- private async Task FetchSeriesData(string tmdbId, string language, string preferredCountryCode, CancellationToken cancellationToken)
+ private async Task> FetchMovieData(string tmdbId, string language, string preferredCountryCode, CancellationToken cancellationToken)
{
string dataFilePath = null;
RootObject seriesInfo = null;
@@ -194,16 +196,18 @@ namespace MediaBrowser.Providers.TV
tmdbId = seriesInfo.id.ToString(_usCulture);
dataFilePath = GetDataFilePath(tmdbId, language);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(seriesInfo, dataFilePath);
await EnsureSeriesInfo(tmdbId, language, cancellationToken).ConfigureAwait(false);
- var item = new Series();
+ var result = new MetadataResult();
+ result.Item = new Series();
+ result.ResultLanguage = seriesInfo.ResultLanguage;
- ProcessMainInfo(item, seriesInfo, preferredCountryCode);
+ ProcessMainInfo(result.Item, seriesInfo, preferredCountryCode);
- return item;
+ return result;
}
private void ProcessMainInfo(Series series, RootObject seriesInfo, string preferredCountryCode)
@@ -324,7 +328,7 @@ namespace MediaBrowser.Providers.TV
var dataFilePath = GetDataFilePath(id, preferredMetadataLanguage);
- _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(dataFilePath));
_jsonSerializer.SerializeToFile(mainResult, dataFilePath);
}
@@ -354,6 +358,11 @@ namespace MediaBrowser.Providers.TV
}).ConfigureAwait(false))
{
mainResult = _jsonSerializer.DeserializeFromStream(json);
+
+ if (!string.IsNullOrEmpty(language))
+ {
+ mainResult.ResultLanguage = language;
+ }
}
cancellationToken.ThrowIfCancellationRequested();
@@ -385,6 +394,7 @@ namespace MediaBrowser.Providers.TV
var englishResult = _jsonSerializer.DeserializeFromStream(json);
mainResult.overview = englishResult.overview;
+ mainResult.ResultLanguage = "en";
}
}
@@ -627,6 +637,7 @@ namespace MediaBrowser.Providers.TV
public ExternalIds external_ids { get; set; }
public Videos videos { get; set; }
public ContentRatings content_ratings { get; set; }
+ public string ResultLanguage { get; set; }
}
public int Order
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs
index a41a95c126..41a2282d80 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs
@@ -108,6 +108,7 @@ namespace MediaBrowser.Providers.TV
public async Task> GetMetadata(EpisodeInfo searchInfo, CancellationToken cancellationToken)
{
var result = new MetadataResult();
+ result.QueriedById = true;
if (TvdbSeriesProvider.IsValidSeries(searchInfo.SeriesProviderIds) &&
(searchInfo.IndexNumber.HasValue || searchInfo.PremiereDate.HasValue))
@@ -713,6 +714,17 @@ namespace MediaBrowser.Providers.TV
}
}
+ break;
+ }
+ case "Language":
+ {
+ var val = reader.ReadElementContentAsString();
+
+ if (!string.IsNullOrWhiteSpace(val))
+ {
+ result.ResultLanguage = val;
+ }
+
break;
}
diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
index 66a02eba21..4ac9e68361 100644
--- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs
@@ -93,9 +93,11 @@ namespace MediaBrowser.Providers.TV
public async Task> GetMetadata(SeriesInfo itemId, CancellationToken cancellationToken)
{
var result = new MetadataResult();
+ result.QueriedById = true;
if (!IsValidSeries(itemId.ProviderIds))
{
+ result.QueriedById = false;
await Identify(itemId).ConfigureAwait(false);
}
@@ -159,7 +161,7 @@ namespace MediaBrowser.Providers.TV
var seriesXmlPath = GetSeriesXmlPath(seriesProviderIds, metadataLanguage);
var actorsXmlPath = Path.Combine(seriesDataPath, "actors.xml");
- FetchSeriesInfo(series, seriesXmlPath, cancellationToken);
+ FetchSeriesInfo(result, seriesXmlPath, cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
@@ -607,7 +609,7 @@ namespace MediaBrowser.Providers.TV
return name.Trim();
}
- private void FetchSeriesInfo(Series item, string seriesXmlPath, CancellationToken cancellationToken)
+ private void FetchSeriesInfo(MetadataResult result, string seriesXmlPath, CancellationToken cancellationToken)
{
var settings = new XmlReaderSettings
{
@@ -639,7 +641,7 @@ namespace MediaBrowser.Providers.TV
{
using (var subtree = reader.ReadSubtree())
{
- FetchDataFromSeriesNode(item, subtree, cancellationToken);
+ FetchDataFromSeriesNode(result, subtree, cancellationToken);
}
break;
}
@@ -667,9 +669,9 @@ namespace MediaBrowser.Providers.TV
}
}
- if (item.Status.HasValue && item.Status.Value == SeriesStatus.Ended && episiodeAirDates.Count > 0)
+ if (result.Item.Status.HasValue && result.Item.Status.Value == SeriesStatus.Ended && episiodeAirDates.Count > 0)
{
- item.EndDate = episiodeAirDates.Max();
+ result.Item.EndDate = episiodeAirDates.Max();
}
}
@@ -861,8 +863,10 @@ namespace MediaBrowser.Providers.TV
}
}
- private void FetchDataFromSeriesNode(Series item, XmlReader reader, CancellationToken cancellationToken)
+ private void FetchDataFromSeriesNode(MetadataResult result, XmlReader reader, CancellationToken cancellationToken)
{
+ Series item = result.Item;
+
reader.MoveToContent();
// Loop through each element
@@ -886,6 +890,12 @@ namespace MediaBrowser.Providers.TV
break;
}
+ case "Language":
+ {
+ result.ResultLanguage = (reader.ReadElementContentAsString() ?? string.Empty).Trim();
+ break;
+ }
+
case "Airs_DayOfWeek":
{
var val = reader.ReadElementContentAsString();
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
index e7e52a8878..b2dd8ec865 100644
--- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
@@ -403,6 +403,14 @@ namespace MediaBrowser.Server.Implementations.Connect
public async Task LinkUser(string userId, string connectUsername)
{
+ if (string.IsNullOrWhiteSpace(userId))
+ {
+ throw new ArgumentNullException("userId");
+ }
+ if (string.IsNullOrWhiteSpace(connectUsername))
+ {
+ throw new ArgumentNullException("connectUsername");
+ }
if (string.IsNullOrWhiteSpace(ConnectServerId))
{
await UpdateConnectInfo().ConfigureAwait(false);
@@ -422,14 +430,6 @@ namespace MediaBrowser.Server.Implementations.Connect
private async Task LinkUserInternal(string userId, string connectUsername)
{
- if (string.IsNullOrWhiteSpace(userId))
- {
- throw new ArgumentNullException("userId");
- }
- if (string.IsNullOrWhiteSpace(connectUsername))
- {
- throw new ArgumentNullException("connectUsername");
- }
if (string.IsNullOrWhiteSpace(ConnectServerId))
{
throw new ArgumentNullException("ConnectServerId");
@@ -446,6 +446,12 @@ namespace MediaBrowser.Server.Implementations.Connect
throw new ArgumentException("The Emby account has been disabled.");
}
+ var existingUser = _userManager.Users.FirstOrDefault(i => string.Equals(i.ConnectUserId, connectUser.Id) && !string.IsNullOrWhiteSpace(i.ConnectAccessKey));
+ if (existingUser != null)
+ {
+ throw new InvalidOperationException("This connect user is already linked to local user " + existingUser.Name);
+ }
+
var user = GetUser(userId);
if (!string.IsNullOrWhiteSpace(user.ConnectUserId))
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index ae676626db..e4f1460c66 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -1509,7 +1509,7 @@ namespace MediaBrowser.Server.Implementations.Dto
}
}
- private string GetMappedPath(IHasMetadata item)
+ private string GetMappedPath(BaseItem item)
{
var path = item.Path;
@@ -1517,7 +1517,7 @@ namespace MediaBrowser.Server.Implementations.Dto
if (locationType == LocationType.FileSystem || locationType == LocationType.Offline)
{
- path = _libraryManager.GetPathAfterNetworkSubstitution(path);
+ path = _libraryManager.GetPathAfterNetworkSubstitution(path, item);
}
return path;
diff --git a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
index ba7e33890a..b550d1dda2 100644
--- a/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
+++ b/MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
@@ -33,7 +33,8 @@ namespace MediaBrowser.Server.Implementations.Library
// Synology
"@eaDir",
- "eaDir"
+ "eaDir",
+ "#recycle"
};
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index 1f8c779539..cef0022cfc 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -2527,8 +2527,29 @@ namespace MediaBrowser.Server.Implementations.Library
}).OrderBy(i => i.Path).ToList();
}
- public string GetPathAfterNetworkSubstitution(string path)
+ public string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem)
{
+ if (ownerItem != null)
+ {
+ var libraryOptions = GetLibraryOptions(ownerItem);
+ if (libraryOptions != null)
+ {
+ foreach (var pathInfo in libraryOptions.PathInfos)
+ {
+ if (string.IsNullOrWhiteSpace(pathInfo.NetworkPath))
+ {
+ continue;
+ }
+
+ var substitutionResult = SubstitutePathInternal(path, pathInfo.Path, pathInfo.NetworkPath);
+ if (substitutionResult.Item2)
+ {
+ return substitutionResult.Item1;
+ }
+ }
+ }
+ }
+
foreach (var map in ConfigurationManager.Configuration.PathSubstitutions)
{
path = SubstitutePath(path, map.From, map.To);
@@ -2538,6 +2559,11 @@ namespace MediaBrowser.Server.Implementations.Library
}
public string SubstitutePath(string path, string from, string to)
+ {
+ return SubstitutePathInternal(path, from, to).Item1;
+ }
+
+ private Tuple SubstitutePathInternal(string path, string from, string to)
{
if (string.IsNullOrWhiteSpace(path))
{
@@ -2552,7 +2578,11 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentNullException("to");
}
- var newPath = path.Replace(from.Trim(), to.Trim(), StringComparison.OrdinalIgnoreCase);
+ from = from.Trim();
+ to = to.Trim();
+
+ var newPath = path.Replace(from, to, StringComparison.OrdinalIgnoreCase);
+ var changed = false;
if (!string.Equals(newPath, path))
{
@@ -2564,9 +2594,11 @@ namespace MediaBrowser.Server.Implementations.Library
{
newPath = newPath.Replace('/', '\\');
}
+
+ changed = true;
}
- return newPath;
+ return new Tuple(newPath, changed);
}
private void SetExtraTypeFromFilename(Video item)
@@ -2695,7 +2727,7 @@ namespace MediaBrowser.Server.Implementations.Library
throw new InvalidOperationException();
}
- public void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, LibraryOptions options, bool refreshLibrary)
+ public void AddVirtualFolder(string name, string collectionType, LibraryOptions options, bool refreshLibrary)
{
if (string.IsNullOrWhiteSpace(name))
{
@@ -2713,12 +2745,13 @@ namespace MediaBrowser.Server.Implementations.Library
virtualFolderPath = Path.Combine(rootFolderPath, name);
}
- if (mediaPaths != null)
+ var mediaPathInfos = options.PathInfos;
+ if (mediaPathInfos != null)
{
- var invalidpath = mediaPaths.FirstOrDefault(i => !_fileSystem.DirectoryExists(i));
+ var invalidpath = mediaPathInfos.FirstOrDefault(i => !_fileSystem.DirectoryExists(i.Path));
if (invalidpath != null)
{
- throw new ArgumentException("The specified path does not exist: " + invalidpath + ".");
+ throw new ArgumentException("The specified path does not exist: " + invalidpath.Path + ".");
}
}
@@ -2740,11 +2773,11 @@ namespace MediaBrowser.Server.Implementations.Library
CollectionFolder.SaveLibraryOptions(virtualFolderPath, options);
- if (mediaPaths != null)
+ if (mediaPathInfos != null)
{
- foreach (var path in mediaPaths)
+ foreach (var path in mediaPathInfos)
{
- AddMediaPath(name, path);
+ AddMediaPathInternal(name, path, false);
}
}
}
@@ -2770,6 +2803,61 @@ namespace MediaBrowser.Server.Implementations.Library
}
}
+ private const string ShortcutFileExtension = ".mblink";
+ private const string ShortcutFileSearch = "*" + ShortcutFileExtension;
+ public void AddMediaPath(string virtualFolderName, MediaPathInfo pathInfo)
+ {
+ AddMediaPathInternal(virtualFolderName, pathInfo, true);
+ }
+
+ private void AddMediaPathInternal(string virtualFolderName, MediaPathInfo pathInfo, bool saveLibraryOptions)
+ {
+ if (pathInfo == null)
+ {
+ throw new ArgumentNullException("path");
+ }
+
+ var path = pathInfo.Path;
+
+ if (string.IsNullOrWhiteSpace(path))
+ {
+ throw new ArgumentNullException("path");
+ }
+
+ if (!_fileSystem.DirectoryExists(path))
+ {
+ throw new DirectoryNotFoundException("The path does not exist.");
+ }
+
+ var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath;
+ var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName);
+
+ var shortcutFilename = _fileSystem.GetFileNameWithoutExtension(path);
+
+ var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension);
+
+ while (_fileSystem.FileExists(lnk))
+ {
+ shortcutFilename += "1";
+ lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension);
+ }
+
+ _fileSystem.CreateShortcut(lnk, path);
+
+ RemoveContentTypeOverrides(path);
+
+ if (saveLibraryOptions)
+ {
+ var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath);
+
+ var list = libraryOptions.PathInfos.ToList();
+ list.Add(pathInfo);
+ libraryOptions.PathInfos = list.ToArray();
+
+ CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions);
+ }
+ }
+
public void RemoveVirtualFolder(string name, bool refreshLibrary)
{
if (string.IsNullOrWhiteSpace(name))
@@ -2814,38 +2902,6 @@ namespace MediaBrowser.Server.Implementations.Library
}
}
- private const string ShortcutFileExtension = ".mblink";
- private const string ShortcutFileSearch = "*" + ShortcutFileExtension;
- public void AddMediaPath(string virtualFolderName, string path)
- {
- if (string.IsNullOrWhiteSpace(path))
- {
- throw new ArgumentNullException("path");
- }
-
- if (!_fileSystem.DirectoryExists(path))
- {
- throw new DirectoryNotFoundException("The path does not exist.");
- }
-
- var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath;
- var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName);
-
- var shortcutFilename = _fileSystem.GetFileNameWithoutExtension(path);
-
- var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension);
-
- while (_fileSystem.FileExists(lnk))
- {
- shortcutFilename += "1";
- lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension);
- }
-
- _fileSystem.CreateShortcut(lnk, path);
-
- RemoveContentTypeOverrides(path);
- }
-
private void RemoveContentTypeOverrides(string path)
{
if (string.IsNullOrWhiteSpace(path))
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index a3ca54b4ac..e358f9d25c 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -143,9 +143,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
continue;
}
+ var mediaPathInfos = pathsToCreate.Select(i => new MediaPathInfo { Path = i }).ToArray();
+
+ var libraryOptions = new LibraryOptions
+ {
+ PathInfos = mediaPathInfos
+ };
try
{
- _libraryManager.AddVirtualFolder(recordingFolder.Name, recordingFolder.CollectionType, pathsToCreate.ToArray(), new LibraryOptions(), true);
+ _libraryManager.AddVirtualFolder(recordingFolder.Name, recordingFolder.CollectionType, libraryOptions, true);
}
catch (Exception ex)
{
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
index 560b0d5b4d..4e7f637b11 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
@@ -253,7 +253,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
}
var durationParam = " -t " + _mediaEncoder.GetTimeParameter(duration.Ticks);
- var commandLineArgs = "-fflags +genpts -async 1 -vsync -1 -re -i \"{0}\"{4} -sn {2} -map_metadata -1 -threads 0 {3} -y \"{1}\"";
+ var commandLineArgs = "-fflags +genpts -async 1 -vsync -1 -i \"{0}\"{4} -sn {2} -map_metadata -1 -threads 0 {3} -y \"{1}\"";
if (mediaSource.ReadAtNativeFramerate)
{
diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
index c3907c0454..b98919282a 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
@@ -171,7 +171,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
var data = images[imageIndex].data ?? new List();
data = data.OrderByDescending(GetSizeOrder).ToList();
- programEntry.primaryImage = GetProgramImage(ApiUrl, data, "Logo", true, 800);
+ programEntry.primaryImage = GetProgramImage(ApiUrl, data, "Logo", true, 600);
//programEntry.thumbImage = GetProgramImage(ApiUrl, data, "Iconic", false);
//programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ??
// GetProgramImage(ApiUrl, data, "Banner-L1", false) ??
@@ -485,7 +485,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
}
}
- if (!string.IsNullOrWhiteSpace(details.originalAirDate))
+ if (!string.IsNullOrWhiteSpace(details.originalAirDate) && (!info.IsSeries || info.IsRepeat))
{
info.OriginalAirDate = DateTime.Parse(details.originalAirDate);
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index df1ef39624..dcef6e84a2 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -2837,6 +2837,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv
feature = "embytvseriesrecordings";
}
+ if (string.Equals(feature, "dvr-l", StringComparison.OrdinalIgnoreCase))
+ {
+ var config = GetConfiguration();
+ if (config.TunerHosts.Count(i => i.IsEnabled) > 0 &&
+ config.ListingProviders.Count(i => (i.EnableAllTuners || i.EnabledTuners.Length > 0) && string.Equals(i.Type, SchedulesDirect.TypeName, StringComparison.OrdinalIgnoreCase)) > 0)
+ {
+ return Task.FromResult(new MBRegistrationRecord
+ {
+ IsRegistered = true,
+ IsValid = true
+ });
+ }
+ }
+
if (string.Equals(feature, "dvr", StringComparison.OrdinalIgnoreCase))
{
var config = GetConfiguration();
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index b25c07fe31..eb3da1a12e 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -73,8 +73,8 @@
..\packages\SimpleInjector.3.2.2\lib\net45\SimpleInjector.dll
True
-
- ..\packages\SocketHttpListener.1.0.0.39\lib\net45\SocketHttpListener.dll
+
+ ..\packages\SocketHttpListener.1.0.0.40\lib\net45\SocketHttpListener.dll
True
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index 5d58aea191..043257fc8a 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -8,5 +8,5 @@
-
+
\ No newline at end of file
diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
index 02e8ad6f22..eaac3e2a0e 100644
--- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs
+++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs
@@ -346,7 +346,7 @@ namespace MediaBrowser.WebDashboard.Api
if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase))
{
- sb.Append("");
+ sb.Append("");
}
else
{
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index eebc0f20ed..00279fb050 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -470,9 +470,6 @@
PreserveNewest
-
- PreserveNewest
-
PreserveNewest
@@ -977,9 +974,6 @@
PreserveNewest
-
- PreserveNewest
-
PreserveNewest