add dynamic images

pull/702/head
Luke Pulverenti 9 years ago
parent 7c99b0a14a
commit dbb7fd61ff

@ -65,6 +65,7 @@ namespace MediaBrowser.Api
_config.Configuration.MergeMetadataAndImagesByName = true;
_config.Configuration.EnableStandaloneMetadata = true;
_config.Configuration.EnableLibraryMetadataSubFolder = true;
_config.Configuration.EnableUserSpecificUserViews = true;
_config.SaveConfiguration();
}

@ -125,13 +125,15 @@ namespace MediaBrowser.Api.Subtitles
private readonly ISubtitleManager _subtitleManager;
private readonly ISubtitleEncoder _subtitleEncoder;
private readonly IMediaSourceManager _mediaSourceManager;
private readonly IProviderManager _providerManager;
public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager)
public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, IProviderManager providerManager)
{
_libraryManager = libraryManager;
_subtitleManager = subtitleManager;
_subtitleEncoder = subtitleEncoder;
_mediaSourceManager = mediaSourceManager;
_providerManager = providerManager;
}
public object Get(GetSubtitlePlaylist request)
@ -256,7 +258,7 @@ namespace MediaBrowser.Api.Subtitles
await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None)
.ConfigureAwait(false);
await video.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService()), CancellationToken.None).ConfigureAwait(false);
_providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions());
}
catch (Exception ex)
{

@ -244,7 +244,7 @@ namespace MediaBrowser.Api.UserLibrary
return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
}
public IEnumerable<VideoType> GetVideoTypes()
public VideoType[] GetVideoTypes()
{
var val = VideoTypes;
@ -253,7 +253,7 @@ namespace MediaBrowser.Api.UserLibrary
return new VideoType[] { };
}
return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => (VideoType)Enum.Parse(typeof(VideoType), v, true));
return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => (VideoType)Enum.Parse(typeof(VideoType), v, true)).ToArray();
}
}
@ -933,7 +933,7 @@ namespace MediaBrowser.Api.UserLibrary
// Filter by VideoType
var videoTypes = request.GetVideoTypes();
if (video == null || !videoTypes.Contains(video.VideoType))
if (videoTypes.Length > 0 && (video == null || !videoTypes.Contains(video.VideoType)))
{
return false;
}

@ -1455,7 +1455,8 @@ namespace MediaBrowser.Controller.Entities
/// <returns>Task.</returns>
public virtual Task ChangedExternally()
{
return RefreshMetadata(CancellationToken.None);
ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions());
return Task.FromResult(true);
}
/// <summary>

@ -1,4 +1,5 @@
using MediaBrowser.Controller.TV;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using System;
@ -15,6 +16,7 @@ namespace MediaBrowser.Controller.Entities
public Guid? UserId { get; set; }
public static ITVSeriesManager TVSeriesManager;
public static IPlaylistManager PlaylistManager;
public bool ContainsDynamicCategories(User user)
{
@ -30,7 +32,7 @@ namespace MediaBrowser.Controller.Entities
parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent;
}
return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager)
return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager, PlaylistManager)
.GetUserItems(parent, this, ViewType, query);
}

