mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-02 22:08:27 +01:00
add option to merge metadata and IBN paths
This commit is contained in:
@@ -88,9 +88,12 @@ namespace MediaBrowser.Server.Implementations.Configuration
|
||||
/// </summary>
|
||||
private void UpdateItemsByNamePath()
|
||||
{
|
||||
((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = string.IsNullOrEmpty(Configuration.ItemsByNamePath) ?
|
||||
null :
|
||||
Configuration.ItemsByNamePath;
|
||||
if (!Configuration.MergeMetadataAndImagesByName)
|
||||
{
|
||||
((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = string.IsNullOrEmpty(Configuration.ItemsByNamePath) ?
|
||||
null :
|
||||
Configuration.ItemsByNamePath;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -101,6 +104,11 @@ namespace MediaBrowser.Server.Implementations.Configuration
|
||||
((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = string.IsNullOrEmpty(Configuration.MetadataPath) ?
|
||||
GetInternalMetadataPath() :
|
||||
Configuration.MetadataPath;
|
||||
|
||||
if (Configuration.MergeMetadataAndImagesByName)
|
||||
{
|
||||
((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetInternalMetadataPath()
|
||||
|
||||
@@ -27,6 +27,8 @@ namespace MediaBrowser.Server.Implementations.Devices
|
||||
private readonly IConfigurationManager _config;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public event EventHandler<GenericEventArgs<CameraImageUploadInfo>> CameraImageUploaded;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [device options updated].
|
||||
/// </summary>
|
||||
@@ -116,7 +118,7 @@ namespace MediaBrowser.Server.Implementations.Devices
|
||||
{
|
||||
devices = devices.Where(i => CanAccessDevice(query.UserId, i.Id));
|
||||
}
|
||||
|
||||
|
||||
var array = devices.ToArray();
|
||||
return new QueryResult<DeviceInfo>
|
||||
{
|
||||
@@ -137,7 +139,8 @@ namespace MediaBrowser.Server.Implementations.Devices
|
||||
|
||||
public async Task AcceptCameraUpload(string deviceId, Stream stream, LocalFileInfo file)
|
||||
{
|
||||
var path = GetUploadPath(deviceId);
|
||||
var device = GetDevice(deviceId);
|
||||
var path = GetUploadPath(device);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(file.Album))
|
||||
{
|
||||
@@ -163,11 +166,27 @@ namespace MediaBrowser.Server.Implementations.Devices
|
||||
{
|
||||
_libraryMonitor.ReportFileSystemChangeComplete(path, true);
|
||||
}
|
||||
|
||||
if (CameraImageUploaded != null)
|
||||
{
|
||||
EventHelper.FireEventIfNotNull(CameraImageUploaded, this, new GenericEventArgs<CameraImageUploadInfo>
|
||||
{
|
||||
Argument = new CameraImageUploadInfo
|
||||
{
|
||||
Device = device,
|
||||
FileInfo = file
|
||||
}
|
||||
}, _logger);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetUploadPath(string deviceId)
|
||||
{
|
||||
var device = GetDevice(deviceId);
|
||||
return GetUploadPath(GetDevice(deviceId));
|
||||
}
|
||||
|
||||
private string GetUploadPath(DeviceInfo device)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(device.CameraUploadPath))
|
||||
{
|
||||
return device.CameraUploadPath;
|
||||
|
||||
@@ -3,6 +3,7 @@ using MediaBrowser.Common.Plugins;
|
||||
using MediaBrowser.Common.ScheduledTasks;
|
||||
using MediaBrowser.Common.Updates;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Devices;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Library;
|
||||
@@ -44,8 +45,9 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
|
||||
private readonly object _libraryChangedSyncLock = new object();
|
||||
|
||||
private readonly IConfigurationManager _config;
|
||||
private readonly IDeviceManager _deviceManager;
|
||||
|
||||
public Notifications(IInstallationManager installationManager, IUserManager userManager, ILogger logger, ITaskManager taskManager, INotificationManager notificationManager, ILibraryManager libraryManager, ISessionManager sessionManager, IServerApplicationHost appHost, IConfigurationManager config)
|
||||
public Notifications(IInstallationManager installationManager, IUserManager userManager, ILogger logger, ITaskManager taskManager, INotificationManager notificationManager, ILibraryManager libraryManager, ISessionManager sessionManager, IServerApplicationHost appHost, IConfigurationManager config, IDeviceManager deviceManager)
|
||||
{
|
||||
_installationManager = installationManager;
|
||||
_userManager = userManager;
|
||||
@@ -56,6 +58,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
|
||||
_sessionManager = sessionManager;
|
||||
_appHost = appHost;
|
||||
_config = config;
|
||||
_deviceManager = deviceManager;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
@@ -74,6 +77,21 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
|
||||
_appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged;
|
||||
_appHost.HasUpdateAvailableChanged += _appHost_HasUpdateAvailableChanged;
|
||||
_appHost.ApplicationUpdated += _appHost_ApplicationUpdated;
|
||||
_deviceManager.CameraImageUploaded +=_deviceManager_CameraImageUploaded;
|
||||
}
|
||||
|
||||
async void _deviceManager_CameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e)
|
||||
{
|
||||
var type = NotificationType.CameraImageUploaded.ToString();
|
||||
|
||||
var notification = new NotificationRequest
|
||||
{
|
||||
NotificationType = type
|
||||
};
|
||||
|
||||
notification.Variables["DeviceName"] = e.Argument.Device.Name;
|
||||
|
||||
await SendNotification(notification).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
async void _appHost_ApplicationUpdated(object sender, GenericEventArgs<PackageVersionInfo> e)
|
||||
@@ -451,6 +469,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
|
||||
_appHost.HasPendingRestartChanged -= _appHost_HasPendingRestartChanged;
|
||||
_appHost.HasUpdateAvailableChanged -= _appHost_HasUpdateAvailableChanged;
|
||||
_appHost.ApplicationUpdated -= _appHost_ApplicationUpdated;
|
||||
|
||||
_deviceManager.CameraImageUploaded -= _deviceManager_CameraImageUploaded;
|
||||
}
|
||||
|
||||
private void DisposeLibraryUpdateTimer()
|
||||
|
||||
@@ -566,7 +566,10 @@ namespace MediaBrowser.Server.Implementations.IO
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
foreach (var p in paths) Logger.Info(p + " reports change.");
|
||||
foreach (var p in paths)
|
||||
{
|
||||
Logger.Info(p + " reports change.");
|
||||
}
|
||||
|
||||
// If the root folder changed, run the library task so the user can see it
|
||||
if (itemsToRefresh.Any(i => i is AggregateFolder))
|
||||
|
||||
@@ -219,11 +219,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
/// <summary>
|
||||
/// The _root folder sync lock
|
||||
/// </summary>
|
||||
private object _rootFolderSyncLock = new object();
|
||||
/// <summary>
|
||||
/// The _root folder initialized
|
||||
/// </summary>
|
||||
private bool _rootFolderInitialized;
|
||||
private readonly object _rootFolderSyncLock = new object();
|
||||
/// <summary>
|
||||
/// Gets the root folder.
|
||||
/// </summary>
|
||||
@@ -232,17 +228,17 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
{
|
||||
get
|
||||
{
|
||||
LazyInitializer.EnsureInitialized(ref _rootFolder, ref _rootFolderInitialized, ref _rootFolderSyncLock, CreateRootFolder);
|
||||
return _rootFolder;
|
||||
}
|
||||
private set
|
||||
{
|
||||
_rootFolder = value;
|
||||
|
||||
if (value == null)
|
||||
if (_rootFolder == null)
|
||||
{
|
||||
_rootFolderInitialized = false;
|
||||
lock (_rootFolderSyncLock)
|
||||
{
|
||||
if (_rootFolder == null)
|
||||
{
|
||||
_rootFolder = CreateRootFolder();
|
||||
}
|
||||
}
|
||||
}
|
||||
return _rootFolder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -849,11 +845,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ConfigurationManager.Configuration.StoreArtistsInMetadata)
|
||||
{
|
||||
return Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "artists");
|
||||
}
|
||||
|
||||
return Path.Combine(ConfigurationManager.ApplicationPaths.ItemsByNamePath, "artists");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,5 +83,40 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
.Take(100)
|
||||
.OrderBy(i => Guid.NewGuid());
|
||||
}
|
||||
|
||||
public IEnumerable<Audio> GetInstantMixFromItem(BaseItem item, User user)
|
||||
{
|
||||
var genre = item as MusicGenre;
|
||||
if (genre != null)
|
||||
{
|
||||
return GetInstantMixFromGenres(new[] { item.Name }, user);
|
||||
}
|
||||
|
||||
var playlist = item as Playlist;
|
||||
if (playlist != null)
|
||||
{
|
||||
return GetInstantMixFromPlaylist(playlist, user);
|
||||
}
|
||||
|
||||
var album = item as MusicAlbum;
|
||||
if (album != null)
|
||||
{
|
||||
return GetInstantMixFromAlbum(album, user);
|
||||
}
|
||||
|
||||
var artist = item as MusicArtist;
|
||||
if (artist != null)
|
||||
{
|
||||
return GetInstantMixFromArtist(artist.Name, user);
|
||||
}
|
||||
|
||||
var song = item as Audio;
|
||||
if (song != null)
|
||||
{
|
||||
return GetInstantMixFromSong(song, user);
|
||||
}
|
||||
|
||||
return new Audio[] { };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MoreLinq;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.Library
|
||||
{
|
||||
@@ -56,7 +57,9 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
|
||||
var excludeFolderIds = user.Configuration.ExcludeFoldersFromGrouping.Select(i => new Guid(i)).ToList();
|
||||
|
||||
var standaloneFolders = folders.Where(i => UserView.IsExcludedFromGrouping(i) || excludeFolderIds.Contains(i.Id)).ToList();
|
||||
var standaloneFolders = folders
|
||||
.Where(i => UserView.IsExcludedFromGrouping(i) || excludeFolderIds.Contains(i.Id))
|
||||
.ToList();
|
||||
|
||||
var foldersWithViewTypes = folders
|
||||
.Except(standaloneFolders)
|
||||
@@ -164,5 +167,141 @@ namespace MediaBrowser.Server.Implementations.Library
|
||||
|
||||
return _libraryManager.GetNamedView(name, type, sortName, cancellationToken);
|
||||
}
|
||||
|
||||
public List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request)
|
||||
{
|
||||
var user = _userManager.GetUserById(request.UserId);
|
||||
|
||||
var includeTypes = request.IncludeItemTypes;
|
||||
|
||||
var currentUser = user;
|
||||
|
||||
Func<BaseItem, bool> filter = i =>
|
||||
{
|
||||
if (includeTypes.Length > 0)
|
||||
{
|
||||
if (!includeTypes.Contains(i.GetType().Name, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (request.IsPlayed.HasValue)
|
||||
{
|
||||
var val = request.IsPlayed.Value;
|
||||
if (i.IsPlayed(currentUser) != val)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return i.LocationType != LocationType.Virtual && !i.IsFolder;
|
||||
};
|
||||
|
||||
// Avoid implicitly captured closure
|
||||
var libraryItems = string.IsNullOrEmpty(request.ParentId) && user != null ?
|
||||
GetItemsConfiguredForLatest(user, filter) :
|
||||
GetAllLibraryItems(request.UserId, _userManager, _libraryManager, request.ParentId, filter);
|
||||
|
||||
libraryItems = libraryItems.OrderByDescending(i => i.DateCreated);
|
||||
|
||||
if (request.IsPlayed.HasValue)
|
||||
{
|
||||
var takeLimit = (request.Limit ?? 20) * 20;
|
||||
libraryItems = libraryItems.Take(takeLimit);
|
||||
}
|
||||
|
||||
// Avoid implicitly captured closure
|
||||
var items = libraryItems
|
||||
.ToList();
|
||||
|
||||
var list = new List<Tuple<BaseItem, List<BaseItem>>>();
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
// Only grab the index container for media
|
||||
var container = item.IsFolder || !request.GroupItems ? null : item.LatestItemsIndexContainer;
|
||||
|
||||
if (container == null)
|
||||
{
|
||||
list.Add(new Tuple<BaseItem, List<BaseItem>>(null, new List<BaseItem> { item }));
|
||||
}
|
||||
else
|
||||
{
|
||||
var current = list.FirstOrDefault(i => i.Item1 != null && i.Item1.Id == container.Id);
|
||||
|
||||
if (current != null)
|
||||
{
|
||||
current.Item2.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(new Tuple<BaseItem, List<BaseItem>>(container, new List<BaseItem> { item }));
|
||||
}
|
||||
}
|
||||
|
||||
if (list.Count >= request.Limit)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
protected IList<BaseItem> GetAllLibraryItems(string userId, IUserManager userManager, ILibraryManager libraryManager, string parentId, Func<BaseItem, bool> filter)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(parentId))
|
||||
{
|
||||
var folder = (Folder)libraryManager.GetItemById(new Guid(parentId));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(userId))
|
||||
{
|
||||
var user = userManager.GetUserById(userId);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentException("User not found");
|
||||
}
|
||||
|
||||
return folder
|
||||
.GetRecursiveChildren(user, filter)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
return folder
|
||||
.GetRecursiveChildren(filter);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(userId))
|
||||
{
|
||||
var user = userManager.GetUserById(userId);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
throw new ArgumentException("User not found");
|
||||
}
|
||||
|
||||
return user
|
||||
.RootFolder
|
||||
.GetRecursiveChildren(user, filter)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
return libraryManager
|
||||
.RootFolder
|
||||
.GetRecursiveChildren(filter);
|
||||
}
|
||||
|
||||
private IEnumerable<BaseItem> GetItemsConfiguredForLatest(User user, Func<BaseItem, bool> filter)
|
||||
{
|
||||
// Avoid implicitly captured closure
|
||||
var currentUser = user;
|
||||
|
||||
return user.RootFolder.GetChildren(user, true)
|
||||
.OfType<Folder>()
|
||||
.Where(i => !user.Configuration.LatestItemsExcludes.Contains(i.Id.ToString("N")))
|
||||
.SelectMany(i => i.GetRecursiveChildren(currentUser, filter))
|
||||
.DistinctBy(i => i.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
"HeaderAudio": "Audio",
|
||||
"HeaderVideo": "Video",
|
||||
"HeaderPaths": "Paths",
|
||||
"CategorySync": "Sync",
|
||||
"HeaderSyncRequiresSupporterMembership": "Sync Requires a Supporter Membership",
|
||||
"HeaderEnjoyDayTrial": "Enjoy a 14 Day Free Trial",
|
||||
"LabelSyncTempPath": "Temporary file path:",
|
||||
@@ -669,6 +670,7 @@
|
||||
"NotificationOptionInstallationFailed": "Installation failure",
|
||||
"NotificationOptionNewLibraryContent": "New content added",
|
||||
"NotificationOptionNewLibraryContentMultiple": "New content added (multiple)",
|
||||
"NotificationOptionCameraImageUploaded": "Camera image uploaded",
|
||||
"SendNotificationHelp": "By default, notifications are delivered to the dashboard inbox. Browse the plugin catalog to install additional notification options.",
|
||||
"NotificationOptionServerRestartRequired": "Server restart required",
|
||||
"LabelNotificationEnabled": "Enable this notification",
|
||||
@@ -893,7 +895,7 @@
|
||||
"OptionCommunityMostWatchedSort": "Most Watched",
|
||||
"TabNextUp": "Next Up",
|
||||
"HeaderBecomeMediaBrowserSupporter": "Become a Media Browser Supporter",
|
||||
"TextAccessPremiumFeatures": "Enjoy Premium Features",
|
||||
"TextEnjoyBonusFeatures": "Enjoy Bonus Features",
|
||||
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
|
||||
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the + button to start creating Collections.",
|
||||
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
|
||||
@@ -957,7 +959,7 @@
|
||||
"OptionLatestTvRecordings": "Latest recordings",
|
||||
"LabelProtocolInfo": "Protocol info:",
|
||||
"LabelProtocolInfoHelp": "The value that will be used when responding to GetProtocolInfo requests from the device.",
|
||||
"TabKodiMetadata": "Kodi",
|
||||
"TabNfo": "Nfo",
|
||||
"HeaderKodiMetadataHelp": "Media Browser includes native support for Kodi Nfo metadata and images. To enable or disable Kodi metadata, use the Advanced tab to configure options for your media types.",
|
||||
"LabelKodiMetadataUser": "Sync user watch data to nfo's for:",
|
||||
"LabelKodiMetadataUserHelp": "Enable this to keep watch data in sync between Media Browser and Kodi.",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Controller.Notifications;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Notifications;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -137,6 +136,13 @@ namespace MediaBrowser.Server.Implementations.Notifications
|
||||
Type = NotificationType.VideoPlaybackStopped.ToString(),
|
||||
DefaultTitle = "{UserName} has finished playing {ItemName} on {DeviceName}.",
|
||||
Variables = new List<string>{"UserName", "ItemName", "DeviceName", "AppName"}
|
||||
},
|
||||
|
||||
new NotificationTypeInfo
|
||||
{
|
||||
Type = NotificationType.CameraImageUploaded.ToString(),
|
||||
DefaultTitle = "A new camera image has been uploaded from {DeviceName}.",
|
||||
Variables = new List<string>{"DeviceName"}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -171,10 +177,14 @@ namespace MediaBrowser.Server.Implementations.Notifications
|
||||
{
|
||||
note.Category = _localization.GetLocalizedString("CategoryUser");
|
||||
}
|
||||
else if (note.Type.IndexOf("Plugin", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
else if (note.Type.IndexOf("Plugin", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
note.Category = _localization.GetLocalizedString("CategoryPlugin");
|
||||
}
|
||||
else if (note.Type.IndexOf("CameraImageUploaded", StringComparison.OrdinalIgnoreCase) != -1)
|
||||
{
|
||||
note.Category = _localization.GetLocalizedString("CategorySync");
|
||||
}
|
||||
else
|
||||
{
|
||||
note.Category = _localization.GetLocalizedString("CategorySystem");
|
||||
|
||||
@@ -870,14 +870,14 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||
{
|
||||
if (items.Any(i => !session.QueueableMediaTypes.Contains(i.MediaType, StringComparer.OrdinalIgnoreCase)))
|
||||
{
|
||||
throw new ArgumentException(string.Format("{0} is unable to queue the requested media type.", session.DeviceName ?? session.Id.ToString()));
|
||||
throw new ArgumentException(string.Format("{0} is unable to queue the requested media type.", session.DeviceName ?? session.Id));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (items.Any(i => !session.PlayableMediaTypes.Contains(i.MediaType, StringComparer.OrdinalIgnoreCase)))
|
||||
{
|
||||
throw new ArgumentException(string.Format("{0} is unable to play the requested media type.", session.DeviceName ?? session.Id.ToString()));
|
||||
throw new ArgumentException(string.Format("{0} is unable to play the requested media type.", session.DeviceName ?? session.Id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -895,6 +895,19 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||
{
|
||||
var item = _libraryManager.GetItemById(new Guid(id));
|
||||
|
||||
var byName = item as IItemByName;
|
||||
|
||||
if (byName != null)
|
||||
{
|
||||
var items = user == null ?
|
||||
_libraryManager.RootFolder.GetRecursiveChildren(i => !i.IsFolder && byName.ItemFilter(i)) :
|
||||
user.RootFolder.GetRecursiveChildren(user, i => !i.IsFolder && byName.ItemFilter(i));
|
||||
|
||||
items = items.OrderBy(i => i.SortName);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
if (item.IsFolder)
|
||||
{
|
||||
var folder = (Folder)item;
|
||||
@@ -913,37 +926,9 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||
|
||||
private IEnumerable<BaseItem> TranslateItemForInstantMix(string id, User user)
|
||||
{
|
||||
var item = _libraryManager.GetItemById(new Guid(id));
|
||||
var item = _libraryManager.GetItemById(id);
|
||||
|
||||
var audio = item as Audio;
|
||||
|
||||
if (audio != null)
|
||||
{
|
||||
return _musicManager.GetInstantMixFromSong(audio, user);
|
||||
}
|
||||
|
||||
var artist = item as MusicArtist;
|
||||
|
||||
if (artist != null)
|
||||
{
|
||||
return _musicManager.GetInstantMixFromArtist(artist.Name, user);
|
||||
}
|
||||
|
||||
var album = item as MusicAlbum;
|
||||
|
||||
if (album != null)
|
||||
{
|
||||
return _musicManager.GetInstantMixFromAlbum(album, user);
|
||||
}
|
||||
|
||||
var genre = item as MusicGenre;
|
||||
|
||||
if (genre != null)
|
||||
{
|
||||
return _musicManager.GetInstantMixFromGenres(new[] { genre.Name }, user);
|
||||
}
|
||||
|
||||
return new BaseItem[] { };
|
||||
return _musicManager.GetInstantMixFromItem(item, user);
|
||||
}
|
||||
|
||||
public Task SendBrowseCommand(string controllingSessionId, string sessionId, BrowseRequest command, CancellationToken cancellationToken)
|
||||
|
||||
@@ -93,7 +93,8 @@ namespace MediaBrowser.Server.Implementations.TV
|
||||
return FilterSeries(request, series)
|
||||
.AsParallel()
|
||||
.Select(i => GetNextUp(i, currentUser))
|
||||
.Where(i => i.Item1 != null)
|
||||
// Include if an episode was found, and either the series is not unwatched or the specific series was requested
|
||||
.Where(i => i.Item1 != null && (!i.Item3 || !string.IsNullOrWhiteSpace(request.SeriesId)))
|
||||
.OrderByDescending(i =>
|
||||
{
|
||||
var episode = i.Item1;
|
||||
@@ -123,7 +124,7 @@ namespace MediaBrowser.Server.Implementations.TV
|
||||
/// <param name="series">The series.</param>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns>Task{Episode}.</returns>
|
||||
private Tuple<Episode, DateTime> GetNextUp(Series series, User user)
|
||||
private Tuple<Episode, DateTime, bool> GetNextUp(Series series, User user)
|
||||
{
|
||||
// Get them in display order, then reverse
|
||||
var allEpisodes = series.GetSeasons(user, true, true)
|
||||
@@ -162,13 +163,13 @@ namespace MediaBrowser.Server.Implementations.TV
|
||||
|
||||
if (lastWatched != null)
|
||||
{
|
||||
return new Tuple<Episode, DateTime>(nextUp, lastWatchedDate);
|
||||
return new Tuple<Episode, DateTime, bool>(nextUp, lastWatchedDate, false);
|
||||
}
|
||||
|
||||
var firstEpisode = allEpisodes.LastOrDefault(i => i.LocationType != LocationType.Virtual && !i.IsPlayed(user));
|
||||
|
||||
// Return the first episode
|
||||
return new Tuple<Episode, DateTime>(firstEpisode, DateTime.MinValue);
|
||||
return new Tuple<Episode, DateTime, bool>(firstEpisode, DateTime.MinValue, true);
|
||||
}
|
||||
|
||||
private IEnumerable<Series> FilterSeries(NextUpQuery request, IEnumerable<Series> items)
|
||||
|
||||
Reference in New Issue
Block a user