mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
Merge branch 'beta'
This commit is contained in:
commit
1e299549a8
@ -488,13 +488,17 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Logger.Info("Killing ffmpeg process for {0}", job.Path);
|
Logger.Info("Stopping ffmpeg process with q command for {0}", job.Path);
|
||||||
|
|
||||||
//process.Kill();
|
//process.Kill();
|
||||||
process.StandardInput.WriteLine("q");
|
process.StandardInput.WriteLine("q");
|
||||||
|
|
||||||
// Need to wait because killing is asynchronous
|
// Need to wait because killing is asynchronous
|
||||||
process.WaitForExit(5000);
|
if (!process.WaitForExit(5000))
|
||||||
|
{
|
||||||
|
Logger.Info("Killing ffmpeg process for {0}", job.Path);
|
||||||
|
process.Kill();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -79,7 +79,7 @@ namespace MediaBrowser.Api
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// To the optimized serialized result using cache.
|
/// To the optimized serialized result using cache.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -118,9 +118,6 @@ namespace MediaBrowser.Api
|
|||||||
return ResultFactory.GetStaticFileResult(Request, path);
|
return ResultFactory.GetStaticFileResult(Request, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly char[] _dashReplaceChars = { '?', '/', '&' };
|
|
||||||
private const char SlugChar = '-';
|
|
||||||
|
|
||||||
protected DtoOptions GetDtoOptions(object request)
|
protected DtoOptions GetDtoOptions(object request)
|
||||||
{
|
{
|
||||||
var options = new DtoOptions();
|
var options = new DtoOptions();
|
||||||
@ -154,152 +151,122 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
protected MusicArtist GetArtist(string name, ILibraryManager libraryManager)
|
protected MusicArtist GetArtist(string name, ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
return libraryManager.GetArtist(DeSlugArtistName(name, libraryManager));
|
if (name.IndexOf(BaseItem.SlugChar) != -1)
|
||||||
|
{
|
||||||
|
var result = libraryManager.GetItemList(new InternalItemsQuery
|
||||||
|
{
|
||||||
|
SlugName = name,
|
||||||
|
IncludeItemTypes = new[] { typeof(MusicArtist).Name }
|
||||||
|
|
||||||
|
}).OfType<MusicArtist>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return libraryManager.GetArtist(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Studio GetStudio(string name, ILibraryManager libraryManager)
|
protected Studio GetStudio(string name, ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
return libraryManager.GetStudio(DeSlugStudioName(name, libraryManager));
|
if (name.IndexOf(BaseItem.SlugChar) != -1)
|
||||||
|
{
|
||||||
|
var result = libraryManager.GetItemList(new InternalItemsQuery
|
||||||
|
{
|
||||||
|
SlugName = name,
|
||||||
|
IncludeItemTypes = new[] { typeof(Studio).Name }
|
||||||
|
|
||||||
|
}).OfType<Studio>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return libraryManager.GetStudio(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Genre GetGenre(string name, ILibraryManager libraryManager)
|
protected Genre GetGenre(string name, ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
return libraryManager.GetGenre(DeSlugGenreName(name, libraryManager));
|
if (name.IndexOf(BaseItem.SlugChar) != -1)
|
||||||
|
{
|
||||||
|
var result = libraryManager.GetItemList(new InternalItemsQuery
|
||||||
|
{
|
||||||
|
SlugName = name,
|
||||||
|
IncludeItemTypes = new[] { typeof(Genre).Name }
|
||||||
|
|
||||||
|
}).OfType<Genre>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return libraryManager.GetGenre(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MusicGenre GetMusicGenre(string name, ILibraryManager libraryManager)
|
protected MusicGenre GetMusicGenre(string name, ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
return libraryManager.GetMusicGenre(DeSlugGenreName(name, libraryManager));
|
if (name.IndexOf(BaseItem.SlugChar) != -1)
|
||||||
|
{
|
||||||
|
var result = libraryManager.GetItemList(new InternalItemsQuery
|
||||||
|
{
|
||||||
|
SlugName = name,
|
||||||
|
IncludeItemTypes = new[] { typeof(MusicGenre).Name }
|
||||||
|
|
||||||
|
}).OfType<MusicGenre>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return libraryManager.GetMusicGenre(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected GameGenre GetGameGenre(string name, ILibraryManager libraryManager)
|
protected GameGenre GetGameGenre(string name, ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
return libraryManager.GetGameGenre(DeSlugGameGenreName(name, libraryManager));
|
if (name.IndexOf(BaseItem.SlugChar) != -1)
|
||||||
|
{
|
||||||
|
var result = libraryManager.GetItemList(new InternalItemsQuery
|
||||||
|
{
|
||||||
|
SlugName = name,
|
||||||
|
IncludeItemTypes = new[] { typeof(GameGenre).Name }
|
||||||
|
|
||||||
|
}).OfType<GameGenre>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return libraryManager.GetGameGenre(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Person GetPerson(string name, ILibraryManager libraryManager)
|
protected Person GetPerson(string name, ILibraryManager libraryManager)
|
||||||
{
|
{
|
||||||
return libraryManager.GetPerson(DeSlugPersonName(name, libraryManager));
|
if (name.IndexOf(BaseItem.SlugChar) != -1)
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deslugs an artist name by finding the correct entry in the library
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="name"></param>
|
|
||||||
/// <param name="libraryManager"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
protected string DeSlugArtistName(string name, ILibraryManager libraryManager)
|
|
||||||
{
|
|
||||||
if (name.IndexOf(SlugChar) == -1)
|
|
||||||
{
|
{
|
||||||
return name;
|
var result = libraryManager.GetItemList(new InternalItemsQuery
|
||||||
|
{
|
||||||
|
SlugName = name,
|
||||||
|
IncludeItemTypes = new[] { typeof(Person).Name }
|
||||||
|
|
||||||
|
}).OfType<Person>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var items = libraryManager.GetItemList(new InternalItemsQuery
|
return libraryManager.GetPerson(name);
|
||||||
{
|
|
||||||
IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name }
|
|
||||||
});
|
|
||||||
|
|
||||||
return items
|
|
||||||
.OfType<IHasArtist>()
|
|
||||||
.SelectMany(i => i.AllArtists)
|
|
||||||
.DistinctNames()
|
|
||||||
.FirstOrDefault(i =>
|
|
||||||
{
|
|
||||||
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
|
|
||||||
|
|
||||||
return string.Equals(i, name, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
}) ?? name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deslugs a genre name by finding the correct entry in the library
|
|
||||||
/// </summary>
|
|
||||||
protected string DeSlugGenreName(string name, ILibraryManager libraryManager)
|
|
||||||
{
|
|
||||||
if (name.IndexOf(SlugChar) == -1)
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return libraryManager.RootFolder.GetRecursiveChildren()
|
|
||||||
.SelectMany(i => i.Genres)
|
|
||||||
.DistinctNames()
|
|
||||||
.FirstOrDefault(i =>
|
|
||||||
{
|
|
||||||
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
|
|
||||||
|
|
||||||
return string.Equals(i, name, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
}) ?? name;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected string DeSlugGameGenreName(string name, ILibraryManager libraryManager)
|
|
||||||
{
|
|
||||||
if (name.IndexOf(SlugChar) == -1)
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
var items = libraryManager.GetItemList(new InternalItemsQuery
|
|
||||||
{
|
|
||||||
IncludeItemTypes = new[] { typeof(Game).Name }
|
|
||||||
});
|
|
||||||
|
|
||||||
return items
|
|
||||||
.SelectMany(i => i.Genres)
|
|
||||||
.DistinctNames()
|
|
||||||
.FirstOrDefault(i =>
|
|
||||||
{
|
|
||||||
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
|
|
||||||
|
|
||||||
return string.Equals(i, name, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
}) ?? name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deslugs a studio name by finding the correct entry in the library
|
|
||||||
/// </summary>
|
|
||||||
protected string DeSlugStudioName(string name, ILibraryManager libraryManager)
|
|
||||||
{
|
|
||||||
if (name.IndexOf(SlugChar) == -1)
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return libraryManager.RootFolder
|
|
||||||
.GetRecursiveChildren()
|
|
||||||
.SelectMany(i => i.Studios)
|
|
||||||
.DistinctNames()
|
|
||||||
.FirstOrDefault(i =>
|
|
||||||
{
|
|
||||||
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
|
|
||||||
|
|
||||||
return string.Equals(i, name, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
}) ?? name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deslugs a person name by finding the correct entry in the library
|
|
||||||
/// </summary>
|
|
||||||
protected string DeSlugPersonName(string name, ILibraryManager libraryManager)
|
|
||||||
{
|
|
||||||
if (name.IndexOf(SlugChar) == -1)
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return libraryManager.GetPeopleNames(new InternalPeopleQuery())
|
|
||||||
.FirstOrDefault(i =>
|
|
||||||
{
|
|
||||||
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));
|
|
||||||
|
|
||||||
return string.Equals(i, name, StringComparison.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
}) ?? name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected string GetPathValue(int index)
|
protected string GetPathValue(int index)
|
||||||
|
@ -10,6 +10,7 @@ namespace MediaBrowser.Api
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Route("/Branding/Css", "GET", Summary = "Gets custom css")]
|
[Route("/Branding/Css", "GET", Summary = "Gets custom css")]
|
||||||
|
[Route("/Branding/Css.css", "GET", Summary = "Gets custom css")]
|
||||||
public class GetBrandingCss
|
public class GetBrandingCss
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -247,6 +247,12 @@ namespace MediaBrowser.Api
|
|||||||
hasBudget.Revenue = request.Revenue;
|
hasBudget.Revenue = request.Revenue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasOriginalTitle = item as IHasOriginalTitle;
|
||||||
|
if (hasOriginalTitle != null)
|
||||||
|
{
|
||||||
|
hasOriginalTitle.OriginalTitle = hasOriginalTitle.OriginalTitle;
|
||||||
|
}
|
||||||
|
|
||||||
var hasCriticRating = item as IHasCriticRating;
|
var hasCriticRating = item as IHasCriticRating;
|
||||||
if (hasCriticRating != null)
|
if (hasCriticRating != null)
|
||||||
{
|
{
|
||||||
|
@ -119,8 +119,6 @@ namespace MediaBrowser.Api.Library
|
|||||||
{
|
{
|
||||||
private readonly IFileOrganizationService _iFileOrganizationService;
|
private readonly IFileOrganizationService _iFileOrganizationService;
|
||||||
|
|
||||||
/// The _json serializer
|
|
||||||
/// </summary>
|
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
|
|
||||||
public FileOrganizationService(IFileOrganizationService iFileOrganizationService, IJsonSerializer jsonSerializer)
|
public FileOrganizationService(IFileOrganizationService iFileOrganizationService, IJsonSerializer jsonSerializer)
|
||||||
|
@ -1,89 +0,0 @@
|
|||||||
using MediaBrowser.Controller;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using CommonIO;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Library
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class LibraryHelpers
|
|
||||||
/// </summary>
|
|
||||||
public static class LibraryHelpers
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The shortcut file extension
|
|
||||||
/// </summary>
|
|
||||||
private const string ShortcutFileExtension = ".mblink";
|
|
||||||
/// <summary>
|
|
||||||
/// The shortcut file search
|
|
||||||
/// </summary>
|
|
||||||
private const string ShortcutFileSearch = "*" + ShortcutFileExtension;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes a shortcut from within a virtual folder, within either the default view or a user view
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fileSystem">The file system.</param>
|
|
||||||
/// <param name="virtualFolderName">Name of the virtual folder.</param>
|
|
||||||
/// <param name="mediaPath">The media path.</param>
|
|
||||||
/// <param name="appPaths">The app paths.</param>
|
|
||||||
/// <exception cref="System.IO.DirectoryNotFoundException">The media folder does not exist</exception>
|
|
||||||
public static void RemoveMediaPath(IFileSystem fileSystem, string virtualFolderName, string mediaPath, IServerApplicationPaths appPaths)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(mediaPath))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("mediaPath");
|
|
||||||
}
|
|
||||||
|
|
||||||
var rootFolderPath = appPaths.DefaultUserViewsPath;
|
|
||||||
var path = Path.Combine(rootFolderPath, virtualFolderName);
|
|
||||||
|
|
||||||
if (!fileSystem.DirectoryExists(path))
|
|
||||||
{
|
|
||||||
throw new DirectoryNotFoundException(string.Format("The media collection {0} does not exist", virtualFolderName));
|
|
||||||
}
|
|
||||||
|
|
||||||
var shortcut = Directory.EnumerateFiles(path, ShortcutFileSearch, SearchOption.AllDirectories).FirstOrDefault(f => fileSystem.ResolveShortcut(f).Equals(mediaPath, StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(shortcut))
|
|
||||||
{
|
|
||||||
fileSystem.DeleteFile(shortcut);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds an additional mediaPath to an existing virtual folder, within either the default view or a user view
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="fileSystem">The file system.</param>
|
|
||||||
/// <param name="virtualFolderName">Name of the virtual folder.</param>
|
|
||||||
/// <param name="path">The path.</param>
|
|
||||||
/// <param name="appPaths">The app paths.</param>
|
|
||||||
public static void AddMediaPath(IFileSystem fileSystem, string virtualFolderName, string path, IServerApplicationPaths appPaths)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(path))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException("path");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fileSystem.DirectoryExists(path))
|
|
||||||
{
|
|
||||||
throw new DirectoryNotFoundException("The path does not exist.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var rootFolderPath = appPaths.DefaultUserViewsPath;
|
|
||||||
var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName);
|
|
||||||
|
|
||||||
var shortcutFilename = fileSystem.GetFileNameWithoutExtension(path);
|
|
||||||
|
|
||||||
var lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension);
|
|
||||||
|
|
||||||
while (fileSystem.FileExists(lnk))
|
|
||||||
{
|
|
||||||
shortcutFilename += "1";
|
|
||||||
lnk = Path.Combine(virtualFolderPath, shortcutFilename + ShortcutFileExtension);
|
|
||||||
}
|
|
||||||
|
|
||||||
fileSystem.CreateShortcut(lnk, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -190,75 +190,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
public void Post(AddVirtualFolder request)
|
public void Post(AddVirtualFolder request)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(request.Name))
|
_libraryManager.AddVirtualFolder(request.Name, request.CollectionType, request.Paths, request.RefreshLibrary);
|
||||||
{
|
|
||||||
throw new ArgumentNullException("request");
|
|
||||||
}
|
|
||||||
|
|
||||||
var name = _fileSystem.GetValidFilename(request.Name);
|
|
||||||
|
|
||||||
var rootFolderPath = _appPaths.DefaultUserViewsPath;
|
|
||||||
|
|
||||||
var virtualFolderPath = Path.Combine(rootFolderPath, name);
|
|
||||||
while (_fileSystem.DirectoryExists(virtualFolderPath))
|
|
||||||
{
|
|
||||||
name += "1";
|
|
||||||
virtualFolderPath = Path.Combine(rootFolderPath, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.Paths != null)
|
|
||||||
{
|
|
||||||
var invalidpath = request.Paths.FirstOrDefault(i => !_fileSystem.DirectoryExists(i));
|
|
||||||
if (invalidpath != null)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("The specified path does not exist: " + invalidpath + ".");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_libraryMonitor.Stop();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_fileSystem.CreateDirectory(virtualFolderPath);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.CollectionType))
|
|
||||||
{
|
|
||||||
var path = Path.Combine(virtualFolderPath, request.CollectionType + ".collection");
|
|
||||||
|
|
||||||
using (File.Create(path))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.Paths != null)
|
|
||||||
{
|
|
||||||
foreach (var path in request.Paths)
|
|
||||||
{
|
|
||||||
LibraryHelpers.AddMediaPath(_fileSystem, name, path, _appPaths);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Task.Run(() =>
|
|
||||||
{
|
|
||||||
// No need to start if scanning the library because it will handle it
|
|
||||||
if (request.RefreshLibrary)
|
|
||||||
{
|
|
||||||
_libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Need to add a delay here or directory watchers may still pick up the changes
|
|
||||||
var task = Task.Delay(1000);
|
|
||||||
// Have to block here to allow exceptions to bubble
|
|
||||||
Task.WaitAll(task);
|
|
||||||
|
|
||||||
_libraryMonitor.Start();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -336,46 +268,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
/// <param name="request">The request.</param>
|
/// <param name="request">The request.</param>
|
||||||
public void Delete(RemoveVirtualFolder request)
|
public void Delete(RemoveVirtualFolder request)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(request.Name))
|
_libraryManager.RemoveVirtualFolder(request.Name, request.RefreshLibrary);
|
||||||
{
|
|
||||||
throw new ArgumentNullException("request");
|
|
||||||
}
|
|
||||||
|
|
||||||
var rootFolderPath = _appPaths.DefaultUserViewsPath;
|
|
||||||
|
|
||||||
var path = Path.Combine(rootFolderPath, request.Name);
|
|
||||||
|
|
||||||
if (!_fileSystem.DirectoryExists(path))
|
|
||||||
{
|
|
||||||
throw new DirectoryNotFoundException("The media folder does not exist");
|
|
||||||
}
|
|
||||||
|
|
||||||
_libraryMonitor.Stop();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_fileSystem.DeleteDirectory(path, true);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Task.Run(() =>
|
|
||||||
{
|
|
||||||
// No need to start if scanning the library because it will handle it
|
|
||||||
if (request.RefreshLibrary)
|
|
||||||
{
|
|
||||||
_libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Need to add a delay here or directory watchers may still pick up the changes
|
|
||||||
var task = Task.Delay(1000);
|
|
||||||
// Have to block here to allow exceptions to bubble
|
|
||||||
Task.WaitAll(task);
|
|
||||||
|
|
||||||
_libraryMonitor.Start();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -393,7 +286,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LibraryHelpers.AddMediaPath(_fileSystem, request.Name, request.Path, _appPaths);
|
_libraryManager.AddMediaPath(request.Name, request.Path);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@ -432,7 +325,7 @@ namespace MediaBrowser.Api.Library
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
LibraryHelpers.RemoveMediaPath(_fileSystem, request.Name, request.Path, _appPaths);
|
_libraryManager.RemoveMediaPath(request.Name, request.Path);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -254,6 +254,8 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? EnableImages { get; set; }
|
public bool? EnableImages { get; set; }
|
||||||
|
|
||||||
|
public bool EnableTotalRecordCount { get; set; }
|
||||||
|
|
||||||
[ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
public int? ImageTypeLimit { get; set; }
|
public int? ImageTypeLimit { get; set; }
|
||||||
|
|
||||||
@ -266,12 +268,24 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
/// <value>The fields.</value>
|
/// <value>The fields.</value>
|
||||||
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
[ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, CriticRatingSummary, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
|
||||||
public string Fields { get; set; }
|
public string Fields { get; set; }
|
||||||
|
|
||||||
|
public GetPrograms()
|
||||||
|
{
|
||||||
|
EnableTotalRecordCount = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route("/LiveTv/Programs/Recommended", "GET", Summary = "Gets available live tv epgs..")]
|
[Route("/LiveTv/Programs/Recommended", "GET", Summary = "Gets available live tv epgs..")]
|
||||||
[Authenticated]
|
[Authenticated]
|
||||||
public class GetRecommendedPrograms : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
|
public class GetRecommendedPrograms : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
|
||||||
{
|
{
|
||||||
|
public bool EnableTotalRecordCount { get; set; }
|
||||||
|
|
||||||
|
public GetRecommendedPrograms()
|
||||||
|
{
|
||||||
|
EnableTotalRecordCount = true;
|
||||||
|
}
|
||||||
|
|
||||||
[ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
[ApiMember(Name = "UserId", Description = "Optional filter by user id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET,POST")]
|
||||||
public string UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
|
|
||||||
@ -662,7 +676,8 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
{
|
{
|
||||||
ChannelIds = (request.ChannelIds ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToArray(),
|
ChannelIds = (request.ChannelIds ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToArray(),
|
||||||
UserId = request.UserId,
|
UserId = request.UserId,
|
||||||
HasAired = request.HasAired
|
HasAired = request.HasAired,
|
||||||
|
EnableTotalRecordCount = request.EnableTotalRecordCount
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.MinStartDate))
|
if (!string.IsNullOrEmpty(request.MinStartDate))
|
||||||
@ -709,7 +724,8 @@ namespace MediaBrowser.Api.LiveTv
|
|||||||
HasAired = request.HasAired,
|
HasAired = request.HasAired,
|
||||||
IsMovie = request.IsMovie,
|
IsMovie = request.IsMovie,
|
||||||
IsKids = request.IsKids,
|
IsKids = request.IsKids,
|
||||||
IsSports = request.IsSports
|
IsSports = request.IsSports,
|
||||||
|
EnableTotalRecordCount = request.EnableTotalRecordCount
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = await _liveTvManager.GetRecommendedPrograms(query, GetDtoOptions(request), CancellationToken.None).ConfigureAwait(false);
|
var result = await _liveTvManager.GetRecommendedPrograms(query, GetDtoOptions(request), CancellationToken.None).ConfigureAwait(false);
|
||||||
|
@ -129,7 +129,6 @@
|
|||||||
<Compile Include="ItemUpdateService.cs" />
|
<Compile Include="ItemUpdateService.cs" />
|
||||||
<Compile Include="Library\LibraryService.cs" />
|
<Compile Include="Library\LibraryService.cs" />
|
||||||
<Compile Include="Library\FileOrganizationService.cs" />
|
<Compile Include="Library\FileOrganizationService.cs" />
|
||||||
<Compile Include="Library\LibraryHelpers.cs" />
|
|
||||||
<Compile Include="Library\LibraryStructureService.cs" />
|
<Compile Include="Library\LibraryStructureService.cs" />
|
||||||
<Compile Include="LiveTv\LiveTvService.cs" />
|
<Compile Include="LiveTv\LiveTvService.cs" />
|
||||||
<Compile Include="LocalizationService.cs" />
|
<Compile Include="LocalizationService.cs" />
|
||||||
|
@ -144,7 +144,6 @@ namespace MediaBrowser.Api.Movies
|
|||||||
|
|
||||||
var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
|
var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
|
||||||
var movies = _libraryManager.GetItemList(query, parentIds);
|
var movies = _libraryManager.GetItemList(query, parentIds);
|
||||||
movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
|
|
||||||
|
|
||||||
var listEligibleForCategories = new List<BaseItem>();
|
var listEligibleForCategories = new List<BaseItem>();
|
||||||
var listEligibleForSuggestion = new List<BaseItem>();
|
var listEligibleForSuggestion = new List<BaseItem>();
|
||||||
@ -197,12 +196,6 @@ namespace MediaBrowser.Api.Movies
|
|||||||
|
|
||||||
var parentIds = new string[] { };
|
var parentIds = new string[] { };
|
||||||
var list = _libraryManager.GetItemList(query, parentIds)
|
var list = _libraryManager.GetItemList(query, parentIds)
|
||||||
.Where(i =>
|
|
||||||
{
|
|
||||||
// Strip out secondary versions
|
|
||||||
var v = i as Video;
|
|
||||||
return v != null && !v.PrimaryVersionId.HasValue;
|
|
||||||
})
|
|
||||||
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
.DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@ -247,7 +240,7 @@ namespace MediaBrowser.Api.Movies
|
|||||||
var recentlyPlayedMovies = allMoviesForCategories
|
var recentlyPlayedMovies = allMoviesForCategories
|
||||||
.Select(i =>
|
.Select(i =>
|
||||||
{
|
{
|
||||||
var userdata = _userDataRepository.GetUserData(user.Id, i.GetUserDataKey());
|
var userdata = _userDataRepository.GetUserData(user, i);
|
||||||
return new Tuple<BaseItem, bool, DateTime>(i, userdata.Played, userdata.LastPlayedDate ?? DateTime.MinValue);
|
return new Tuple<BaseItem, bool, DateTime>(i, userdata.Played, userdata.LastPlayedDate ?? DateTime.MinValue);
|
||||||
})
|
})
|
||||||
.Where(i => i.Item2)
|
.Where(i => i.Item2)
|
||||||
@ -260,7 +253,7 @@ namespace MediaBrowser.Api.Movies
|
|||||||
.Select(i =>
|
.Select(i =>
|
||||||
{
|
{
|
||||||
var score = 0;
|
var score = 0;
|
||||||
var userData = _userDataRepository.GetUserData(user.Id, i.GetUserDataKey());
|
var userData = _userDataRepository.GetUserData(user, i);
|
||||||
|
|
||||||
if (userData.IsFavorite)
|
if (userData.IsFavorite)
|
||||||
{
|
{
|
||||||
|
@ -288,9 +288,9 @@ namespace MediaBrowser.Api.Playback
|
|||||||
{
|
{
|
||||||
if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
|
||||||
return "h264_qsv";
|
return "h264_qsv";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "libx264";
|
return "libx264";
|
||||||
@ -460,7 +460,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
// Boost volume to 200% when downsampling from 6ch to 2ch
|
// Boost volume to 200% when downsampling from 6ch to 2ch
|
||||||
if (channels.HasValue && channels.Value <= 2)
|
if (channels.HasValue && channels.Value <= 2)
|
||||||
{
|
{
|
||||||
if (state.AudioStream != null && state.AudioStream.Channels.HasValue && state.AudioStream.Channels.Value > 5)
|
if (state.AudioStream != null && state.AudioStream.Channels.HasValue && state.AudioStream.Channels.Value > 5 && !ApiEntryPoint.Instance.GetEncodingOptions().DownMixAudioBoost.Equals(1))
|
||||||
{
|
{
|
||||||
volParam = ",volume=" + ApiEntryPoint.Instance.GetEncodingOptions().DownMixAudioBoost.ToString(UsCulture);
|
volParam = ",volume=" + ApiEntryPoint.Instance.GetEncodingOptions().DownMixAudioBoost.ToString(UsCulture);
|
||||||
}
|
}
|
||||||
@ -712,15 +712,16 @@ namespace MediaBrowser.Api.Playback
|
|||||||
inputChannels = null;
|
inputChannels = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int? resultChannels = null;
|
||||||
var codec = outputAudioCodec ?? string.Empty;
|
var codec = outputAudioCodec ?? string.Empty;
|
||||||
|
|
||||||
if (codec.IndexOf("wma", StringComparison.OrdinalIgnoreCase) != -1)
|
if (codec.IndexOf("wma", StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
{
|
{
|
||||||
// wmav2 currently only supports two channel output
|
// wmav2 currently only supports two channel output
|
||||||
return Math.Min(2, inputChannels ?? 2);
|
resultChannels = Math.Min(2, inputChannels ?? 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.MaxAudioChannels.HasValue)
|
else if (request.MaxAudioChannels.HasValue)
|
||||||
{
|
{
|
||||||
var channelLimit = codec.IndexOf("mp3", StringComparison.OrdinalIgnoreCase) != -1
|
var channelLimit = codec.IndexOf("mp3", StringComparison.OrdinalIgnoreCase) != -1
|
||||||
? 2
|
? 2
|
||||||
@ -732,10 +733,18 @@ namespace MediaBrowser.Api.Playback
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we don't have any media info then limit it to 5 to prevent encoding errors due to asking for too many channels
|
// If we don't have any media info then limit it to 5 to prevent encoding errors due to asking for too many channels
|
||||||
return Math.Min(request.MaxAudioChannels.Value, channelLimit);
|
resultChannels = Math.Min(request.MaxAudioChannels.Value, channelLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
return request.AudioChannels;
|
if (resultChannels.HasValue && !string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
if (request.TranscodingMaxAudioChannels.HasValue)
|
||||||
|
{
|
||||||
|
resultChannels = Math.Min(request.TranscodingMaxAudioChannels.Value, resultChannels.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultChannels ?? request.AudioChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -821,9 +830,14 @@ namespace MediaBrowser.Api.Playback
|
|||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected string GetVideoDecoder(StreamState state)
|
protected string GetVideoDecoder(StreamState state)
|
||||||
{
|
{
|
||||||
if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec))
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec))
|
||||||
|
{
|
||||||
|
if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
switch (state.MediaSource.VideoStream.Codec.ToLower())
|
switch (state.MediaSource.VideoStream.Codec.ToLower())
|
||||||
{
|
{
|
||||||
@ -831,7 +845,8 @@ namespace MediaBrowser.Api.Playback
|
|||||||
case "h264":
|
case "h264":
|
||||||
if (MediaEncoder.SupportsDecoder("h264_qsv"))
|
if (MediaEncoder.SupportsDecoder("h264_qsv"))
|
||||||
{
|
{
|
||||||
return "-c:v h264_qsv ";
|
// Seeing stalls and failures with decoding. Not worth it compared to encoding.
|
||||||
|
//return "-c:v h264_qsv ";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "mpeg2video":
|
case "mpeg2video":
|
||||||
@ -947,6 +962,21 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false);
|
await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (state.VideoRequest != null && !string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
var auth = AuthorizationContext.GetAuthorizationInfo(Request);
|
||||||
|
if (!string.IsNullOrWhiteSpace(auth.UserId))
|
||||||
|
{
|
||||||
|
var user = UserManager.GetUserById(auth.UserId);
|
||||||
|
if (!user.Policy.EnableVideoPlaybackTranscoding)
|
||||||
|
{
|
||||||
|
ApiEntryPoint.Instance.OnTranscodeFailedToStart(outputPath, TranscodingJobType, state);
|
||||||
|
|
||||||
|
throw new ArgumentException("User does not have access to video transcoding");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var transcodingId = Guid.NewGuid().ToString("N");
|
var transcodingId = Guid.NewGuid().ToString("N");
|
||||||
var commandLineArgs = GetCommandLineArguments(outputPath, state, true);
|
var commandLineArgs = GetCommandLineArguments(outputPath, state, true);
|
||||||
|
|
||||||
@ -1033,7 +1063,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
process.BeginOutputReadLine();
|
process.BeginOutputReadLine();
|
||||||
|
|
||||||
// Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
|
// Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
|
||||||
StartStreamingLog(transcodingJob, state, process.StandardError.BaseStream, state.LogFileStream);
|
Task.Run(() => StartStreamingLog(transcodingJob, state, process.StandardError.BaseStream, state.LogFileStream));
|
||||||
|
|
||||||
// Wait for the file to exist before proceeeding
|
// Wait for the file to exist before proceeeding
|
||||||
while (!FileSystem.FileExists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited)
|
while (!FileSystem.FileExists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited)
|
||||||
@ -1076,7 +1106,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void StartStreamingLog(TranscodingJob transcodingJob, StreamState state, Stream source, Stream target)
|
private async Task StartStreamingLog(TranscodingJob transcodingJob, StreamState state, Stream source, Stream target)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -1498,6 +1528,10 @@ namespace MediaBrowser.Api.Playback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (i == 26)
|
||||||
|
{
|
||||||
|
request.TranscodingMaxAudioChannels = int.Parse(val, UsCulture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1804,6 +1838,15 @@ namespace MediaBrowser.Api.Playback
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
if (videoStream.IsAVC.HasValue && !videoStream.IsAVC.Value)
|
||||||
|
{
|
||||||
|
Logger.Debug("Cannot stream copy video. Stream is marked as not AVC");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Source and target codecs must match
|
// Source and target codecs must match
|
||||||
if (!string.Equals(request.VideoCodec, videoStream.Codec, StringComparison.OrdinalIgnoreCase))
|
if (!string.Equals(request.VideoCodec, videoStream.Codec, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
@ -2222,9 +2265,10 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
if (state.VideoRequest != null)
|
if (state.VideoRequest != null)
|
||||||
{
|
{
|
||||||
|
// Important: If this is ever re-enabled, make sure not to use it with wtv because it breaks seeking
|
||||||
if (string.Equals(state.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase) && state.VideoRequest.CopyTimestamps)
|
if (string.Equals(state.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase) && state.VideoRequest.CopyTimestamps)
|
||||||
{
|
{
|
||||||
inputModifier += " -noaccurate_seek";
|
//inputModifier += " -noaccurate_seek";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,17 +289,5 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
|
|
||||||
return isLiveStream;
|
return isLiveStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool CanStreamCopyAudio(StreamState state, List<string> supportedAudioCodecs)
|
|
||||||
{
|
|
||||||
var isLiveStream = IsLiveStream(state);
|
|
||||||
|
|
||||||
if (!isLiveStream)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CanStreamCopyAudio(state, supportedAudioCodecs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -500,18 +500,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
|
return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary<string, string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsLiveStream(StreamState state)
|
|
||||||
{
|
|
||||||
var isLiveStream = (state.RunTimeTicks ?? 0) == 0;
|
|
||||||
|
|
||||||
if (state.VideoRequest.ForceLiveStream)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return isLiveStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetMasterPlaylistFileText(StreamState state, int totalBitrate)
|
private string GetMasterPlaylistFileText(StreamState state, int totalBitrate)
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
@ -830,11 +818,10 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
{
|
{
|
||||||
if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize);
|
|
||||||
args += " -bsf:v h264_mp4toannexb";
|
args += " -bsf:v h264_mp4toannexb";
|
||||||
}
|
}
|
||||||
|
|
||||||
args += " -flags -global_header -sc_threshold 0";
|
args += " -flags -global_header";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -859,7 +846,12 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
args += GetGraphicalSubtitleParam(state, codec);
|
args += GetGraphicalSubtitleParam(state, codec);
|
||||||
}
|
}
|
||||||
|
|
||||||
args += " -flags -global_header -sc_threshold 0";
|
args += " -flags -global_header";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EnableCopyTs(state) && args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1)
|
||||||
|
{
|
||||||
|
args += " -copyts";
|
||||||
}
|
}
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
@ -867,7 +859,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
|
|
||||||
private bool EnableCopyTs(StreamState state)
|
private bool EnableCopyTs(StreamState state)
|
||||||
{
|
{
|
||||||
return state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
|
//return state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
|
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
|
||||||
@ -889,24 +882,28 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
|
|
||||||
var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty;
|
var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty;
|
||||||
|
|
||||||
//var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state);
|
var enableGenericSegmenter = false;
|
||||||
|
|
||||||
//return string.Format("{0} {11} {1}{10} -map_metadata -1 -threads {2} {3} {4} {5} -f segment -segment_time {6} -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
|
if (enableGenericSegmenter)
|
||||||
// inputModifier,
|
{
|
||||||
// GetInputArgument(state),
|
var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state);
|
||||||
// threads,
|
|
||||||
// mapArgs,
|
|
||||||
// GetVideoArguments(state),
|
|
||||||
// GetAudioArguments(state),
|
|
||||||
// state.SegmentLength.ToString(UsCulture),
|
|
||||||
// startNumberParam,
|
|
||||||
// outputPath,
|
|
||||||
// outputTsArg,
|
|
||||||
// slowSeekParam,
|
|
||||||
// toTimeParam
|
|
||||||
// ).Trim();
|
|
||||||
|
|
||||||
return string.Format("{0}{11} {1} -map_metadata -1 -threads {2} {3} {4}{5} {6} -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"",
|
return string.Format("{0} {10} {1} -map_metadata -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"",
|
||||||
|
inputModifier,
|
||||||
|
GetInputArgument(state),
|
||||||
|
threads,
|
||||||
|
mapArgs,
|
||||||
|
GetVideoArguments(state),
|
||||||
|
GetAudioArguments(state),
|
||||||
|
state.SegmentLength.ToString(UsCulture),
|
||||||
|
startNumberParam,
|
||||||
|
outputPath,
|
||||||
|
outputTsArg,
|
||||||
|
toTimeParam
|
||||||
|
).Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Format("{0}{11} {1} -map_metadata -1 -threads {2} {3} {4}{5} {6} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"",
|
||||||
inputModifier,
|
inputModifier,
|
||||||
GetInputArgument(state),
|
GetInputArgument(state),
|
||||||
threads,
|
threads,
|
||||||
@ -946,10 +943,10 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
{
|
{
|
||||||
var isLiveStream = IsLiveStream(state);
|
var isLiveStream = IsLiveStream(state);
|
||||||
|
|
||||||
if (!isLiveStream)
|
//if (!isLiveStream && Request.QueryString["AllowCustomSegmenting"] != "true")
|
||||||
{
|
//{
|
||||||
return false;
|
// return false;
|
||||||
}
|
//}
|
||||||
|
|
||||||
return base.CanStreamCopyVideo(state);
|
return base.CanStreamCopyVideo(state);
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,6 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
// if h264_mp4toannexb is ever added, do not use it for live tv
|
// if h264_mp4toannexb is ever added, do not use it for live tv
|
||||||
if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize);
|
|
||||||
args += " -bsf:v h264_mp4toannexb";
|
args += " -bsf:v h264_mp4toannexb";
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
|
@ -15,6 +15,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
|
|
||||||
namespace MediaBrowser.Api.Playback
|
namespace MediaBrowser.Api.Playback
|
||||||
{
|
{
|
||||||
@ -66,14 +67,16 @@ namespace MediaBrowser.Api.Playback
|
|||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly INetworkManager _networkManager;
|
private readonly INetworkManager _networkManager;
|
||||||
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
|
|
||||||
public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager)
|
public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager, IMediaEncoder mediaEncoder)
|
||||||
{
|
{
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
_deviceManager = deviceManager;
|
_deviceManager = deviceManager;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
_config = config;
|
_config = config;
|
||||||
_networkManager = networkManager;
|
_networkManager = networkManager;
|
||||||
|
_mediaEncoder = mediaEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Get(GetBitrateTestBytes request)
|
public object Get(GetBitrateTestBytes request)
|
||||||
@ -241,7 +244,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
int? subtitleStreamIndex,
|
int? subtitleStreamIndex,
|
||||||
string playSessionId)
|
string playSessionId)
|
||||||
{
|
{
|
||||||
var streamBuilder = new StreamBuilder(Logger);
|
var streamBuilder = new StreamBuilder(_mediaEncoder, Logger);
|
||||||
|
|
||||||
var options = new VideoOptions
|
var options = new VideoOptions
|
||||||
{
|
{
|
||||||
|
@ -141,7 +141,6 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
{
|
{
|
||||||
if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize);
|
|
||||||
args += " -bsf:v h264_mp4toannexb";
|
args += " -bsf:v h264_mp4toannexb";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,9 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
[ApiMember(Name = "MaxAudioChannels", Description = "Optional. Specify a maximum number of audio channels to encode to, e.g. 2", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "MaxAudioChannels", Description = "Optional. Specify a maximum number of audio channels to encode to, e.g. 2", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
|
||||||
public int? MaxAudioChannels { get; set; }
|
public int? MaxAudioChannels { get; set; }
|
||||||
|
|
||||||
|
public int? TranscodingMaxAudioChannels { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the audio sample rate.
|
/// Gets or sets the audio sample rate.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -69,7 +69,19 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
public List<string> PlayableStreamFileNames { get; set; }
|
public List<string> PlayableStreamFileNames { get; set; }
|
||||||
|
|
||||||
public int SegmentLength = 3;
|
public int SegmentLength
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int HlsListSize
|
public int HlsListSize
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -429,7 +429,7 @@ namespace MediaBrowser.Api
|
|||||||
if (request.IsMissing.HasValue)
|
if (request.IsMissing.HasValue)
|
||||||
{
|
{
|
||||||
var val = request.IsMissing.Value;
|
var val = request.IsMissing.Value;
|
||||||
items = items.Where(i => i.IsMissingSeason == val);
|
items = items.Where(i => (i.IsMissingSeason ?? false) == val);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.IsVirtualUnaired.HasValue)
|
if (request.IsVirtualUnaired.HasValue)
|
||||||
@ -508,8 +508,7 @@ namespace MediaBrowser.Api
|
|||||||
returnItems = UserViewBuilder.FilterForAdjacency(returnItems, request.AdjacentTo);
|
returnItems = UserViewBuilder.FilterForAdjacency(returnItems, request.AdjacentTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
var returnList = _libraryManager.ReplaceVideosWithPrimaryVersions(returnItems)
|
var returnList = returnItems.ToList();
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var pagedItems = ApplyPaging(returnList, request.StartIndex, request.Limit);
|
var pagedItems = ApplyPaging(returnList, request.StartIndex, request.Limit);
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
{
|
{
|
||||||
items = items.Where(i =>
|
items = items.Where(i =>
|
||||||
{
|
{
|
||||||
var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey());
|
var userdata = UserDataRepository.GetUserData(user, i);
|
||||||
|
|
||||||
return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value;
|
return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value;
|
||||||
});
|
});
|
||||||
@ -284,7 +284,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
{
|
{
|
||||||
items = items.Where(i =>
|
items = items.Where(i =>
|
||||||
{
|
{
|
||||||
var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey());
|
var userdata = UserDataRepository.GetUserData(user, i);
|
||||||
|
|
||||||
return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value;
|
return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value;
|
||||||
});
|
});
|
||||||
@ -294,7 +294,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
{
|
{
|
||||||
items = items.Where(i =>
|
items = items.Where(i =>
|
||||||
{
|
{
|
||||||
var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey());
|
var userdata = UserDataRepository.GetUserData(user, i);
|
||||||
|
|
||||||
var likes = userdata.Likes ?? false;
|
var likes = userdata.Likes ?? false;
|
||||||
var favorite = userdata.IsFavorite;
|
var favorite = userdata.IsFavorite;
|
||||||
@ -307,7 +307,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
{
|
{
|
||||||
items = items.Where(i =>
|
items = items.Where(i =>
|
||||||
{
|
{
|
||||||
var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey());
|
var userdata = UserDataRepository.GetUserData(user, i);
|
||||||
|
|
||||||
return userdata != null && userdata.IsFavorite;
|
return userdata != null && userdata.IsFavorite;
|
||||||
});
|
});
|
||||||
|
@ -12,6 +12,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
protected BaseItemsRequest()
|
protected BaseItemsRequest()
|
||||||
{
|
{
|
||||||
EnableImages = true;
|
EnableImages = true;
|
||||||
|
EnableTotalRecordCount = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -104,7 +105,9 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
[ApiMember(Name = "IsInBoxSet", Description = "Optional filter by items that are in boxsets, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
[ApiMember(Name = "IsInBoxSet", Description = "Optional filter by items that are in boxsets, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
|
||||||
public bool? IsInBoxSet { get; set; }
|
public bool? IsInBoxSet { get; set; }
|
||||||
|
|
||||||
|
public bool EnableTotalRecordCount { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Skips over a given number of items within the results. Use for paging.
|
/// Skips over a given number of items within the results. Use for paging.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -230,7 +230,8 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
ParentId = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId),
|
ParentId = string.IsNullOrWhiteSpace(request.ParentId) ? (Guid?)null : new Guid(request.ParentId),
|
||||||
ParentIndexNumber = request.ParentIndexNumber,
|
ParentIndexNumber = request.ParentIndexNumber,
|
||||||
AiredDuringSeason = request.AiredDuringSeason,
|
AiredDuringSeason = request.AiredDuringSeason,
|
||||||
AlbumArtistStartsWithOrGreater = request.AlbumArtistStartsWithOrGreater
|
AlbumArtistStartsWithOrGreater = request.AlbumArtistStartsWithOrGreater,
|
||||||
|
EnableTotalRecordCount = request.EnableTotalRecordCount
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(request.Ids))
|
if (!string.IsNullOrWhiteSpace(request.Ids))
|
||||||
|
@ -519,10 +519,8 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
var item = string.IsNullOrEmpty(itemId) ? user.RootFolder : _libraryManager.GetItemById(itemId);
|
var item = string.IsNullOrEmpty(itemId) ? user.RootFolder : _libraryManager.GetItemById(itemId);
|
||||||
|
|
||||||
var key = item.GetUserDataKey();
|
|
||||||
|
|
||||||
// Get the user data for this item
|
// Get the user data for this item
|
||||||
var data = _userDataRepository.GetUserData(user.Id, key);
|
var data = _userDataRepository.GetUserData(user, item);
|
||||||
|
|
||||||
// Set favorite status
|
// Set favorite status
|
||||||
data.IsFavorite = isFavorite;
|
data.IsFavorite = isFavorite;
|
||||||
@ -567,10 +565,8 @@ namespace MediaBrowser.Api.UserLibrary
|
|||||||
|
|
||||||
var item = string.IsNullOrEmpty(itemId) ? user.RootFolder : _libraryManager.GetItemById(itemId);
|
var item = string.IsNullOrEmpty(itemId) ? user.RootFolder : _libraryManager.GetItemById(itemId);
|
||||||
|
|
||||||
var key = item.GetUserDataKey();
|
|
||||||
|
|
||||||
// Get the user data for this item
|
// Get the user data for this item
|
||||||
var data = _userDataRepository.GetUserData(user.Id, key);
|
var data = _userDataRepository.GetUserData(user, item);
|
||||||
|
|
||||||
data.Likes = likes;
|
data.Likes = likes;
|
||||||
|
|
||||||
|
@ -130,6 +130,7 @@ namespace MediaBrowser.Api
|
|||||||
var items = request.Ids.Split(',')
|
var items = request.Ids.Split(',')
|
||||||
.Select(i => new Guid(i))
|
.Select(i => new Guid(i))
|
||||||
.Select(i => _libraryManager.GetItemById(i))
|
.Select(i => _libraryManager.GetItemById(i))
|
||||||
|
.OfType<Video>()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (items.Count < 2)
|
if (items.Count < 2)
|
||||||
@ -137,14 +138,7 @@ namespace MediaBrowser.Api
|
|||||||
throw new ArgumentException("Please supply at least two videos to merge.");
|
throw new ArgumentException("Please supply at least two videos to merge.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (items.Any(i => !(i is Video)))
|
var videosWithVersions = items.Where(i => i.MediaSourceCount > 1)
|
||||||
{
|
|
||||||
throw new ArgumentException("Only videos can be grouped together.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var videos = items.Cast<Video>().ToList();
|
|
||||||
|
|
||||||
var videosWithVersions = videos.Where(i => i.MediaSourceCount > 1)
|
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (videosWithVersions.Count > 1)
|
if (videosWithVersions.Count > 1)
|
||||||
@ -156,7 +150,7 @@ namespace MediaBrowser.Api
|
|||||||
|
|
||||||
if (primaryVersion == null)
|
if (primaryVersion == null)
|
||||||
{
|
{
|
||||||
primaryVersion = videos.OrderBy(i =>
|
primaryVersion = items.OrderBy(i =>
|
||||||
{
|
{
|
||||||
if (i.Video3DFormat.HasValue)
|
if (i.Video3DFormat.HasValue)
|
||||||
{
|
{
|
||||||
@ -179,9 +173,9 @@ namespace MediaBrowser.Api
|
|||||||
}).First();
|
}).First();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var item in videos.Where(i => i.Id != primaryVersion.Id))
|
foreach (var item in items.Where(i => i.Id != primaryVersion.Id))
|
||||||
{
|
{
|
||||||
item.PrimaryVersionId = primaryVersion.Id;
|
item.PrimaryVersionId = primaryVersion.Id.ToString("N");
|
||||||
|
|
||||||
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
await item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
@ -54,8 +54,9 @@
|
|||||||
<Reference Include="MoreLinq">
|
<Reference Include="MoreLinq">
|
||||||
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
<HintPath>..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="NLog">
|
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\NLog.4.2.3\lib\net45\NLog.dll</HintPath>
|
<HintPath>..\packages\NLog.4.3.1\lib\net45\NLog.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Patterns.Logging">
|
<Reference Include="Patterns.Logging">
|
||||||
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
|
||||||
@ -64,8 +65,9 @@
|
|||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
<HintPath>..\ThirdParty\SharpCompress\SharpCompress.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SimpleInjector">
|
<Reference Include="SimpleInjector, Version=3.1.3.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\SimpleInjector.3.1.2\lib\net45\SimpleInjector.dll</HintPath>
|
<HintPath>..\packages\SimpleInjector.3.1.3\lib\net45\SimpleInjector.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Configuration" />
|
<Reference Include="System.Configuration" />
|
||||||
|
@ -311,7 +311,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
|
|||||||
|
|
||||||
trigger.Triggered -= trigger_Triggered;
|
trigger.Triggered -= trigger_Triggered;
|
||||||
trigger.Triggered += trigger_Triggered;
|
trigger.Triggered += trigger_Triggered;
|
||||||
trigger.Start(LastExecutionResult, isApplicationStartup);
|
trigger.Start(LastExecutionResult, Logger, Name, isApplicationStartup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,7 +339,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
|
|||||||
|
|
||||||
await Task.Delay(1000).ConfigureAwait(false);
|
await Task.Delay(1000).ConfigureAwait(false);
|
||||||
|
|
||||||
trigger.Start(LastExecutionResult, false);
|
trigger.Start(LastExecutionResult, Logger, Name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task _currentTask;
|
private Task _currentTask;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<packages>
|
<packages>
|
||||||
<package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
|
<package id="CommonIO" version="1.0.0.9" targetFramework="net45" />
|
||||||
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
<package id="morelinq" version="1.4.0" targetFramework="net45" />
|
||||||
<package id="NLog" version="4.2.3" targetFramework="net45" />
|
<package id="NLog" version="4.3.1" targetFramework="net45" />
|
||||||
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
|
||||||
<package id="SimpleInjector" version="3.1.2" targetFramework="net45" />
|
<package id="SimpleInjector" version="3.1.3" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -1,7 +1,9 @@
|
|||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.ScheduledTasks
|
namespace MediaBrowser.Common.ScheduledTasks
|
||||||
{
|
{
|
||||||
@ -35,7 +37,7 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lastResult">The last result.</param>
|
/// <param name="lastResult">The last result.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public void Start(TaskResult lastResult, bool isApplicationStartup)
|
public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
DisposeTimer();
|
DisposeTimer();
|
||||||
|
|
||||||
@ -44,7 +46,11 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
var triggerDate = now.TimeOfDay > TimeOfDay ? now.Date.AddDays(1) : now.Date;
|
var triggerDate = now.TimeOfDay > TimeOfDay ? now.Date.AddDays(1) : now.Date;
|
||||||
triggerDate = triggerDate.Add(TimeOfDay);
|
triggerDate = triggerDate.Add(TimeOfDay);
|
||||||
|
|
||||||
Timer = new Timer(state => OnTriggered(), null, triggerDate - now, TimeSpan.FromMilliseconds(-1));
|
var dueTime = triggerDate - now;
|
||||||
|
|
||||||
|
logger.Info("Daily trigger for {0} set to fire at {1}, which is {2} minutes from now.", taskName, triggerDate.ToString(), dueTime.TotalMinutes.ToString(CultureInfo.InvariantCulture));
|
||||||
|
|
||||||
|
Timer = new Timer(state => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
using System;
|
using System;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.ScheduledTasks
|
namespace MediaBrowser.Common.ScheduledTasks
|
||||||
{
|
{
|
||||||
@ -19,7 +20,7 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lastResult">The last result.</param>
|
/// <param name="lastResult">The last result.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
void Start(TaskResult lastResult, bool isApplicationStartup);
|
void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stops waiting for the trigger action
|
/// Stops waiting for the trigger action
|
||||||
|
@ -3,6 +3,7 @@ using MediaBrowser.Model.Tasks;
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.ScheduledTasks
|
namespace MediaBrowser.Common.ScheduledTasks
|
||||||
{
|
{
|
||||||
@ -38,7 +39,7 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lastResult">The last result.</param>
|
/// <param name="lastResult">The last result.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public void Start(TaskResult lastResult, bool isApplicationStartup)
|
public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
DisposeTimer();
|
DisposeTimer();
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.ScheduledTasks
|
namespace MediaBrowser.Common.ScheduledTasks
|
||||||
{
|
{
|
||||||
@ -30,7 +31,7 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lastResult">The last result.</param>
|
/// <param name="lastResult">The last result.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public async void Start(TaskResult lastResult, bool isApplicationStartup)
|
public async void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
if (isApplicationStartup)
|
if (isApplicationStartup)
|
||||||
{
|
{
|
||||||
|
@ -3,6 +3,7 @@ using MediaBrowser.Model.Tasks;
|
|||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.ScheduledTasks
|
namespace MediaBrowser.Common.ScheduledTasks
|
||||||
{
|
{
|
||||||
@ -30,7 +31,7 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lastResult">The last result.</param>
|
/// <param name="lastResult">The last result.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public void Start(TaskResult lastResult, bool isApplicationStartup)
|
public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
switch (SystemEvent)
|
switch (SystemEvent)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Tasks;
|
using MediaBrowser.Model.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.ScheduledTasks
|
namespace MediaBrowser.Common.ScheduledTasks
|
||||||
@ -41,7 +42,7 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="lastResult">The last result.</param>
|
/// <param name="lastResult">The last result.</param>
|
||||||
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
/// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param>
|
||||||
public void Start(TaskResult lastResult, bool isApplicationStartup)
|
public void Start(TaskResult lastResult, ILogger logger, string taskName, bool isApplicationStartup)
|
||||||
{
|
{
|
||||||
DisposeTimer();
|
DisposeTimer();
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
IArchivable
|
IArchivable
|
||||||
{
|
{
|
||||||
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
|
||||||
|
|
||||||
public long? Size { get; set; }
|
public long? Size { get; set; }
|
||||||
public string Container { get; set; }
|
public string Container { get; set; }
|
||||||
public int? TotalBitrate { get; set; }
|
public int? TotalBitrate { get; set; }
|
||||||
@ -40,12 +40,6 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
|
|
||||||
public List<string> AlbumArtists { get; set; }
|
public List<string> AlbumArtists { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the album.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The album.</value>
|
|
||||||
public string Album { get; set; }
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsThemeMedia
|
public bool IsThemeMedia
|
||||||
{
|
{
|
||||||
@ -150,12 +144,10 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
|
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
|
if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
|
||||||
{
|
{
|
||||||
var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty;
|
var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty;
|
||||||
@ -165,7 +157,7 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
{
|
{
|
||||||
songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey;
|
songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey;
|
||||||
}
|
}
|
||||||
songKey+= Name;
|
songKey += Name;
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(Album))
|
if (!string.IsNullOrWhiteSpace(Album))
|
||||||
{
|
{
|
||||||
@ -178,25 +170,25 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
songKey = albumArtist + "-" + songKey;
|
songKey = albumArtist + "-" + songKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
return songKey;
|
list.Insert(0, songKey);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
var parent = AlbumEntity;
|
|
||||||
|
|
||||||
if (parent != null)
|
|
||||||
{
|
{
|
||||||
var parentKey = parent.GetUserDataKey();
|
var parent = AlbumEntity;
|
||||||
|
|
||||||
if (IndexNumber.HasValue)
|
if (parent != null && IndexNumber.HasValue)
|
||||||
{
|
{
|
||||||
var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
|
list.InsertRange(0, parent.GetUserDataKeys().Select(i =>
|
||||||
+ IndexNumber.Value.ToString("0000 - ");
|
{
|
||||||
|
var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
|
||||||
|
+ IndexNumber.Value.ToString("0000 - ");
|
||||||
|
|
||||||
return parentKey + songKey;
|
return i + songKey;
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.CreateUserDataKey();
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override UnratedItem GetBlockUnratedType()
|
public override UnratedItem GetBlockUnratedType()
|
||||||
|
@ -48,6 +48,15 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsCumulativeRunTimeTicks
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public List<string> AllArtists
|
public List<string> AllArtists
|
||||||
{
|
{
|
||||||
@ -96,36 +105,34 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
|
|
||||||
public List<string> Artists { get; set; }
|
public List<string> Artists { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
var id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(id))
|
|
||||||
{
|
|
||||||
return "MusicAlbum-MusicBrainzReleaseGroup-" + id;
|
|
||||||
}
|
|
||||||
|
|
||||||
id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(id))
|
|
||||||
{
|
|
||||||
return "MusicAlbum-Musicbrainz-" + id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
|
if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
|
||||||
{
|
{
|
||||||
var albumArtist = AlbumArtist;
|
var albumArtist = AlbumArtist;
|
||||||
if (!string.IsNullOrWhiteSpace(albumArtist))
|
if (!string.IsNullOrWhiteSpace(albumArtist))
|
||||||
{
|
{
|
||||||
return albumArtist + "-" + Name;
|
list.Insert(0, albumArtist + "-" + Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.CreateUserDataKey();
|
var id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(id))
|
||||||
|
{
|
||||||
|
list.Insert(0, "MusicAlbum-Musicbrainz-" + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(id))
|
||||||
|
{
|
||||||
|
list.Insert(0, "MusicAlbum-MusicBrainzReleaseGroup-" + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||||
|
@ -17,7 +17,12 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class MusicArtist : Folder, IMetadataContainer, IItemByName, IHasMusicGenres, IHasDualAccess, IHasProductionLocations, IHasLookupInfo<ArtistInfo>
|
public class MusicArtist : Folder, IMetadataContainer, IItemByName, IHasMusicGenres, IHasDualAccess, IHasProductionLocations, IHasLookupInfo<ArtistInfo>
|
||||||
{
|
{
|
||||||
public bool IsAccessedByName { get; set; }
|
[IgnoreDataMember]
|
||||||
|
public bool IsAccessedByName
|
||||||
|
{
|
||||||
|
get { return ParentId == Guid.Empty; }
|
||||||
|
}
|
||||||
|
|
||||||
public List<string> ProductionLocations { get; set; }
|
public List<string> ProductionLocations { get; set; }
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
@ -29,6 +34,15 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsCumulativeRunTimeTicks
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsAddingToPlaylist
|
public override bool SupportsAddingToPlaylist
|
||||||
{
|
{
|
||||||
@ -40,6 +54,40 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
return !IsAccessedByName;
|
return !IsAccessedByName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
var itemByNameFilter = GetItemFilter();
|
||||||
|
|
||||||
|
if (query.User != null)
|
||||||
|
{
|
||||||
|
return query.User.RootFolder
|
||||||
|
.GetRecursiveChildren(query.User, i =>
|
||||||
|
{
|
||||||
|
if (query.IsFolder.HasValue)
|
||||||
|
{
|
||||||
|
if (query.IsFolder.Value != i.IsFolder)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return itemByNameFilter(i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return LibraryManager.RootFolder
|
||||||
|
.GetRecursiveChildren(i =>
|
||||||
|
{
|
||||||
|
if (query.IsFolder.HasValue)
|
||||||
|
{
|
||||||
|
if (query.IsFolder.Value != i.IsFolder)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return itemByNameFilter(i);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
protected override IEnumerable<BaseItem> ActualChildren
|
protected override IEnumerable<BaseItem> ActualChildren
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -80,13 +128,12 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
ProductionLocations = new List<string>();
|
ProductionLocations = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
return GetUserDataKey(this);
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
|
list.InsertRange(0, GetUserDataKeys(this));
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -121,16 +168,18 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item.</param>
|
/// <param name="item">The item.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
private static string GetUserDataKey(MusicArtist item)
|
private static List<string> GetUserDataKeys(MusicArtist item)
|
||||||
{
|
{
|
||||||
|
var list = new List<string>();
|
||||||
var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
|
var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(id))
|
if (!string.IsNullOrEmpty(id))
|
||||||
{
|
{
|
||||||
return "Artist-Musicbrainz-" + id;
|
list.Add("Artist-Musicbrainz-" + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Artist-" + item.Name;
|
list.Add("Artist-" + item.Name);
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||||
|
@ -10,13 +10,12 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class MusicGenre : BaseItem, IItemByName
|
public class MusicGenre : BaseItem, IItemByName
|
||||||
{
|
{
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
return "MusicGenre-" + Name;
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
|
list.Insert(0, "MusicGenre-" + Name);
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
@ -80,5 +79,13 @@ namespace MediaBrowser.Controller.Entities.Audio
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
query.Genres = new[] { Name };
|
||||||
|
query.IncludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
|
||||||
|
|
||||||
|
return LibraryManager.GetItemList(query);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,9 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
ImageInfos = new List<ItemImageInfo>();
|
ImageInfos = new List<ItemImageInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static readonly char[] SlugReplaceChars = { '?', '/', '&' };
|
||||||
|
public static char SlugChar = '-';
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The supported image extensions
|
/// The supported image extensions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -66,6 +69,12 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public List<ItemImageInfo> ImageInfos { get; set; }
|
public List<ItemImageInfo> ImageInfos { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the album.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The album.</value>
|
||||||
|
public string Album { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the channel identifier.
|
/// Gets or sets the channel identifier.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -125,6 +134,29 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public string SlugName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var name = Name;
|
||||||
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SlugReplaceChars.Aggregate(name, (current, c) => current.Replace(c, SlugChar));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsUnaired
|
||||||
|
{
|
||||||
|
get { return PremiereDate.HasValue && PremiereDate.Value.ToLocalTime().Date >= DateTime.Now.Date; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string OriginalTitle { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the id.
|
/// Gets or sets the id.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -726,12 +758,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Gets or sets the critic rating.
|
/// Gets or sets the critic rating.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The critic rating.</value>
|
/// <value>The critic rating.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public float? CriticRating { get; set; }
|
public float? CriticRating { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the critic rating summary.
|
/// Gets or sets the critic rating summary.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The critic rating summary.</value>
|
/// <value>The critic rating summary.</value>
|
||||||
|
[IgnoreDataMember]
|
||||||
public string CriticRatingSummary { get; set; }
|
public string CriticRatingSummary { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -1147,33 +1181,31 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
get { return null; }
|
get { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private string _userDataKey;
|
[IgnoreDataMember]
|
||||||
/// <summary>
|
public virtual string PresentationUniqueKey
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
public string GetUserDataKey()
|
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(_userDataKey))
|
get { return Id.ToString("N"); }
|
||||||
{
|
|
||||||
var key = CreateUserDataKey();
|
|
||||||
_userDataKey = key;
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _userDataKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual string CreateUserDataKey()
|
public virtual bool RequiresRefresh()
|
||||||
{
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual List<string> GetUserDataKeys()
|
||||||
|
{
|
||||||
|
var list = new List<string>();
|
||||||
|
|
||||||
if (SourceType == SourceType.Channel)
|
if (SourceType == SourceType.Channel)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(ExternalId))
|
if (!string.IsNullOrWhiteSpace(ExternalId))
|
||||||
{
|
{
|
||||||
return ExternalId;
|
list.Add(ExternalId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Id.ToString();
|
|
||||||
|
list.Add(Id.ToString());
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal virtual bool IsValidFromResolver(BaseItem newItem)
|
internal virtual bool IsValidFromResolver(BaseItem newItem)
|
||||||
@ -1186,7 +1218,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public void AfterMetadataRefresh()
|
public void AfterMetadataRefresh()
|
||||||
{
|
{
|
||||||
_sortName = null;
|
_sortName = null;
|
||||||
_userDataKey = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -1540,11 +1571,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(info.Path))
|
if (!string.IsNullOrEmpty(info.Path))
|
||||||
{
|
{
|
||||||
var itemByPath = LibraryManager.FindByPath(info.Path);
|
var itemByPath = LibraryManager.FindByPath(info.Path, null);
|
||||||
|
|
||||||
if (itemByPath == null)
|
if (itemByPath == null)
|
||||||
{
|
{
|
||||||
Logger.Warn("Unable to find linked item at path {0}", info.Path);
|
//Logger.Warn("Unable to find linked item at path {0}", info.Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return itemByPath;
|
return itemByPath;
|
||||||
@ -1553,6 +1584,15 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public virtual bool EnableRememberingTrackSelections
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a studio to the item
|
/// Adds a studio to the item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -1606,9 +1646,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException();
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = GetUserDataKey();
|
var data = UserDataManager.GetUserData(user, this);
|
||||||
|
|
||||||
var data = UserDataManager.GetUserData(user.Id, key);
|
|
||||||
|
|
||||||
if (datePlayed.HasValue)
|
if (datePlayed.HasValue)
|
||||||
{
|
{
|
||||||
@ -1643,9 +1681,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException();
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = GetUserDataKey();
|
var data = UserDataManager.GetUserData(user, this);
|
||||||
|
|
||||||
var data = UserDataManager.GetUserData(user.Id, key);
|
|
||||||
|
|
||||||
//I think it is okay to do this here.
|
//I think it is okay to do this here.
|
||||||
// if this is only called when a user is manually forcing something to un-played
|
// if this is only called when a user is manually forcing something to un-played
|
||||||
@ -1976,14 +2012,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public virtual bool IsPlayed(User user)
|
public virtual bool IsPlayed(User user)
|
||||||
{
|
{
|
||||||
var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey());
|
var userdata = UserDataManager.GetUserData(user, this);
|
||||||
|
|
||||||
return userdata != null && userdata.Played;
|
return userdata != null && userdata.Played;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsFavoriteOrLiked(User user)
|
public bool IsFavoriteOrLiked(User user)
|
||||||
{
|
{
|
||||||
var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey());
|
var userdata = UserDataManager.GetUserData(user, this);
|
||||||
|
|
||||||
return userdata != null && (userdata.IsFavorite || (userdata.Likes ?? false));
|
return userdata != null && (userdata.IsFavorite || (userdata.Likes ?? false));
|
||||||
}
|
}
|
||||||
@ -1995,7 +2031,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
throw new ArgumentNullException("user");
|
throw new ArgumentNullException("user");
|
||||||
}
|
}
|
||||||
|
|
||||||
var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey());
|
var userdata = UserDataManager.GetUserData(user, this);
|
||||||
|
|
||||||
return userdata == null || !userdata.Played;
|
return userdata == null || !userdata.Played;
|
||||||
}
|
}
|
||||||
@ -2026,7 +2062,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool BeforeMetadataRefresh()
|
public virtual bool BeforeMetadataRefresh()
|
||||||
{
|
{
|
||||||
_userDataKey = null;
|
|
||||||
_sortName = null;
|
_sortName = null;
|
||||||
|
|
||||||
var hasChanges = false;
|
var hasChanges = false;
|
||||||
|
@ -8,6 +8,7 @@ using System.Runtime.Serialization;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommonIO;
|
using CommonIO;
|
||||||
|
using MoreLinq;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -97,7 +98,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return base.IsValidFromResolver(newItem);
|
return base.IsValidFromResolver(newItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,9 +200,30 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public IEnumerable<Folder> GetPhysicalParents()
|
public IEnumerable<Folder> GetPhysicalParents()
|
||||||
{
|
{
|
||||||
return LibraryManager.RootFolder.Children
|
var rootChildren = LibraryManager.RootFolder.Children
|
||||||
.OfType<Folder>()
|
.OfType<Folder>()
|
||||||
.Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase));
|
.ToList();
|
||||||
|
|
||||||
|
return PhysicalLocations.Where(i => !string.Equals(i, Path, StringComparison.OrdinalIgnoreCase)).SelectMany(i => GetPhysicalParents(i, rootChildren)).DistinctBy(i => i.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<Folder> GetPhysicalParents(string path, List<Folder> rootChildren)
|
||||||
|
{
|
||||||
|
var result = rootChildren
|
||||||
|
.Where(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
if (result.Count == 0)
|
||||||
|
{
|
||||||
|
var folder = LibraryManager.FindByPath(path, true) as Folder;
|
||||||
|
|
||||||
|
if (folder != null)
|
||||||
|
{
|
||||||
|
result.Add(folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -28,6 +28,9 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public List<Guid> ThemeSongIds { get; set; }
|
public List<Guid> ThemeSongIds { get; set; }
|
||||||
public List<Guid> ThemeVideoIds { get; set; }
|
public List<Guid> ThemeVideoIds { get; set; }
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public DateTime? DateLastMediaAdded { get; set; }
|
||||||
|
|
||||||
public Folder()
|
public Folder()
|
||||||
{
|
{
|
||||||
LinkedChildren = new List<LinkedChild>();
|
LinkedChildren = new List<LinkedChild>();
|
||||||
@ -55,6 +58,36 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public virtual bool SupportsCumulativeRunTimeTicks
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public virtual bool SupportsDateLastMediaAdded
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool RequiresRefresh()
|
||||||
|
{
|
||||||
|
var baseResult = base.RequiresRefresh();
|
||||||
|
|
||||||
|
if (SupportsCumulativeRunTimeTicks && !RunTimeTicks.HasValue)
|
||||||
|
{
|
||||||
|
baseResult = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseResult;
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override string FileNameWithoutExtension
|
public override string FileNameWithoutExtension
|
||||||
{
|
{
|
||||||
@ -199,8 +232,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <returns>Dictionary{System.StringFunc{UserIEnumerable{BaseItem}}}.</returns>
|
/// <returns>Dictionary{System.StringFunc{UserIEnumerable{BaseItem}}}.</returns>
|
||||||
protected virtual IEnumerable<string> GetIndexByOptions()
|
protected virtual IEnumerable<string> GetIndexByOptions()
|
||||||
{
|
{
|
||||||
return new List<string> {
|
return new List<string> {
|
||||||
{"None"},
|
{"None"},
|
||||||
{"Performer"},
|
{"Performer"},
|
||||||
{"Genre"},
|
{"Genre"},
|
||||||
{"Director"},
|
{"Director"},
|
||||||
@ -707,8 +740,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
return ItemRepository.GetItemIdsList(new InternalItemsQuery
|
return ItemRepository.GetItemIdsList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
ParentId = Id
|
ParentId = Id,
|
||||||
|
GroupByPresentationUniqueKey = false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -751,39 +784,44 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var supportsUserDataQueries = ConfigurationManager.Configuration.SchemaVersion >= 76;
|
||||||
|
|
||||||
if (query.SortBy != null && query.SortBy.Length > 0)
|
if (query.SortBy != null && query.SortBy.Length > 0)
|
||||||
{
|
{
|
||||||
if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
|
if (!supportsUserDataQueries)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.DatePlayed");
|
if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
|
||||||
return true;
|
{
|
||||||
}
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
|
||||||
if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase))
|
return true;
|
||||||
{
|
}
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
|
if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase))
|
||||||
return true;
|
{
|
||||||
}
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.PlayCount");
|
||||||
if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase))
|
return true;
|
||||||
{
|
}
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsPlayed");
|
if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase))
|
||||||
return true;
|
{
|
||||||
}
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
|
||||||
if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase))
|
return true;
|
||||||
{
|
}
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsUnplayed");
|
if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase))
|
||||||
return true;
|
{
|
||||||
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsPlayed");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.IsUnplayed");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
|
if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (query.SortBy.Contains(ItemSortBy.Album, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Album");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
|
if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
|
||||||
@ -799,11 +837,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Budget");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Budget");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (query.SortBy.Contains(ItemSortBy.DateLastContentAdded, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.DateLastContentAdded");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.GameSystem, StringComparer.OrdinalIgnoreCase))
|
if (query.SortBy.Contains(ItemSortBy.GameSystem, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.GameSystem");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.GameSystem");
|
||||||
@ -819,11 +852,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.OfficialRating");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.OfficialRating");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.PlayCount");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase))
|
if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Players");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Players");
|
||||||
@ -839,11 +867,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (query.SortBy.Contains(ItemSortBy.StartDate, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.StartDate");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (query.SortBy.Contains(ItemSortBy.Studio, StringComparer.OrdinalIgnoreCase))
|
if (query.SortBy.Contains(ItemSortBy.Studio, StringComparer.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ItemSortBy.Studio");
|
Logger.Debug("Query requires post-filtering due to ItemSortBy.Studio");
|
||||||
@ -868,34 +891,37 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.IsLiked.HasValue)
|
if (!supportsUserDataQueries)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to IsLiked");
|
if (query.IsLiked.HasValue)
|
||||||
return true;
|
{
|
||||||
}
|
Logger.Debug("Query requires post-filtering due to IsLiked");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (query.IsFavoriteOrLiked.HasValue)
|
if (query.IsFavoriteOrLiked.HasValue)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to IsFavoriteOrLiked");
|
Logger.Debug("Query requires post-filtering due to IsFavoriteOrLiked");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.IsFavorite.HasValue)
|
if (query.IsFavorite.HasValue)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to IsFavorite");
|
Logger.Debug("Query requires post-filtering due to IsFavorite");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.IsResumable.HasValue)
|
if (query.IsResumable.HasValue)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to IsResumable");
|
Logger.Debug("Query requires post-filtering due to IsResumable");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.IsPlayed.HasValue)
|
if (query.IsPlayed.HasValue)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to IsPlayed");
|
Logger.Debug("Query requires post-filtering due to IsPlayed");
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.IsInBoxSet.HasValue)
|
if (query.IsInBoxSet.HasValue)
|
||||||
@ -1059,30 +1085,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(query.NameContains))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to NameContains");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(query.NameLessThan))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to NameLessThan");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(query.NameStartsWith))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to NameStartsWith");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(query.NameStartsWithOrGreater))
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to NameStartsWithOrGreater");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.AirDays.Length > 0)
|
if (query.AirDays.Length > 0)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to AirDays");
|
Logger.Debug("Query requires post-filtering due to AirDays");
|
||||||
@ -1107,12 +1109,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.AlbumNames.Length > 0)
|
|
||||||
{
|
|
||||||
Logger.Debug("Query requires post-filtering due to AlbumNames");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (query.ArtistNames.Length > 0)
|
if (query.ArtistNames.Length > 0)
|
||||||
{
|
{
|
||||||
Logger.Debug("Query requires post-filtering due to ArtistNames");
|
Logger.Debug("Query requires post-filtering due to ArtistNames");
|
||||||
@ -1297,33 +1293,42 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter)
|
public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter)
|
||||||
{
|
{
|
||||||
var list = new List<BaseItem>();
|
var result = new Dictionary<Guid, BaseItem>();
|
||||||
|
|
||||||
AddChildrenToList(list, true, filter);
|
AddChildrenToList(result, true, true, filter);
|
||||||
|
|
||||||
return list;
|
return result.Values.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the children to list.
|
/// Adds the children to list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="list">The list.</param>
|
private void AddChildrenToList(Dictionary<Guid,BaseItem> result, bool includeLinkedChildren, bool recursive, Func<BaseItem, bool> filter)
|
||||||
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
|
|
||||||
/// <param name="filter">The filter.</param>
|
|
||||||
private void AddChildrenToList(List<BaseItem> list, bool recursive, Func<BaseItem, bool> filter)
|
|
||||||
{
|
{
|
||||||
foreach (var child in Children)
|
foreach (var child in Children)
|
||||||
{
|
{
|
||||||
if (filter == null || filter(child))
|
if (filter == null || filter(child))
|
||||||
{
|
{
|
||||||
list.Add(child);
|
result[child.Id] = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recursive && child.IsFolder)
|
if (recursive && child.IsFolder)
|
||||||
{
|
{
|
||||||
var folder = (Folder)child;
|
var folder = (Folder)child;
|
||||||
|
|
||||||
folder.AddChildrenToList(list, true, filter);
|
// We can only support includeLinkedChildren for the first folder, or we might end up stuck in a loop of linked items
|
||||||
|
folder.AddChildrenToList(result, false, true, filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeLinkedChildren)
|
||||||
|
{
|
||||||
|
foreach (var child in GetLinkedChildren())
|
||||||
|
{
|
||||||
|
if (filter == null || filter(child))
|
||||||
|
{
|
||||||
|
result[child.Id] = child;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1567,38 +1572,17 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Finds an item by path, recursively
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path.</param>
|
|
||||||
/// <returns>BaseItem.</returns>
|
|
||||||
/// <exception cref="System.ArgumentNullException"></exception>
|
|
||||||
public BaseItem FindByPath(string path)
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(path))
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.Equals(Path, path, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetRecursiveChildren(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) ||
|
|
||||||
(!i.IsFolder && !i.IsInMixedFolder && string.Equals(i.ContainingFolderPath, path, StringComparison.OrdinalIgnoreCase)) ||
|
|
||||||
i.PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase))
|
|
||||||
.FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsPlayed(User user)
|
public override bool IsPlayed(User user)
|
||||||
{
|
{
|
||||||
return GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual)
|
var itemsResult = GetItems(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
Recursive = true,
|
||||||
|
IsFolder = false,
|
||||||
|
ExcludeLocationTypes = new[] { LocationType.Virtual }
|
||||||
|
|
||||||
|
}).Result;
|
||||||
|
|
||||||
|
return itemsResult.Items
|
||||||
.All(i => i.IsPlayed(user));
|
.All(i => i.IsPlayed(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1607,26 +1591,50 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return !IsPlayed(user);
|
return !IsPlayed(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public virtual bool SupportsUserDataFromChildren
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// These are just far too slow.
|
||||||
|
if (this is ICollectionFolder)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this is UserView)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this is UserRootFolder)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
|
public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
|
||||||
{
|
{
|
||||||
|
if (!SupportsUserDataFromChildren)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var recursiveItemCount = 0;
|
var recursiveItemCount = 0;
|
||||||
var unplayed = 0;
|
var unplayed = 0;
|
||||||
|
|
||||||
double totalPercentPlayed = 0;
|
double totalPercentPlayed = 0;
|
||||||
|
|
||||||
IEnumerable<BaseItem> children;
|
var itemsResult = GetItems(new InternalItemsQuery(user)
|
||||||
var folder = this;
|
|
||||||
|
|
||||||
var season = folder as Season;
|
|
||||||
|
|
||||||
if (season != null)
|
|
||||||
{
|
{
|
||||||
children = season.GetEpisodes(user).Where(i => i.LocationType != LocationType.Virtual);
|
Recursive = true,
|
||||||
}
|
IsFolder = false,
|
||||||
else
|
ExcludeLocationTypes = new[] { LocationType.Virtual }
|
||||||
{
|
|
||||||
children = folder.GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual);
|
}).Result;
|
||||||
}
|
|
||||||
|
var children = itemsResult.Items;
|
||||||
|
|
||||||
// Loop through each recursive child
|
// Loop through each recursive child
|
||||||
foreach (var child in children)
|
foreach (var child in children)
|
||||||
@ -1635,7 +1643,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
var isUnplayed = true;
|
var isUnplayed = true;
|
||||||
|
|
||||||
var itemUserData = UserDataManager.GetUserData(user.Id, child.GetUserDataKey());
|
var itemUserData = UserDataManager.GetUserData(user, child);
|
||||||
|
|
||||||
// Incrememt totalPercentPlayed
|
// Incrememt totalPercentPlayed
|
||||||
if (itemUserData != null)
|
if (itemUserData != null)
|
||||||
|
@ -76,15 +76,16 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> MultiPartGameFiles { get; set; }
|
public List<string> MultiPartGameFiles { get; set; }
|
||||||
|
|
||||||
protected override string CreateUserDataKey()
|
public override List<string> GetUserDataKeys()
|
||||||
{
|
{
|
||||||
|
var list = base.GetUserDataKeys();
|
||||||
var id = this.GetProviderId(MetadataProviders.Gamesdb);
|
var id = this.GetProviderId(MetadataProviders.Gamesdb);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(id))
|
if (!string.IsNullOrEmpty(id))
|
||||||
{
|
{
|
||||||
return "Game-Gamesdb-" + id;
|
list.Insert(0, "Game-Gamesdb-" + id);
|
||||||
}
|
}
|
||||||
return base.CreateUserDataKey();
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<string> GetDeletePaths()
|
public override IEnumerable<string> GetDeletePaths()
|
||||||
|
@ -7,13 +7,12 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
public class GameGenre : BaseItem, IItemByName
|
public class GameGenre : BaseItem, IItemByName
|
||||||
{
|
{
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
return "GameGenre-" + Name;
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
|
list.Insert(0, "GameGenre-" + Name);
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -63,6 +62,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return i => i is Game && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase);
|
return i => i is Game && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
query.Genres = new[] { Name };
|
||||||
|
query.IncludeItemTypes = new[] { typeof(Game).Name };
|
||||||
|
|
||||||
|
return LibraryManager.GetItemList(query);
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsPeople
|
public override bool SupportsPeople
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using MediaBrowser.Controller.Providers;
|
using MediaBrowser.Controller.Providers;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using MediaBrowser.Model.Users;
|
using MediaBrowser.Model.Users;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
@ -31,17 +32,15 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <value>The game system.</value>
|
/// <value>The game system.</value>
|
||||||
public string GameSystemName { get; set; }
|
public string GameSystemName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(GameSystemName))
|
if (!string.IsNullOrEmpty(GameSystemName))
|
||||||
{
|
{
|
||||||
return "GameSystem-" + GameSystemName;
|
list.Insert(0, "GameSystem-" + GameSystemName);
|
||||||
}
|
}
|
||||||
return base.CreateUserDataKey();
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||||
|
@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Genre : BaseItem, IItemByName
|
public class Genre : BaseItem, IItemByName
|
||||||
{
|
{
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
return "Genre-" + Name;
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
|
list.Insert(0, "Genre-" + Name);
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -67,6 +66,14 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return i => !(i is Game) && !(i is IHasMusicGenres) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase);
|
return i => !(i is Game) && !(i is IHasMusicGenres) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
query.Genres = new[] { Name };
|
||||||
|
query.ExcludeItemTypes = new[] { typeof(Game).Name, typeof(MusicVideo).Name, typeof(Audio.Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
|
||||||
|
|
||||||
|
return LibraryManager.GetItemList(query);
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsPeople
|
public override bool SupportsPeople
|
||||||
{
|
{
|
||||||
|
@ -49,5 +49,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value><c>true</c> if [supports people]; otherwise, <c>false</c>.</value>
|
/// <value><c>true</c> if [supports people]; otherwise, <c>false</c>.</value>
|
||||||
bool SupportsPeople { get; }
|
bool SupportsPeople { get; }
|
||||||
|
|
||||||
|
bool RequiresRefresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Model.Dto;
|
using System.Collections.Generic;
|
||||||
|
using MediaBrowser.Model.Dto;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities
|
namespace MediaBrowser.Controller.Entities
|
||||||
{
|
{
|
||||||
@ -7,11 +8,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IHasUserData : IHasId
|
public interface IHasUserData : IHasId
|
||||||
{
|
{
|
||||||
/// <summary>
|
List<string> GetUserDataKeys();
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
string GetUserDataKey();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fills the user data dto values.
|
/// Fills the user data dto values.
|
||||||
@ -20,5 +17,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <param name="userData">The user data.</param>
|
/// <param name="userData">The user data.</param>
|
||||||
/// <param name="user">The user.</param>
|
/// <param name="user">The user.</param>
|
||||||
void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user);
|
void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user);
|
||||||
|
|
||||||
|
bool EnableRememberingTrackSelections { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Func<BaseItem, System.Boolean>.</returns>
|
/// <returns>Func<BaseItem, System.Boolean>.</returns>
|
||||||
Func<BaseItem, bool> GetItemFilter();
|
Func<BaseItem, bool> GetItemFilter();
|
||||||
|
|
||||||
|
IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IHasDualAccess : IItemByName
|
public interface IHasDualAccess : IItemByName
|
||||||
|
@ -46,8 +46,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
public string NameLessThan { get; set; }
|
public string NameLessThan { get; set; }
|
||||||
public string NameContains { get; set; }
|
public string NameContains { get; set; }
|
||||||
|
|
||||||
|
public string PresentationUniqueKey { get; set; }
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string SlugName { get; set; }
|
||||||
|
|
||||||
public string Person { get; set; }
|
public string Person { get; set; }
|
||||||
public string[] PersonIds { get; set; }
|
public string[] PersonIds { get; set; }
|
||||||
public string[] ItemIds { get; set; }
|
public string[] ItemIds { get; set; }
|
||||||
@ -106,6 +109,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
|
internal List<Guid> ItemIdsFromPersonFilters { get; set; }
|
||||||
public int? ParentIndexNumber { get; set; }
|
public int? ParentIndexNumber { get; set; }
|
||||||
|
public int? IndexNumber { get; set; }
|
||||||
public int? MinParentalRating { get; set; }
|
public int? MinParentalRating { get; set; }
|
||||||
public int? MaxParentalRating { get; set; }
|
public int? MaxParentalRating { get; set; }
|
||||||
|
|
||||||
@ -130,9 +134,16 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
public string[] AlbumNames { get; set; }
|
public string[] AlbumNames { get; set; }
|
||||||
public string[] ArtistNames { get; set; }
|
public string[] ArtistNames { get; set; }
|
||||||
|
public string AncestorWithPresentationUniqueKey { get; set; }
|
||||||
|
|
||||||
|
public bool GroupByPresentationUniqueKey { get; set; }
|
||||||
|
public bool EnableTotalRecordCount { get; set; }
|
||||||
|
|
||||||
public InternalItemsQuery()
|
public InternalItemsQuery()
|
||||||
{
|
{
|
||||||
|
GroupByPresentationUniqueKey = true;
|
||||||
|
EnableTotalRecordCount = true;
|
||||||
|
|
||||||
AlbumNames = new string[] { };
|
AlbumNames = new string[] { };
|
||||||
ArtistNames = new string[] { };
|
ArtistNames = new string[] { };
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using MediaBrowser.Controller.Entities.Audio;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.Movies
|
namespace MediaBrowser.Controller.Entities.Movies
|
||||||
{
|
{
|
||||||
@ -118,7 +119,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
// Gather all possible ratings
|
// Gather all possible ratings
|
||||||
var ratings = GetRecursiveChildren()
|
var ratings = GetRecursiveChildren()
|
||||||
.Concat(GetLinkedChildren())
|
.Concat(GetLinkedChildren())
|
||||||
.Where(i => i is Movie || i is Series)
|
.Where(i => i is Movie || i is Series || i is MusicAlbum || i is Game)
|
||||||
.Select(i => i.OfficialRating)
|
.Select(i => i.OfficialRating)
|
||||||
.Where(i => !string.IsNullOrEmpty(i))
|
.Where(i => !string.IsNullOrEmpty(i))
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
@ -18,8 +18,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
{
|
{
|
||||||
public List<Guid> SpecialFeatureIds { get; set; }
|
public List<Guid> SpecialFeatureIds { get; set; }
|
||||||
|
|
||||||
public string OriginalTitle { get; set; }
|
|
||||||
|
|
||||||
public List<Guid> ThemeSongIds { get; set; }
|
public List<Guid> ThemeSongIds { get; set; }
|
||||||
public List<Guid> ThemeVideoIds { get; set; }
|
public List<Guid> ThemeVideoIds { get; set; }
|
||||||
public List<string> ProductionLocations { get; set; }
|
public List<string> ProductionLocations { get; set; }
|
||||||
@ -77,34 +75,6 @@ namespace MediaBrowser.Controller.Entities.Movies
|
|||||||
get { return TmdbCollectionName; }
|
get { return TmdbCollectionName; }
|
||||||
set { TmdbCollectionName = value; }
|
set { TmdbCollectionName = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
|
||||||
var key = GetMovieUserDataKey(this);
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(key))
|
|
||||||
{
|
|
||||||
key = base.CreateUserDataKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetMovieUserDataKey(BaseItem movie)
|
|
||||||
{
|
|
||||||
var key = movie.GetProviderId(MetadataProviders.Tmdb);
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(key))
|
|
||||||
{
|
|
||||||
key = movie.GetProviderId(MetadataProviders.Imdb);
|
|
||||||
}
|
|
||||||
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
@ -9,12 +9,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasProductionLocations, IHasBudget, IHasLookupInfo<MusicVideoInfo>
|
public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasProductionLocations, IHasBudget, IHasLookupInfo<MusicVideoInfo>
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the album.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The album.</value>
|
|
||||||
public string Album { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the budget.
|
/// Gets or sets the budget.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -44,15 +38,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
|
||||||
return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override UnratedItem GetBlockUnratedType()
|
public override UnratedItem GetBlockUnratedType()
|
||||||
{
|
{
|
||||||
return UnratedItem.Music;
|
return UnratedItem.Music;
|
||||||
|
@ -18,13 +18,12 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <value>The place of birth.</value>
|
/// <value>The place of birth.</value>
|
||||||
public string PlaceOfBirth { get; set; }
|
public string PlaceOfBirth { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
return "Person-" + Name;
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
|
list.Insert(0, "Person-" + Name);
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PersonLookupInfo GetLookupInfo()
|
public PersonLookupInfo GetLookupInfo()
|
||||||
@ -32,6 +31,13 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return GetItemLookupInfo<PersonLookupInfo>();
|
return GetItemLookupInfo<PersonLookupInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
query.Person = Name;
|
||||||
|
|
||||||
|
return LibraryManager.GetItemList(query);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the folder containing the item.
|
/// Returns the folder containing the item.
|
||||||
/// If the item is a folder, it returns the folder itself
|
/// If the item is a folder, it returns the folder itself
|
||||||
|
@ -7,15 +7,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
public class PhotoAlbum : Folder
|
public class PhotoAlbum : Folder
|
||||||
{
|
{
|
||||||
[IgnoreDataMember]
|
|
||||||
public override bool SupportsLocalMetadata
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool AlwaysScanInternalMetadataPath
|
public override bool AlwaysScanInternalMetadataPath
|
||||||
{
|
{
|
||||||
|
@ -10,13 +10,12 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Studio : BaseItem, IItemByName, IHasTags
|
public class Studio : BaseItem, IItemByName, IHasTags
|
||||||
{
|
{
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
return "Studio-" + Name;
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
|
list.Insert(0, "Studio-" + Name);
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -66,6 +65,13 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return i => i.Studios.Contains(Name, StringComparer.OrdinalIgnoreCase);
|
return i => i.Studios.Contains(Name, StringComparer.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
query.Studios = new[] { Name };
|
||||||
|
|
||||||
|
return LibraryManager.GetItemList(query);
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override bool SupportsPeople
|
public override bool SupportsPeople
|
||||||
{
|
{
|
||||||
|
@ -58,25 +58,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return AirsAfterSeasonNumber ?? AirsBeforeSeasonNumber ?? PhysicalSeasonNumber;
|
return AirsAfterSeasonNumber ?? AirsBeforeSeasonNumber ?? ParentIndexNumber;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public int? PhysicalSeasonNumber
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var value = ParentIndexNumber;
|
|
||||||
|
|
||||||
if (value.HasValue)
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
var season = Season;
|
|
||||||
|
|
||||||
return season != null ? season.IndexNumber : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,20 +80,26 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
[IgnoreDataMember]
|
||||||
/// Gets the user data key.
|
protected override bool EnableDefaultVideoUserDataKeys
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
var series = Series;
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<string> GetUserDataKeys()
|
||||||
|
{
|
||||||
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
|
var series = Series;
|
||||||
if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
|
if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
|
||||||
{
|
{
|
||||||
return series.GetUserDataKey() + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000");
|
list.InsertRange(0, series.GetUserDataKeys().Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000")));
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.CreateUserDataKey();
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -222,12 +210,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public bool IsUnaired
|
|
||||||
{
|
|
||||||
get { return PremiereDate.HasValue && PremiereDate.Value.ToLocalTime().Date >= DateTime.Now.Date; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsVirtualUnaired
|
public bool IsVirtualUnaired
|
||||||
{
|
{
|
||||||
@ -310,6 +292,19 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
Logger.ErrorException("Error in FillMissingEpisodeNumbersFromPath. Episode: {0}", ex, Path ?? Name ?? Id.ToString());
|
Logger.ErrorException("Error in FillMissingEpisodeNumbersFromPath. Episode: {0}", ex, Path ?? Name ?? Id.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ParentIndexNumber.HasValue)
|
||||||
|
{
|
||||||
|
var season = Season;
|
||||||
|
if (season != null)
|
||||||
|
{
|
||||||
|
if (season.ParentIndexNumber.HasValue)
|
||||||
|
{
|
||||||
|
ParentIndexNumber = season.ParentIndexNumber;
|
||||||
|
hasChanges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return hasChanges;
|
return hasChanges;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,15 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsDateLastMediaAdded
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override Guid? DisplayParentId
|
public override Guid? DisplayParentId
|
||||||
{
|
{
|
||||||
@ -45,27 +54,25 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
// Genre, Rating and Stuido will all be the same
|
// Genre, Rating and Stuido will all be the same
|
||||||
protected override IEnumerable<string> GetIndexByOptions()
|
protected override IEnumerable<string> GetIndexByOptions()
|
||||||
{
|
{
|
||||||
return new List<string> {
|
return new List<string> {
|
||||||
{"None"},
|
{"None"},
|
||||||
{"Performer"},
|
{"Performer"},
|
||||||
{"Director"},
|
{"Director"},
|
||||||
{"Year"},
|
{"Year"},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
if (Series != null)
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
|
var series = Series;
|
||||||
|
if (series != null)
|
||||||
{
|
{
|
||||||
var seasonNo = IndexNumber ?? 0;
|
list.InsertRange(0, series.GetUserDataKeys().Select(i => i + (IndexNumber ?? 0).ToString("000")));
|
||||||
return Series.GetUserDataKey() + seasonNo.ToString("000");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.CreateUserDataKey();
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -94,6 +101,24 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override string PresentationUniqueKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (IndexNumber.HasValue)
|
||||||
|
{
|
||||||
|
var series = Series;
|
||||||
|
if (series != null)
|
||||||
|
{
|
||||||
|
return series.PresentationUniqueKey + "-" + (IndexNumber ?? 0).ToString("000");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.PresentationUniqueKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the name of the sort.
|
/// Creates the name of the sort.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -103,17 +128,23 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
public override bool RequiresRefresh()
|
||||||
public bool IsMissingSeason
|
|
||||||
{
|
{
|
||||||
get { return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.IsMissingEpisode); }
|
var result = base.RequiresRefresh();
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
if (!IsMissingSeason.HasValue)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsUnaired
|
public bool? IsMissingSeason { get; set; }
|
||||||
{
|
|
||||||
get { return GetEpisodes().All(i => i.IsUnaired); }
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsVirtualUnaired
|
public bool IsVirtualUnaired
|
||||||
@ -124,7 +155,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public bool IsMissingOrVirtualUnaired
|
public bool IsMissingOrVirtualUnaired
|
||||||
{
|
{
|
||||||
get { return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); }
|
get { return (IsMissingSeason ?? false) || (LocationType == LocationType.Virtual && IsUnaired); }
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
@ -135,22 +166,16 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
|
|
||||||
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
|
protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
|
||||||
{
|
{
|
||||||
|
if (query.User == null)
|
||||||
|
{
|
||||||
|
return base.GetItemsInternal(query);
|
||||||
|
}
|
||||||
|
|
||||||
var user = query.User;
|
var user = query.User;
|
||||||
|
|
||||||
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
|
||||||
|
|
||||||
IEnumerable<BaseItem> items;
|
var items = GetEpisodes(user).Where(filter);
|
||||||
|
|
||||||
if (query.User == null)
|
|
||||||
{
|
|
||||||
items = query.Recursive
|
|
||||||
? GetRecursiveChildren(filter)
|
|
||||||
: Children.Where(filter);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
items = GetEpisodes(query.User).Where(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = PostFilterAndSort(items, query);
|
var result = PostFilterAndSort(items, query);
|
||||||
|
|
||||||
@ -171,16 +196,16 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
|
|
||||||
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
||||||
{
|
{
|
||||||
var episodes = GetRecursiveChildren(user)
|
|
||||||
.OfType<Episode>();
|
|
||||||
|
|
||||||
var series = Series;
|
var series = Series;
|
||||||
|
|
||||||
if (IndexNumber.HasValue && series != null)
|
if (IndexNumber.HasValue && series != null)
|
||||||
{
|
{
|
||||||
return series.GetEpisodes(user, IndexNumber.Value, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
|
return series.GetEpisodes(user, IndexNumber.Value, includeMissingEpisodes, includeVirtualUnairedEpisodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var episodes = GetRecursiveChildren(user)
|
||||||
|
.OfType<Episode>();
|
||||||
|
|
||||||
if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
|
if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
|
||||||
{
|
{
|
||||||
var seasonNumber = IndexNumber;
|
var seasonNumber = IndexNumber;
|
||||||
@ -199,7 +224,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
|
|
||||||
episodes = list.DistinctBy(i => i.Id);
|
episodes = list.DistinctBy(i => i.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!includeMissingEpisodes)
|
if (!includeMissingEpisodes)
|
||||||
{
|
{
|
||||||
episodes = episodes.Where(i => !i.IsMissingEpisode);
|
episodes = episodes.Where(i => !i.IsMissingEpisode);
|
||||||
@ -214,7 +239,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
.Cast<Episode>();
|
.Cast<Episode>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<Episode> GetEpisodes()
|
public IEnumerable<Episode> GetEpisodes()
|
||||||
{
|
{
|
||||||
var episodes = GetRecursiveChildren().OfType<Episode>();
|
var episodes = GetRecursiveChildren().OfType<Episode>();
|
||||||
var series = Series;
|
var series = Series;
|
||||||
|
@ -9,6 +9,7 @@ using System.Linq;
|
|||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MoreLinq;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Entities.TV
|
namespace MediaBrowser.Controller.Entities.TV
|
||||||
{
|
{
|
||||||
@ -19,8 +20,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
public List<Guid> SpecialFeatureIds { get; set; }
|
public List<Guid> SpecialFeatureIds { get; set; }
|
||||||
|
|
||||||
public string OriginalTitle { get; set; }
|
|
||||||
|
|
||||||
public int? AnimeSeriesIndex { get; set; }
|
public int? AnimeSeriesIndex { get; set; }
|
||||||
|
|
||||||
public Series()
|
public Series()
|
||||||
@ -49,6 +48,15 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsDateLastMediaAdded
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool DisplaySpecialsWithSeasons { get; set; }
|
public bool DisplaySpecialsWithSeasons { get; set; }
|
||||||
|
|
||||||
public List<Guid> LocalTrailerIds { get; set; }
|
public List<Guid> LocalTrailerIds { get; set; }
|
||||||
@ -93,25 +101,40 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override string PresentationUniqueKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (EnablePooling())
|
||||||
|
{
|
||||||
|
return GetUserDataKeys().First();
|
||||||
|
}
|
||||||
|
return base.PresentationUniqueKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data key.
|
/// Gets the user data key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
protected override string CreateUserDataKey()
|
public override List<string> GetUserDataKeys()
|
||||||
{
|
{
|
||||||
var key = this.GetProviderId(MetadataProviders.Tvdb);
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(key))
|
var key = this.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(key))
|
||||||
{
|
{
|
||||||
key = this.GetProviderId(MetadataProviders.Imdb);
|
list.Insert(0, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(key))
|
key = this.GetProviderId(MetadataProviders.Tvdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(key))
|
||||||
{
|
{
|
||||||
key = base.CreateUserDataKey();
|
list.Insert(0, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
return key;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -128,8 +151,8 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
// Studio, Genre and Rating will all be the same so makes no sense to index by these
|
// Studio, Genre and Rating will all be the same so makes no sense to index by these
|
||||||
protected override IEnumerable<string> GetIndexByOptions()
|
protected override IEnumerable<string> GetIndexByOptions()
|
||||||
{
|
{
|
||||||
return new List<string> {
|
return new List<string> {
|
||||||
{"None"},
|
{"None"},
|
||||||
{"Performer"},
|
{"Performer"},
|
||||||
{"Director"},
|
{"Director"},
|
||||||
{"Year"},
|
{"Year"},
|
||||||
@ -174,7 +197,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
items = query.Recursive
|
items = query.Recursive
|
||||||
? GetRecursiveChildren(user, filter)
|
? GetSeasons(user).Cast<BaseItem>().Concat(GetEpisodes(user)).Where(filter)
|
||||||
: GetSeasons(user).Where(filter);
|
: GetSeasons(user).Where(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,8 +208,35 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
|
|
||||||
public IEnumerable<Season> GetSeasons(User user, bool includeMissingSeasons, bool includeVirtualUnaired)
|
public IEnumerable<Season> GetSeasons(User user, bool includeMissingSeasons, bool includeVirtualUnaired)
|
||||||
{
|
{
|
||||||
var seasons = base.GetChildren(user, true)
|
IEnumerable<Season> seasons;
|
||||||
.OfType<Season>();
|
|
||||||
|
if (EnablePooling())
|
||||||
|
{
|
||||||
|
var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
PresentationUniqueKey = PresentationUniqueKey,
|
||||||
|
IncludeItemTypes = new[] { typeof(Series).Name }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (seriesIds.Count > 1)
|
||||||
|
{
|
||||||
|
seasons = LibraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(),
|
||||||
|
IncludeItemTypes = new[] { typeof(Season).Name },
|
||||||
|
SortBy = new[] { ItemSortBy.SortName }
|
||||||
|
|
||||||
|
}).Cast<Season>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType<Season>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType<Season>();
|
||||||
|
}
|
||||||
|
|
||||||
if (!includeMissingSeasons && !includeVirtualUnaired)
|
if (!includeMissingSeasons && !includeVirtualUnaired)
|
||||||
{
|
{
|
||||||
@ -196,7 +246,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
if (!includeMissingSeasons)
|
if (!includeMissingSeasons)
|
||||||
{
|
{
|
||||||
seasons = seasons.Where(i => !i.IsMissingSeason);
|
seasons = seasons.Where(i => !(i.IsMissingSeason ?? false));
|
||||||
}
|
}
|
||||||
if (!includeVirtualUnaired)
|
if (!includeVirtualUnaired)
|
||||||
{
|
{
|
||||||
@ -204,9 +254,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return LibraryManager
|
return seasons;
|
||||||
.Sort(seasons, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending)
|
|
||||||
.Cast<Season>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Episode> GetEpisodes(User user)
|
public IEnumerable<Episode> GetEpisodes(User user)
|
||||||
@ -226,17 +274,8 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
// Specials could appear twice based on above - once in season 0, once in the aired season
|
// Specials could appear twice based on above - once in season 0, once in the aired season
|
||||||
// This depends on settings for that series
|
// This depends on settings for that series
|
||||||
// When this happens, remove the duplicate from season 0
|
// When this happens, remove the duplicate from season 0
|
||||||
var returnList = new List<Episode>();
|
|
||||||
|
|
||||||
foreach (var episode in allEpisodes)
|
return allEpisodes.DistinctBy(i => i.Id).Reverse();
|
||||||
{
|
|
||||||
if (!returnList.Contains(episode))
|
|
||||||
{
|
|
||||||
returnList.Insert(0, episode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
|
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
|
||||||
@ -257,7 +296,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
// Refresh current item
|
// Refresh current item
|
||||||
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
// Refresh TV
|
// Refresh seasons
|
||||||
foreach (var item in seasons)
|
foreach (var item in seasons)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
@ -270,12 +309,30 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
progress.Report(percent * 100);
|
progress.Report(percent * 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh all non-songs
|
// Refresh episodes and other children
|
||||||
foreach (var item in otherItems)
|
foreach (var item in otherItems)
|
||||||
{
|
{
|
||||||
cancellationToken.ThrowIfCancellationRequested();
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
var skipItem = false;
|
||||||
|
|
||||||
|
var episode = item as Episode;
|
||||||
|
|
||||||
|
if (episode != null
|
||||||
|
&& refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh
|
||||||
|
&& !refreshOptions.ReplaceAllMetadata
|
||||||
|
&& episode.IsMissingEpisode
|
||||||
|
&& episode.LocationType == Model.Entities.LocationType.Virtual
|
||||||
|
&& episode.PremiereDate.HasValue
|
||||||
|
&& (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30)
|
||||||
|
{
|
||||||
|
skipItem = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipItem)
|
||||||
|
{
|
||||||
|
await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
numComplete++;
|
numComplete++;
|
||||||
double percent = numComplete;
|
double percent = numComplete;
|
||||||
@ -295,21 +352,47 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
return GetEpisodes(user, seasonNumber, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
|
return GetEpisodes(user, seasonNumber, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<Episode> GetEpisodes(User user, int seasonNumber, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
private bool EnablePooling()
|
||||||
{
|
{
|
||||||
return GetEpisodes(user, seasonNumber, includeMissingEpisodes, includeVirtualUnairedEpisodes,
|
return false;
|
||||||
new List<Episode>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal IEnumerable<Episode> GetEpisodes(User user, int seasonNumber, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> additionalEpisodes)
|
public IEnumerable<Episode> GetEpisodes(User user, int seasonNumber, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
|
||||||
{
|
{
|
||||||
var episodes = GetRecursiveChildren(user, i => i is Episode)
|
IEnumerable<Episode> episodes;
|
||||||
.Cast<Episode>();
|
|
||||||
|
if (EnablePooling())
|
||||||
|
{
|
||||||
|
var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
PresentationUniqueKey = PresentationUniqueKey,
|
||||||
|
IncludeItemTypes = new[] { typeof(Series).Name }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (seriesIds.Count > 1)
|
||||||
|
{
|
||||||
|
episodes = LibraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
|
AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(),
|
||||||
|
IncludeItemTypes = new[] { typeof(Episode).Name },
|
||||||
|
SortBy = new[] { ItemSortBy.SortName }
|
||||||
|
|
||||||
|
}).Cast<Episode>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
episodes = GetRecursiveChildren(user, i => i is Episode)
|
||||||
|
.Cast<Episode>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
episodes = GetRecursiveChildren(user, i => i is Episode)
|
||||||
|
.Cast<Episode>();
|
||||||
|
}
|
||||||
|
|
||||||
episodes = FilterEpisodesBySeason(episodes, seasonNumber, DisplaySpecialsWithSeasons);
|
episodes = FilterEpisodesBySeason(episodes, seasonNumber, DisplaySpecialsWithSeasons);
|
||||||
|
|
||||||
episodes = episodes.Concat(additionalEpisodes).Distinct();
|
|
||||||
|
|
||||||
if (!includeMissingEpisodes)
|
if (!includeMissingEpisodes)
|
||||||
{
|
{
|
||||||
episodes = episodes.Where(i => !i.IsMissingEpisode);
|
episodes = episodes.Where(i => !i.IsMissingEpisode);
|
||||||
@ -336,7 +419,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
{
|
{
|
||||||
if (!includeSpecials || seasonNumber < 1)
|
if (!includeSpecials || seasonNumber < 1)
|
||||||
{
|
{
|
||||||
return episodes.Where(i => (i.PhysicalSeasonNumber ?? -1) == seasonNumber);
|
return episodes.Where(i => (i.ParentIndexNumber ?? -1) == seasonNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
return episodes.Where(i =>
|
return episodes.Where(i =>
|
||||||
|
@ -11,7 +11,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class Trailer
|
/// Class Trailer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo<TrailerInfo>
|
public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo<TrailerInfo>
|
||||||
{
|
{
|
||||||
public List<string> ProductionLocations { get; set; }
|
public List<string> ProductionLocations { get; set; }
|
||||||
|
|
||||||
@ -56,26 +56,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <value>The revenue.</value>
|
/// <value>The revenue.</value>
|
||||||
public double? Revenue { get; set; }
|
public double? Revenue { get; set; }
|
||||||
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
|
||||||
var key = Movie.GetMovieUserDataKey(this);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(key))
|
|
||||||
{
|
|
||||||
key = key + "-trailer";
|
|
||||||
|
|
||||||
// Make sure different trailers have their own data.
|
|
||||||
if (RunTimeTicks.HasValue)
|
|
||||||
{
|
|
||||||
key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CreateUserDataKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override UnratedItem GetBlockUnratedType()
|
public override UnratedItem GetBlockUnratedType()
|
||||||
{
|
{
|
||||||
return UnratedItem.Trailer;
|
return UnratedItem.Trailer;
|
||||||
|
@ -88,6 +88,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The index of the subtitle stream.</value>
|
/// <value>The index of the subtitle stream.</value>
|
||||||
public int? SubtitleStreamIndex { get; set; }
|
public int? SubtitleStreamIndex { get; set; }
|
||||||
|
|
||||||
|
public const double MinLikeValue = 6.5;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is an interpreted property to indicate likes or dislikes
|
/// This is an interpreted property to indicate likes or dislikes
|
||||||
@ -101,7 +103,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
if (Rating != null)
|
if (Rating != null)
|
||||||
{
|
{
|
||||||
return Rating >= 6.5;
|
return Rating >= MinLikeValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -102,10 +102,5 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
LibraryManager.RegisterItem(item);
|
LibraryManager.RegisterItem(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
|
|
||||||
{
|
|
||||||
// Nothing meaninful here and will only waste resources
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,7 +348,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
.Where(i => !i.IsFolder)
|
.Where(i => !i.IsFolder)
|
||||||
.OfType<IHasAlbumArtist>();
|
.OfType<IHasAlbumArtist>();
|
||||||
|
|
||||||
var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite);
|
var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite);
|
||||||
|
|
||||||
return GetResult(artists, parent, query);
|
return GetResult(artists, parent, query);
|
||||||
}
|
}
|
||||||
@ -1077,7 +1077,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
var e = i as Season;
|
var e = i as Season;
|
||||||
if (e != null)
|
if (e != null)
|
||||||
{
|
{
|
||||||
return e.IsMissingSeason == val;
|
return (e.IsMissingSeason ?? false) == val;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@ -1218,7 +1218,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
if (query.IsLiked.HasValue)
|
if (query.IsLiked.HasValue)
|
||||||
{
|
{
|
||||||
userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
|
userData = userData ?? userDataManager.GetUserData(user, item);
|
||||||
|
|
||||||
if (!userData.Likes.HasValue || userData.Likes != query.IsLiked.Value)
|
if (!userData.Likes.HasValue || userData.Likes != query.IsLiked.Value)
|
||||||
{
|
{
|
||||||
@ -1228,7 +1228,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
if (query.IsFavoriteOrLiked.HasValue)
|
if (query.IsFavoriteOrLiked.HasValue)
|
||||||
{
|
{
|
||||||
userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
|
userData = userData ?? userDataManager.GetUserData(user, item);
|
||||||
var isFavoriteOrLiked = userData.IsFavorite || (userData.Likes ?? false);
|
var isFavoriteOrLiked = userData.IsFavorite || (userData.Likes ?? false);
|
||||||
|
|
||||||
if (isFavoriteOrLiked != query.IsFavoriteOrLiked.Value)
|
if (isFavoriteOrLiked != query.IsFavoriteOrLiked.Value)
|
||||||
@ -1239,7 +1239,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
if (query.IsFavorite.HasValue)
|
if (query.IsFavorite.HasValue)
|
||||||
{
|
{
|
||||||
userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
|
userData = userData ?? userDataManager.GetUserData(user, item);
|
||||||
|
|
||||||
if (userData.IsFavorite != query.IsFavorite.Value)
|
if (userData.IsFavorite != query.IsFavorite.Value)
|
||||||
{
|
{
|
||||||
@ -1249,7 +1249,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
if (query.IsResumable.HasValue)
|
if (query.IsResumable.HasValue)
|
||||||
{
|
{
|
||||||
userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
|
userData = userData ?? userDataManager.GetUserData(user, item);
|
||||||
var isResumable = userData.PlaybackPositionTicks > 0;
|
var isResumable = userData.PlaybackPositionTicks > 0;
|
||||||
|
|
||||||
if (isResumable != query.IsResumable.Value)
|
if (isResumable != query.IsResumable.Value)
|
||||||
|
@ -28,7 +28,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
IThemeMedia,
|
IThemeMedia,
|
||||||
IArchivable
|
IArchivable
|
||||||
{
|
{
|
||||||
public Guid? PrimaryVersionId { get; set; }
|
[IgnoreDataMember]
|
||||||
|
public string PrimaryVersionId { get; set; }
|
||||||
|
|
||||||
public List<string> AdditionalParts { get; set; }
|
public List<string> AdditionalParts { get; set; }
|
||||||
public List<string> LocalAlternateVersions { get; set; }
|
public List<string> LocalAlternateVersions { get; set; }
|
||||||
@ -44,6 +45,20 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override string PresentationUniqueKey
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(PrimaryVersionId))
|
||||||
|
{
|
||||||
|
return PrimaryVersionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base.PresentationUniqueKey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public long? Size { get; set; }
|
public long? Size { get; set; }
|
||||||
public string Container { get; set; }
|
public string Container { get; set; }
|
||||||
public int? TotalBitrate { get; set; }
|
public int? TotalBitrate { get; set; }
|
||||||
@ -56,143 +71,6 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <value>The timestamp.</value>
|
/// <value>The timestamp.</value>
|
||||||
public TransportStreamTimestamp? Timestamp { get; set; }
|
public TransportStreamTimestamp? Timestamp { get; set; }
|
||||||
|
|
||||||
public Video()
|
|
||||||
{
|
|
||||||
PlayableStreamFileNames = new List<string>();
|
|
||||||
AdditionalParts = new List<string>();
|
|
||||||
LocalAlternateVersions = new List<string>();
|
|
||||||
Tags = new List<string>();
|
|
||||||
SubtitleFiles = new List<string>();
|
|
||||||
LinkedAlternateVersions = new List<LinkedChild>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CanDownload()
|
|
||||||
{
|
|
||||||
if (VideoType == VideoType.HdDvd || VideoType == VideoType.Dvd ||
|
|
||||||
VideoType == VideoType.BluRay)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var locationType = LocationType;
|
|
||||||
return locationType != LocationType.Remote &&
|
|
||||||
locationType != LocationType.Virtual;
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public override bool SupportsAddingToPlaylist
|
|
||||||
{
|
|
||||||
get { return LocationType == LocationType.FileSystem && RunTimeTicks.HasValue; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public int MediaSourceCount
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return LinkedAlternateVersions.Count + LocalAlternateVersions.Count + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public bool IsStacked
|
|
||||||
{
|
|
||||||
get { return AdditionalParts.Count > 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public bool HasLocalAlternateVersions
|
|
||||||
{
|
|
||||||
get { return LocalAlternateVersions.Count > 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
|
||||||
public bool IsArchive
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (string.IsNullOrWhiteSpace(Path))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var ext = System.IO.Path.GetExtension(Path) ?? string.Empty;
|
|
||||||
|
|
||||||
return new[] { ".zip", ".rar", ".7z" }.Contains(ext, StringComparer.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<Guid> GetAdditionalPartIds()
|
|
||||||
{
|
|
||||||
return AdditionalParts.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<Guid> GetLocalAlternateVersionIds()
|
|
||||||
{
|
|
||||||
return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
|
||||||
if (ExtraType.HasValue)
|
|
||||||
{
|
|
||||||
var key = this.GetProviderId(MetadataProviders.Imdb) ?? this.GetProviderId(MetadataProviders.Tmdb);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(key))
|
|
||||||
{
|
|
||||||
key = key + "-" + ExtraType.ToString().ToLower();
|
|
||||||
|
|
||||||
// Make sure different trailers have their own data.
|
|
||||||
if (RunTimeTicks.HasValue)
|
|
||||||
{
|
|
||||||
key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
|
|
||||||
}
|
|
||||||
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CreateUserDataKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the linked children.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>IEnumerable{BaseItem}.</returns>
|
|
||||||
public IEnumerable<Video> GetAlternateVersions()
|
|
||||||
{
|
|
||||||
var filesWithinSameDirectory = GetLocalAlternateVersionIds()
|
|
||||||
.Select(i => LibraryManager.GetItemById(i))
|
|
||||||
.Where(i => i != null)
|
|
||||||
.OfType<Video>();
|
|
||||||
|
|
||||||
return filesWithinSameDirectory.Concat(GetLinkedAlternateVersions())
|
|
||||||
.OrderBy(i => i.SortName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<Video> GetLinkedAlternateVersions()
|
|
||||||
{
|
|
||||||
var linkedVersions = LinkedAlternateVersions
|
|
||||||
.Select(GetLinkedChild)
|
|
||||||
.Where(i => i != null)
|
|
||||||
.OfType<Video>();
|
|
||||||
|
|
||||||
return linkedVersions
|
|
||||||
.OrderBy(i => i.SortName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the additional parts.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>IEnumerable{Video}.</returns>
|
|
||||||
public IEnumerable<Video> GetAdditionalParts()
|
|
||||||
{
|
|
||||||
return GetAdditionalPartIds()
|
|
||||||
.Select(i => LibraryManager.GetItemById(i))
|
|
||||||
.Where(i => i != null)
|
|
||||||
.OfType<Video>()
|
|
||||||
.OrderBy(i => i.SortName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the subtitle paths.
|
/// Gets or sets the subtitle paths.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -259,6 +137,174 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <value>The aspect ratio.</value>
|
/// <value>The aspect ratio.</value>
|
||||||
public string AspectRatio { get; set; }
|
public string AspectRatio { get; set; }
|
||||||
|
|
||||||
|
public Video()
|
||||||
|
{
|
||||||
|
PlayableStreamFileNames = new List<string>();
|
||||||
|
AdditionalParts = new List<string>();
|
||||||
|
LocalAlternateVersions = new List<string>();
|
||||||
|
Tags = new List<string>();
|
||||||
|
SubtitleFiles = new List<string>();
|
||||||
|
LinkedAlternateVersions = new List<LinkedChild>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanDownload()
|
||||||
|
{
|
||||||
|
if (VideoType == VideoType.HdDvd || VideoType == VideoType.Dvd ||
|
||||||
|
VideoType == VideoType.BluRay)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var locationType = LocationType;
|
||||||
|
return locationType != LocationType.Remote &&
|
||||||
|
locationType != LocationType.Virtual;
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsAddingToPlaylist
|
||||||
|
{
|
||||||
|
get { return LocationType == LocationType.FileSystem && RunTimeTicks.HasValue; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public int MediaSourceCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrWhiteSpace(PrimaryVersionId))
|
||||||
|
{
|
||||||
|
var item = LibraryManager.GetItemById(PrimaryVersionId) as Video;
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
return item.MediaSourceCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LinkedAlternateVersions.Count + LocalAlternateVersions.Count + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsStacked
|
||||||
|
{
|
||||||
|
get { return AdditionalParts.Count > 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool HasLocalAlternateVersions
|
||||||
|
{
|
||||||
|
get { return LocalAlternateVersions.Count > 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public bool IsArchive
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(Path))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var ext = System.IO.Path.GetExtension(Path) ?? string.Empty;
|
||||||
|
|
||||||
|
return new[] { ".zip", ".rar", ".7z" }.Contains(ext, StringComparer.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Guid> GetAdditionalPartIds()
|
||||||
|
{
|
||||||
|
return AdditionalParts.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Guid> GetLocalAlternateVersionIds()
|
||||||
|
{
|
||||||
|
return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
protected virtual bool EnableDefaultVideoUserDataKeys
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<string> GetUserDataKeys()
|
||||||
|
{
|
||||||
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
|
if (EnableDefaultVideoUserDataKeys)
|
||||||
|
{
|
||||||
|
if (ExtraType.HasValue)
|
||||||
|
{
|
||||||
|
var key = this.GetProviderId(MetadataProviders.Tmdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(key))
|
||||||
|
{
|
||||||
|
list.Insert(0, GetUserDataKey(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
key = this.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(key))
|
||||||
|
{
|
||||||
|
list.Insert(0, GetUserDataKey(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var key = this.GetProviderId(MetadataProviders.Imdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(key))
|
||||||
|
{
|
||||||
|
list.Insert(0, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
key = this.GetProviderId(MetadataProviders.Tmdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(key))
|
||||||
|
{
|
||||||
|
list.Insert(0, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetUserDataKey(string providerId)
|
||||||
|
{
|
||||||
|
var key = providerId + "-" + ExtraType.ToString().ToLower();
|
||||||
|
|
||||||
|
// Make sure different trailers have their own data.
|
||||||
|
if (RunTimeTicks.HasValue)
|
||||||
|
{
|
||||||
|
key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Video> GetLinkedAlternateVersions()
|
||||||
|
{
|
||||||
|
var linkedVersions = LinkedAlternateVersions
|
||||||
|
.Select(GetLinkedChild)
|
||||||
|
.Where(i => i != null)
|
||||||
|
.OfType<Video>();
|
||||||
|
|
||||||
|
return linkedVersions
|
||||||
|
.OrderBy(i => i.SortName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the additional parts.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>IEnumerable{Video}.</returns>
|
||||||
|
public IEnumerable<Video> GetAdditionalParts()
|
||||||
|
{
|
||||||
|
return GetAdditionalPartIds()
|
||||||
|
.Select(i => LibraryManager.GetItemById(i))
|
||||||
|
.Where(i => i != null)
|
||||||
|
.OfType<Video>()
|
||||||
|
.OrderBy(i => i.SortName);
|
||||||
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override string ContainingFolderPath
|
public override string ContainingFolderPath
|
||||||
{
|
{
|
||||||
@ -317,6 +363,11 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (newAsVideo.VideoType != VideoType)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.IsValidFromResolver(newItem);
|
return base.IsValidFromResolver(newItem);
|
||||||
@ -463,6 +514,36 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
}).FirstOrDefault();
|
}).FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Tuple<Video, MediaSourceType>> GetAllVideosForMediaSources()
|
||||||
|
{
|
||||||
|
var list = new List<Tuple<Video, MediaSourceType>>();
|
||||||
|
|
||||||
|
list.Add(new Tuple<Video, MediaSourceType>(this, MediaSourceType.Default));
|
||||||
|
list.AddRange(GetLinkedAlternateVersions().Select(i => new Tuple<Video, MediaSourceType>(i, MediaSourceType.Grouping)));
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(PrimaryVersionId))
|
||||||
|
{
|
||||||
|
var primary = LibraryManager.GetItemById(PrimaryVersionId) as Video;
|
||||||
|
if (primary != null)
|
||||||
|
{
|
||||||
|
var existingIds = list.Select(i => i.Item1.Id).ToList();
|
||||||
|
list.Add(new Tuple<Video, MediaSourceType>(primary, MediaSourceType.Grouping));
|
||||||
|
list.AddRange(primary.GetLinkedAlternateVersions().Where(i => !existingIds.Contains(i.Id)).Select(i => new Tuple<Video, MediaSourceType>(i, MediaSourceType.Grouping)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var localAlternates = list
|
||||||
|
.SelectMany(i => i.Item1.GetLocalAlternateVersionIds())
|
||||||
|
.Select(LibraryManager.GetItemById)
|
||||||
|
.Where(i => i != null)
|
||||||
|
.OfType<Video>()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
list.AddRange(localAlternates.Select(i => new Tuple<Video, MediaSourceType>(i, MediaSourceType.Default)));
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||||
{
|
{
|
||||||
if (SourceType == SourceType.Channel)
|
if (SourceType == SourceType.Channel)
|
||||||
@ -481,13 +562,8 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
var item = this;
|
var list = GetAllVideosForMediaSources();
|
||||||
|
var result = list.Select(i => GetVersionInfo(enablePathSubstitution, i.Item1, i.Item2)).ToList();
|
||||||
var result = item.GetAlternateVersions()
|
|
||||||
.Select(i => GetVersionInfo(enablePathSubstitution, i, MediaSourceType.Grouping))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
result.Add(GetVersionInfo(enablePathSubstitution, item, MediaSourceType.Default));
|
|
||||||
|
|
||||||
return result.OrderBy(i =>
|
return result.OrderBy(i =>
|
||||||
{
|
{
|
||||||
|
@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Year : BaseItem, IItemByName
|
public class Year : BaseItem, IItemByName
|
||||||
{
|
{
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
return "Year-" + Name;
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
|
list.Insert(0, "Year-" + Name);
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -71,6 +70,22 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
return inputItems.Where(i => i.ProductionYear.HasValue && i.ProductionYear.Value == year);
|
return inputItems.Where(i => i.ProductionYear.HasValue && i.ProductionYear.Value == year);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
|
||||||
|
{
|
||||||
|
int year;
|
||||||
|
|
||||||
|
var usCulture = new CultureInfo("en-US");
|
||||||
|
|
||||||
|
if (!int.TryParse(Name, NumberStyles.Integer, usCulture, out year))
|
||||||
|
{
|
||||||
|
return new List<BaseItem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
query.Years = new[] { year };
|
||||||
|
|
||||||
|
return LibraryManager.GetItemList(query);
|
||||||
|
}
|
||||||
|
|
||||||
public int? GetYearValue()
|
public int? GetYearValue()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
12
MediaBrowser.Controller/Health/IHealthMonitor.cs
Normal file
12
MediaBrowser.Controller/Health/IHealthMonitor.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Notifications;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Controller.Health
|
||||||
|
{
|
||||||
|
public interface IHealthMonitor
|
||||||
|
{
|
||||||
|
Task<List<Notification>> GetNotifications(CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
@ -25,7 +25,7 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <param name="fileInfo">The file information.</param>
|
/// <param name="fileInfo">The file information.</param>
|
||||||
/// <param name="parent">The parent.</param>
|
/// <param name="parent">The parent.</param>
|
||||||
/// <returns>BaseItem.</returns>
|
/// <returns>BaseItem.</returns>
|
||||||
BaseItem ResolvePath(FileSystemMetadata fileInfo,
|
BaseItem ResolvePath(FileSystemMetadata fileInfo,
|
||||||
Folder parent = null);
|
Folder parent = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -36,9 +36,9 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <param name="parent">The parent.</param>
|
/// <param name="parent">The parent.</param>
|
||||||
/// <param name="collectionType">Type of the collection.</param>
|
/// <param name="collectionType">Type of the collection.</param>
|
||||||
/// <returns>List{``0}.</returns>
|
/// <returns>List{``0}.</returns>
|
||||||
IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files,
|
IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files,
|
||||||
IDirectoryService directoryService,
|
IDirectoryService directoryService,
|
||||||
Folder parent, string
|
Folder parent, string
|
||||||
collectionType = null);
|
collectionType = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -59,8 +59,8 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The path.</param>
|
/// <param name="path">The path.</param>
|
||||||
/// <returns>BaseItem.</returns>
|
/// <returns>BaseItem.</returns>
|
||||||
BaseItem FindByPath(string path);
|
BaseItem FindByPath(string path, bool? isFolder);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the artist.
|
/// Gets the artist.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -156,7 +156,7 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <param name="id">The identifier.</param>
|
/// <param name="id">The identifier.</param>
|
||||||
/// <returns>BaseItem.</returns>
|
/// <returns>BaseItem.</returns>
|
||||||
BaseItem GetMemoryItemById(Guid id);
|
BaseItem GetMemoryItemById(Guid id);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the intros.
|
/// Gets the intros.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -243,6 +243,8 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <returns>BaseItem.</returns>
|
/// <returns>BaseItem.</returns>
|
||||||
BaseItem RetrieveItem(Guid id);
|
BaseItem RetrieveItem(Guid id);
|
||||||
|
|
||||||
|
bool IsScanRunning { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Occurs when [item added].
|
/// Occurs when [item added].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -290,7 +292,7 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <param name="path">The path.</param>
|
/// <param name="path">The path.</param>
|
||||||
/// <returns>System.String.</returns>
|
/// <returns>System.String.</returns>
|
||||||
string GetConfiguredContentType(string path);
|
string GetConfiguredContentType(string path);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Normalizes the root path list.
|
/// Normalizes the root path list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -332,8 +334,8 @@ namespace MediaBrowser.Controller.Library
|
|||||||
Task<UserView> GetNamedView(User user,
|
Task<UserView> GetNamedView(User user,
|
||||||
string name,
|
string name,
|
||||||
string parentId,
|
string parentId,
|
||||||
string viewType,
|
string viewType,
|
||||||
string sortName,
|
string sortName,
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -346,8 +348,8 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task<UserView>.</returns>
|
/// <returns>Task<UserView>.</returns>
|
||||||
Task<UserView> GetNamedView(User user,
|
Task<UserView> GetNamedView(User user,
|
||||||
string name,
|
string name,
|
||||||
string viewType,
|
string viewType,
|
||||||
string sortName,
|
string sortName,
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
@ -393,7 +395,7 @@ namespace MediaBrowser.Controller.Library
|
|||||||
string viewType,
|
string viewType,
|
||||||
string sortName,
|
string sortName,
|
||||||
CancellationToken cancellationToken);
|
CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether [is video file] [the specified path].
|
/// Determines whether [is video file] [the specified path].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -477,14 +479,14 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <returns>List<PersonInfo>.</returns>
|
/// <returns>List<PersonInfo>.</returns>
|
||||||
List<PersonInfo> GetPeople(InternalPeopleQuery query);
|
List<PersonInfo> GetPeople(InternalPeopleQuery query);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the people items.
|
/// Gets the people items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <returns>List<Person>.</returns>
|
/// <returns>List<Person>.</returns>
|
||||||
List<Person> GetPeopleItems(InternalPeopleQuery query);
|
List<Person> GetPeopleItems(InternalPeopleQuery query);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all people names.
|
/// Gets all people names.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -559,7 +561,7 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <param name="query">The query.</param>
|
/// <param name="query">The query.</param>
|
||||||
/// <returns>QueryResult<BaseItem>.</returns>
|
/// <returns>QueryResult<BaseItem>.</returns>
|
||||||
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query);
|
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ignores the file.
|
/// Ignores the file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -567,5 +569,10 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <param name="parent">The parent.</param>
|
/// <param name="parent">The parent.</param>
|
||||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
||||||
bool IgnoreFile(FileSystemMetadata file, BaseItem parent);
|
bool IgnoreFile(FileSystemMetadata file, BaseItem parent);
|
||||||
|
|
||||||
|
void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, bool refreshLibrary);
|
||||||
|
void RemoveVirtualFolder(string name, bool refreshLibrary);
|
||||||
|
void AddMediaPath(string virtualFolderName, string path);
|
||||||
|
void RemoveMediaPath(string virtualFolderName, string path);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -29,21 +29,10 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task SaveUserData(Guid userId, IHasUserData item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken);
|
Task SaveUserData(Guid userId, IHasUserData item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
UserItemData GetUserData(IHasUserData user, IHasUserData item);
|
||||||
/// Gets the user data.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="userId">The user id.</param>
|
|
||||||
/// <param name="key">The key.</param>
|
|
||||||
/// <returns>Task{UserItemData}.</returns>
|
|
||||||
UserItemData GetUserData(string userId, string key);
|
|
||||||
|
|
||||||
/// <summary>
|
UserItemData GetUserData(string userId, IHasUserData item);
|
||||||
/// Gets the user data.
|
UserItemData GetUserData(Guid userId, IHasUserData item);
|
||||||
/// </summary>
|
|
||||||
/// <param name="userId">The user id.</param>
|
|
||||||
/// <param name="key">The key.</param>
|
|
||||||
/// <returns>Task{UserItemData}.</returns>
|
|
||||||
UserItemData GetUserData(Guid userId, string key);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the user data dto.
|
/// Gets the user data dto.
|
||||||
|
@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The banner URL
|
/// The banner URL
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly string BannerUrl = "http://www.thetvdb.com/banners/";
|
public static readonly string BannerUrl = "https://www.thetvdb.com/banners/";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the air days.
|
/// Gets the air days.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Library
|
namespace MediaBrowser.Controller.Library
|
||||||
{
|
{
|
||||||
@ -15,11 +16,7 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <value>The user id.</value>
|
/// <value>The user id.</value>
|
||||||
public Guid UserId { get; set; }
|
public Guid UserId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
public List<string> Keys { get; set; }
|
||||||
/// Gets or sets the key.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The key.</value>
|
|
||||||
public string Key { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the save reason.
|
/// Gets or sets the save reason.
|
||||||
|
@ -46,6 +46,8 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task<List<MediaSourceInfo>>.</returns>
|
/// <returns>Task<List<MediaSourceInfo>>.</returns>
|
||||||
Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken);
|
Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
string ApplyDuration(string streamPath, TimeSpan duration);
|
||||||
}
|
}
|
||||||
public interface IConfigurableTunerHost
|
public interface IConfigurableTunerHost
|
||||||
{
|
{
|
||||||
|
@ -45,17 +45,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
|
||||||
var name = GetClientTypeName();
|
|
||||||
|
|
||||||
return name + "-" + Name + (EpisodeTitle ?? string.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value indicating whether this instance is owned item.
|
/// Gets a value indicating whether this instance is owned item.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
{
|
{
|
||||||
public class LiveTvChannel : BaseItem, IHasMediaSources
|
public class LiveTvChannel : BaseItem, IHasMediaSources
|
||||||
{
|
{
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
return GetClientTypeName() + "-" + Name;
|
var list = base.GetUserDataKeys();
|
||||||
|
|
||||||
|
list.Insert(0, GetClientTypeName() + "-" + Name);
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override UnratedItem GetBlockUnratedType()
|
public override UnratedItem GetBlockUnratedType()
|
||||||
@ -45,6 +44,15 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool EnableRememberingTrackSelections
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the number.
|
/// Gets or sets the number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -4,36 +4,40 @@ using MediaBrowser.Controller.Providers;
|
|||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.LiveTv;
|
using MediaBrowser.Model.LiveTv;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.LiveTv
|
namespace MediaBrowser.Controller.LiveTv
|
||||||
{
|
{
|
||||||
public class LiveTvProgram : BaseItem, IHasLookupInfo<LiveTvProgramLookupInfo>, IHasStartDate, IHasProgramAttributes
|
public class LiveTvProgram : BaseItem, IHasLookupInfo<LiveTvProgramLookupInfo>, IHasStartDate, IHasProgramAttributes
|
||||||
{
|
{
|
||||||
/// <summary>
|
public override List<string> GetUserDataKeys()
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
{
|
||||||
if (IsMovie)
|
var list = base.GetUserDataKeys();
|
||||||
{
|
|
||||||
var key = Movie.GetMovieUserDataKey(this);
|
|
||||||
|
|
||||||
|
if (!IsSeries)
|
||||||
|
{
|
||||||
|
var key = this.GetProviderId(MetadataProviders.Imdb);
|
||||||
if (!string.IsNullOrWhiteSpace(key))
|
if (!string.IsNullOrWhiteSpace(key))
|
||||||
{
|
{
|
||||||
return key;
|
list.Insert(0, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
key = this.GetProviderId(MetadataProviders.Tmdb);
|
||||||
|
if (!string.IsNullOrWhiteSpace(key))
|
||||||
|
{
|
||||||
|
list.Insert(0, key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!string.IsNullOrWhiteSpace(EpisodeTitle))
|
||||||
if (IsSeries && !string.IsNullOrWhiteSpace(EpisodeTitle))
|
|
||||||
{
|
{
|
||||||
var name = GetClientTypeName();
|
var name = GetClientTypeName();
|
||||||
|
|
||||||
return name + "-" + Name + (EpisodeTitle ?? string.Empty);
|
list.Insert(0, name + "-" + Name + (EpisodeTitle ?? string.Empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
return base.CreateUserDataKey();
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
|
@ -45,32 +45,6 @@ namespace MediaBrowser.Controller.LiveTv
|
|||||||
set { }
|
set { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the user data key.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>System.String.</returns>
|
|
||||||
protected override string CreateUserDataKey()
|
|
||||||
{
|
|
||||||
if (IsMovie)
|
|
||||||
{
|
|
||||||
var key = Movie.GetMovieUserDataKey(this);
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(key))
|
|
||||||
{
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsSeries && !string.IsNullOrWhiteSpace(EpisodeTitle))
|
|
||||||
{
|
|
||||||
var name = GetClientTypeName();
|
|
||||||
|
|
||||||
return name + "-" + Name + (EpisodeTitle ?? string.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.CreateUserDataKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[IgnoreDataMember]
|
||||||
public override string MediaType
|
public override string MediaType
|
||||||
{
|
{
|
||||||
|
@ -180,6 +180,7 @@
|
|||||||
<Compile Include="Entities\UserView.cs" />
|
<Compile Include="Entities\UserView.cs" />
|
||||||
<Compile Include="Entities\UserViewBuilder.cs" />
|
<Compile Include="Entities\UserViewBuilder.cs" />
|
||||||
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
|
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
|
||||||
|
<Compile Include="Health\IHealthMonitor.cs" />
|
||||||
<Compile Include="IO\ThrottledStream.cs" />
|
<Compile Include="IO\ThrottledStream.cs" />
|
||||||
<Compile Include="Library\DeleteOptions.cs" />
|
<Compile Include="Library\DeleteOptions.cs" />
|
||||||
<Compile Include="Library\ILibraryPostScanTask.cs" />
|
<Compile Include="Library\ILibraryPostScanTask.cs" />
|
||||||
|
@ -4,13 +4,14 @@ using System;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Model.Dlna;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.MediaEncoding
|
namespace MediaBrowser.Controller.MediaEncoding
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interface IMediaEncoder
|
/// Interface IMediaEncoder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IMediaEncoder
|
public interface IMediaEncoder : ITranscoderSupport
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the encoder path.
|
/// Gets the encoder path.
|
||||||
|
@ -19,12 +19,6 @@ namespace MediaBrowser.Controller.Notifications
|
|||||||
/// Occurs when [notifications marked read].
|
/// Occurs when [notifications marked read].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event EventHandler<NotificationReadEventArgs> NotificationsMarkedRead;
|
event EventHandler<NotificationReadEventArgs> NotificationsMarkedRead;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Opens the connection to the repository
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Task.</returns>
|
|
||||||
Task Initialize();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the notifications.
|
/// Gets the notifications.
|
||||||
|
@ -11,12 +11,6 @@ namespace MediaBrowser.Controller.Persistence
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IDisplayPreferencesRepository : IRepository
|
public interface IDisplayPreferencesRepository : IRepository
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Opens the connection to the repository
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Task.</returns>
|
|
||||||
Task Initialize();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves display preferences for an item
|
/// Saves display preferences for an item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -13,12 +13,6 @@ namespace MediaBrowser.Controller.Persistence
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IItemRepository : IRepository
|
public interface IItemRepository : IRepository
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Opens the connection to the repository
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Task.</returns>
|
|
||||||
Task Initialize();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves an item
|
/// Saves an item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -11,12 +11,6 @@ namespace MediaBrowser.Controller.Persistence
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IUserDataRepository : IRepository
|
public interface IUserDataRepository : IRepository
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Opens the connection to the repository
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Task.</returns>
|
|
||||||
Task Initialize();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the user data.
|
/// Saves the user data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -6,6 +6,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.Serialization;
|
using System.Runtime.Serialization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Playlists
|
namespace MediaBrowser.Controller.Playlists
|
||||||
{
|
{
|
||||||
@ -38,6 +39,15 @@ namespace MediaBrowser.Controller.Playlists
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[IgnoreDataMember]
|
||||||
|
public override bool SupportsCumulativeRunTimeTicks
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override bool IsAuthorizedToDelete(User user)
|
public override bool IsAuthorizedToDelete(User user)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -50,12 +60,12 @@ namespace MediaBrowser.Controller.Playlists
|
|||||||
|
|
||||||
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
||||||
{
|
{
|
||||||
return GetPlayableItems(user);
|
return GetPlayableItems(user).Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
|
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
|
||||||
{
|
{
|
||||||
var items = GetPlayableItems(user);
|
var items = GetPlayableItems(user).Result;
|
||||||
|
|
||||||
if (filter != null)
|
if (filter != null)
|
||||||
{
|
{
|
||||||
@ -70,32 +80,40 @@ namespace MediaBrowser.Controller.Playlists
|
|||||||
return GetLinkedChildrenInfos();
|
return GetLinkedChildrenInfos();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<BaseItem> GetPlayableItems(User user)
|
private Task<IEnumerable<BaseItem>> GetPlayableItems(User user)
|
||||||
{
|
{
|
||||||
return GetPlaylistItems(MediaType, base.GetChildren(user, true), user);
|
return GetPlaylistItems(MediaType, base.GetChildren(user, true), user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<BaseItem> GetPlaylistItems(string playlistMediaType, IEnumerable<BaseItem> inputItems, User user)
|
public static async Task<IEnumerable<BaseItem>> GetPlaylistItems(string playlistMediaType, IEnumerable<BaseItem> inputItems, User user)
|
||||||
{
|
{
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
inputItems = inputItems.Where(i => i.IsVisible(user));
|
inputItems = inputItems.Where(i => i.IsVisible(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
return inputItems.SelectMany(i => GetPlaylistItems(i, user))
|
var list = new List<BaseItem>();
|
||||||
.Where(m => string.Equals(m.MediaType, playlistMediaType, StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
foreach (var item in inputItems)
|
||||||
|
{
|
||||||
|
var playlistItems = await GetPlaylistItems(item, user, playlistMediaType).ConfigureAwait(false);
|
||||||
|
list.AddRange(playlistItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<BaseItem> GetPlaylistItems(BaseItem item, User user)
|
private static async Task<IEnumerable<BaseItem>> GetPlaylistItems(BaseItem item, User user, string mediaType)
|
||||||
{
|
{
|
||||||
var musicGenre = item as MusicGenre;
|
var musicGenre = item as MusicGenre;
|
||||||
if (musicGenre != null)
|
if (musicGenre != null)
|
||||||
{
|
{
|
||||||
Func<BaseItem, bool> filter = i => i is Audio && i.Genres.Contains(musicGenre.Name, StringComparer.OrdinalIgnoreCase);
|
var items = LibraryManager.GetItemList(new InternalItemsQuery(user)
|
||||||
|
{
|
||||||
var items = user == null
|
Recursive = true,
|
||||||
? LibraryManager.RootFolder.GetRecursiveChildren(filter)
|
IncludeItemTypes = new[] { typeof(Audio).Name },
|
||||||
: user.RootFolder.GetRecursiveChildren(user, filter);
|
Genres = new[] { musicGenre.Name }
|
||||||
|
});
|
||||||
|
|
||||||
return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending);
|
return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending);
|
||||||
}
|
}
|
||||||
@ -119,15 +137,19 @@ namespace MediaBrowser.Controller.Playlists
|
|||||||
var folder = item as Folder;
|
var folder = item as Folder;
|
||||||
if (folder != null)
|
if (folder != null)
|
||||||
{
|
{
|
||||||
var items = user == null
|
var query = new InternalItemsQuery(user)
|
||||||
? folder.GetRecursiveChildren(m => !m.IsFolder)
|
|
||||||
: folder.GetRecursiveChildren(user, m => !m.IsFolder);
|
|
||||||
|
|
||||||
if (folder.IsPreSorted)
|
|
||||||
{
|
{
|
||||||
return items;
|
Recursive = true,
|
||||||
}
|
IsFolder = false,
|
||||||
return LibraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending);
|
SortBy = new[] { ItemSortBy.SortName },
|
||||||
|
MediaTypes = new[] { mediaType },
|
||||||
|
EnableTotalRecordCount = false
|
||||||
|
};
|
||||||
|
|
||||||
|
var itemsResult = await folder.GetItems(query).ConfigureAwait(false);
|
||||||
|
var items = itemsResult.Items;
|
||||||
|
|
||||||
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new[] { item };
|
return new[] { item };
|
||||||
|
@ -21,11 +21,5 @@ namespace MediaBrowser.Controller.Providers
|
|||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken);
|
Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes this instance.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>Task.</returns>
|
|
||||||
Task Initialize();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,194 +1,41 @@
|
|||||||
namespace MediaBrowser.Dlna.Channels
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net;
|
||||||
|
using MediaBrowser.Controller.Channels;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Dlna;
|
||||||
|
using MediaBrowser.Controller.Providers;
|
||||||
|
using MediaBrowser.Dlna.ContentDirectory;
|
||||||
|
using MediaBrowser.Dlna.PlayTo;
|
||||||
|
using MediaBrowser.Model.Channels;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
|
using MediaBrowser.Model.Logging;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Dlna.Channels
|
||||||
{
|
{
|
||||||
//public class DlnaChannelFactory : IChannelFactory, IDisposable
|
//public class DlnaChannel : IChannel, IDisposable
|
||||||
//{
|
//{
|
||||||
// private readonly IServerConfigurationManager _config;
|
|
||||||
// private readonly ILogger _logger;
|
// private readonly ILogger _logger;
|
||||||
// private readonly IHttpClient _httpClient;
|
// private readonly IHttpClient _httpClient;
|
||||||
|
// private readonly IServerConfigurationManager _config;
|
||||||
// private readonly IDeviceDiscovery _deviceDiscovery;
|
|
||||||
|
|
||||||
// private readonly SemaphoreSlim _syncLock = new SemaphoreSlim(1, 1);
|
|
||||||
// private List<Device> _servers = new List<Device>();
|
// private List<Device> _servers = new List<Device>();
|
||||||
|
|
||||||
// public static DlnaChannelFactory Instance;
|
// private readonly IDeviceDiscovery _deviceDiscovery;
|
||||||
|
// private readonly SemaphoreSlim _syncLock = new SemaphoreSlim(1, 1);
|
||||||
// private Func<List<string>> _localServersLookup;
|
// private Func<List<string>> _localServersLookup;
|
||||||
|
|
||||||
// public DlnaChannelFactory(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger, IDeviceDiscovery deviceDiscovery)
|
// public static DlnaChannel Current;
|
||||||
|
|
||||||
|
// public DlnaChannel(ILogger logger, IHttpClient httpClient, IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config)
|
||||||
// {
|
// {
|
||||||
// _config = config;
|
|
||||||
// _httpClient = httpClient;
|
|
||||||
// _logger = logger;
|
// _logger = logger;
|
||||||
|
// _httpClient = httpClient;
|
||||||
// _deviceDiscovery = deviceDiscovery;
|
// _deviceDiscovery = deviceDiscovery;
|
||||||
// Instance = this;
|
// _config = config;
|
||||||
// }
|
// Current = this;
|
||||||
|
|
||||||
// internal void Start(Func<List<string>> localServersLookup)
|
|
||||||
// {
|
|
||||||
// _localServersLookup = localServersLookup;
|
|
||||||
|
|
||||||
// //deviceDiscovery.DeviceDiscovered += deviceDiscovery_DeviceDiscovered;
|
|
||||||
// _deviceDiscovery.DeviceLeft += deviceDiscovery_DeviceLeft;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async void deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e)
|
|
||||||
// {
|
|
||||||
// string usn;
|
|
||||||
// if (!e.Headers.TryGetValue("USN", out usn)) usn = string.Empty;
|
|
||||||
|
|
||||||
// string nt;
|
|
||||||
// if (!e.Headers.TryGetValue("NT", out nt)) nt = string.Empty;
|
|
||||||
|
|
||||||
// string location;
|
|
||||||
// if (!e.Headers.TryGetValue("Location", out location)) location = string.Empty;
|
|
||||||
|
|
||||||
// if (!IsValid(nt, usn))
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (_localServersLookup != null)
|
|
||||||
// {
|
|
||||||
// if (_localServersLookup().Any(i => usn.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1))
|
|
||||||
// {
|
|
||||||
// // Don't add the local Dlna server to this
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (GetExistingServers(usn).Any())
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// await _syncLock.WaitAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// if (GetExistingServers(usn).Any())
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var device = await Device.CreateuPnpDeviceAsync(new Uri(location), _httpClient, _config, _logger)
|
|
||||||
// .ConfigureAwait(false);
|
|
||||||
|
|
||||||
// if (!_servers.Any(i => string.Equals(i.Properties.UUID, device.Properties.UUID, StringComparison.OrdinalIgnoreCase)))
|
|
||||||
// {
|
|
||||||
// _servers.Add(device);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
|
|
||||||
// }
|
|
||||||
// finally
|
|
||||||
// {
|
|
||||||
// _syncLock.Release();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// async void deviceDiscovery_DeviceLeft(object sender, SsdpMessageEventArgs e)
|
|
||||||
// {
|
|
||||||
// string usn;
|
|
||||||
// if (!e.Headers.TryGetValue("USN", out usn)) usn = String.Empty;
|
|
||||||
|
|
||||||
// string nt;
|
|
||||||
// if (!e.Headers.TryGetValue("NT", out nt)) nt = String.Empty;
|
|
||||||
|
|
||||||
// if (!IsValid(nt, usn))
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!GetExistingServers(usn).Any())
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// await _syncLock.WaitAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var list = _servers.ToList();
|
|
||||||
|
|
||||||
// foreach (var device in GetExistingServers(usn).ToList())
|
|
||||||
// {
|
|
||||||
// list.Remove(device);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// _servers = list;
|
|
||||||
// }
|
|
||||||
// finally
|
|
||||||
// {
|
|
||||||
// _syncLock.Release();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private bool IsValid(string nt, string usn)
|
|
||||||
// {
|
|
||||||
// // It has to report that it's a media renderer
|
|
||||||
// if (usn.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 &&
|
|
||||||
// nt.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 &&
|
|
||||||
// usn.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1 &&
|
|
||||||
// nt.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1)
|
|
||||||
// {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private IEnumerable<Device> GetExistingServers(string usn)
|
|
||||||
// {
|
|
||||||
// return _servers
|
|
||||||
// .Where(i => usn.IndexOf(i.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public IEnumerable<IChannel> GetChannels()
|
|
||||||
// {
|
|
||||||
// //if (_servers.Count > 0)
|
|
||||||
// //{
|
|
||||||
// // var service = _servers[0].Properties.Services
|
|
||||||
// // .FirstOrDefault(i => string.Equals(i.ServiceType, "urn:schemas-upnp-org:service:ContentDirectory:1", StringComparison.OrdinalIgnoreCase));
|
|
||||||
|
|
||||||
// // var controlUrl = service == null ? null : (_servers[0].Properties.BaseUrl.TrimEnd('/') + "/" + service.ControlUrl.TrimStart('/'));
|
|
||||||
|
|
||||||
// // if (!string.IsNullOrEmpty(controlUrl))
|
|
||||||
// // {
|
|
||||||
// // return new List<IChannel>
|
|
||||||
// // {
|
|
||||||
// // new ServerChannel(_servers.ToList(), _httpClient, _logger, controlUrl)
|
|
||||||
// // };
|
|
||||||
// // }
|
|
||||||
// //}
|
|
||||||
|
|
||||||
// return new List<IChannel>();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public void Dispose()
|
|
||||||
// {
|
|
||||||
// if (_deviceDiscovery != null)
|
|
||||||
// {
|
|
||||||
// _deviceDiscovery.DeviceDiscovered -= deviceDiscovery_DeviceDiscovered;
|
|
||||||
// _deviceDiscovery.DeviceLeft -= deviceDiscovery_DeviceLeft;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//public class ServerChannel : IChannel, IFactoryChannel
|
|
||||||
//{
|
|
||||||
// private readonly IHttpClient _httpClient;
|
|
||||||
// private readonly ILogger _logger;
|
|
||||||
// public string ControlUrl { get; set; }
|
|
||||||
// public List<Device> Servers { get; set; }
|
|
||||||
|
|
||||||
// public ServerChannel(IHttpClient httpClient, ILogger logger)
|
|
||||||
// {
|
|
||||||
// _httpClient = httpClient;
|
|
||||||
// _logger = logger;
|
|
||||||
// Servers = new List<Device>();
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// public string Name
|
// public string Name
|
||||||
@ -221,17 +68,17 @@
|
|||||||
// return new InternalChannelFeatures
|
// return new InternalChannelFeatures
|
||||||
// {
|
// {
|
||||||
// ContentTypes = new List<ChannelMediaContentType>
|
// ContentTypes = new List<ChannelMediaContentType>
|
||||||
// {
|
// {
|
||||||
// ChannelMediaContentType.Song,
|
// ChannelMediaContentType.Song,
|
||||||
// ChannelMediaContentType.Clip
|
// ChannelMediaContentType.Clip
|
||||||
// },
|
// },
|
||||||
|
|
||||||
// MediaTypes = new List<ChannelMediaType>
|
// MediaTypes = new List<ChannelMediaType>
|
||||||
// {
|
// {
|
||||||
// ChannelMediaType.Audio,
|
// ChannelMediaType.Audio,
|
||||||
// ChannelMediaType.Video,
|
// ChannelMediaType.Video,
|
||||||
// ChannelMediaType.Photo
|
// ChannelMediaType.Photo
|
||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@ -240,85 +87,219 @@
|
|||||||
// return true;
|
// return true;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// public async Task<ChannelItemResult> GetChannelItems(InternalChannelItemQuery query, CancellationToken cancellationToken)
|
|
||||||
// {
|
|
||||||
// IEnumerable<ChannelItemInfo> items;
|
|
||||||
|
|
||||||
// if (string.IsNullOrWhiteSpace(query.FolderId))
|
|
||||||
// {
|
|
||||||
// items = Servers.Select(i => new ChannelItemInfo
|
|
||||||
// {
|
|
||||||
// FolderType = ChannelFolderType.Container,
|
|
||||||
// Id = GetServerId(i),
|
|
||||||
// Name = i.Properties.Name,
|
|
||||||
// Overview = i.Properties.ModelDescription,
|
|
||||||
// Type = ChannelItemType.Folder
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// var idParts = query.FolderId.Split('|');
|
|
||||||
// var folderId = idParts.Length == 2 ? idParts[1] : null;
|
|
||||||
|
|
||||||
// var result = await new ContentDirectoryBrowser(_httpClient, _logger).Browse(new ContentDirectoryBrowseRequest
|
|
||||||
// {
|
|
||||||
// Limit = query.Limit,
|
|
||||||
// StartIndex = query.StartIndex,
|
|
||||||
// ParentId = folderId,
|
|
||||||
// ContentDirectoryUrl = ControlUrl
|
|
||||||
|
|
||||||
// }, cancellationToken).ConfigureAwait(false);
|
|
||||||
|
|
||||||
// items = result.Items.ToList();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var list = items.ToList();
|
|
||||||
// var count = list.Count;
|
|
||||||
|
|
||||||
// list = ApplyPaging(list, query).ToList();
|
|
||||||
|
|
||||||
// return new ChannelItemResult
|
|
||||||
// {
|
|
||||||
// Items = list,
|
|
||||||
// TotalRecordCount = count
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private string GetServerId(Device device)
|
|
||||||
// {
|
|
||||||
// return device.Properties.UUID.GetMD5().ToString("N");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private IEnumerable<T> ApplyPaging<T>(IEnumerable<T> items, InternalChannelItemQuery query)
|
|
||||||
// {
|
|
||||||
// if (query.StartIndex.HasValue)
|
|
||||||
// {
|
|
||||||
// items = items.Skip(query.StartIndex.Value);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (query.Limit.HasValue)
|
|
||||||
// {
|
|
||||||
// items = items.Take(query.Limit.Value);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return items;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public Task<DynamicImageResponse> GetChannelImage(ImageType type, CancellationToken cancellationToken)
|
// public Task<DynamicImageResponse> GetChannelImage(ImageType type, CancellationToken cancellationToken)
|
||||||
// {
|
// {
|
||||||
// // TODO: Implement
|
// throw new NotImplementedException();
|
||||||
// return Task.FromResult(new DynamicImageResponse
|
|
||||||
// {
|
|
||||||
// HasImage = false
|
|
||||||
// });
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// public IEnumerable<ImageType> GetSupportedChannelImages()
|
// public IEnumerable<ImageType> GetSupportedChannelImages()
|
||||||
// {
|
// {
|
||||||
// return new List<ImageType>
|
// return new List<ImageType>
|
||||||
|
// {
|
||||||
|
// ImageType.Primary
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public void Start(Func<List<string>> localServersLookup)
|
||||||
|
// {
|
||||||
|
// _localServersLookup = localServersLookup;
|
||||||
|
|
||||||
|
// _deviceDiscovery.DeviceDiscovered -= deviceDiscovery_DeviceDiscovered;
|
||||||
|
// _deviceDiscovery.DeviceLeft -= deviceDiscovery_DeviceLeft;
|
||||||
|
|
||||||
|
// _deviceDiscovery.DeviceDiscovered += deviceDiscovery_DeviceDiscovered;
|
||||||
|
// _deviceDiscovery.DeviceLeft += deviceDiscovery_DeviceLeft;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public async Task<ChannelItemResult> GetChannelItems(InternalChannelItemQuery query, CancellationToken cancellationToken)
|
||||||
|
// {
|
||||||
|
// if (string.IsNullOrWhiteSpace(query.FolderId))
|
||||||
// {
|
// {
|
||||||
// ImageType.Primary
|
// return await GetServers(query, cancellationToken).ConfigureAwait(false);
|
||||||
// };
|
// }
|
||||||
|
|
||||||
|
// return new ChannelItemResult();
|
||||||
|
|
||||||
|
// //var idParts = query.FolderId.Split('|');
|
||||||
|
// //var folderId = idParts.Length == 2 ? idParts[1] : null;
|
||||||
|
|
||||||
|
// //var result = await new ContentDirectoryBrowser(_httpClient, _logger).Browse(new ContentDirectoryBrowseRequest
|
||||||
|
// //{
|
||||||
|
// // Limit = query.Limit,
|
||||||
|
// // StartIndex = query.StartIndex,
|
||||||
|
// // ParentId = folderId,
|
||||||
|
// // ContentDirectoryUrl = ControlUrl
|
||||||
|
|
||||||
|
// //}, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// //items = result.Items.ToList();
|
||||||
|
|
||||||
|
// //var list = items.ToList();
|
||||||
|
// //var count = list.Count;
|
||||||
|
|
||||||
|
// //list = ApplyPaging(list, query).ToList();
|
||||||
|
|
||||||
|
// //return new ChannelItemResult
|
||||||
|
// //{
|
||||||
|
// // Items = list,
|
||||||
|
// // TotalRecordCount = count
|
||||||
|
// //};
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public async Task<ChannelItemResult> GetServers(InternalChannelItemQuery query, CancellationToken cancellationToken)
|
||||||
|
// {
|
||||||
|
// await _syncLock.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// var items = _servers.Select(i =>
|
||||||
|
// {
|
||||||
|
// var service = i.Properties.Services
|
||||||
|
// .FirstOrDefault(s => string.Equals(s.ServiceType, "urn:schemas-upnp-org:service:ContentDirectory:1", StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
// var controlUrl = service == null ? null : (_servers[0].Properties.BaseUrl.TrimEnd('/') + "/" + service.ControlUrl.TrimStart('/'));
|
||||||
|
|
||||||
|
// if (string.IsNullOrWhiteSpace(controlUrl))
|
||||||
|
// {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return new ChannelItemInfo
|
||||||
|
// {
|
||||||
|
// Id = i.Properties.UUID,
|
||||||
|
// Name = i.Properties.Name,
|
||||||
|
// Type = ChannelItemType.Folder
|
||||||
|
// };
|
||||||
|
|
||||||
|
// }).Where(i => i != null).ToList();
|
||||||
|
|
||||||
|
// return new ChannelItemResult
|
||||||
|
// {
|
||||||
|
// TotalRecordCount = items.Count,
|
||||||
|
// Items = items
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// finally
|
||||||
|
// {
|
||||||
|
// _syncLock.Release();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async void deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e)
|
||||||
|
// {
|
||||||
|
// string usn;
|
||||||
|
// if (!e.Headers.TryGetValue("USN", out usn)) usn = string.Empty;
|
||||||
|
|
||||||
|
// string nt;
|
||||||
|
// if (!e.Headers.TryGetValue("NT", out nt)) nt = string.Empty;
|
||||||
|
|
||||||
|
// string location;
|
||||||
|
// if (!e.Headers.TryGetValue("Location", out location)) location = string.Empty;
|
||||||
|
|
||||||
|
// if (!IsValid(nt, usn))
|
||||||
|
// {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (_localServersLookup != null)
|
||||||
|
// {
|
||||||
|
// if (_localServersLookup().Any(i => usn.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1))
|
||||||
|
// {
|
||||||
|
// // Don't add the local Dlna server to this
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// await _syncLock.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
// var serverList = _servers.ToList();
|
||||||
|
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// if (GetExistingServers(serverList, usn).Any())
|
||||||
|
// {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var device = await Device.CreateuPnpDeviceAsync(new Uri(location), _httpClient, _config, _logger)
|
||||||
|
// .ConfigureAwait(false);
|
||||||
|
|
||||||
|
// if (!serverList.Any(i => string.Equals(i.Properties.UUID, device.Properties.UUID, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
// {
|
||||||
|
// serverList.Add(device);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
|
||||||
|
// }
|
||||||
|
// finally
|
||||||
|
// {
|
||||||
|
// _syncLock.Release();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async void deviceDiscovery_DeviceLeft(object sender, SsdpMessageEventArgs e)
|
||||||
|
// {
|
||||||
|
// string usn;
|
||||||
|
// if (!e.Headers.TryGetValue("USN", out usn)) usn = String.Empty;
|
||||||
|
|
||||||
|
// string nt;
|
||||||
|
// if (!e.Headers.TryGetValue("NT", out nt)) nt = String.Empty;
|
||||||
|
|
||||||
|
// if (!IsValid(nt, usn))
|
||||||
|
// {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// await _syncLock.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// var serverList = _servers.ToList();
|
||||||
|
|
||||||
|
// var matchingServers = GetExistingServers(serverList, usn);
|
||||||
|
// if (matchingServers.Count > 0)
|
||||||
|
// {
|
||||||
|
// foreach (var device in matchingServers)
|
||||||
|
// {
|
||||||
|
// serverList.Remove(device);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// _servers = serverList;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// finally
|
||||||
|
// {
|
||||||
|
// _syncLock.Release();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private bool IsValid(string nt, string usn)
|
||||||
|
// {
|
||||||
|
// // It has to report that it's a media renderer
|
||||||
|
// if (usn.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 &&
|
||||||
|
// nt.IndexOf("ContentDirectory:", StringComparison.OrdinalIgnoreCase) == -1 &&
|
||||||
|
// usn.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1 &&
|
||||||
|
// nt.IndexOf("MediaServer:", StringComparison.OrdinalIgnoreCase) == -1)
|
||||||
|
// {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private List<Device> GetExistingServers(List<Device> allDevices, string usn)
|
||||||
|
// {
|
||||||
|
// return allDevices
|
||||||
|
// .Where(i => usn.IndexOf(i.Properties.UUID, StringComparison.OrdinalIgnoreCase) != -1)
|
||||||
|
// .ToList();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public void Dispose()
|
||||||
|
// {
|
||||||
|
// _deviceDiscovery.DeviceDiscovered -= deviceDiscovery_DeviceDiscovered;
|
||||||
|
// _deviceDiscovery.DeviceLeft -= deviceDiscovery_DeviceLeft;
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ using MediaBrowser.Model.Logging;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.ContentDirectory
|
namespace MediaBrowser.Dlna.ContentDirectory
|
||||||
{
|
{
|
||||||
@ -27,6 +28,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||||||
private readonly IChannelManager _channelManager;
|
private readonly IChannelManager _channelManager;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
private readonly IUserViewManager _userViewManager;
|
private readonly IUserViewManager _userViewManager;
|
||||||
|
private readonly Func<IMediaEncoder> _mediaEncoder;
|
||||||
|
|
||||||
public ContentDirectory(IDlnaManager dlna,
|
public ContentDirectory(IDlnaManager dlna,
|
||||||
IUserDataManager userDataManager,
|
IUserDataManager userDataManager,
|
||||||
@ -35,7 +37,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||||||
IServerConfigurationManager config,
|
IServerConfigurationManager config,
|
||||||
IUserManager userManager,
|
IUserManager userManager,
|
||||||
ILogger logger,
|
ILogger logger,
|
||||||
IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager)
|
IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager, Func<IMediaEncoder> mediaEncoder)
|
||||||
: base(logger, httpClient)
|
: base(logger, httpClient)
|
||||||
{
|
{
|
||||||
_dlna = dlna;
|
_dlna = dlna;
|
||||||
@ -48,6 +50,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||||||
_channelManager = channelManager;
|
_channelManager = channelManager;
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
_userViewManager = userViewManager;
|
_userViewManager = userViewManager;
|
||||||
|
_mediaEncoder = mediaEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int SystemUpdateId
|
private int SystemUpdateId
|
||||||
@ -89,7 +92,8 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||||||
_localization,
|
_localization,
|
||||||
_channelManager,
|
_channelManager,
|
||||||
_mediaSourceManager,
|
_mediaSourceManager,
|
||||||
_userViewManager)
|
_userViewManager,
|
||||||
|
_mediaEncoder())
|
||||||
.ProcessControlRequest(request);
|
.ProcessControlRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ using System.Text;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.ContentDirectory
|
namespace MediaBrowser.Dlna.ContentDirectory
|
||||||
{
|
{
|
||||||
@ -34,6 +35,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||||||
private readonly IServerConfigurationManager _config;
|
private readonly IServerConfigurationManager _config;
|
||||||
private readonly User _user;
|
private readonly User _user;
|
||||||
private readonly IUserViewManager _userViewManager;
|
private readonly IUserViewManager _userViewManager;
|
||||||
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
|
|
||||||
private const string NS_DC = "http://purl.org/dc/elements/1.1/";
|
private const string NS_DC = "http://purl.org/dc/elements/1.1/";
|
||||||
private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
|
private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
|
||||||
@ -47,7 +49,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||||||
|
|
||||||
private readonly DeviceProfile _profile;
|
private readonly DeviceProfile _profile;
|
||||||
|
|
||||||
public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager)
|
public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager, IMediaEncoder mediaEncoder)
|
||||||
: base(config, logger)
|
: base(config, logger)
|
||||||
{
|
{
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
@ -56,10 +58,11 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||||||
_systemUpdateId = systemUpdateId;
|
_systemUpdateId = systemUpdateId;
|
||||||
_channelManager = channelManager;
|
_channelManager = channelManager;
|
||||||
_userViewManager = userViewManager;
|
_userViewManager = userViewManager;
|
||||||
|
_mediaEncoder = mediaEncoder;
|
||||||
_profile = profile;
|
_profile = profile;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
|
||||||
_didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger, libraryManager);
|
_didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger, libraryManager, _mediaEncoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, Headers methodParams)
|
protected override IEnumerable<KeyValuePair<string, string>> GetResult(string methodName, Headers methodParams)
|
||||||
@ -108,7 +111,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
|
|||||||
|
|
||||||
var newbookmark = int.Parse(sparams["PosSecond"], _usCulture);
|
var newbookmark = int.Parse(sparams["PosSecond"], _usCulture);
|
||||||
|
|
||||||
var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey());
|
var userdata = _userDataManager.GetUserData(user, item);
|
||||||
|
|
||||||
userdata.PlaybackPositionTicks = TimeSpan.FromSeconds(newbookmark).Ticks;
|
userdata.PlaybackPositionTicks = TimeSpan.FromSeconds(newbookmark).Ticks;
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ using System.Globalization;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Didl
|
namespace MediaBrowser.Dlna.Didl
|
||||||
@ -42,8 +43,9 @@ namespace MediaBrowser.Dlna.Didl
|
|||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private readonly ILibraryManager _libraryManager;
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
|
|
||||||
public DidlBuilder(DeviceProfile profile, User user, IImageProcessor imageProcessor, string serverAddress, string accessToken, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, ILogger logger, ILibraryManager libraryManager)
|
public DidlBuilder(DeviceProfile profile, User user, IImageProcessor imageProcessor, string serverAddress, string accessToken, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, ILogger logger, ILibraryManager libraryManager, IMediaEncoder mediaEncoder)
|
||||||
{
|
{
|
||||||
_profile = profile;
|
_profile = profile;
|
||||||
_imageProcessor = imageProcessor;
|
_imageProcessor = imageProcessor;
|
||||||
@ -53,6 +55,7 @@ namespace MediaBrowser.Dlna.Didl
|
|||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_libraryManager = libraryManager;
|
_libraryManager = libraryManager;
|
||||||
|
_mediaEncoder = mediaEncoder;
|
||||||
_accessToken = accessToken;
|
_accessToken = accessToken;
|
||||||
_user = user;
|
_user = user;
|
||||||
}
|
}
|
||||||
@ -142,7 +145,7 @@ namespace MediaBrowser.Dlna.Didl
|
|||||||
{
|
{
|
||||||
var sources = _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList();
|
var sources = _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList();
|
||||||
|
|
||||||
streamInfo = new StreamBuilder(GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions
|
streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions
|
||||||
{
|
{
|
||||||
ItemId = GetClientId(video),
|
ItemId = GetClientId(video),
|
||||||
MediaSources = sources,
|
MediaSources = sources,
|
||||||
@ -385,7 +388,7 @@ namespace MediaBrowser.Dlna.Didl
|
|||||||
{
|
{
|
||||||
var sources = _mediaSourceManager.GetStaticMediaSources(audio, true, _user).ToList();
|
var sources = _mediaSourceManager.GetStaticMediaSources(audio, true, _user).ToList();
|
||||||
|
|
||||||
streamInfo = new StreamBuilder(GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions
|
streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions
|
||||||
{
|
{
|
||||||
ItemId = GetClientId(audio),
|
ItemId = GetClientId(audio),
|
||||||
MediaSources = sources,
|
MediaSources = sources,
|
||||||
|
@ -14,6 +14,9 @@ using MediaBrowser.Dlna.Ssdp;
|
|||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
|
using MediaBrowser.Dlna.Channels;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Main
|
namespace MediaBrowser.Dlna.Main
|
||||||
{
|
{
|
||||||
@ -34,11 +37,13 @@ namespace MediaBrowser.Dlna.Main
|
|||||||
private readonly IUserDataManager _userDataManager;
|
private readonly IUserDataManager _userDataManager;
|
||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
|
|
||||||
private readonly SsdpHandler _ssdpHandler;
|
private readonly SsdpHandler _ssdpHandler;
|
||||||
private readonly IDeviceDiscovery _deviceDiscovery;
|
private readonly IDeviceDiscovery _deviceDiscovery;
|
||||||
|
|
||||||
private readonly List<string> _registeredServerIds = new List<string>();
|
private readonly List<string> _registeredServerIds = new List<string>();
|
||||||
|
private bool _ssdpHandlerStarted;
|
||||||
private bool _dlnaServerStarted;
|
private bool _dlnaServerStarted;
|
||||||
|
|
||||||
public DlnaEntryPoint(IServerConfigurationManager config,
|
public DlnaEntryPoint(IServerConfigurationManager config,
|
||||||
@ -54,7 +59,7 @@ namespace MediaBrowser.Dlna.Main
|
|||||||
IUserDataManager userDataManager,
|
IUserDataManager userDataManager,
|
||||||
ILocalizationManager localization,
|
ILocalizationManager localization,
|
||||||
IMediaSourceManager mediaSourceManager,
|
IMediaSourceManager mediaSourceManager,
|
||||||
ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery)
|
ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery, IMediaEncoder mediaEncoder)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_appHost = appHost;
|
_appHost = appHost;
|
||||||
@ -69,18 +74,29 @@ namespace MediaBrowser.Dlna.Main
|
|||||||
_localization = localization;
|
_localization = localization;
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
_deviceDiscovery = deviceDiscovery;
|
_deviceDiscovery = deviceDiscovery;
|
||||||
|
_mediaEncoder = mediaEncoder;
|
||||||
_ssdpHandler = (SsdpHandler)ssdpHandler;
|
_ssdpHandler = (SsdpHandler)ssdpHandler;
|
||||||
_logger = logManager.GetLogger("Dlna");
|
_logger = logManager.GetLogger("Dlna");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run()
|
public void Run()
|
||||||
{
|
{
|
||||||
StartSsdpHandler();
|
|
||||||
ReloadComponents();
|
ReloadComponents();
|
||||||
|
|
||||||
|
_config.ConfigurationUpdated += _config_ConfigurationUpdated;
|
||||||
_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
|
_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _lastEnableUpnP;
|
||||||
|
void _config_ConfigurationUpdated(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (_lastEnableUpnP != _config.Configuration.EnableUPnP)
|
||||||
|
{
|
||||||
|
ReloadComponents();
|
||||||
|
}
|
||||||
|
_lastEnableUpnP = _config.Configuration.EnableUPnP;
|
||||||
|
}
|
||||||
|
|
||||||
void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
|
void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
|
||||||
{
|
{
|
||||||
if (string.Equals(e.Key, "dlna", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(e.Key, "dlna", StringComparison.OrdinalIgnoreCase))
|
||||||
@ -91,10 +107,27 @@ namespace MediaBrowser.Dlna.Main
|
|||||||
|
|
||||||
private void ReloadComponents()
|
private void ReloadComponents()
|
||||||
{
|
{
|
||||||
var isServerStarted = _dlnaServerStarted;
|
|
||||||
|
|
||||||
var options = _config.GetDlnaConfiguration();
|
var options = _config.GetDlnaConfiguration();
|
||||||
|
|
||||||
|
if (!options.EnableServer && !options.EnablePlayTo && !_config.Configuration.EnableUPnP)
|
||||||
|
{
|
||||||
|
if (_ssdpHandlerStarted)
|
||||||
|
{
|
||||||
|
// Sat/ip live tv depends on device discovery, as well as hd homerun detection
|
||||||
|
// In order to allow this to be disabled, we need a modular way of knowing if there are
|
||||||
|
// any parts of the system that are dependant on it
|
||||||
|
// DisposeSsdpHandler();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_ssdpHandlerStarted)
|
||||||
|
{
|
||||||
|
StartSsdpHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
var isServerStarted = _dlnaServerStarted;
|
||||||
|
|
||||||
if (options.EnableServer && !isServerStarted)
|
if (options.EnableServer && !isServerStarted)
|
||||||
{
|
{
|
||||||
StartDlnaServer();
|
StartDlnaServer();
|
||||||
@ -121,8 +154,9 @@ namespace MediaBrowser.Dlna.Main
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
_ssdpHandler.Start();
|
_ssdpHandler.Start();
|
||||||
|
_ssdpHandlerStarted = true;
|
||||||
|
|
||||||
((DeviceDiscovery)_deviceDiscovery).Start(_ssdpHandler);
|
StartDeviceDiscovery();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -130,6 +164,50 @@ namespace MediaBrowser.Dlna.Main
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void StartDeviceDiscovery()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((DeviceDiscovery)_deviceDiscovery).Start(_ssdpHandler);
|
||||||
|
|
||||||
|
//DlnaChannel.Current.Start(() => _registeredServerIds.ToList());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error starting device discovery", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisposeDeviceDiscovery()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((DeviceDiscovery)_deviceDiscovery).Dispose();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error stopping device discovery", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DisposeSsdpHandler()
|
||||||
|
{
|
||||||
|
DisposeDeviceDiscovery();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
((DeviceDiscovery)_deviceDiscovery).Dispose();
|
||||||
|
|
||||||
|
_ssdpHandler.Dispose();
|
||||||
|
|
||||||
|
_ssdpHandlerStarted = false;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error stopping ssdp handlers", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void StartDlnaServer()
|
public void StartDlnaServer()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -196,7 +274,8 @@ namespace MediaBrowser.Dlna.Main
|
|||||||
_config,
|
_config,
|
||||||
_userDataManager,
|
_userDataManager,
|
||||||
_localization,
|
_localization,
|
||||||
_mediaSourceManager);
|
_mediaSourceManager,
|
||||||
|
_mediaEncoder);
|
||||||
|
|
||||||
_manager.Start();
|
_manager.Start();
|
||||||
}
|
}
|
||||||
@ -230,6 +309,7 @@ namespace MediaBrowser.Dlna.Main
|
|||||||
{
|
{
|
||||||
DisposeDlnaServer();
|
DisposeDlnaServer();
|
||||||
DisposePlayToManager();
|
DisposePlayToManager();
|
||||||
|
DisposeSsdpHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisposeDlnaServer()
|
public void DisposeDlnaServer()
|
||||||
|
@ -18,6 +18,7 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.PlayTo
|
namespace MediaBrowser.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
@ -35,6 +36,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||||||
private readonly ILocalizationManager _localization;
|
private readonly ILocalizationManager _localization;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
private readonly IConfigurationManager _config;
|
private readonly IConfigurationManager _config;
|
||||||
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
|
|
||||||
private readonly IDeviceDiscovery _deviceDiscovery;
|
private readonly IDeviceDiscovery _deviceDiscovery;
|
||||||
private readonly string _serverAddress;
|
private readonly string _serverAddress;
|
||||||
@ -74,7 +76,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||||||
get { return IsSessionActive; }
|
get { return IsSessionActive; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayToController(SessionInfo session, ISessionManager sessionManager, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, string accessToken, IDeviceDiscovery deviceDiscovery, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IConfigurationManager config)
|
public PlayToController(SessionInfo session, ISessionManager sessionManager, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, string accessToken, IDeviceDiscovery deviceDiscovery, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IConfigurationManager config, IMediaEncoder mediaEncoder)
|
||||||
{
|
{
|
||||||
_session = session;
|
_session = session;
|
||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
@ -88,6 +90,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||||||
_localization = localization;
|
_localization = localization;
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
_config = config;
|
_config = config;
|
||||||
|
_mediaEncoder = mediaEncoder;
|
||||||
_accessToken = accessToken;
|
_accessToken = accessToken;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_creationTime = DateTime.UtcNow;
|
_creationTime = DateTime.UtcNow;
|
||||||
@ -478,7 +481,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||||||
|
|
||||||
playlistItem.StreamUrl = playlistItem.StreamInfo.ToDlnaUrl(_serverAddress, _accessToken);
|
playlistItem.StreamUrl = playlistItem.StreamInfo.ToDlnaUrl(_serverAddress, _accessToken);
|
||||||
|
|
||||||
var itemXml = new DidlBuilder(profile, user, _imageProcessor, _serverAddress, _accessToken, _userDataManager, _localization, _mediaSourceManager, _logger, _libraryManager)
|
var itemXml = new DidlBuilder(profile, user, _imageProcessor, _serverAddress, _accessToken, _userDataManager, _localization, _mediaSourceManager, _logger, _libraryManager, _mediaEncoder)
|
||||||
.GetItemDidl(_config.GetDlnaConfiguration(), item, null, _session.DeviceId, new Filter(), playlistItem.StreamInfo);
|
.GetItemDidl(_config.GetDlnaConfiguration(), item, null, _session.DeviceId, new Filter(), playlistItem.StreamInfo);
|
||||||
|
|
||||||
playlistItem.Didl = itemXml;
|
playlistItem.Didl = itemXml;
|
||||||
@ -550,7 +553,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||||||
{
|
{
|
||||||
return new PlaylistItem
|
return new PlaylistItem
|
||||||
{
|
{
|
||||||
StreamInfo = new StreamBuilder(GetStreamBuilderLogger()).BuildVideoItem(new VideoOptions
|
StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildVideoItem(new VideoOptions
|
||||||
{
|
{
|
||||||
ItemId = item.Id.ToString("N"),
|
ItemId = item.Id.ToString("N"),
|
||||||
MediaSources = mediaSources,
|
MediaSources = mediaSources,
|
||||||
@ -570,7 +573,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||||||
{
|
{
|
||||||
return new PlaylistItem
|
return new PlaylistItem
|
||||||
{
|
{
|
||||||
StreamInfo = new StreamBuilder(GetStreamBuilderLogger()).BuildAudioItem(new AudioOptions
|
StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildAudioItem(new AudioOptions
|
||||||
{
|
{
|
||||||
ItemId = item.Id.ToString("N"),
|
ItemId = item.Id.ToString("N"),
|
||||||
MediaSources = mediaSources,
|
MediaSources = mediaSources,
|
||||||
|
@ -12,6 +12,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using MediaBrowser.Controller.MediaEncoding;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.PlayTo
|
namespace MediaBrowser.Dlna.PlayTo
|
||||||
{
|
{
|
||||||
@ -32,11 +33,12 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||||||
|
|
||||||
private readonly IDeviceDiscovery _deviceDiscovery;
|
private readonly IDeviceDiscovery _deviceDiscovery;
|
||||||
private readonly IMediaSourceManager _mediaSourceManager;
|
private readonly IMediaSourceManager _mediaSourceManager;
|
||||||
|
private readonly IMediaEncoder _mediaEncoder;
|
||||||
|
|
||||||
private readonly List<string> _nonRendererUrls = new List<string>();
|
private readonly List<string> _nonRendererUrls = new List<string>();
|
||||||
private DateTime _lastRendererClear;
|
private DateTime _lastRendererClear;
|
||||||
|
|
||||||
public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager)
|
public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_sessionManager = sessionManager;
|
_sessionManager = sessionManager;
|
||||||
@ -51,6 +53,7 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||||||
_userDataManager = userDataManager;
|
_userDataManager = userDataManager;
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
_mediaSourceManager = mediaSourceManager;
|
_mediaSourceManager = mediaSourceManager;
|
||||||
|
_mediaEncoder = mediaEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
@ -132,7 +135,8 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||||||
_userDataManager,
|
_userDataManager,
|
||||||
_localization,
|
_localization,
|
||||||
_mediaSourceManager,
|
_mediaSourceManager,
|
||||||
_config);
|
_config,
|
||||||
|
_mediaEncoder);
|
||||||
|
|
||||||
controller.Init(device);
|
controller.Init(device);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using System.Xml.Serialization;
|
using MediaBrowser.Model.Dlna;
|
||||||
using MediaBrowser.Model.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
@ -10,8 +10,6 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
{
|
{
|
||||||
Name = "BubbleUPnp";
|
Name = "BubbleUPnp";
|
||||||
|
|
||||||
TimelineOffsetSeconds = 5;
|
|
||||||
|
|
||||||
Identification = new DeviceIdentification
|
Identification = new DeviceIdentification
|
||||||
{
|
{
|
||||||
ModelName = "BubbleUPnp",
|
ModelName = "BubbleUPnp",
|
||||||
@ -27,16 +25,18 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
new TranscodingProfile
|
new TranscodingProfile
|
||||||
{
|
{
|
||||||
Container = "mp3",
|
Container = "mp3",
|
||||||
Type = DlnaProfileType.Audio,
|
AudioCodec = "mp3",
|
||||||
AudioCodec = "mp3"
|
Type = DlnaProfileType.Audio
|
||||||
},
|
},
|
||||||
|
|
||||||
new TranscodingProfile
|
new TranscodingProfile
|
||||||
{
|
{
|
||||||
Container = "ts",
|
Container = "ts",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video,
|
||||||
VideoCodec = "h264",
|
AudioCodec = "aac",
|
||||||
AudioCodec = "aac"
|
VideoCodec = "h264"
|
||||||
},
|
},
|
||||||
|
|
||||||
new TranscodingProfile
|
new TranscodingProfile
|
||||||
{
|
{
|
||||||
Container = "jpeg",
|
Container = "jpeg",
|
||||||
@ -48,21 +48,20 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
{
|
{
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "avi,mpeg,mkv,ts,mp4,mov,m4v,asf,webm,ogg,ogv,iso",
|
Container = "",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp3,flac,asf,off,oga,aac",
|
Container = "",
|
||||||
Type = DlnaProfileType.Audio
|
Type = DlnaProfileType.Audio
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
|
Container = "",
|
||||||
Type = DlnaProfileType.Photo,
|
Type = DlnaProfileType.Photo,
|
||||||
|
|
||||||
Container = "jpeg,png,gif,bmp,tiff"
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -71,6 +70,77 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
ContainerProfiles = new ContainerProfile[] { };
|
ContainerProfiles = new ContainerProfile[] { };
|
||||||
|
|
||||||
CodecProfiles = new CodecProfile[] { };
|
CodecProfiles = new CodecProfile[] { };
|
||||||
|
|
||||||
|
SubtitleProfiles = new[]
|
||||||
|
{
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "srt",
|
||||||
|
Method = SubtitleDeliveryMethod.External,
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "sub",
|
||||||
|
Method = SubtitleDeliveryMethod.External,
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "srt",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "ass",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "ssa",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "smi",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "dvdsub",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "pgs",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "pgssub",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "sub",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
MaxIconWidth = 48;
|
MaxIconWidth = 48;
|
||||||
MaxIconHeight = 48;
|
MaxIconHeight = 48;
|
||||||
|
|
||||||
MaxStreamingBitrate = 15000000;
|
MaxStreamingBitrate = 20000000;
|
||||||
MaxStaticBitrate = 15000000;
|
MaxStaticBitrate = 20000000;
|
||||||
MusicStreamingTranscodingBitrate = 192000;
|
MusicStreamingTranscodingBitrate = 192000;
|
||||||
MusicSyncBitrate = 192000;
|
MusicSyncBitrate = 192000;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using System.Xml.Serialization;
|
using MediaBrowser.Model.Dlna;
|
||||||
using MediaBrowser.Model.Dlna;
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace MediaBrowser.Dlna.Profiles
|
namespace MediaBrowser.Dlna.Profiles
|
||||||
{
|
{
|
||||||
@ -10,6 +10,7 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
{
|
{
|
||||||
Name = "Vlc";
|
Name = "Vlc";
|
||||||
|
|
||||||
|
|
||||||
TimelineOffsetSeconds = 5;
|
TimelineOffsetSeconds = 5;
|
||||||
|
|
||||||
Identification = new DeviceIdentification
|
Identification = new DeviceIdentification
|
||||||
@ -27,16 +28,18 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
new TranscodingProfile
|
new TranscodingProfile
|
||||||
{
|
{
|
||||||
Container = "mp3",
|
Container = "mp3",
|
||||||
Type = DlnaProfileType.Audio,
|
AudioCodec = "mp3",
|
||||||
AudioCodec = "mp3"
|
Type = DlnaProfileType.Audio
|
||||||
},
|
},
|
||||||
|
|
||||||
new TranscodingProfile
|
new TranscodingProfile
|
||||||
{
|
{
|
||||||
Container = "ts",
|
Container = "ts",
|
||||||
Type = DlnaProfileType.Video,
|
Type = DlnaProfileType.Video,
|
||||||
VideoCodec = "h264",
|
AudioCodec = "aac",
|
||||||
AudioCodec = "aac"
|
VideoCodec = "h264"
|
||||||
},
|
},
|
||||||
|
|
||||||
new TranscodingProfile
|
new TranscodingProfile
|
||||||
{
|
{
|
||||||
Container = "jpeg",
|
Container = "jpeg",
|
||||||
@ -48,21 +51,20 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
{
|
{
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "avi,mpeg,mkv,ts,mp4,mov,m4v,asf,webm,ogg,ogv,iso",
|
Container = "",
|
||||||
Type = DlnaProfileType.Video
|
Type = DlnaProfileType.Video
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
Container = "mp3,flac,asf,off,oga,aac",
|
Container = "",
|
||||||
Type = DlnaProfileType.Audio
|
Type = DlnaProfileType.Audio
|
||||||
},
|
},
|
||||||
|
|
||||||
new DirectPlayProfile
|
new DirectPlayProfile
|
||||||
{
|
{
|
||||||
|
Container = "",
|
||||||
Type = DlnaProfileType.Photo,
|
Type = DlnaProfileType.Photo,
|
||||||
|
|
||||||
Container = "jpeg,png,gif,bmp,tiff"
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -71,6 +73,77 @@ namespace MediaBrowser.Dlna.Profiles
|
|||||||
ContainerProfiles = new ContainerProfile[] { };
|
ContainerProfiles = new ContainerProfile[] { };
|
||||||
|
|
||||||
CodecProfiles = new CodecProfile[] { };
|
CodecProfiles = new CodecProfile[] { };
|
||||||
|
|
||||||
|
SubtitleProfiles = new[]
|
||||||
|
{
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "srt",
|
||||||
|
Method = SubtitleDeliveryMethod.External,
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "sub",
|
||||||
|
Method = SubtitleDeliveryMethod.External,
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "srt",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "ass",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "ssa",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "smi",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "dvdsub",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "pgs",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "pgssub",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
},
|
||||||
|
|
||||||
|
new SubtitleProfile
|
||||||
|
{
|
||||||
|
Format = "sub",
|
||||||
|
Method = SubtitleDeliveryMethod.Embed,
|
||||||
|
DidlMode = "",
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@ -16,8 +16,8 @@
|
|||||||
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
||||||
<MaxIconWidth>48</MaxIconWidth>
|
<MaxIconWidth>48</MaxIconWidth>
|
||||||
<MaxIconHeight>48</MaxIconHeight>
|
<MaxIconHeight>48</MaxIconHeight>
|
||||||
<MaxStreamingBitrate>15000000</MaxStreamingBitrate>
|
<MaxStreamingBitrate>20000000</MaxStreamingBitrate>
|
||||||
<MaxStaticBitrate>15000000</MaxStaticBitrate>
|
<MaxStaticBitrate>20000000</MaxStaticBitrate>
|
||||||
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
||||||
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
||||||
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
||||||
@ -33,9 +33,9 @@
|
|||||||
<DirectPlayProfile container="avi,mp4" type="Video" />
|
<DirectPlayProfile container="avi,mp4" type="Video" />
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<TranscodingProfiles>
|
||||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
</TranscodingProfiles>
|
</TranscodingProfiles>
|
||||||
<ContainerProfiles />
|
<ContainerProfiles />
|
||||||
<CodecProfiles />
|
<CodecProfiles />
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
||||||
<MaxIconWidth>48</MaxIconWidth>
|
<MaxIconWidth>48</MaxIconWidth>
|
||||||
<MaxIconHeight>48</MaxIconHeight>
|
<MaxIconHeight>48</MaxIconHeight>
|
||||||
<MaxStreamingBitrate>15000000</MaxStreamingBitrate>
|
<MaxStreamingBitrate>20000000</MaxStreamingBitrate>
|
||||||
<MaxStaticBitrate>15000000</MaxStaticBitrate>
|
<MaxStaticBitrate>20000000</MaxStaticBitrate>
|
||||||
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
||||||
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
||||||
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
||||||
@ -37,9 +37,9 @@
|
|||||||
<DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
|
<DirectPlayProfile container="mp3,flac,m4a,wma" type="Audio" />
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<TranscodingProfiles>
|
||||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
</TranscodingProfiles>
|
</TranscodingProfiles>
|
||||||
<ContainerProfiles />
|
<ContainerProfiles />
|
||||||
<CodecProfiles />
|
<CodecProfiles />
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
||||||
<MaxIconWidth>48</MaxIconWidth>
|
<MaxIconWidth>48</MaxIconWidth>
|
||||||
<MaxIconHeight>48</MaxIconHeight>
|
<MaxIconHeight>48</MaxIconHeight>
|
||||||
<MaxStreamingBitrate>15000000</MaxStreamingBitrate>
|
<MaxStreamingBitrate>20000000</MaxStreamingBitrate>
|
||||||
<MaxStaticBitrate>15000000</MaxStaticBitrate>
|
<MaxStaticBitrate>20000000</MaxStaticBitrate>
|
||||||
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
||||||
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
||||||
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
||||||
@ -39,8 +39,8 @@
|
|||||||
<DirectPlayProfile container="jpeg,jpg" type="Photo" />
|
<DirectPlayProfile container="jpeg,jpg" type="Photo" />
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<TranscodingProfiles>
|
||||||
<TranscodingProfile container="mpeg" type="Video" videoCodec="mpeg2video" audioCodec="mp2" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="mpeg" type="Video" videoCodec="mpeg2video" audioCodec="mp2" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
</TranscodingProfiles>
|
</TranscodingProfiles>
|
||||||
<ContainerProfiles />
|
<ContainerProfiles />
|
||||||
<CodecProfiles>
|
<CodecProfiles>
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
||||||
<MaxIconWidth>48</MaxIconWidth>
|
<MaxIconWidth>48</MaxIconWidth>
|
||||||
<MaxIconHeight>48</MaxIconHeight>
|
<MaxIconHeight>48</MaxIconHeight>
|
||||||
<MaxStreamingBitrate>15000000</MaxStreamingBitrate>
|
<MaxStreamingBitrate>20000000</MaxStreamingBitrate>
|
||||||
<MaxStaticBitrate>15000000</MaxStaticBitrate>
|
<MaxStaticBitrate>20000000</MaxStaticBitrate>
|
||||||
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
||||||
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
||||||
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
||||||
@ -43,9 +43,9 @@
|
|||||||
<DirectPlayProfile container="jpeg" type="Photo" />
|
<DirectPlayProfile container="jpeg" type="Photo" />
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<TranscodingProfiles>
|
||||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="mp4" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="mp4" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
</TranscodingProfiles>
|
</TranscodingProfiles>
|
||||||
<ContainerProfiles />
|
<ContainerProfiles />
|
||||||
<CodecProfiles>
|
<CodecProfiles>
|
||||||
|
@ -40,9 +40,9 @@
|
|||||||
<DirectPlayProfile container="" type="Photo" />
|
<DirectPlayProfile container="" type="Photo" />
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<TranscodingProfiles>
|
||||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
</TranscodingProfiles>
|
</TranscodingProfiles>
|
||||||
<ContainerProfiles />
|
<ContainerProfiles />
|
||||||
<CodecProfiles />
|
<CodecProfiles />
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
||||||
<MaxIconWidth>48</MaxIconWidth>
|
<MaxIconWidth>48</MaxIconWidth>
|
||||||
<MaxIconHeight>48</MaxIconHeight>
|
<MaxIconHeight>48</MaxIconHeight>
|
||||||
<MaxStreamingBitrate>15000000</MaxStreamingBitrate>
|
<MaxStreamingBitrate>20000000</MaxStreamingBitrate>
|
||||||
<MaxStaticBitrate>15000000</MaxStaticBitrate>
|
<MaxStaticBitrate>20000000</MaxStaticBitrate>
|
||||||
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
||||||
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
||||||
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
||||||
@ -42,9 +42,9 @@
|
|||||||
<DirectPlayProfile container="jpeg" type="Photo" />
|
<DirectPlayProfile container="jpeg" type="Photo" />
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<TranscodingProfiles>
|
||||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="ac3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
</TranscodingProfiles>
|
</TranscodingProfiles>
|
||||||
<ContainerProfiles>
|
<ContainerProfiles>
|
||||||
<ContainerProfile type="Photo">
|
<ContainerProfile type="Photo">
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
||||||
<MaxIconWidth>48</MaxIconWidth>
|
<MaxIconWidth>48</MaxIconWidth>
|
||||||
<MaxIconHeight>48</MaxIconHeight>
|
<MaxIconHeight>48</MaxIconHeight>
|
||||||
<MaxStreamingBitrate>15000000</MaxStreamingBitrate>
|
<MaxStreamingBitrate>20000000</MaxStreamingBitrate>
|
||||||
<MaxStaticBitrate>15000000</MaxStaticBitrate>
|
<MaxStaticBitrate>20000000</MaxStaticBitrate>
|
||||||
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
||||||
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
||||||
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
||||||
@ -37,9 +37,9 @@
|
|||||||
<DirectPlayProfile container="avi,mp4,mkv,ts" type="Video" />
|
<DirectPlayProfile container="avi,mp4,mkv,ts" type="Video" />
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<TranscodingProfiles>
|
||||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
</TranscodingProfiles>
|
</TranscodingProfiles>
|
||||||
<ContainerProfiles />
|
<ContainerProfiles />
|
||||||
<CodecProfiles />
|
<CodecProfiles />
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
<MaxAlbumArtHeight>480</MaxAlbumArtHeight>
|
||||||
<MaxIconWidth>48</MaxIconWidth>
|
<MaxIconWidth>48</MaxIconWidth>
|
||||||
<MaxIconHeight>48</MaxIconHeight>
|
<MaxIconHeight>48</MaxIconHeight>
|
||||||
<MaxStreamingBitrate>15000000</MaxStreamingBitrate>
|
<MaxStreamingBitrate>20000000</MaxStreamingBitrate>
|
||||||
<MaxStaticBitrate>15000000</MaxStaticBitrate>
|
<MaxStaticBitrate>20000000</MaxStaticBitrate>
|
||||||
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
<MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
|
||||||
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
<MusicSyncBitrate>192000</MusicSyncBitrate>
|
||||||
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
<XDlnaDoc>DMS-1.50</XDlnaDoc>
|
||||||
@ -43,9 +43,9 @@
|
|||||||
<DirectPlayProfile container="ogg" audioCodec="vorbis" type="Audio" />
|
<DirectPlayProfile container="ogg" audioCodec="vorbis" type="Audio" />
|
||||||
</DirectPlayProfiles>
|
</DirectPlayProfiles>
|
||||||
<TranscodingProfiles>
|
<TranscodingProfiles>
|
||||||
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="mp3" type="Audio" audioCodec="mp3" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="ts" type="Video" videoCodec="h264" audioCodec="aac" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" />
|
<TranscodingProfile container="jpeg" type="Photo" estimateContentLength="false" enableMpegtsM2TsMode="false" transcodeSeekInfo="Auto" copyTimestamps="false" context="Streaming" forceLiveStream="false" />
|
||||||
</TranscodingProfiles>
|
</TranscodingProfiles>
|
||||||
<ContainerProfiles />
|
<ContainerProfiles />
|
||||||
<CodecProfiles />
|
<CodecProfiles />
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user