@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Entities;
@ -30,8 +31,9 @@ namespace MediaBrowser.Controller.Entities
private readonly IUserDataManager _userDataManager;
private readonly ITVSeriesManager _tvSeriesManager;
private readonly ICollectionManager _collectionManager;
private readonly IPlaylistManager _playlistManager;
public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, ICollectionManager collectionManager)
public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, ICollectionManager collectionManager, IPlaylistManager playlistManager)
{
_userViewManager = userViewManager;
_liveTvManager = liveTvManager;
@ -41,6 +43,7 @@ namespace MediaBrowser.Controller.Entities
_userDataManager = userDataManager;
_tvSeriesManager = tvSeriesManager;
_collectionManager = collectionManager;
_playlistManager = playlistManager;
}
public async Task<QueryResult<BaseItem>> GetUserItems(Folder queryParent, Folder displayParent, string viewType, InternalItemsQuery query)
@ -115,6 +118,9 @@ namespace MediaBrowser.Controller.Entities
case CollectionType.Games:
return await GetGameView(user, queryParent, query).ConfigureAwait(false);
case CollectionType.Playlists:
return await GetPlaylistsView(queryParent, user, query).ConfigureAwait(false);
case CollectionType.BoxSets:
return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false);
@ -572,6 +578,11 @@ namespace MediaBrowser.Controller.Entities
return GetResult(items, queryParent, query);
}
private async Task<QueryResult<BaseItem>> GetPlaylistsView(Folder parent, User user, InternalItemsQuery query)
{
return GetResult(_playlistManager.GetPlaylists(user.Id.ToString("N")), parent, query);
}
private async Task<QueryResult<BaseItem>> GetBoxsetView(Folder parent, User user, InternalItemsQuery query)
{
return GetResult(GetMediaFolders(user).SelectMany(i =>
@ -1718,7 +1729,7 @@ namespace MediaBrowser.Controller.Entities
var parent = user.RootFolder;
//list.Add(await GetUserView(SpecialFolder.LiveTvNowPlaying, user, "0", parent).ConfigureAwait(false));
//list.Add(await GetUserSubView(SpecialFolder.LiveTvNowPlaying, user, "0", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.LiveTvChannels, user, string.Empty, parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.LiveTvRecordingGroups, user, string.Empty, parent).ConfigureAwait(false));
@ -1727,7 +1738,7 @@ namespace MediaBrowser.Controller.Entities
private async Task<UserView> GetUserView(string name, string type, User user, string sortName, BaseItem parent)
{
var view = await _userViewManager.GetUserView(name, parent.Id.ToString("N"), type, user, sortName, CancellationToken.None)
var view = await _userViewManager.GetUserSubView(name, parent.Id.ToString("N"), type, user, sortName, CancellationToken.None)
.ConfigureAwait(false);
return view;
@ -1735,7 +1746,7 @@ namespace MediaBrowser.Controller.Entities
private async Task<UserView> GetUserView(string type, User user, string sortName, BaseItem parent)
{
var view = await _userViewManager.GetUserView(parent.Id.ToString("N"), type, user, sortName, CancellationToken.None)
var view = await _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, user, sortName, CancellationToken.None)
.ConfigureAwait(false);
return view;

@ -302,7 +302,7 @@ namespace MediaBrowser.Controller.Library
IEnumerable<BaseItem> ReplaceVideosWithPrimaryVersions(IEnumerable<BaseItem> items);
/// <summary>
/// Gets the special folder.
/// Gets the named view.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="name">The name.</param>
@ -311,7 +311,7 @@ namespace MediaBrowser.Controller.Library
/// <param name="sortName">Name of the sort.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;UserView&gt;.</returns>
Task<UserView> GetSpecialFolder(User user,
Task<UserView> GetNamedView(User user,
string name,
string parentId,
string viewType,
@ -321,12 +321,14 @@ namespace MediaBrowser.Controller.Library
/// <summary>
/// Gets the named view.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="name">The name.</param>
/// <param name="viewType">Type of the view.</param>
/// <param name="sortName">Name of the sort.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;UserView&gt;.</returns>
Task<UserView> GetNamedView(string name,
Task<UserView> GetNamedView(User user,
string name,
string viewType,
string sortName,
CancellationToken cancellationToken);

@ -12,12 +12,10 @@ namespace MediaBrowser.Controller.Library
{
Task<IEnumerable<Folder>> GetUserViews(UserViewQuery query, CancellationToken cancellationToken);
Task<UserView> GetUserView(string name, string parentId, string type, User user, string sortName,
Task<UserView> GetUserSubView(string name, string parentId, string type, User user, string sortName,
CancellationToken cancellationToken);
Task<UserView> GetUserView(string type, string sortName, CancellationToken cancellationToken);
Task<UserView> GetUserView(string category, string type, User user, string sortName, CancellationToken cancellationToken);
Task<UserView> GetUserSubView(string category, string type, User user, string sortName, CancellationToken cancellationToken);
List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request);
}

@ -4,6 +4,7 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
@ -16,6 +17,13 @@ namespace MediaBrowser.Controller.Providers
/// </summary>
public interface IProviderManager
{
/// <summary>
/// Queues the refresh.
/// </summary>
/// <param name="itemId">The item identifier.</param>
/// <param name="options">The options.</param>
void QueueRefresh(Guid itemId, MetadataRefreshOptions options);
/// <summary>
/// Refreshes the metadata.
/// </summary>

@ -251,12 +251,12 @@ namespace MediaBrowser.Model.ApiClient
Task<ItemsResult> GetAdditionalParts(string itemId, string userId);
/// <summary>
/// Gets the live media information.
/// Gets the playback information.
/// </summary>
/// <param name="itemId">The item identifier.</param>
/// <param name="userId">The user identifier.</param>
/// <returns>Task&lt;LiveMediaInfoResult&gt;.</returns>
Task<LiveMediaInfoResult> GetLiveMediaInfo(string itemId, string userId);
Task<LiveMediaInfoResult> GetPlaybackInfo(string itemId, string userId);
/// <summary>
/// Gets the users async.

@ -44,6 +44,12 @@ namespace MediaBrowser.Model.Configuration
/// <value><c>true</c> if [use HTTPS]; otherwise, <c>false</c>.</value>
public bool EnableHttps { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [enable user specific user views].
/// </summary>
/// <value><c>true</c> if [enable user specific user views]; otherwise, <c>false</c>.</value>
public bool EnableUserSpecificUserViews { get; set; }
/// <summary>
/// Gets or sets the value pointing to the file system where the ssl certiifcate is located..
/// </summary>

@ -36,16 +36,16 @@ namespace MediaBrowser.Providers.FolderImages
if (view != null)
{
return GetImages(view.ViewType, view.UserId.HasValue, cancellationToken);
return GetImages(view.ViewType, view.ParentId != Guid.Empty, cancellationToken);
}
var folder = (ICollectionFolder)item;
return GetImages(folder.CollectionType, false, cancellationToken);
}
private Task<IEnumerable<RemoteImageInfo>> GetImages(string viewType, bool isUserSpecificView, CancellationToken cancellationToken)
private Task<IEnumerable<RemoteImageInfo>> GetImages(string viewType, bool isSubView, CancellationToken cancellationToken)
{
var url = GetImageUrl(viewType, isUserSpecificView);
var url = GetImageUrl(viewType, isSubView);
var list = new List<RemoteImageInfo>();
if (!string.IsNullOrWhiteSpace(url))
@ -71,7 +71,7 @@ namespace MediaBrowser.Providers.FolderImages
return Task.FromResult<IEnumerable<RemoteImageInfo>>(list);
}
private string GetImageUrl(string viewType, bool isUserSpecificView)
private string GetImageUrl(string viewType, bool isSubView)
{
const string urlPrefix = "https://raw.githubusercontent.com/MediaBrowser/MediaBrowser.Resources/master/images/folders/";
@ -108,7 +108,7 @@ namespace MediaBrowser.Providers.FolderImages
return urlPrefix + "movies.png";
}
if (isUserSpecificView)
if (isSubView)
{
return null;
}

@ -26,7 +26,7 @@ namespace MediaBrowser.Providers.Manager
/// <summary>
/// Class ProviderManager
/// </summary>
public class ProviderManager : IProviderManager
public class ProviderManager : IProviderManager, IDisposable
{
/// <summary>
/// The _logger
@ -63,6 +63,8 @@ namespace MediaBrowser.Providers.Manager
private IExternalId[] _externalIds;
private readonly Func<ILibraryManager> _libraryManagerFactory;
/// <summary>
/// Initializes a new instance of the <see cref="ProviderManager" /> class.
/// </summary>
@ -71,7 +73,7 @@ namespace MediaBrowser.Providers.Manager
/// <param name="libraryMonitor">The directory watchers.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="fileSystem">The file system.</param>
public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths)
public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func<ILibraryManager> libraryManagerFactory)
{
_logger = logManager.GetLogger("ProviderManager");
_httpClient = httpClient;
@ -79,6 +81,7 @@ namespace MediaBrowser.Providers.Manager
_libraryMonitor = libraryMonitor;
_fileSystem = fileSystem;
_appPaths = appPaths;
_libraryManagerFactory = libraryManagerFactory;
}
/// <summary>
@ -841,5 +844,80 @@ namespace MediaBrowser.Providers.Manager
});
}
private readonly ConcurrentQueue<Tuple<Guid, MetadataRefreshOptions>> _refreshQueue =
new ConcurrentQueue<Tuple<Guid, MetadataRefreshOptions>>();
private readonly object _refreshTimerLock = new object();
private Timer _refreshTimer;
public void QueueRefresh(Guid id, MetadataRefreshOptions options)
{
if (_disposed)
{
return;
}
_refreshQueue.Enqueue(new Tuple<Guid, MetadataRefreshOptions>(id, options));
StartRefreshTimer();
}
private void StartRefreshTimer()
{
lock (_refreshTimerLock)
{
if (_refreshTimer == null)
{
_refreshTimer = new Timer(RefreshTimerCallback, null, 100, Timeout.Infinite);
}
}
}
private void StopRefreshTimer()
{
lock (_refreshTimerLock)
{
if (_refreshTimer != null)
{
_refreshTimer.Dispose();
_refreshTimer = null;
}
}
}
private async void RefreshTimerCallback(object state)
{
Tuple<Guid, MetadataRefreshOptions> refreshItem;
var libraryManager = _libraryManagerFactory();
while (_refreshQueue.TryDequeue(out refreshItem))
{
if (_disposed)
{
return;
}
try
{
var item = libraryManager.GetItemById(refreshItem.Item1);
if (item != null)
{
await item.RefreshMetadata(refreshItem.Item2, CancellationToken.None).ConfigureAwait(false);
}
}
catch (Exception ex)
{
_logger.ErrorException("Error refreshing item", ex);
}
}
StopRefreshTimer();
}
private bool _disposed;
public void Dispose()
{
_disposed = true;
}
}
}

@ -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,

@ -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");

@ -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)

@ -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);
}
}
}

