create collections from movies page

This commit is contained in:
Luke Pulverenti 2014-06-03 23:34:36 -04:00
parent 71351344d7
commit 3640f62086
16 changed files with 182 additions and 31 deletions

View File

@ -1,13 +1,16 @@
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Model.Querying;
using ServiceStack;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Api.Movies
{
[Route("/Collections", "POST", Summary = "Creates a new collection")]
public class CreateCollection : IReturnVoid
public class CreateCollection : IReturn<CollectionCreationResult>
{
[ApiMember(Name = "IsLocked", Description = "Whether or not to lock the new collection.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
public bool IsLocked { get; set; }
@ -17,6 +20,9 @@ namespace MediaBrowser.Api.Movies
[ApiMember(Name = "ParentId", Description = "Optional - create the collection within a specific folder", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public Guid? ParentId { get; set; }
[ApiMember(Name = "Ids", Description = "Item Ids to add to the collection", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
public string Ids { get; set; }
}
[Route("/Collections/{Id}/Items", "POST", Summary = "Adds items to a collection")]
@ -42,22 +48,32 @@ namespace MediaBrowser.Api.Movies
public class CollectionService : BaseApiService
{
private readonly ICollectionManager _collectionManager;
private readonly IDtoService _dtoService;
public CollectionService(ICollectionManager collectionManager)
public CollectionService(ICollectionManager collectionManager, IDtoService dtoService)
{
_collectionManager = collectionManager;
_dtoService = dtoService;
}
public void Post(CreateCollection request)
public object Post(CreateCollection request)
{
var task = _collectionManager.CreateCollection(new CollectionCreationOptions
{
IsLocked = request.IsLocked,
Name = request.Name,
ParentId = request.ParentId
ParentId = request.ParentId,
ItemIdList = (request.Ids ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => new Guid(i)).ToList()
});
Task.WaitAll(task);
var item = task.Result;
var dto = _dtoService.GetBaseItemDto(item, new List<ItemFields>());
return ToOptimizedResult(new CollectionCreationResult
{
Id = dto.Id
});
}
public void Post(AddToCollection request)
@ -74,4 +90,9 @@ namespace MediaBrowser.Api.Movies
Task.WaitAll(task);
}
}
public class CollectionCreationResult
{
public string Id { get; set; }
}
}

View File

@ -1065,8 +1065,12 @@ namespace MediaBrowser.Api.Playback
/// <returns>System.String.</returns>
private string GetUserAgentParam(StreamState state)
{
string useragent;
string useragent = null;
if (state.RemoteHttpHeaders != null)
{
state.RemoteHttpHeaders.TryGetValue("User-Agent", out useragent);
}
if (string.IsNullOrWhiteSpace(useragent))
{

View File

@ -128,6 +128,11 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager
request.Host = options.Host;
}
if (!string.IsNullOrEmpty(options.Referer))
{
request.Referer = options.Referer;
}
#if !__MonoCS__
if (options.EnableKeepAlive)
{

View File

@ -52,6 +52,12 @@ namespace MediaBrowser.Common.Net
}
}
/// <summary>
/// Gets or sets the referrer.
/// </summary>
/// <value>The referrer.</value>
public string Referer { get; set; }
/// <summary>
/// Gets or sets the host.
/// </summary>

View File

@ -121,11 +121,16 @@ namespace MediaBrowser.Controller.Entities
/// <param name="refreshOptions">The refresh options.</param>
/// <param name="directoryService">The directory service.</param>
/// <returns>Task.</returns>
protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
protected override async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
{
var list = PhysicalLocationsList.ToList();
CreateResolveArgs(directoryService);
return NullTaskResult;
if (!list.SequenceEqual(PhysicalLocationsList))
{
await UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
}
}
/// <summary>
@ -164,8 +169,7 @@ namespace MediaBrowser.Controller.Entities
LibraryManager.RootFolder.Children
.OfType<Folder>()
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase))
.SelectMany(c => c.Children)
.ToList();
.SelectMany(c => c.Children);
}
}
}

View File

