aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations
diff options
context:
space:
mode:
authorT. Adams <t.adams88@gmail.com>2015-03-13 21:57:10 -0700
committerT. Adams <t.adams88@gmail.com>2015-03-13 21:57:10 -0700
commiteff23da3737718c944a59078c24e3ccf19435b90 (patch)
tree68d1c42e2bcd4a4be0398c8f4c0f1ba88d42e56e /MediaBrowser.Server.Implementations
parentb7b28ffd31892dac13004199766262126d2785c5 (diff)
parentdbb7fd61ff0545f8ebf7b9ece432f1408d43040c (diff)
Merge branch 'dev' into Video-Playlist-Controls
Diffstat (limited to 'MediaBrowser.Server.Implementations')
-rw-r--r--MediaBrowser.Server.Implementations/Channels/ChannelManager.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Dto/DtoService.cs61
-rw-r--r--MediaBrowser.Server.Implementations/Library/LibraryManager.cs65
-rw-r--r--MediaBrowser.Server.Implementations/Library/MusicManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserViewManager.cs27
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs3
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/server.json2
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj2
-rw-r--r--MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs113
-rw-r--r--MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Photos/DynamicImageProvider.cs87
-rw-r--r--MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Photos/StripCollageBuilder.cs179
-rw-r--r--MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Sync/MediaSync.cs17
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs4
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncManager.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncRepository.cs2
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs23
20 files changed, 456 insertions, 151 deletions
diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
index 2b17442dea..f0f30229ec 100644
--- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
+++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
@@ -1400,7 +1400,9 @@ namespace MediaBrowser.Server.Implementations.Channels
public async Task<Folder> GetInternalChannelFolder(string userId, CancellationToken cancellationToken)
{
var name = _localization.GetLocalizedString("ViewTypeChannels");
- return await _libraryManager.GetNamedView(name, "channels", "zz_" + name, cancellationToken).ConfigureAwait(false);
+ var user = _userManager.GetUserById(userId);
+
+ return await _libraryManager.GetNamedView(user, name, "channels", "zz_" + name, cancellationToken).ConfigureAwait(false);
}
public async Task DownloadChannelItem(IChannelMediaItem item, string destination,
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs
index b756fb6c4d..80a7c50d19 100644
--- a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs
@@ -14,7 +14,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Collections
{
- public class CollectionImageProvider : BaseDynamicImageProvider<BoxSet>, ICustomMetadataProvider<BoxSet>
+ public class CollectionImageProvider : BaseDynamicImageProvider<BoxSet>
{
public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths)
{
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index f9b7470b2c..3280cf264b 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -504,7 +504,6 @@ namespace MediaBrowser.Server.Implementations.Dto
}
dto.Album = item.Album;
- dto.Artists = item.Artists;
}
private void SetGameProperties(BaseItemDto dto, Game item)
@@ -1142,7 +1141,6 @@ namespace MediaBrowser.Server.Implementations.Dto
if (audio != null)
{
dto.Album = audio.Album;
- dto.Artists = audio.Artists;
var albumParent = audio.FindParent<MusicAlbum>();
@@ -1163,18 +1161,65 @@ namespace MediaBrowser.Server.Implementations.Dto
if (album != null)
{
- dto.Artists = album.Artists;
-
dto.SoundtrackIds = album.SoundtrackIds
.Select(i => i.ToString("N"))
.ToArray();
}
- var hasAlbumArtist = item as IHasAlbumArtist;
+ var hasArtist = item as IHasArtist;
+ if (hasArtist != null)
+ {
+ dto.Artists = hasArtist.Artists;
+
+ dto.ArtistItems = hasArtist
+ .Artists
+ .Select(i =>
+ {
+ try
+ {
+ var artist = _libraryManager.GetArtist(i);
+ return new NameIdPair
+ {
+ Name = artist.Name,
+ Id = artist.Id.ToString("N")
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error getting artist", ex);
+ return null;
+ }
+ })
+ .Where(i => i != null)
+ .ToList();
+ }
+ var hasAlbumArtist = item as IHasAlbumArtist;
if (hasAlbumArtist != null)
{
dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault();
+
+ dto.AlbumArtists = hasAlbumArtist
+ .AlbumArtists
+ .Select(i =>
+ {
+ try
+ {
+ var artist = _libraryManager.GetArtist(i);
+ return new NameIdPair
+ {
+ Name = artist.Name,
+ Id = artist.Id.ToString("N")
+ };
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error getting album artist", ex);
+ return null;
+ }
+ })
+ .Where(i => i != null)
+ .ToList();
}
// Add video info
@@ -1231,7 +1276,6 @@ namespace MediaBrowser.Server.Implementations.Dto
// Add MovieInfo
var movie = item as Movie;
-
if (movie != null)
{
if (fields.Contains(ItemFields.TmdbCollectionName))
@@ -1241,7 +1285,6 @@ namespace MediaBrowser.Server.Implementations.Dto
}
var hasSpecialFeatures = item as IHasSpecialFeatures;
-
if (hasSpecialFeatures != null)
{
var specialFeatureCount = hasSpecialFeatures.SpecialFeatureIds.Count;
@@ -1254,7 +1297,6 @@ namespace MediaBrowser.Server.Implementations.Dto
// Add EpisodeInfo
var episode = item as Episode;
-
if (episode != null)
{
dto.IndexNumberEnd = episode.IndexNumberEnd;
@@ -1296,7 +1338,6 @@ namespace MediaBrowser.Server.Implementations.Dto
// Add SeriesInfo
var series = item as Series;
-
if (series != null)
{
dto.AirDays = series.AirDays;
@@ -1346,7 +1387,6 @@ namespace MediaBrowser.Server.Implementations.Dto
// Add SeasonInfo
var season = item as Season;
-
if (season != null)
{
series = season.Series;
@@ -1380,7 +1420,6 @@ namespace MediaBrowser.Server.Implementations.Dto
}
var musicVideo = item as MusicVideo;
-
if (musicVideo != null)
{
SetMusicVideoProperties(dto, musicVideo);
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index 070b111ee8..f6809c924c 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -1584,15 +1584,22 @@ namespace MediaBrowser.Server.Implementations.Library
.FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
}
- public async Task<UserView> GetNamedView(string name,
- string type,
+ public async Task<UserView> GetNamedView(User user,
+ string name,
+ string viewType,
string sortName,
CancellationToken cancellationToken)
{
+ if (ConfigurationManager.Configuration.EnableUserSpecificUserViews)
+ {
+ return await GetNamedViewInternal(user, name, null, viewType, sortName, cancellationToken)
+ .ConfigureAwait(false);
+ }
+
var path = Path.Combine(ConfigurationManager.ApplicationPaths.ItemsByNamePath,
"views");
- path = Path.Combine(path, _fileSystem.GetValidFilename(type));
+ path = Path.Combine(path, _fileSystem.GetValidFilename(viewType));
var id = GetNewItemId(path + "_namedview_" + name, typeof(UserView));
@@ -1611,7 +1618,7 @@ namespace MediaBrowser.Server.Implementations.Library
Id = id,
DateCreated = DateTime.UtcNow,
Name = name,
- ViewType = type,
+ ViewType = viewType,
ForcedSortName = sortName
};
@@ -1627,31 +1634,38 @@ namespace MediaBrowser.Server.Implementations.Library
if (refresh)
{
- await item.RefreshMetadata(new MetadataRefreshOptions
- {
- ForceSave = true
-
- }, cancellationToken).ConfigureAwait(false);
+ await item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None).ConfigureAwait(false);
+ _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions());
}
return item;
}
- public async Task<UserView> GetSpecialFolder(User user,
+ public Task<UserView> GetNamedView(User user,
string name,
string parentId,
string viewType,
string sortName,
CancellationToken cancellationToken)
{
- if (string.IsNullOrWhiteSpace(name))
+ if (string.IsNullOrWhiteSpace(parentId))
{
- throw new ArgumentNullException("name");
+ throw new ArgumentNullException("parentId");
}
- if (string.IsNullOrWhiteSpace(parentId))
+ return GetNamedViewInternal(user, name, parentId, viewType, sortName, cancellationToken);
+ }
+
+ private async Task<UserView> GetNamedViewInternal(User user,
+ string name,
+ string parentId,
+ string viewType,
+ string sortName,
+ CancellationToken cancellationToken)
+ {
+ if (string.IsNullOrWhiteSpace(name))
{
- throw new ArgumentNullException("parentId");
+ throw new ArgumentNullException("name");
}
if (string.IsNullOrWhiteSpace(viewType))
@@ -1659,9 +1673,9 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentNullException("viewType");
}
- var id = GetNewItemId("7_namedview_" + name + user.Id.ToString("N") + parentId, typeof(UserView));
+ var id = GetNewItemId("23_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty), typeof(UserView));
- var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", "specialviews", id.ToString("N"));
+ var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N"));
var item = GetItemById(id) as UserView;
@@ -1679,27 +1693,28 @@ namespace MediaBrowser.Server.Implementations.Library
Name = name,
ViewType = viewType,
ForcedSortName = sortName,
- UserId = user.Id,
- ParentId = new Guid(parentId)
+ UserId = user.Id
};
+ if (!string.IsNullOrWhiteSpace(parentId))
+ {
+ item.ParentId = new Guid(parentId);
+ }
+
await CreateItem(item, cancellationToken).ConfigureAwait(false);
refresh = true;
}
- if (!refresh && item != null)
+ if (!refresh)
{
refresh = (DateTime.UtcNow - item.DateLastSaved).TotalHours >= 24;
}
if (refresh)
{
- await item.RefreshMetadata(new MetadataRefreshOptions
- {
- ForceSave = true
-
- }, cancellationToken).ConfigureAwait(false);
+ await item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None).ConfigureAwait(false);
+ _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions());
}
return item;
@@ -1849,7 +1864,7 @@ namespace MediaBrowser.Server.Implementations.Library
// These cause apps to have problems
options.AudioFileExtensions.Remove(".m3u");
options.AudioFileExtensions.Remove(".wpl");
-
+
if (!ConfigurationManager.Configuration.EnableAudioArchiveFiles)
{
options.AudioFileExtensions.Remove(".rar");
diff --git a/MediaBrowser.Server.Implementations/Library/MusicManager.cs b/MediaBrowser.Server.Implementations/Library/MusicManager.cs
index 7733e7d379..3a854f2fe0 100644
--- a/MediaBrowser.Server.Implementations/Library/MusicManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/MusicManager.cs
@@ -34,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.Library
var genres = user.RootFolder
.GetRecursiveChildren(user, i => i is Audio)
.Cast<Audio>()
- .Where(i => i.HasArtist(name))
+ .Where(i => i.HasAnyArtist(name))
.SelectMany(i => i.Genres)
.Concat(artist.Genres)
.Distinct(StringComparer.OrdinalIgnoreCase);
diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
index 8b7cfa9f2f..a583534eed 100644
--- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
@@ -70,40 +70,41 @@ namespace MediaBrowser.Server.Implementations.Library
if (foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) ||
foldersWithViewTypes.Any(i => string.IsNullOrWhiteSpace(i.CollectionType)))
{
- list.Add(await GetUserView(CollectionType.TvShows, string.Empty, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.TvShows, string.Empty, user, cancellationToken).ConfigureAwait(false));
}
if (foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase)) ||
foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)))
{
- list.Add(await GetUserView(CollectionType.Music, string.Empty, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.Music, string.Empty, user, cancellationToken).ConfigureAwait(false));
}
if (foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) ||
foldersWithViewTypes.Any(i => string.IsNullOrWhiteSpace(i.CollectionType)))
{
- list.Add(await GetUserView(CollectionType.Movies, string.Empty, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.Movies, string.Empty, user, cancellationToken).ConfigureAwait(false));
}
if (foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.Games, StringComparison.OrdinalIgnoreCase)))
{
- list.Add(await GetUserView(CollectionType.Games, string.Empty, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.Games, string.Empty, user, cancellationToken).ConfigureAwait(false));
}
if (foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase)))
{
//list.Add(_collectionManager.GetCollectionsFolder(user.Id.ToString("N")));
- list.Add(await GetUserView(CollectionType.BoxSets, string.Empty, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.BoxSets, string.Empty, user, cancellationToken).ConfigureAwait(false));
}
if (foldersWithViewTypes.Any(i => string.Equals(i.CollectionType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase)))
{
- list.Add(_playlists.GetPlaylistsFolder(user.Id.ToString("N")));
+ //list.Add(_playlists.GetPlaylistsFolder(user.Id.ToString("N")));
+ list.Add(await GetUserView(CollectionType.Playlists, string.Empty, user, cancellationToken).ConfigureAwait(false));
}
if (user.Configuration.DisplayFoldersView)
{
- list.Add(await GetUserView(CollectionType.Folders, "zz_" + CollectionType.Folders, cancellationToken).ConfigureAwait(false));
+ list.Add(await GetUserView(CollectionType.Folders, "zz_" + CollectionType.Folders, user, cancellationToken).ConfigureAwait(false));
}
if (query.IncludeExternalContent)
@@ -148,23 +149,23 @@ namespace MediaBrowser.Server.Implementations.Library
.ThenBy(i => i.SortName);
}
- public Task<UserView> GetUserView(string name, string parentId, string type, User user, string sortName, CancellationToken cancellationToken)
+ public Task<UserView> GetUserSubView(string name, string parentId, string type, User user, string sortName, CancellationToken cancellationToken)
{
- return _libraryManager.GetSpecialFolder(user, name, parentId, type, sortName, cancellationToken);
+ return _libraryManager.GetNamedView(user, name, parentId, type, sortName, cancellationToken);
}
- public Task<UserView> GetUserView(string parentId, string type, User user, string sortName, CancellationToken cancellationToken)
+ public Task<UserView> GetUserSubView(string parentId, string type, User user, string sortName, CancellationToken cancellationToken)
{
var name = _localizationManager.GetLocalizedString("ViewType" + type);
- return GetUserView(name, parentId, type, user, sortName, cancellationToken);
+ return GetUserSubView(name, parentId, type, user, sortName, cancellationToken);
}
- public Task<UserView> GetUserView(string type, string sortName, CancellationToken cancellationToken)
+ public Task<UserView> GetUserView(string type, string sortName, User user, CancellationToken cancellationToken)
{
var name = _localizationManager.GetLocalizedString("ViewType" + type);
- return _libraryManager.GetNamedView(name, type, sortName, cancellationToken);
+ return _libraryManager.GetNamedView(user, name, type, sortName, cancellationToken);
}
public List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request)
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index ec5ac3caea..33f1a4dac0 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -1827,7 +1827,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv
public async Task<Folder> GetInternalLiveTvFolder(string userId, CancellationToken cancellationToken)
{
var name = _localization.GetLocalizedString("ViewTypeLiveTV");
- return await _libraryManager.GetNamedView(name, "livetv", "zz_" + name, cancellationToken).ConfigureAwait(false);
+ var user = _userManager.GetUserById(userId);
+ return await _libraryManager.GetNamedView(user, name, "livetv", "zz_" + name, cancellationToken).ConfigureAwait(false);
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json
index 9464309b70..0805c9ce93 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/server.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json
@@ -926,6 +926,7 @@
"LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.",
"ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.",
"ButtonOptions": "Options",
+ "ViewTypePlaylists": "Playlists",
"ViewTypeMovies": "Movies",
"ViewTypeTvShows": "TV",
"ViewTypeGames": "Games",
@@ -1172,6 +1173,7 @@
"LabelIfYouWishToContinueWithDeletion": "If you wish to continue, please confirm by entering the value of:",
"ButtonIdentify": "Identify",
"LabelAlbumArtist": "Album artist:",
+ "LabelAlbumArtists": "Album artists:",
"LabelAlbum": "Album:",
"LabelCommunityRating": "Community rating:",
"LabelVoteCount": "Vote count:",
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 6292defc15..396d378bcd 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -248,6 +248,7 @@
<Compile Include="Persistence\TypeMapper.cs" />
<Compile Include="Photos\BaseDynamicImageProvider.cs" />
<Compile Include="Photos\DynamicImageHelpers.cs" />
+ <Compile Include="Photos\StripCollageBuilder.cs" />
<Compile Include="Playlists\ManualPlaylistsFolder.cs" />
<Compile Include="Photos\PhotoAlbumImageProvider.cs" />
<Compile Include="Playlists\PlaylistImageProvider.cs" />
@@ -428,6 +429,7 @@
<EmbeddedResource Include="Localization\Server\uk.json" />
<EmbeddedResource Include="Drawing\fonts\webdings.ttf" />
<EmbeddedResource Include="Drawing\fonts\robotoregular.ttf" />
+ <EmbeddedResource Include="Drawing\fonts\MontserratLight.otf" />
<None Include="Localization\JavaScript\sl_SI.json" />
<EmbeddedResource Include="Localization\Server\sl_SI.json" />
<None Include="packages.config" />
diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs
index 40b85dad10..9cae362836 100644
--- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs
@@ -2,8 +2,8 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
@@ -15,8 +15,8 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Photos
{
- public abstract class BaseDynamicImageProvider<T> : IHasChangeMonitor, IForcedProvider
- where T : IHasImages
+ public abstract class BaseDynamicImageProvider<T> : IHasChangeMonitor, IForcedProvider, IDynamicImageProvider, IHasOrder
+ where T : IHasMetadata
{
protected IFileSystem FileSystem { get; private set; }
protected IProviderManager ProviderManager { get; private set; }
@@ -29,81 +29,51 @@ namespace MediaBrowser.Server.Implementations.Photos
FileSystem = fileSystem;
}
- public async Task<ItemUpdateType> FetchAsync(T item, MetadataRefreshOptions options, CancellationToken cancellationToken)
+ public virtual bool Supports(IHasImages item)
{
- if (!Supports(item))
- {
- return ItemUpdateType.None;
- }
-
- var primaryResult = await FetchAsync(item, ImageType.Primary, options, cancellationToken).ConfigureAwait(false);
- var thumbResult = await FetchAsync(item, ImageType.Thumb, options, cancellationToken).ConfigureAwait(false);
-
- return primaryResult | thumbResult;
- }
-
- protected virtual bool Supports(IHasImages item)
- {
- return true;
+ return item is T;
}
- protected abstract Task<List<BaseItem>> GetItemsWithImages(IHasImages item);
-
- private const string Version = "3";
- protected string GetConfigurationCacheKey(List<BaseItem> items)
+ public virtual IEnumerable<ImageType> GetSupportedImages(IHasImages item)
{
- return (Version + "_" + string.Join(",", items.Select(i => i.Id.ToString("N")).ToArray())).GetMD5().ToString("N");
+ return new List<ImageType>
+ {
+ ImageType.Primary,
+ ImageType.Thumb
+ };
}
- protected async Task<ItemUpdateType> FetchAsync(IHasImages item, ImageType imageType, MetadataRefreshOptions options, CancellationToken cancellationToken)
+ public async Task<DynamicImageResponse> GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken)
{
var items = await GetItemsWithImages(item).ConfigureAwait(false);
var cacheKey = GetConfigurationCacheKey(items);
- if (!HasChanged(item, imageType, cacheKey))
+ var result = await FetchAsyncInternal(item, items, type, cacheKey, cancellationToken).ConfigureAwait(false);
+
+ return new DynamicImageResponse
{
- return ItemUpdateType.None;
- }
+ HasImage = result != null,
+ Stream = result,
+ InternalCacheKey = cacheKey,
+ Format = ImageFormat.Png
+ };
+ }
+
+ protected abstract Task<List<BaseItem>> GetItemsWithImages(IHasImages item);
- return await FetchAsyncInternal(item, items, imageType, cacheKey, options, cancellationToken).ConfigureAwait(false);
+ private const string Version = "3";
+ protected string GetConfigurationCacheKey(List<BaseItem> items)
+ {
+ return (Version + "_" + string.Join(",", items.Select(i => i.Id.ToString("N")).ToArray())).GetMD5().ToString("N");
}
- protected async Task<ItemUpdateType> FetchAsyncInternal(IHasImages item,
+ protected Task<Stream> FetchAsyncInternal(IHasImages item,
List<BaseItem> itemsWithImages,
- ImageType imageType,
- string cacheKey,
- MetadataRefreshOptions options,
+ ImageType imageType,
+ string cacheKey,
CancellationToken cancellationToken)
{
- var stream = await CreateImageAsync(item, itemsWithImages, imageType, 0).ConfigureAwait(false);
-
- if (stream == null)
- {
- return ItemUpdateType.None;
- }
-
- if (stream is MemoryStream)
- {
- using (stream)
- {
- stream.Position = 0;
-
- await ProviderManager.SaveImage(item, stream, "image/png", imageType, null, cacheKey, cancellationToken).ConfigureAwait(false);
- }
- }
- else
- {
- using (var ms = new MemoryStream())
- {
- await stream.CopyToAsync(ms).ConfigureAwait(false);
-
- ms.Position = 0;
-
- await ProviderManager.SaveImage(item, ms, "image/png", imageType, null, cacheKey, cancellationToken).ConfigureAwait(false);
- }
- }
-
- return ItemUpdateType.ImageUpdate;
+ return CreateImageAsync(item, itemsWithImages, imageType, 0);
}
protected Task<Stream> GetThumbCollage(List<BaseItem> items)
@@ -137,9 +107,9 @@ namespace MediaBrowser.Server.Implementations.Photos
get { return "Dynamic Image Provider"; }
}
- public async Task<Stream> CreateImageAsync(IHasImages item,
+ protected virtual async Task<Stream> CreateImageAsync(IHasImages item,
List<BaseItem> itemsWithImages,
- ImageType imageType,
+ ImageType imageType,
int imageIndex)
{
if (itemsWithImages.Count == 0)
@@ -190,11 +160,17 @@ namespace MediaBrowser.Server.Implementations.Photos
protected List<BaseItem> GetFinalItems(List<BaseItem> items)
{
// Rotate the images no more than once per week
+ return GetFinalItems(items, 4);
+ }
+
+ protected List<BaseItem> GetFinalItems(List<BaseItem> items, int limit)
+ {
+ // Rotate the images no more than once per week
var random = new Random(GetWeekOfYear()).Next();
return items
.OrderBy(i => random - items.IndexOf(i))
- .Take(4)
+ .Take(limit)
.OrderBy(i => i.Name)
.ToList();
}
@@ -209,5 +185,14 @@ namespace MediaBrowser.Server.Implementations.Photos
return weekNo;
}
+
+ public int Order
+ {
+ get
+ {
+ // Run before the default image provider which will download placeholders
+ return 0;
+ }
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs b/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs
index e7cd2f4d26..fce8c9b6bf 100644
--- a/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs
+++ b/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs
@@ -107,7 +107,7 @@ namespace MediaBrowser.Server.Implementations.Photos
return Task.FromResult<Stream>(fileSystem.GetFileStream(files[0], FileMode.Open, FileAccess.Read, FileShare.Read));
}
- private static Stream GetStream(MagickWand image, IApplicationPaths appPaths)
+ internal static Stream GetStream(MagickWand image, IApplicationPaths appPaths)
{
var tempFile = Path.Combine(appPaths.TempDirectory, Guid.NewGuid().ToString("N") + ".png");
diff --git a/MediaBrowser.Server.Implementations/Photos/DynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/DynamicImageProvider.cs
index 4e1330144e..1a02d413e4 100644
--- a/MediaBrowser.Server.Implementations/Photos/DynamicImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Photos/DynamicImageProvider.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
@@ -8,22 +9,42 @@ using MediaBrowser.Model.Entities;
using MoreLinq;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Photos
{
- public class DynamicImageProvider : BaseDynamicImageProvider<UserView>, ICustomMetadataProvider<UserView>
+ public class DynamicImageProvider : BaseDynamicImageProvider<UserView>
{
private readonly IUserManager _userManager;
private readonly ILibraryManager _libraryManager;
- public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IUserManager userManager, ILibraryManager libraryManager) : base(fileSystem, providerManager, applicationPaths)
+ public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IUserManager userManager, ILibraryManager libraryManager)
+ : base(fileSystem, providerManager, applicationPaths)
{
_userManager = userManager;
_libraryManager = libraryManager;
}
+ public override IEnumerable<ImageType> GetSupportedImages(IHasImages item)
+ {
+ var view = (UserView)item;
+ if (IsUsingCollectionStrip(view))
+ {
+ return new List<ImageType>
+ {
+ ImageType.Primary
+ };
+ }
+
+ return new List<ImageType>
+ {
+ ImageType.Primary,
+ ImageType.Thumb
+ };
+ }
+
protected override async Task<List<BaseItem>> GetItemsWithImages(IHasImages item)
{
var view = (UserView)item;
@@ -71,9 +92,15 @@ namespace MediaBrowser.Server.Implementations.Photos
return list;
}
+ var isUsingCollectionStrip = IsUsingCollectionStrip(view);
+ var recursive = isUsingCollectionStrip && !new[] {CollectionType.Playlists, CollectionType.Channels}.Contains(view.ViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
+
var result = await view.GetItems(new InternalItemsQuery
{
- User = _userManager.GetUserById(view.UserId.Value)
+ User = _userManager.GetUserById(view.UserId.Value),
+ CollapseBoxSetItems = false,
+ Recursive = recursive,
+ ExcludeItemTypes = new[] { "UserView", "CollectionFolder"}
}).ConfigureAwait(false);
@@ -108,14 +135,29 @@ namespace MediaBrowser.Server.Implementations.Photos
return season;
}
+ var audio = i as Audio;
+ if (audio != null)
+ {
+ var album = audio.FindParent<MusicAlbum>();
+ if (album != null && album.HasImage(ImageType.Primary))
+ {
+ return album;
+ }
+ }
+
return i;
}).DistinctBy(i => i.Id);
+ if (isUsingCollectionStrip)
+ {
+ return GetFinalItems(items.Where(i => i.HasImage(ImageType.Primary) || i.HasImage(ImageType.Thumb)).ToList(), 8);
+ }
+
return GetFinalItems(items.Where(i => i.HasImage(ImageType.Primary)).ToList());
}
- protected override bool Supports(IHasImages item)
+ public override bool Supports(IHasImages item)
{
var view = item as UserView;
@@ -160,11 +202,46 @@ namespace MediaBrowser.Server.Implementations.Photos
SpecialFolder.MusicFavoriteSongs
};
- return supported.Contains(view.ViewType, StringComparer.OrdinalIgnoreCase) &&
+ return (IsUsingCollectionStrip(view) || supported.Contains(view.ViewType, StringComparer.OrdinalIgnoreCase)) &&
_userManager.GetUserById(view.UserId.Value) != null;
}
return false;
}
+
+ private bool IsUsingCollectionStrip(UserView view)
+ {
+ string[] collectionStripViewTypes =
+ {
+ CollectionType.Movies,
+ CollectionType.TvShows,
+ CollectionType.Games,
+ CollectionType.Music,
+ CollectionType.BoxSets,
+ CollectionType.Playlists,
+ CollectionType.Channels
+ };
+
+ return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty);
+ }
+
+ protected override Task<Stream> CreateImageAsync(IHasImages item, List<BaseItem> itemsWithImages, ImageType imageType, int imageIndex)
+ {
+ var view = (UserView)item;
+ if (imageType == ImageType.Primary && IsUsingCollectionStrip(view))
+ {
+ var stream = new StripCollageBuilder(ApplicationPaths).BuildThumbCollage(GetStripCollageImagePaths(itemsWithImages), item.Name, 960, 540);
+ return Task.FromResult(stream);
+ }
+
+ return base.CreateImageAsync(item, itemsWithImages, imageType, imageIndex);
+ }
+
+ private IEnumerable<String> GetStripCollageImagePaths(IEnumerable<BaseItem> items)
+ {
+ return items
+ .Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb))
+ .Where(i => !string.IsNullOrWhiteSpace(i));
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs
index e369869705..73d9183a5d 100644
--- a/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs
@@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Photos
{
- public class PhotoAlbumImageProvider : BaseDynamicImageProvider<PhotoAlbum>, ICustomMetadataProvider<PhotoAlbum>
+ public class PhotoAlbumImageProvider : BaseDynamicImageProvider<PhotoAlbum>
{
public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths)
{
diff --git a/MediaBrowser.Server.Implementations/Photos/StripCollageBuilder.cs b/MediaBrowser.Server.Implementations/Photos/StripCollageBuilder.cs
new file mode 100644
index 0000000000..6fd33f6e42
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/Photos/StripCollageBuilder.cs
@@ -0,0 +1,179 @@
+using ImageMagickSharp;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Server.Implementations.Drawing;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace MediaBrowser.Server.Implementations.Photos
+{
+ public class StripCollageBuilder
+ {
+ private readonly IApplicationPaths _appPaths;
+
+ public StripCollageBuilder(IApplicationPaths appPaths)
+ {
+ _appPaths = appPaths;
+ }
+
+ public Stream BuildThumbCollage(IEnumerable<string> paths, string text, int width, int height)
+ {
+ using (var wand = BuildThumbCollageWandWithText(paths, text, width, height))
+ {
+ return DynamicImageHelpers.GetStream(wand, _appPaths);
+ }
+ }
+
+ private string[] ProjectPaths(IEnumerable<string> paths, int count)
+ {
+ var clone = paths.ToList();
+ var list = new List<string>();
+
+ while (list.Count < count)
+ {
+ foreach (var path in clone)
+ {
+ list.Add(path);
+
+ if (list.Count >= count)
+ {
+ break;
+ }
+ }
+ }
+
+ return list.Take(count).ToArray();
+ }
+
+ private MagickWand BuildThumbCollageWandWithText(IEnumerable<string> paths, string text, int width, int height)
+ {
+ var inputPaths = ProjectPaths(paths, 8);
+ using (var wandImages = new MagickWand(inputPaths))
+ {
+ var wand = new MagickWand(width, height);
+ wand.OpenImage("gradient:#111111-#111111");
+ using (var draw = new DrawingWand())
+ {
+ using (var fcolor = new PixelWand(ColorName.White))
+ {
+ draw.FillColor = fcolor;
+ draw.Font = MontserratLightFont;
+ draw.FontSize = 50;
+ draw.FontWeight = FontWeightType.LightStyle;
+ draw.TextAntialias = true;
+ }
+
+ var fontMetrics = wand.QueryFontMetrics(draw, text);
+ var textContainerY = Convert.ToInt32(height * .165);
+ wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, text);
+
+ var iSlice = Convert.ToInt32(width * .1166666667);
+ int iTrans = Convert.ToInt32(height * 0.2);
+ int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296);
+ var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
+
+ foreach (var element in wandImages.ImageList)
+ {
+ int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
+ element.Gravity = GravityType.CenterGravity;
+ element.BackgroundColor = new PixelWand("none", 1);
+ element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
+ int ix = (int)Math.Abs((iWidth - iSlice) / 2);
+ element.CropImage(iSlice, iHeight, ix, 0);
+
+ element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
+ }
+
+ wandImages.SetFirstIterator();
+ using (var wandList = wandImages.AppendImages())
+ {
+ wandList.CurrentImage.TrimImage(1);
+ using (var mwr = wandList.CloneMagickWand())
+ {
+ mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
+ mwr.CurrentImage.FlipImage();
+
+ mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
+ mwr.CurrentImage.ColorizeImage(ColorName.Black, ColorName.Grey70);
+
+ using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
+ {
+ mwg.OpenImage("gradient:black-none");
+ var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
+ mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.DstInCompositeOp, 0, verticalSpacing);
+
+ wandList.AddImage(mwr);
+ int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
+ wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * 0.26851851851851851851851851851852));
+ }
+ }
+ }
+ }
+
+ return wand;
+ }
+ }
+
+ private MagickWand BuildThumbCollageWand(IEnumerable<string> paths, int width, int height)
+ {
+ var inputPaths = ProjectPaths(paths, 8);
+ using (var wandImages = new MagickWand(inputPaths))
+ {
+ var wand = new MagickWand(width, height);
+ wand.OpenImage("gradient:#111111-#111111");
+ using (var draw = new DrawingWand())
+ {
+ var iSlice = Convert.ToInt32(width * .1166666667);
+ int iTrans = Convert.ToInt32(height * .25);
+ int iHeight = Convert.ToInt32(height * .6);
+ var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
+
+ foreach (var element in wandImages.ImageList)
+ {
+ int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
+ element.Gravity = GravityType.CenterGravity;
+ element.BackgroundColor = ColorName.Black;
+ element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
+ int ix = (int)Math.Abs((iWidth - iSlice) / 2);
+ element.CropImage(iSlice, iHeight, ix, 0);
+
+ element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
+ }
+
+ wandImages.SetFirstIterator();
+ using (var wandList = wandImages.AppendImages())
+ {
+ wandList.CurrentImage.TrimImage(1);
+ using (var mwr = wandList.CloneMagickWand())
+ {
+ mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
+ mwr.CurrentImage.FlipImage();
+
+ mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
+ mwr.CurrentImage.ColorizeImage(ColorName.Black, ColorName.Grey60);
+
+ using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
+ {
+ mwg.OpenImage("gradient:black-none");
+ var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
+ mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing);
+
+ wandList.AddImage(mwr);
+ int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
+ wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .1));
+ }
+ }
+ }
+ }
+
+ return wand;
+ }
+ }
+
+ private string MontserratLightFont
+ {
+ get { return PlayedIndicatorDrawer.ExtractFont("MontserratLight.otf", _appPaths); }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs
index d009a03aee..81f9438b9f 100644
--- a/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs
+++ b/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs
@@ -14,7 +14,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Playlists
{
- public class PlaylistImageProvider : BaseDynamicImageProvider<Playlist>, ICustomMetadataProvider<Playlist>
+ public class PlaylistImageProvider : BaseDynamicImageProvider<Playlist>
{
public PlaylistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths)
{
diff --git a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs
index 8391dbd7a2..48f682f98a 100644
--- a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs
+++ b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs
@@ -152,7 +152,18 @@ namespace MediaBrowser.Server.Implementations.Sync
try
{
- await SendFile(provider, internalSyncJobItem.OutputPath, localItem, target, cancellationToken).ConfigureAwait(false);
+ var sendFileResult = await SendFile(provider, internalSyncJobItem.OutputPath, localItem, target, cancellationToken).ConfigureAwait(false);
+
+ if (localItem.Item.MediaSources != null)
+ {
+ var mediaSource = localItem.Item.MediaSources.FirstOrDefault();
+ if (mediaSource != null)
+ {
+ mediaSource.Path = sendFileResult.Path;
+ mediaSource.Protocol = sendFileResult.Protocol;
+ mediaSource.SupportsTranscoding = false;
+ }
+ }
// Create db record
await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false);
@@ -203,11 +214,11 @@ namespace MediaBrowser.Server.Implementations.Sync
}
}
- private async Task SendFile(IServerSyncProvider provider, string inputPath, LocalItem item, SyncTarget target, CancellationToken cancellationToken)
+ private async Task<SendFileResult> SendFile(IServerSyncProvider provider, string inputPath, LocalItem item, SyncTarget target, CancellationToken cancellationToken)
{
using (var stream = _fileSystem.GetFileStream(inputPath, FileMode.Open, FileAccess.Read, FileShare.Read, true))
{
- await provider.SendFile(stream, item.LocalPath, target, new Progress<double>(), cancellationToken).ConfigureAwait(false);
+ return await provider.SendFile(stream, item.LocalPath, target, new Progress<double>(), cancellationToken).ConfigureAwait(false);
}
}
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
index 2dbf8fc1b6..8fb4b5a3ad 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
@@ -581,6 +581,8 @@ namespace MediaBrowser.Server.Implementations.Sync
jobItem.MediaSource = mediaSource;
}
+ jobItem.MediaSource.SupportsTranscoding = false;
+
if (externalSubs.Count > 0)
{
// Save the job item now since conversion could take a while
@@ -757,6 +759,8 @@ namespace MediaBrowser.Server.Implementations.Sync
jobItem.MediaSource = mediaSource;
}
+ jobItem.MediaSource.SupportsTranscoding = false;
+
jobItem.Progress = 50;
jobItem.Status = SyncJobItemStatus.ReadyToTransfer;
await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false);
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
index a974a7675a..0bf9a2e23a 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs
@@ -136,6 +136,14 @@ namespace MediaBrowser.Server.Implementations.Sync
var jobId = Guid.NewGuid().ToString("N");
+ if (string.IsNullOrWhiteSpace(request.Quality))
+ {
+ request.Quality = GetQualityOptions(request.TargetId)
+ .Where(i => i.IsDefault)
+ .Select(i => i.Id)
+ .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i));
+ }
+
var job = new SyncJob
{
Id = jobId,
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
index 45b35523a6..9d820eaa2b 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs
@@ -50,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.Sync
string[] queries = {
- "create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Quality TEXT NOT NULL, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)",
+ "create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Quality TEXT, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)",
"create index if not exists idx_SyncJobs on SyncJobs(Id)",
"create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, TemporaryPath TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT, AdditionalFiles TEXT, MediaSource TEXT, IsMarkedForRemoval BIT, JobItemIndex INT)",
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs b/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs
index 0422e97919..93a466c526 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncedMediaSourceProvider.cs
@@ -3,11 +3,9 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Sync;
using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Sync;
using System;
using System.Collections.Generic;
-using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -58,7 +56,7 @@ namespace MediaBrowser.Server.Implementations.Sync
foreach (var localItem in localItems)
{
- list.AddRange(GetPlayableMediaSources(localItem));
+ list.AddRange(localItem.Item.MediaSources);
}
}
}
@@ -66,24 +64,5 @@ namespace MediaBrowser.Server.Implementations.Sync
return list;
}
-
- private IEnumerable<MediaSourceInfo> GetPlayableMediaSources(LocalItem item)
- {
- return item.Item.MediaSources
- .Where(IsMediaSourcePlayable);
- }
-
- private bool IsMediaSourcePlayable(MediaSourceInfo mediaSource)
- {
- if (mediaSource.Protocol == MediaProtocol.File)
- {
- if (!File.Exists(mediaSource.Path))
- {
- return false;
- }
- }
-
- return true;
- }
}
}