@ -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",

@ -34,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.Photos
return item is T;
}
public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
public virtual IEnumerable<ImageType> GetSupportedImages(IHasImages item)
{
return new List<ImageType>
{

@ -20,12 +20,29 @@ namespace MediaBrowser.Server.Implementations.Photos
private readonly IUserManager _userManager;
private readonly ILibraryManager _libraryManager;
public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IUserManager userManager, ILibraryManager libraryManager, string[] collectionStripViewTypes)
public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IUserManager userManager, ILibraryManager libraryManager)
: base(fileSystem, providerManager, applicationPaths)
{
_userManager = userManager;
_libraryManager = libraryManager;
_collectionStripViewTypes = collectionStripViewTypes;
}
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)
@ -75,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);
@ -115,13 +138,10 @@ namespace MediaBrowser.Server.Implementations.Photos
var audio = i as Audio;
if (audio != null)
{
if (!audio.HasImage(ImageType.Primary))
var album = audio.FindParent<MusicAlbum>();
if (album != null && album.HasImage(ImageType.Primary))
{
var album = audio.FindParent<MusicAlbum>();
if (album != null)
{
return album;
}
return album;
}
}
@ -129,7 +149,7 @@ namespace MediaBrowser.Server.Implementations.Photos
}).DistinctBy(i => i.Id);
if (IsUsingCollectionStrip(view))
if (isUsingCollectionStrip)
{
return GetFinalItems(items.Where(i => i.HasImage(ImageType.Primary) || i.HasImage(ImageType.Thumb)).ToList(), 8);
}
@ -137,8 +157,6 @@ namespace MediaBrowser.Server.Implementations.Photos
return GetFinalItems(items.Where(i => i.HasImage(ImageType.Primary)).ToList());
}
private readonly string[] _collectionStripViewTypes = { CollectionType.Movies };
public override bool Supports(IHasImages item)
{
var view = item as UserView;
@ -193,7 +211,18 @@ namespace MediaBrowser.Server.Implementations.Photos
private bool IsUsingCollectionStrip(UserView view)
{
return _collectionStripViewTypes.Contains(view.ViewType ?? string.Empty);
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)

@ -19,31 +19,40 @@ namespace MediaBrowser.Server.Implementations.Photos
public Stream BuildThumbCollage(IEnumerable<string> paths, string text, int width, int height)
{
using (var wand = BuildThumbCollageWand(paths, text, width, height))
using (var wand = BuildThumbCollageWandWithText(paths, text, width, height))
{
return DynamicImageHelpers.GetStream(wand, _appPaths);
}
}
private IEnumerable<string> ProjectPaths(IEnumerable<string> paths, int count)
private string[] ProjectPaths(IEnumerable<string> paths, int count)
{
var clone = paths.ToList();
var list = new List<string>();
while (list.Count < count)
{
list.AddRange(clone);
foreach (var path in clone)
{
list.Add(path);
if (list.Count >= count)
{
break;
}
}
}
return list.Take(count);
return list.Take(count).ToArray();
}
private MagickWand BuildThumbCollageWand(IEnumerable<string> paths, string text, int width, int height)
private MagickWand BuildThumbCollageWandWithText(IEnumerable<string> paths, string text, int width, int height)
{
using (var wandImages = new MagickWand(ProjectPaths(paths, 8).ToArray()))
var inputPaths = ProjectPaths(paths, 8);
using (var wandImages = new MagickWand(inputPaths))
{
var wand = new MagickWand(width, height);
wand.OpenImage("gradient:#111111-#252525");
wand.OpenImage("gradient:#111111-#111111");
using (var draw = new DrawingWand())
{
using (var fcolor = new PixelWand(ColorName.White))
@ -86,12 +95,12 @@ namespace MediaBrowser.Server.Implementations.Photos
mwr.CurrentImage.FlipImage();
mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
mwr.CurrentImage.ColorizeImage(ColorName.Black, ColorName.Grey56);
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.00555555555555555555555555555556);
var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.DstInCompositeOp, 0, verticalSpacing);
wandList.AddImage(mwr);
@ -106,6 +115,62 @@ namespace MediaBrowser.Server.Implementations.Photos
}
}
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); }