@ -445,6 +445,11 @@ namespace MediaBrowser.Controller.Entities
cancellationToken.ThrowIfCancellationRequested();
if (this is UserRootFolder)
{
var b = true;
}
foreach (var child in nonCachedChildren)
{
BaseItem currentChild;

View File

@ -2,6 +2,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Entities
{
@ -32,5 +34,22 @@ namespace MediaBrowser.Controller.Entities
return hasChanges;
}
protected override async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
{
await base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService)
.ConfigureAwait(false);
// Not the best way to handle this, but it solves an issue
// CollectionFolders aren't always getting saved after changes
// This means that grabbing the item by Id may end up returning the old one
// Fix is in two places - make sure the folder gets saved
// And here to remedy it for affected users.
// In theory this can be removed eventually.
foreach (var item in Children)
{
LibraryManager.RegisterItem(item);
}
}
}
}

View File

@ -147,10 +147,13 @@ namespace MediaBrowser.Dlna.Ssdp
SendDatagram(header, values, endpoint, null);
if (_config.Configuration.DlnaOptions.EnableDebugLogging)
{
_logger.Debug("{1} - Responded to a {0} request to {2}", d.Type, endpoint, d.Address.ToString());
}
}
}
}
private readonly object _queueTimerSyncLock = new object();
private void StartQueueTimer()

View File

@ -611,6 +611,8 @@ namespace MediaBrowser.Providers.Manager
try
{
var isEnabledFor = saver.IsEnabledFor(item, updateType);
if (!includeDisabled)
{
if (options.DisabledMetadataSavers.Contains(saver.Name, StringComparer.OrdinalIgnoreCase))
@ -626,7 +628,7 @@ namespace MediaBrowser.Providers.Manager
// Manual edit occurred
// Even if save local is off, save locally anyway if the metadata file already exists
if (fileSaver == null || !File.Exists(fileSaver.GetSavePath(item)))
if (fileSaver == null || !isEnabledFor || !File.Exists(fileSaver.GetSavePath(item)))
{
return false;
}
@ -640,7 +642,7 @@ namespace MediaBrowser.Providers.Manager
}
}
return saver.IsEnabledFor(item, updateType);
return isEnabledFor;
}
catch (Exception ex)
{

View File

@ -674,15 +674,20 @@ namespace MediaBrowser.Server.Implementations.Library
{
var folder = child.GetFolder();
if (folder != null)
{
if (folder.Id == Guid.Empty)
{
folder.Id = (folder.Path ?? folder.GetType().Name).GetMBId(folder.GetType());
}
folder = GetItemById(folder.Id) as BasePluginFolder ?? folder;
rootFolder.AddVirtualChild(folder);
RegisterItem(folder);
}
}
return rootFolder;
}

View File

@ -115,7 +115,8 @@
"HeaderSplitMedia": "Split Media Apart",
"MessageConfirmSplitMedia": "Are you sure you wish to split the media sources into separate items?",
"HeaderError": "Error",
"MessagePleaseSelectItemsToGroup": "Please select two or more items to group together.",
"MessagePleaseSelectOneItem": "Please select at least one item.",
"MessagePleaseSelectTwoItems": "Please select at least two items.",
"MessageTheFollowingItemsWillBeGrouped": "The following titles will be grouped into one item:",
"MessageConfirmItemGrouping": "Media Browser clients will automatically choose the optimal version to play based on device and network performance. Are you sure you wish to continue?",
"HeaderResume": "Resume",
@ -138,5 +139,6 @@
"HeaderSelectImagesByNamePathHelp": "Browse or enter the path to your items by name folder. The folder must be writeable.",
"HeaderSelectMetadataPathHelp": "Browse or enter the path you'd like to store metadata within. The folder must be writeable.",
"HeaderSelectChannelDownloadPath": "Select Channel Download Path",
"HeaderSelectChannelDownloadPathHelp": "Browse or enter the path to use for storing channel cache files. The folder must be writeable."
"HeaderSelectChannelDownloadPathHelp": "Browse or enter the path to use for storing channel cache files. The folder must be writeable.",
"OptionNewCollection": "New..."
}