@ -197,6 +197,7 @@ namespace MediaBrowser.Server.Startup.Common
private ITVSeriesManager TVSeriesManager { get; set; }
private ICollectionManager CollectionManager { get; set; }
private IMediaSourceManager MediaSourceManager { get; set; }
private IPlaylistManager PlaylistManager { get; set; }
private readonly StartupOptions _startupOptions;
private readonly string _remotePackageName;
@ -423,7 +424,7 @@ namespace MediaBrowser.Server.Startup.Common
LibraryMonitor = new LibraryMonitor(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager);
RegisterSingleInstance(LibraryMonitor);
ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager, ApplicationPaths);
ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager, ApplicationPaths, () => LibraryManager);
RegisterSingleInstance(ProviderManager);
SeriesOrderManager = new SeriesOrderManager();
@ -491,13 +492,13 @@ namespace MediaBrowser.Server.Startup.Common
CollectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("CollectionManager"));
RegisterSingleInstance(CollectionManager);
var playlistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("PlaylistManager"), UserManager);
RegisterSingleInstance<IPlaylistManager>(playlistManager);
PlaylistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("PlaylistManager"), UserManager);
RegisterSingleInstance<IPlaylistManager>(PlaylistManager);
LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer);
RegisterSingleInstance(LiveTvManager);
UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, playlistManager, CollectionManager, ServerConfigurationManager);
UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, PlaylistManager, CollectionManager, ServerConfigurationManager);
RegisterSingleInstance(UserViewManager);
var contentDirectory = new ContentDirectory(dlnaManager, UserDataManager, ImageProcessor, LibraryManager, ServerConfigurationManager, UserManager, LogManager.GetLogger("UpnpContentDirectory"), HttpClient, LocalizationManager, ChannelManager, MediaSourceManager);
@ -702,6 +703,7 @@ namespace MediaBrowser.Server.Startup.Common
BaseItem.LiveTvManager = LiveTvManager;
Folder.UserViewManager = UserViewManager;
UserView.TVSeriesManager = TVSeriesManager;
UserView.PlaylistManager = PlaylistManager;
BaseItem.CollectionManager = CollectionManager;
BaseItem.MediaSourceManager = MediaSourceManager;
}

Loading…
Cancel
Save