View File

@ -234,6 +234,7 @@
"ButtonSelect": "Select",
"ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"ButtonAddToCollection": "Add to Collection",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java/C# converters through a donated license.",
"HeaderCredits": "Credits",
@ -452,6 +453,8 @@
"LabelPreferredDisplayLanguageHelp": "Translating Media Browser is an ongoing project and is not yet complete.",
"LabelReadHowYouCanContribute": "Read about how you can contribute.",
"HeaderNewCollection": "New Collection",
"HeaderAddToCollection": "Add to Collection",
"ButtonSubmit": "Submit",
"NewCollectionNameExample": "Example: Star Wars Collection",
"OptionSearchForInternetMetadata": "Search the internet for artwork and metadata",
"ButtonCreate": "Create",
@ -807,5 +810,6 @@
"LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.",
"LabelChannelDownloadAge": "Delete content after: (days)",
"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."
"ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog.",
"LabelSelectCollection": "Select collection:"
}

View File

@ -1,4 +1,5 @@
using MediaBrowser.Common.Events;
using System.IO;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
@ -142,6 +143,16 @@ namespace MediaBrowser.Server.Implementations.Session
SessionInfo = info
}, _logger);
if (!string.IsNullOrWhiteSpace(info.DeviceId))
{
var capabilities = GetSavedCapabilities(info.DeviceId);
if (capabilities != null)
{
ReportCapabilities(info, capabilities, false);
}
}
}
private async void OnSessionEnded(SessionInfo info)
@ -1148,6 +1159,13 @@ namespace MediaBrowser.Server.Implementations.Session
{
var session = GetSession(sessionId);
ReportCapabilities(session, capabilities, true);
}
private async void ReportCapabilities(SessionInfo session,
SessionCapabilities capabilities,
bool saveCapabilities)
{
session.PlayableMediaTypes = capabilities.PlayableMediaTypes;
session.SupportedCommands = capabilities.SupportedCommands;
@ -1168,6 +1186,59 @@ namespace MediaBrowser.Server.Implementations.Session
SessionInfo = session
}, _logger);
if (saveCapabilities)
{
await SaveCapabilities(session.DeviceId, capabilities).ConfigureAwait(false);
}
}
private string GetCapabilitiesFilePath(string deviceId)
{
var filename = deviceId.GetMD5().ToString("N") + ".json";
return Path.Combine(_configurationManager.ApplicationPaths.CachePath, "devices", filename);
}
private SessionCapabilities GetSavedCapabilities(string deviceId)
{
var path = GetCapabilitiesFilePath(deviceId);
try
{
return _jsonSerializer.DeserializeFromFile<SessionCapabilities>(path);
}
catch (DirectoryNotFoundException)
{
return null;
}
catch (FileNotFoundException)
{
return null;
}
catch (Exception ex)
{
_logger.ErrorException("Error getting saved capabilities", ex);
return null;
}
}
private readonly SemaphoreSlim _capabilitiesLock = new SemaphoreSlim(1, 1);
private async Task SaveCapabilities(string deviceId, SessionCapabilities capabilities)
{
var path = GetCapabilitiesFilePath(deviceId);
Directory.CreateDirectory(Path.GetDirectoryName(path));
await _capabilitiesLock.WaitAsync().ConfigureAwait(false);
try
{
_jsonSerializer.SerializeToFile(capabilities, path);
}
finally
{
_capabilitiesLock.Release();
}
}
public SessionInfoDto GetSessionInfoDto(SessionInfo session)

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
<version>3.0.393</version>
<version>3.0.394</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.393" />
<dependency id="MediaBrowser.Common" version="3.0.394" />
<dependency id="NLog" version="2.1.0" />
<dependency id="SimpleInjector" version="2.5.0" />
<dependency id="sharpcompress" version="0.10.2" />

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
<version>3.0.393</version>
<version>3.0.394</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
<version>3.0.393</version>
<version>3.0.394</version>
<title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.393" />
<dependency id="MediaBrowser.Common" version="3.0.394" />
</dependencies>
</metadata>
<files>